I got it right this february even though didn't have the time to respond and it's not quite necessary now that iOS 8 has come. Still, this is how you load your own keyboard:
%hook UIKeyboardInputMode
+ (id)keyboardInputModeWithIdentifier:(id)arg1 {
id o = %orig;
return o;
}
- (id)primaryLanguage {
if([TegakiLayout isTegaki:[self identifier]]) return @"Tegaki";
return %orig;
}
%end
%hook UIKeyboardImpl
/* This is where the magic is! */
+ (Class)layoutClassForInputMode:(NSString*)arg1 keyboardType:(int)arg2 {
Class sass = %orig;
if ([TegakiLayout isTegaki: arg1]) {
return [TegakiLayout class];
}
return sass;
}
%end
extern "C" NSArray*UIKeyboardGetSupportedInputModes();
extern "C" NSArray*UIKeyboardGetActiveInputModes();
static NSArray* (*orig_modes)();
NSArray* rep_modes() {
NSArray* res = [orig_modes() arrayByAddingObjectsFromArray:@[@"TEGAKI", @"TEGAKI_Graffiti"]];
return res;
}
static NSArray* (*orig_active_modes)();
NSArray* rep_active_modes() {
NSArray* res = orig_active_modes();
return res;
}
%ctor {
%init;
MSHookFunction(UIKeyboardGetSupportedInputModes, rep_modes, &orig_modes);
MSHookFunction(UIKeyboardGetActiveInputModes, rep_active_modes, &orig_active_modes);
}
where TegakiLayout is a subclass of UIKeyboardLayout.
You then implement - (BOOL)isAlphabeticPlane
for returning whether it's a traditional keyboard thing and do the custom view creation in showKeyboardWithInputTraits:screenTraits:splitTraits:
.
To type in you then use [[UIKeyboardImpl activeInstance]insertText:@"\n"];
.
To create a 'globe' button you use this:
Class sw = NSClassFromString(@"UIInputSwitcherView");
[[sw sharedInstance]selectNextInputMode];
Don't forget to implement -keyboardName
and -keyplaneName
as well!
I'll post the whole project one day probably, but for now it's too large to describe here. This should be enough to get you up and running, though.