├── .gitignore ├── Makefile ├── Tweak.xm ├── Utils.h ├── Utils.m ├── control ├── flickplus.plist ├── h ├── TUIKeyboardLayoutFactory.h ├── UIKBKeyView.h ├── UIKBKeyViewAnimator.h ├── UIKBRenderConfig.h ├── UIKBRenderFactory.h ├── UIKBRenderFactoryiPhone.h ├── UIKBRenderTraits.h ├── UIKBTextStyle.h ├── UIKBTouchState.h ├── UIKBTree.h ├── UIKeyboardCache.h ├── UIKeyboardInputMode.h ├── UIKeyboardInputModeController.h ├── UIKeyboardLayout.h ├── UIKeyboardLayoutStar.h ├── UIKeyboardTaskExecutionContext.h ├── UIKeyboardTouchInfo.h └── UITextInputMode.h ├── notes ├── prefs ├── Makefile ├── NFPKeyPropsController.h ├── NFPKeyPropsController.m ├── NFPKeyboardController.h ├── NFPKeyboardController.m ├── NFPKeyplaneController.h ├── NFPKeyplaneController.m ├── NFPRootListController.h ├── NFPRootListController.m ├── Resources │ ├── Info.plist │ └── Root.plist └── entry.plist └── scripts ├── frida-fetch-kbcache.js └── frida-introspect-kb.js /.gitignore: -------------------------------------------------------------------------------- 1 | .theos/ 2 | packages/ 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | INSTALL_TARGET_PROCESSES = SpringBoard 2 | 3 | ifeq ($(FP_SIMULATOR),1) 4 | TARGET = simulator:clang::13.2 5 | ARCHS = x86_64 6 | else 7 | ARCHS = arm64 arm64e 8 | endif 9 | 10 | include $(THEOS)/makefiles/common.mk 11 | 12 | TWEAK_NAME = flickplus 13 | 14 | flickplus_FILES = Tweak.xm Utils.m 15 | flickplus_CFLAGS = -fobjc-arc 16 | ifeq ($(FP_SIMULATOR),1) 17 | flickplus_CFLAGS += -DFP_NO_CEPHEI 18 | else 19 | flickplus_EXTRA_FRAMEWORKS += Cephei 20 | endif 21 | 22 | include $(THEOS_MAKE_PATH)/tweak.mk 23 | 24 | ifneq ($(FP_SIMULATOR),1) 25 | SUBPROJECTS += prefs 26 | include $(THEOS_MAKE_PATH)/aggregate.mk 27 | endif 28 | 29 | ifneq (,$(filter x86_64 i386,$(ARCHS))) 30 | setup:: clean all 31 | @rm -f /opt/simject/$(TWEAK_NAME).dylib 32 | @cp -v $(THEOS_OBJ_DIR)/$(TWEAK_NAME).dylib /opt/simject/$(TWEAK_NAME).dylib 33 | @codesign -f -s - /opt/simject/$(TWEAK_NAME).dylib 34 | @cp -v $(PWD)/$(TWEAK_NAME).plist /opt/simject 35 | endif 36 | -------------------------------------------------------------------------------- /Tweak.xm: -------------------------------------------------------------------------------- 1 | #include "h/UIKBTree.h" 2 | #include "h/UIKeyboardCache.h" 3 | #include "h/UIKBTouchState.h" 4 | #include "h/UIKeyboardTaskExecutionContext.h" 5 | #include "h/UIKeyboardTouchInfo.h" 6 | #include "h/UIKeyboardLayout.h" 7 | #include "h/UIKeyboardLayoutStar.h" 8 | #include "h/UIKBTextStyle.h" 9 | #include "h/UIKBRenderTraits.h" 10 | #include "h/UIKBRenderConfig.h" 11 | #include "h/UIKBRenderFactory.h" 12 | #include "h/UIKBRenderFactoryiPhone.h" 13 | #include "h/UIKBKeyView.h" 14 | #include "h/UIKBKeyViewAnimator.h" 15 | #include 16 | #include 17 | #include "Utils.h" 18 | 19 | #ifndef FP_NO_CEPHEI 20 | #include 21 | #endif 22 | 23 | #ifndef kCFCoreFoundationVersionNumber_iOS_13_0 24 | #define kCFCoreFoundationVersionNumber_iOS_13_0 1665.15 25 | #endif 26 | 27 | #ifndef FP_NO_CEPHEI 28 | static HBPreferences *preferences; 29 | #else 30 | @interface NSUserDefaults (Private) 31 | - (instancetype)_initWithSuiteName:(NSString *)suiteName container:(NSURL *)container; 32 | @end 33 | static NSUserDefaults *preferences; 34 | #endif 35 | static NSMutableDictionary *kbPropCache; 36 | static NSString *lightSymbolsColour, *darkSymbolsColour; 37 | static bool hapticFeedbackEnabled = YES; 38 | static double symbolFontScale = 1.0; 39 | 40 | static id kbFetchProp(NSString *key) { 41 | id value = kbPropCache[key]; 42 | if (value == nil) { 43 | value = [preferences objectForKey:key]; 44 | kbPropCache[key] = value; 45 | } 46 | return value; 47 | } 48 | 49 | @interface _UIClickFeedbackGenerator : UIFeedbackGenerator 50 | -(id)initWithCoordinateSpace:(id)arg1; 51 | -(void)pressedDown; 52 | -(void)pressedUp; 53 | @end 54 | 55 | static bool lieAboutGestureKeys = false; 56 | static bool doingDragOnKey = false; 57 | static _UIClickFeedbackGenerator *clickFeedback = nil; 58 | static bool lastFeedbackWasDown = false; 59 | 60 | %hook UIKeyboardTouchInfo 61 | %property (nonatomic, assign) bool fpAllow; 62 | - (id)init { 63 | self.fpAllow = false; 64 | return %orig; 65 | } 66 | %end 67 | 68 | %hook UIKeyboardLayoutStar 69 | - (void)touchDragged:(UIKBTouchState *)state executionContext:(UIKeyboardTaskExecutionContext *)ctx { 70 | UIKeyboardTouchInfo *touchInfo = [self infoForTouch:state]; // UIKeyboardTouchInfo * 71 | 72 | // are we gonna let this one become a continuous path? 73 | CGPoint initial = touchInfo.initialPoint; 74 | CGPoint now = touchInfo.initialDragPoint; // TODO check if this is correct 75 | double deltaX = now.x - initial.x; 76 | double deltaY = now.y - initial.y; 77 | double distanceSq = (deltaX * deltaX) + (deltaY * deltaY); 78 | 79 | // NSLog(@"delta:%f,%f distanceSq:%f", deltaX, deltaY, distanceSq); 80 | if (deltaX < -30 || deltaX > 30 || distanceSq > (85*85)) 81 | touchInfo.fpAllow = true; 82 | 83 | if (touchInfo.fpAllow) { 84 | // this lets a continuous path happen 85 | if (clickFeedback != nil) { 86 | // if we played a click-down feedback, nullify it 87 | // to signal to the user that the flick is now off-limitsb 88 | if (lastFeedbackWasDown) 89 | [clickFeedback pressedUp]; 90 | clickFeedback = nil; 91 | } 92 | 93 | lieAboutGestureKeys = true; 94 | %orig; 95 | lieAboutGestureKeys = false; 96 | } else { 97 | %orig; 98 | } 99 | } 100 | 101 | - (void)updatePanAlternativesForTouchInfo:(UIKeyboardTouchInfo *)touchInfo { 102 | if (clickFeedback == nil && hapticFeedbackEnabled) { 103 | // delaying the prepare call might be possible slightly 104 | // to potentially save a bit of battery 105 | clickFeedback = [[_UIClickFeedbackGenerator alloc] initWithCoordinateSpace:self]; 106 | [clickFeedback prepare]; 107 | lastFeedbackWasDown = false; 108 | } 109 | 110 | doingDragOnKey = true; 111 | %orig; 112 | doingDragOnKey = false; 113 | } 114 | 115 | - (void)resetPanAlternativesForEndedTouch:(id)touch { 116 | if (clickFeedback != nil) { 117 | clickFeedback = nil; 118 | } 119 | } 120 | %end 121 | 122 | %hook UIKBTree 123 | - (void)setSelectedVariantIndex:(long long)index { 124 | if (doingDragOnKey && clickFeedback != nil) { 125 | if (self.selectedVariantIndex != index) { 126 | if (index == 0 || index == 1) { 127 | [clickFeedback pressedDown]; 128 | lastFeedbackWasDown = true; 129 | } else { 130 | [clickFeedback pressedUp]; 131 | lastFeedbackWasDown = false; 132 | } 133 | } 134 | } 135 | %orig; 136 | } 137 | %end 138 | 139 | @implementation UIKBTree (FlickPlus) 140 | - (NSDictionary *)nfpGenerateKeylayoutConfigBasedOffKeylayout:(UIKBTree *)subLayout inKeyplane:(UIKBTree *)keyplane rewriteCapitalToSmall:(BOOL)capsToSmall { 141 | // context: keylayout (NOT keyplane!) 142 | if (subLayout == nil) { 143 | NSLog(@"nfpGenerateKeylayoutConfigBasedOffKeylayout passed null sublayout!"); 144 | return [NSDictionary dictionary]; 145 | } 146 | 147 | // mostly same as pre-0.0.6 versions of the tweak 148 | NSMutableDictionary *result = [NSMutableDictionary dictionary]; 149 | 150 | UIKBTree *thisKeyset = self.keySet, *subKeyset = subLayout.keySet; 151 | 152 | UIKBTree *thisTopRow = thisKeyset.subtrees[0]; 153 | UIKBTree *thisMiddleRow = thisKeyset.subtrees[1]; 154 | UIKBTree *thisBottomRow = thisKeyset.subtrees[2]; 155 | UIKBTree *subTopRow = subKeyset.subtrees[0]; 156 | UIKBTree *subMiddleRow = subKeyset.subtrees[1]; 157 | UIKBTree *subBottomRow = subKeyset.subtrees[2]; 158 | 159 | // top row is mapped as-is 160 | int count = MIN(thisTopRow.subtrees.count, subTopRow.subtrees.count); 161 | for (int i = 0; i < count; i++) { 162 | UIKBTree *thisKey = thisTopRow.subtrees[i], *subKey = subTopRow.subtrees[i]; 163 | NSString *cleanName = [thisKey.name stringByReplacingOccurrencesOfString:@"-Small-Display" withString:@""]; 164 | if (capsToSmall) cleanName = [cleanName stringByReplacingOccurrencesOfString:@"-Capital-Letter" withString:@"-Small-Letter"]; 165 | result[cleanName] = @[subKey.representedString, subKey.displayString]; 166 | } 167 | 168 | // middle row is mapped as-is 169 | count = MIN(thisMiddleRow.subtrees.count, subMiddleRow.subtrees.count); 170 | for (int i = 0; i < count; i++) { 171 | UIKBTree *thisKey = thisMiddleRow.subtrees[i], *subKey = subMiddleRow.subtrees[i]; 172 | NSString *cleanName = [thisKey.name stringByReplacingOccurrencesOfString:@"-Small-Display" withString:@""]; 173 | if (capsToSmall) cleanName = [cleanName stringByReplacingOccurrencesOfString:@"-Capital-Letter" withString:@"-Small-Letter"]; 174 | result[cleanName] = @[subKey.representedString, subKey.displayString]; 175 | } 176 | 177 | // bottom row requires a bit more work 178 | NSMutableArray *bottomKeys = [NSMutableArray array]; 179 | if (thisMiddleRow.subtrees.count == (subMiddleRow.subtrees.count - 1)) { 180 | // carry the last key over if it's been left behind 181 | UIKBTree *subKey = subMiddleRow.subtrees.lastObject; 182 | [bottomKeys addObject:@[subKey.representedString, subKey.displayString]]; 183 | } 184 | 185 | for (UIKBTree *subKey in subBottomRow.subtrees) { 186 | [bottomKeys addObject:@[subKey.representedString, subKey.displayString]]; 187 | } 188 | 189 | // add the ellipsis because it's cool 190 | if ([keyplane.name containsString:@"-Letters"] && bottomKeys.count < thisBottomRow.subtrees.count) { 191 | [bottomKeys insertObject:@[@"…", @"…"] atIndex:2]; 192 | } 193 | 194 | // now shove all those in 195 | count = MIN(thisBottomRow.subtrees.count, bottomKeys.count); 196 | for (int i = 0; i < count; i++) { 197 | UIKBTree *thisKey = thisBottomRow.subtrees[i]; 198 | NSString *cleanName = [thisKey.name stringByReplacingOccurrencesOfString:@"-Small-Display" withString:@""]; 199 | if (capsToSmall) cleanName = [cleanName stringByReplacingOccurrencesOfString:@"-Capital-Letter" withString:@"-Small-Letter"]; 200 | if (![thisKey.representedString isEqualToString:bottomKeys[i][0]]) 201 | result[cleanName] = bottomKeys[i]; 202 | } 203 | 204 | // NSLog(@"Built:: %@", result); 205 | return [NSDictionary dictionaryWithDictionary:result]; 206 | } 207 | @end 208 | 209 | 210 | 211 | extern "C" { 212 | NSString *UIKeyboardGetCurrentInputMode(); 213 | NSString *UIKeyboardLocalizedString(NSString *key, NSString *language, NSString *unk, NSString *def); 214 | id UIKeyboardLocalizedObject(NSString *key, NSString *language, NSString *unk, id def, BOOL unk2); 215 | }; 216 | 217 | @interface NSLocale (MissingStuff) 218 | + (NSLocale *)preferredLocale; // iOS 13+ 219 | + (NSLocale *)_UIKBPreferredLocale; // iOS 12 220 | @end 221 | 222 | %group Polyfill12 223 | %hook NSLocale 224 | %new + (NSLocale *)preferredLocale { 225 | return [NSLocale _UIKBPreferredLocale]; 226 | } 227 | %end 228 | %end 229 | 230 | static NSString *currencyFix(NSString *str) { 231 | // based heavily off the logic in -[UIKeyboardLayoutStar setCurrencyKeysForCurrentLocaleOnKeyplane:] 232 | NSString *localObjName = nil, *defChar = nil; 233 | if ([str isEqualToString:@"¤1"]) { 234 | localObjName = @"UI-PrimaryCurrencySign"; 235 | defChar = @"$"; 236 | } else if ([str isEqualToString:@"¤2"]) { 237 | localObjName = @"UI-AlternateCurrencySign-1"; 238 | defChar = @"€"; 239 | } else if ([str isEqualToString:@"¤3"]) { 240 | localObjName = @"UI-AlternateCurrencySign-2"; 241 | defChar = @"@"; 242 | } else if ([str isEqualToString:@"¤4"]) { 243 | localObjName = @"UI-AlternateCurrencySign-3"; 244 | defChar = @"¥"; 245 | } else if ([str isEqualToString:@"¤5"]) { 246 | localObjName = @"UI-AlternateCurrencySign-4"; 247 | defChar = @"₩"; 248 | } else { 249 | return str; 250 | } 251 | 252 | // could probably optimise things by caching some of these calls...? 253 | str = UIKeyboardLocalizedObject(localObjName, [[NSLocale preferredLocale] localeIdentifier], 0, 0, NO); 254 | if (!str) 255 | str = UIKeyboardLocalizedString(localObjName, UIKeyboardGetCurrentInputMode(), 0, defChar); 256 | return str; 257 | } 258 | 259 | %hook UIKBTree 260 | - (int)displayTypeHint { 261 | int type = %orig; 262 | if (lieAboutGestureKeys && type == 10) 263 | return 0; 264 | else 265 | return type; 266 | } 267 | 268 | - (void)updateFlickKeycapOnKeys { 269 | // it's Keyboard Fun Time! 270 | // we are in a keyplane, we need to know what keyboard we are 271 | NSLog(@"I'm being patched...! %@ -> %@", self.name, [self stringForProperty:@"fp-kb-name"]); 272 | 273 | // two cases: 274 | // altflag is capsAreSeparate 275 | // true -> two planes, one Capital, one Small 276 | // false -> one Small plane, used for both 277 | // in which case we need to do special work on Capital plane 278 | BOOL replaceCapitalBySmall = NO; 279 | 280 | NSString *kbName = [self stringForProperty:@"fp-kb-name"]; 281 | if (kbName == nil) 282 | return; 283 | 284 | if ([self.name hasSuffix:@"Capital-Letters"]) { 285 | // we might need to fallback 286 | NSString *propName = [self stringForProperty:@"fp-kb-altflag"]; 287 | id flag = kbFetchProp(propName); 288 | if (![flag boolValue]) { 289 | // user is not using separate caps 290 | // so, use the Small plane, and pretend every key is Small 291 | kbName = [self stringForProperty:@"fp-kb-altname"]; 292 | replaceCapitalBySmall = YES; 293 | if (flag == nil) 294 | kbPropCache[propName] = @NO; 295 | } 296 | } 297 | 298 | NSDictionary *config = kbFetchProp(kbName); 299 | if (config == nil) { 300 | NSLog(@"Can't find config %@!! Using a default...", kbName); 301 | UIKBTree *keylayout = self.subtrees[0]; 302 | UIKBTree *subKeylayout = keylayout.cachedGestureLayout; 303 | config = [keylayout nfpGenerateKeylayoutConfigBasedOffKeylayout:subKeylayout inKeyplane:self rewriteCapitalToSmall:replaceCapitalBySmall]; 304 | // we store this in the propcache but not to preferences 305 | kbPropCache[kbName] = config; 306 | } 307 | 308 | for (UIKBTree *keylayout in self.subtrees) { 309 | if (keylayout.type != 3) 310 | continue; 311 | 312 | UIKBTree *keySet = [keylayout keySet]; 313 | 314 | for (UIKBTree *list in keySet.subtrees) { 315 | for (UIKBTree *key in list.subtrees) { 316 | if (key.displayType == 0 || key.displayType == 8) { 317 | NSString *checkName = [key.name stringByReplacingOccurrencesOfString:@"-Small-Display" withString:@""]; 318 | if (replaceCapitalBySmall) 319 | checkName = [checkName stringByReplacingOccurrencesOfString:@"-Capital" withString:@"-Small"]; 320 | 321 | NSArray *cfgKey = config[checkName]; 322 | if (cfgKey == nil) { 323 | // NSLog(@"map for %@ not found", checkName); 324 | if (key.displayTypeHint == 10) { 325 | // clear existing gesture keys just in case 326 | key.displayTypeHint = 0; 327 | } 328 | } else if (cfgKey.count == 2) { 329 | // NSLog(@"map for %@ found -> %@", checkName, cfgKey); 330 | // text key 331 | key.displayTypeHint = 10; 332 | NSString *rep = cfgKey[0], *disp = cfgKey[1]; 333 | if ([rep hasPrefix:@"¤"]) rep = currencyFix(rep); 334 | if ([disp hasPrefix:@"¤"]) disp = currencyFix(disp); 335 | key.secondaryRepresentedStrings = @[rep]; 336 | key.secondaryDisplayStrings = @[ 337 | (disp && disp.length) ? disp : rep 338 | ]; 339 | } else if (cfgKey.count == 4) { 340 | // dual key 341 | key.displayTypeHint = 10; 342 | NSString *repA = cfgKey[0], *dispA = cfgKey[1]; 343 | NSString *repB = cfgKey[2], *dispB = cfgKey[3]; 344 | if ([repA hasPrefix:@"¤"]) repA = currencyFix(repA); 345 | if ([repB hasPrefix:@"¤"]) repB = currencyFix(repB); 346 | if ([dispA hasPrefix:@"¤"]) dispA = currencyFix(dispA); 347 | if ([dispB hasPrefix:@"¤"]) dispB = currencyFix(dispB); 348 | key.secondaryRepresentedStrings = @[repA, repB]; 349 | key.secondaryDisplayStrings = @[ 350 | (dispA && dispA.length) ? dispA : repA, 351 | (dispB && dispB.length) ? dispB : repB 352 | ]; 353 | } 354 | } 355 | } 356 | } 357 | } 358 | } 359 | %end 360 | 361 | %hook TUIKBGraphSerialization 362 | 363 | - (UIKBTree *)keyboardForName:(NSString *)name { 364 | // TODO: do not patch the same keyboard multiple times! 365 | NSLog(@"Requesting deserialisation of keyboard %@", name); 366 | UIKBTree *tree = %orig; 367 | 368 | NSString *cleanName = name; 369 | 370 | // for now, we exclude certain ones... 371 | if ([cleanName hasSuffix:@"-URL"]) return tree; 372 | if ([cleanName hasSuffix:@"-NumberPad"]) return tree; 373 | if ([cleanName hasSuffix:@"-PhonePad"]) return tree; 374 | if ([cleanName hasSuffix:@"-NamePhonePad"]) return tree; 375 | if ([cleanName hasSuffix:@"-Email"]) return tree; 376 | if ([cleanName hasSuffix:@"-DecimalPad"]) return tree; 377 | if ([cleanName hasSuffix:@"-AlphaWithURL"]) return tree; 378 | if ([cleanName containsString:@"Emoji"]) return tree; 379 | 380 | // Twitter keyboard just uses standard stuff 381 | if ([cleanName hasSuffix:@"-Twitter"]) 382 | cleanName = [cleanName substringToIndex:(cleanName.length - 8)]; 383 | 384 | // take out iPhone-{variant}- 385 | if ([cleanName hasPrefix:@"iPhone-"]) { 386 | NSRange searchRange = NSMakeRange(7, cleanName.length - 7); 387 | NSUInteger secondHyphen = [cleanName rangeOfString:@"-" options:0 range:searchRange].location; 388 | if (secondHyphen != NSNotFound) 389 | cleanName = [cleanName substringFromIndex:secondHyphen + 1]; 390 | } 391 | 392 | for (UIKBTree *keyplane in tree.subtrees) { 393 | NSString *cleanPlaneName = [keyplane.name sliceAfterLastUnderscore]; 394 | cleanPlaneName = [cleanPlaneName stringByReplacingOccurrencesOfString:@"-Small-Display" withString:@""]; 395 | 396 | NSString *mainName = [NSString stringWithFormat:@"kb-%@--%@--flicks", cleanName, cleanPlaneName]; 397 | [keyplane setObject:mainName forProperty:@"fp-kb-name"]; 398 | if ([cleanPlaneName isEqualToString:@"Capital-Letters"]) { 399 | NSString *flagName = [NSString stringWithFormat:@"kb-%@-capsAreSeparate", cleanName]; 400 | [keyplane setObject:flagName forProperty:@"fp-kb-altflag"]; 401 | NSString *altName = [NSString stringWithFormat:@"kb-%@--Small-Letters--flicks", cleanName]; 402 | [keyplane setObject:altName forProperty:@"fp-kb-altname"]; 403 | } 404 | 405 | // this is necessary so that cachedGestureLayout will be set 406 | // which we need when calling nfpGenerateKeylayoutConfigBasedOffKeylayout 407 | // to generate a default config 408 | if ([cleanPlaneName hasSuffix:@"Letters"]) 409 | [keyplane setObject:[keyplane alternateKeyplaneName] forProperty:@"gesture-keyplane"]; 410 | else if ([cleanPlaneName isEqualToString:@"Numbers-And-Punctuation"]) 411 | [keyplane setObject:[keyplane shiftAlternateKeyplaneName] forProperty:@"gesture-keyplane"]; 412 | } 413 | 414 | return tree; 415 | } 416 | 417 | %end 418 | 419 | %hook TIPreferencesController 420 | - (bool)boolForPreferenceKey:(NSString *)key { 421 | if ([key isEqualToString:@"GesturesEnabled"]) { 422 | return YES; 423 | } else { 424 | return %orig; 425 | } 426 | } 427 | %end 428 | 429 | %group SpringBoard 430 | %hook SpringBoard 431 | // clear the KB cache on respring 432 | - (void)applicationDidFinishLaunching:(id)application { 433 | [[%c(UIKeyboardCache) sharedInstance] purge]; 434 | %orig; 435 | } 436 | %end 437 | %end 438 | 439 | 440 | // recolour the symbols 441 | %hook UIKBRenderFactoryiPhone 442 | - (UIKBRenderTraits *)_traitsForKey:(UIKBTree *)key onKeyplane:(UIKBTree *)plane { 443 | UIKBRenderTraits *traits = %orig; 444 | 445 | NSArray *styles = traits.secondarySymbolStyles; 446 | if (styles != nil) { 447 | NSString *which = self.renderConfig.lightKeyboard ? lightSymbolsColour : darkSymbolsColour; 448 | 449 | for (UIKBTextStyle *style in styles) { 450 | style.textColor = which; 451 | style.textOpacity = 1.0; 452 | style.fontSize *= symbolFontScale; 453 | } 454 | 455 | // force the blurred background to be applied to light KB 456 | // stops the label from showing through and making things weird 457 | if (!self.allowsPaddles) 458 | traits.blurBlending = YES; 459 | } 460 | 461 | return traits; 462 | } 463 | %end 464 | 465 | // make animations less of a disaster 466 | enum AnimHackMode { AHMNone, AHMPaddles, AHMNoPaddles }; 467 | static AnimHackMode animHackMode = AHMNone; 468 | 469 | static void enterAnimHackMode(UIKBKeyView *keyView) { 470 | // TODO: might want to check the keyboard's interface idiom 471 | // in case people decide to run this on an iPad 472 | animHackMode = keyView.factory.allowsPaddles ? AHMPaddles : AHMNoPaddles; 473 | } 474 | 475 | static void endAnimHackMode(UIKBKeyView *keyView) { 476 | animHackMode = AHMNone; 477 | } 478 | 479 | %hook UIKBKeyViewAnimator 480 | - (void)transitionKeyView:(UIKBKeyView *)keyView fromState:(int)from toState:(int)to completion:(void *)c { 481 | enterAnimHackMode(keyView); 482 | %orig; 483 | if (animHackMode != AHMNone) { 484 | // force the symbol opacity to zero 485 | // we can't change a double constant with a simple hook, alas 486 | UIKBTree *key = keyView.key; 487 | if (to == 4 && key.displayType != 7 && key.displayTypeHint == 10) { 488 | CALayer *symbolLayer = [keyView layerForRenderFlags:16]; 489 | if (symbolLayer) 490 | symbolLayer.opacity = 0; 491 | } 492 | } 493 | endAnimHackMode(keyView); 494 | } 495 | - (void)updateTransitionForKeyView:(UIKBKeyView *)keyView normalizedDragSize:(CGSize)size { 496 | enterAnimHackMode(keyView); 497 | %orig; 498 | endAnimHackMode(keyView); 499 | } 500 | - (void)endTransitionForKeyView:(UIKBKeyView *)keyView { 501 | enterAnimHackMode(keyView); 502 | %orig; 503 | endAnimHackMode(keyView); 504 | } 505 | + (id)normalizedAnimationWithKeyPath:(NSString *)path fromValue:(id)from toValue:(id)to { 506 | // we want to force symbol opacity to 0... 507 | if (animHackMode != AHMNone && [path isEqualToString:@"opacity"]) { 508 | // awful kludge alert!! 509 | double v = [from doubleValue]; 510 | if (v >= 0.2 && v <= 0.35) { 511 | return %orig(path, @0, to); 512 | } 513 | } 514 | return %orig; 515 | } 516 | + (id)normalizedUnwindOpacityAnimationWithKeyPath:(NSString *)path originallyFromValue:(id)from toValue:(id)to offset:(double)offset { 517 | // it's a great day in UIKit, and you are a horrible goose 518 | if (animHackMode != AHMNone && [path isEqualToString:@"opacity"]) { 519 | // awful kludge alert!! (part 2) 520 | double v = [from doubleValue]; 521 | if (v >= 0.2 && v <= 0.35) { 522 | return %orig(path, @0, to, offset); 523 | } 524 | } 525 | return %orig; 526 | } 527 | 528 | - (id)keycapPrimaryTransform { 529 | // don't relocate the primary keycap, at all 530 | if (animHackMode == AHMNone) 531 | return %orig; 532 | else 533 | return self.keycapNullTransform; 534 | } 535 | 536 | - (id)keycapAlternateTransform:(UIKBKeyView *)keyView { 537 | // move the symbol out of view at the top 538 | // not ideal, but it's less glitchy-looking than the default... 539 | if (animHackMode == AHMNone) 540 | return %orig; 541 | else { 542 | return [self keycapMeshTransformFromRect:CGRectMake(0.115, 0.28, 0.77, 0.44) 543 | toRect:CGRectMake(0.5, 0, 0, 0)]; 544 | } 545 | // eventually, it would be good to render paddle-less mode to match 546 | // the non-pressed keys, but that requires more work to determine the 547 | // correct rects for all configurations 548 | } 549 | 550 | // TODO: do similar stopgap animations for the left/right bits 551 | %end 552 | 553 | 554 | 555 | 556 | static NSString *resolveColour(NSString *name) { 557 | if ([name isEqualToString:@"white"]) { 558 | return @"UIKBColorWhite"; 559 | } else if ([name isEqualToString:@"lgrey"]) { 560 | return @"UIKBColorGray_Percent68"; 561 | } else if ([name isEqualToString:@"dgrey"]) { 562 | return @"UIKBColorGray_Percent31_37"; 563 | } else if ([name isEqualToString:@"black"]) { 564 | return @"UIKBColorBlack"; 565 | } else { 566 | return @"UIKBColorRed"; 567 | } 568 | } 569 | 570 | 571 | static void syncPreferences() { 572 | lightSymbolsColour = resolveColour([preferences objectForKey:@"lightSymbols"]); 573 | darkSymbolsColour = resolveColour([preferences objectForKey:@"darkSymbols"]); 574 | hapticFeedbackEnabled = [preferences boolForKey:@"hapticFeedback"]; 575 | symbolFontScale = [preferences boolForKey:@"smallSymbols"] ? 0.7 : 1.0; 576 | [kbPropCache removeAllObjects]; 577 | [[%c(UIKeyboardCache) sharedInstance] purge]; 578 | // maybe also [UIKBRenderer clearInternalCaches] ?? 579 | } 580 | 581 | 582 | %ctor { 583 | kbPropCache = [NSMutableDictionary dictionary]; 584 | 585 | #ifndef FP_NO_CEPHEI 586 | preferences = [[HBPreferences alloc] initWithIdentifier:@"org.wuffs.flickplus"]; 587 | [preferences registerDefaults:@{ 588 | @"lightSymbols": @"lgrey", 589 | @"darkSymbols": @"lgrey", 590 | @"hapticFeedback": @YES, 591 | @"smallSymbols": @NO 592 | }]; 593 | [preferences registerPreferenceChangeBlock:^{ 594 | syncPreferences(); 595 | }]; 596 | #else 597 | preferences = [[NSUserDefaults alloc] _initWithSuiteName:@"org.wuffs.flickplus" container:[NSURL URLWithString:@"/var/mobile"]]; 598 | // TODO watch for a thing, probably 599 | syncPreferences(); 600 | #endif 601 | 602 | // trick thanks to poomsmart 603 | // https://github.com/PoomSmart/EmojiPort-Legacy/blob/8573de11226ac2e1c4108c044078109dbfb07a02/KBResizeLegacy.xm 604 | dlopen("/System/Library/PrivateFrameworks/TextInputUI.framework/TextInputUI", RTLD_LAZY); 605 | 606 | NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier]; 607 | if ([bundleID isEqualToString:@"com.apple.springboard"]) { 608 | %init(SpringBoard); 609 | } 610 | 611 | if (!IS_IOS_OR_NEWER(iOS_13_0)) { 612 | %init(Polyfill12); 613 | } 614 | %init; 615 | } 616 | -------------------------------------------------------------------------------- /Utils.h: -------------------------------------------------------------------------------- 1 | @interface NSString (FlickPlus) 2 | - (NSString *)sliceAfterLastUnderscore; 3 | - (NSString *)hyphensToSpaces; 4 | @end 5 | 6 | -------------------------------------------------------------------------------- /Utils.m: -------------------------------------------------------------------------------- 1 | #import "Utils.h" 2 | 3 | @implementation NSString (FlickPlus) 4 | - (NSString *)sliceAfterLastUnderscore { 5 | NSUInteger lastUnderscore = [self rangeOfString:@"_" options:NSBackwardsSearch].location; 6 | if (lastUnderscore != NSNotFound) 7 | return [self substringFromIndex:lastUnderscore + 1]; 8 | else 9 | return self; 10 | } 11 | 12 | - (NSString *)hyphensToSpaces { 13 | return [self stringByReplacingOccurrencesOfString:@"-" withString:@" "]; 14 | } 15 | @end 16 | -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: org.wuffs.flickplus 2 | Name: FlicksForAll 3 | Depends: mobilesubstrate, ws.hbang.common (>= 1.13) 4 | Version: 0.0.8 5 | Architecture: iphoneos-arm 6 | Description: iPad-like key flicks on iPhone (iOS 13) 7 | Maintainer: Ninji 8 | Author: Ninji 9 | Section: Tweaks 10 | -------------------------------------------------------------------------------- /flickplus.plist: -------------------------------------------------------------------------------- 1 | { Filter = { Bundles = ( "com.apple.TextInput" ); }; } 2 | -------------------------------------------------------------------------------- /h/TUIKeyboardLayoutFactory.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit) (Debug version compiled Oct 15 2018 10:31:50). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2015 by Steve Nygard. 5 | // 6 | 7 | #import 8 | 9 | @class NSMutableDictionary, TUIKBGraphSerialization, UIKBTree; 10 | 11 | @interface TUIKeyboardLayoutFactory : NSObject 12 | { 13 | void *_layoutsLibraryHandle; 14 | NSMutableDictionary *_internalCache; 15 | TUIKBGraphSerialization *_decoder; 16 | } 17 | 18 | + (id)layoutsFileName; 19 | + (TUIKeyboardLayoutFactory *)sharedKeyboardFactory; 20 | @property(retain) TUIKBGraphSerialization *decoder; // @synthesize decoder=_decoder; 21 | @property(retain) NSMutableDictionary *internalCache; // @synthesize internalCache=_internalCache; 22 | @property(readonly, nonatomic) void *layoutsLibraryHandle; // @synthesize layoutsLibraryHandle=_layoutsLibraryHandle; 23 | - (id)keyboardPrefixForWidth:(double)arg1 andEdge:(_Bool)arg2; 24 | - (UIKBTree *)keyboardWithName:(id)arg1 inCache:(id)arg2; 25 | - (void)_createDecoderIfNecessary; 26 | - (id)init; 27 | - (void)dealloc; 28 | 29 | @end 30 | 31 | -------------------------------------------------------------------------------- /h/UIKBKeyView.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit) (Debug version compiled Oct 15 2018 10:31:50). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2015 by Steve Nygard. 5 | // 6 | 7 | // #import 8 | 9 | // #import 10 | 11 | @class NSMutableDictionary, NSString, UIKBRenderConfig, UIKBRenderFactory, UIKBTree, UIKeyboardMenuView; 12 | 13 | __attribute__((visibility("hidden"))) 14 | @interface UIKBKeyView : UIView // 15 | { 16 | UIKBTree *m_keyplane; 17 | UIKBTree *m_key; 18 | struct CGRect m_drawFrame; 19 | struct __CFBoolean *m_allowsCaching; 20 | UIKBRenderConfig *m_renderConfig; 21 | UIKBRenderFactory *m_factory; 22 | NSMutableDictionary *_keyLayers; 23 | int _renderedKeyState; 24 | NSString *_cachedTraitsHashString; 25 | struct CGColor *_activeBackgroundColor; 26 | id _activeCompositingFilter; 27 | _Bool _singleRerender; 28 | double _cachedBackgroundOpacity; 29 | _Bool _cachedControlKeyRenderingPreference; 30 | _Bool _renderAsMask; 31 | unsigned long long _cachedAnchorCorner; 32 | unsigned long long _cachedShiftState; 33 | long long _cachedSelector; 34 | UIKeyboardMenuView *_popupMenu; 35 | double _endingTransitionDuration; 36 | } 37 | 38 | @property(nonatomic) _Bool renderAsMask; // @synthesize renderAsMask=_renderAsMask; 39 | @property(nonatomic) double endingTransitionDuration; // @synthesize endingTransitionDuration=_endingTransitionDuration; 40 | @property(nonatomic) UIKeyboardMenuView *popupMenu; // @synthesize popupMenu=_popupMenu; 41 | @property(nonatomic) _Bool cachedControlKeyRenderingPreference; // @synthesize cachedControlKeyRenderingPreference=_cachedControlKeyRenderingPreference; 42 | @property(nonatomic) long long cachedSelector; // @synthesize cachedSelector=_cachedSelector; 43 | @property(nonatomic) unsigned long long cachedShiftState; // @synthesize cachedShiftState=_cachedShiftState; 44 | @property(nonatomic) unsigned long long cachedAnchorCorner; // @synthesize cachedAnchorCorner=_cachedAnchorCorner; 45 | @property(retain, nonatomic) NSString *cachedTraitsHashString; // @synthesize cachedTraitsHashString=_cachedTraitsHashString; 46 | @property(retain, nonatomic) UIKBRenderFactory *factory; // @synthesize factory=m_factory; 47 | @property(retain, nonatomic) UIKBRenderConfig *renderConfig; // @synthesize renderConfig=m_renderConfig; 48 | @property(nonatomic) struct CGRect drawFrame; // @synthesize drawFrame=m_drawFrame; 49 | @property(readonly, nonatomic) UIKBTree *key; // @synthesize key=m_key; 50 | @property(readonly, nonatomic) UIKBTree *keyplane; // @synthesize keyplane=m_keyplane; 51 | - (void)changeBackgroundToActiveIfNecessary; 52 | - (void)changeBackgroundToEnabled; 53 | - (void)configureBackdropView:(id)arg1 forRenderConfig:(id)arg2; 54 | - (id)_generateBackdropMaskImage; 55 | - (_Bool)_canDrawContent; 56 | - (void)drawContentsOfRenderers:(id)arg1; 57 | @property(readonly, nonatomic) _Bool keepNonPersistent; 58 | @property(readonly, nonatomic) double cachedWidth; 59 | @property(readonly, nonatomic) _Bool cacheDeferable; 60 | - (void)displayLayer:(id)arg1; 61 | - (id)renderFlagsForTraits:(id)arg1; 62 | - (void)_populateLayer:(id)arg1 withContents:(id)arg2; 63 | - (long long)imageOrientationForLayer:(id)arg1; 64 | - (id)layerForRenderFlags:(long long)arg1; 65 | - (void)removeFromSuperview; 66 | - (void)prepareForDisplay; 67 | - (_Bool)requiresSublayers; 68 | - (_Bool)_shouldUpdateLayers; 69 | @property(readonly, nonatomic) _Bool hasRendered; 70 | @property(readonly) long long cachedRenderFlags; 71 | - (_Bool)allowBackgroundCachingForRenderFlags:(long long)arg1; 72 | - (id)cacheKeysForRenderFlags:(id)arg1; 73 | @property(readonly, nonatomic) NSString *cacheKey; 74 | @property(readonly, nonatomic) struct UIEdgeInsets displayInsets; 75 | - (void)hideKeyCap:(_Bool)arg1; 76 | - (void)dimKeys:(id)arg1; 77 | // - (void)willDisplayModalActionView:(id)arg1 withSubTreeKeyView:(id)arg2 completion:(CDUnknownBlockType)arg3; 78 | - (long long)didInputSubTree:(id)arg1; 79 | - (id)subTreeHitTest:(struct CGPoint)arg1; 80 | - (unsigned long long)focusableVariantCount; 81 | - (void)touchesEnded:(id)arg1 withEvent:(id)arg2; 82 | - (void)_applyAppearanceInvocations; 83 | - (_Bool)_viewShouldBeOpaque; 84 | @property(readonly, nonatomic) UIKBKeyView *contentsKeyView; 85 | @property(readonly, nonatomic) struct CGRect variantFrame; 86 | - (int)textEffectsVisibilityLevel; 87 | - (void)dealloc; 88 | - (void)updateForKeyplane:(id)arg1 key:(id)arg2; 89 | - (id)initWithFrame:(struct CGRect)arg1 keyplane:(id)arg2 key:(id)arg3; 90 | 91 | // Remaining properties 92 | @property(readonly, nonatomic) long long cacheDeferPriority; 93 | @property(readonly, copy) NSString *debugDescription; 94 | @property(readonly, copy) NSString *description; 95 | @property(readonly) unsigned long long hash; 96 | @property(readonly) Class superclass; 97 | 98 | @end 99 | 100 | -------------------------------------------------------------------------------- /h/UIKBKeyViewAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit) (Debug version compiled Oct 15 2018 10:31:50). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2015 by Steve Nygard. 5 | // 6 | 7 | #import 8 | 9 | // #import 10 | 11 | @class NSString; 12 | 13 | __attribute__((visibility("hidden"))) 14 | @interface UIKBKeyViewAnimator : NSObject 15 | { 16 | _Bool _disabled; 17 | } 18 | 19 | + (id)normalizedUnwindAnimationWithKeyPath:(id)arg1 originallyFromValue:(id)arg2 toValue:(id)arg3 offset:(double)arg4; 20 | + (id)normalizedUnwindOpacityAnimationWithKeyPath:(id)arg1 originallyFromValue:(id)arg2 toValue:(id)arg3 offset:(double)arg4; 21 | + (id)normalizedUnwindAnimationWithKeyPath:(id)arg1 fromValue:(id)arg2 toValue:(id)arg3 offset:(double)arg4; 22 | + (id)normalizedAnimationWithKeyPath:(id)arg1 fromValue:(id)arg2 toValue:(id)arg3; 23 | @property(nonatomic) _Bool disabled; // @synthesize disabled=_disabled; 24 | - (void)reset; 25 | - (void)endTransitionForKeyView:(id)arg1; 26 | - (void)updateTransitionForKeyView:(id)arg1 normalizedDragSize:(struct CGSize)arg2; 27 | - (void)transitionEndedForKeyView:(id)arg1 alternateCount:(unsigned long long)arg2; 28 | - (void)transitionStartedForKeyView:(id)arg1 alternateCount:(unsigned long long)arg2 toLeft:(_Bool)arg3; 29 | - (void)transitionOutKeyView:(id)arg1 fromState:(int)arg2 toState:(int)arg3 completion:(id)arg4; 30 | - (void)transitionKeyView:(id)arg1 fromState:(int)arg2 toState:(int)arg3 completion:(id)arg4; 31 | - (_Bool)shouldTransitionKeyView:(id)arg1 fromState:(int)arg2 toState:(int)arg3; 32 | - (_Bool)shouldAssertCurrentKeyState:(id)arg1; 33 | - (id)keycapRightSelectRightTransform; 34 | - (id)keycapRightSelectLeftTransform; 35 | - (id)keycapRightSelectPrimaryTransform; 36 | - (id)keycapLeftSelectRightTransform; 37 | - (id)keycapLeftSelectLeftTransform; 38 | - (id)keycapLeftSelectPrimaryTransform; 39 | - (id)keycapPrimaryExitTransform; 40 | - (id)keycapRightTransform; 41 | - (id)keycapLeftTransform; 42 | - (id)keycapAlternateDualStringTransform:(id)arg1; 43 | - (id)keycapAlternateTransform:(id)arg1; 44 | - (id)keycapPrimaryDualStringTransform:(id)arg1; 45 | - (id)keycapPrimaryTransform; 46 | - (id)keycapNullTransform; 47 | - (id)keycapMeshTransformFromRect:(struct CGRect)arg1 toRect:(struct CGRect)arg2; 48 | @property(readonly, nonatomic) struct CGRect secondaryGlyphNormalizedExitRect; 49 | @property(readonly, nonatomic) struct CGRect primaryGlyphNormalizedExitRect; 50 | - (void)_fadeInKeyView:(id)arg1 duration:(double)arg2 completion:(id)arg3; 51 | - (void)_fadeOutKeyView:(id)arg1 duration:(double)arg2 completion:(id)arg3; 52 | - (double)delayedDeactivationTimeForKeyView:(id)arg1; 53 | - (Class)keyViewClassForKey:(id)arg1 traits:(id)arg2; 54 | - (Class)_keyViewClassForSpecialtyKey:(id)arg1; 55 | @property(readonly, nonatomic) _Bool shouldPurgeKeyViews; 56 | 57 | // Remaining properties 58 | @property(readonly, copy) NSString *debugDescription; 59 | @property(readonly, copy) NSString *description; 60 | // @property(readonly) unsigned long long hash; 61 | @property(readonly) Class superclass; 62 | 63 | @end 64 | 65 | -------------------------------------------------------------------------------- /h/UIKBRenderConfig.h: -------------------------------------------------------------------------------- 1 | /* Generated by RuntimeBrowser 2 | Image: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore 3 | */ 4 | 5 | @interface UIKBRenderConfig : NSObject { 6 | double _blurRadius; 7 | double _blurSaturation; 8 | /*_UIButtonBarButtonVisualProvider **/id _buttonBarVisualProvider; 9 | long long _forceQuality; 10 | double _keycapOpacity; 11 | bool _lightKeyboard; 12 | double _lightKeycapOpacity; 13 | bool _useEmojiStyles; 14 | } 15 | 16 | @property (nonatomic, readonly) long long backdropStyle; 17 | @property (nonatomic, readonly) long long blurEffectStyle; 18 | @property (nonatomic) double blurRadius; 19 | @property (nonatomic) double blurSaturation; 20 | // @property (nonatomic, readonly) _UIButtonBarButtonVisualProvider *buttonBarVisualProvider; 21 | @property (nonatomic) long long forceQuality; 22 | @property (nonatomic) double keycapOpacity; 23 | @property (nonatomic) bool lightKeyboard; 24 | @property (nonatomic) double lightKeycapOpacity; 25 | @property (nonatomic, readonly) bool whiteText; 26 | 27 | + (long long)backdropStyleForStyle:(long long)arg1 quality:(long long)arg2; 28 | + (id)configForAppearance:(long long)arg1 inputMode:(id)arg2; 29 | + (id)darkConfig; 30 | + (id)defaultConfig; 31 | + (id)defaultEmojiConfig; 32 | + (id)lowQualityDarkConfig; 33 | 34 | - (long long)backdropStyle; 35 | - (long long)blurEffectStyle; 36 | - (double)blurRadius; 37 | - (double)blurSaturation; 38 | - (id)buttonBarVisualProvider; 39 | - (id)copyWithZone:(NSZone *)arg1; 40 | - (id)description; 41 | - (long long)forceQuality; 42 | - (bool)isEqual:(id)arg1; 43 | - (double)keycapOpacity; 44 | - (bool)lightKeyboard; 45 | - (double)lightKeycapOpacity; 46 | - (void)setBlurRadius:(double)arg1; 47 | - (void)setBlurSaturation:(double)arg1; 48 | - (void)setForceQuality:(long long)arg1; 49 | - (void)setKeycapOpacity:(double)arg1; 50 | - (void)setLightKeyboard:(bool)arg1; 51 | - (void)setLightKeycapOpacity:(double)arg1; 52 | - (bool)whiteText; 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /h/UIKBRenderFactory.h: -------------------------------------------------------------------------------- 1 | /* Generated by RuntimeBrowser 2 | Image: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore 3 | */ 4 | 5 | @interface UIKBRenderFactory : NSObject { 6 | bool _allowsPaddles; 7 | bool _boldTextEnabled; 8 | bool _drawsOneHandedAffordance; 9 | bool _increasedContrastEnabled; 10 | bool _lightweightFactory; 11 | bool _preferStringKeycapOverImage; 12 | /*UIKBRenderingContext **/id _renderingContext; 13 | double _rivenSizeFactor; 14 | double _scale; 15 | NSMutableArray * _segmentTraits; 16 | CGSize _stretchFactor; 17 | bool _suppressSegmentTraits; 18 | } 19 | 20 | @property (nonatomic) bool allowsPaddles; 21 | @property (nonatomic, readonly) bool boldTextEnabled; 22 | @property (nonatomic) bool drawsOneHandedAffordance; 23 | @property (nonatomic) bool increasedContrastEnabled; 24 | @property (nonatomic) bool lightweightFactory; 25 | @property (nonatomic) bool preferStringKeycapOverImage; 26 | @property (getter=renderConfig, readonly) UIKBRenderConfig *renderConfig; 27 | // @property (nonatomic, retain) UIKBRenderingContext *renderingContext; 28 | @property (nonatomic) double rivenSizeFactor; 29 | @property (nonatomic) double scale; 30 | @property (nonatomic, readonly) NSArray *segmentTraits; 31 | @property (nonatomic) CGSize stretchFactor; 32 | 33 | + (id)_characterSetForGlyphSelectors; 34 | + (bool)_enabled; 35 | + (long long)_graphicsQuality; 36 | + (id)cacheKeyForString:(id)arg1 withRenderFlags:(long long)arg2 renderingContext:(id)arg3; 37 | + (bool)couldUseGlyphSelectorForDisplayString:(id)arg1; 38 | // + (Class)factoryClassForVisualStyle:(struct { unsigned int x1 : 6; unsigned int x2 : 1; unsigned int x3 : 1; unsigned int x4 : 8; unsigned int x5 : 8; unsigned int x6 : 8; })arg1; 39 | // + (id)factoryForVisualStyle:(struct { unsigned int x1 : 6; unsigned int x2 : 1; unsigned int x3 : 1; unsigned int x4 : 8; unsigned int x5 : 8; unsigned int x6 : 8; })arg1 renderingContext:(id)arg2; 40 | // + (id)factoryForVisualStyle:(struct { unsigned int x1 : 6; unsigned int x2 : 1; unsigned int x3 : 1; unsigned int x4 : 8; unsigned int x5 : 8; unsigned int x6 : 8; })arg1 renderingContext:(id)arg2 skipLayoutSegments:(bool)arg3; 41 | // + (id)lightweightFactoryForVisualStyle:(struct { unsigned int x1 : 6; unsigned int x2 : 1; unsigned int x3 : 1; unsigned int x4 : 8; unsigned int x5 : 8; unsigned int x6 : 8; })arg1 renderingContext:(id)arg2; 42 | + (id)segmentedControlColor:(bool)arg1; 43 | 44 | - (double)RivenFactor:(double)arg1; 45 | - (CGPoint)RivenPointFactor:(CGPoint)arg1; 46 | - (id)ZWNJKeyImageName; 47 | - (id)_controlKeyBackgroundColorName; 48 | - (void)_customizeTraits:(id)arg1 forPopupForKey:(id)arg2 withRenderingContext:(id)arg3 keycapsFontName:(id)arg4; 49 | - (UIKBRenderTraits *)_traitsForKey:(UIKBTree *)key onKeyplane:(UIKBTree *)plane; 50 | - (void)addLayoutSegment:(id)arg1; 51 | - (bool)allowsPaddles; 52 | - (void)applyBoldTextForContent:(id)arg1 withKey:(id)arg2; 53 | - (id)backgroundTraitsForKeyplane:(id)arg1; 54 | - (id)biuKeyImageName; 55 | - (id)boldKeyImageName; 56 | - (bool)boldTextEnabled; 57 | - (Class)contentViewClassForPopupKey:(id)arg1; 58 | - (id)controlKeyBackgroundColorName; 59 | - (id)controlKeyForegroundColorName; 60 | - (id)controlKeyShadowColorName; 61 | - (id)copyKeyImageName; 62 | - (id)cutKeyImageName; 63 | - (void)dealloc; 64 | - (id)defaultKeyBackgroundColorName; 65 | - (id)defaultKeyShadowColorName; 66 | - (id)deleteKeyImageName; 67 | - (id)deleteOnKeyImageName; 68 | - (id)dictationKeyImageName; 69 | - (id)dismissKeyImageName; 70 | - (id)displayContentsForKey:(id)arg1; 71 | - (bool)drawsOneHandedAffordance; 72 | - (CGPoint)dualStringKeyBottomTextOffset:(id)arg1 keyplane:(id)arg2; 73 | - (CGPoint)dualStringKeyTopTextOffset:(id)arg1 keyplane:(id)arg2; 74 | - (double)emojiPopupDividerKeyOffset; 75 | - (long long)enabledBlendForm; 76 | - (id)globalEmojiKeyImageName; 77 | - (id)globalKeyImageName; 78 | - (long long)glyphSelectorForDisplayString:(id)arg1; 79 | - (id)handwritingMoreKeyImageName; 80 | - (id)hashStringElement; 81 | - (bool)increasedContrastEnabled; 82 | - (id)initWithRenderingContext:(id)arg1 skipLayoutSegments:(bool)arg2; 83 | - (double)keyCornerRadius; 84 | - (id)keyImageNameWithSkinnyVariation:(id)arg1; 85 | - (bool)keyIsRightToLeftSensitive:(id)arg1; 86 | - (id)leftArrowKeyImageName; 87 | - (long long)lightHighQualityEnabledBlendForm; 88 | - (id)lightKeycapsFontName; 89 | - (id)lightPadKeycapsFontName; 90 | - (id)lightTextFontName; 91 | - (bool)lightweightFactory; 92 | - (id)lowQualityLayeredBackgroundColorName; 93 | - (void)lowQualityTraits:(id)arg1; 94 | - (id)messagesWriteboardKeyImageName; 95 | - (void)modifyTraitsForDetachedInputSwitcher:(id)arg1 withKey:(id)arg2; 96 | - (void)modifyTraitsForDividerVariant:(id)arg1 withKey:(id)arg2; 97 | - (id)multitapCompleteKeyImageName; 98 | - (id)muttitapReverseKeyImageName; 99 | - (id)pasteKeyImageName; 100 | - (bool)popupKeyUsesCustomKeyContentView:(id)arg1; 101 | - (bool)preferStringKeycapOverImage; 102 | - (UIKBRenderConfig *)renderConfig; 103 | - (id)renderingContext; 104 | - (id)rightArrowKeyImageName; 105 | - (double)rivenSizeFactor; 106 | - (double)scale; 107 | - (void)scaleTraits:(id)arg1; 108 | - (NSArray *)segmentTraits; 109 | - (void)setAllowsPaddles:(bool)arg1; 110 | - (void)setDrawsOneHandedAffordance:(bool)arg1; 111 | - (void)setIncreasedContrastEnabled:(bool)arg1; 112 | - (void)setLightweightFactory:(bool)arg1; 113 | - (void)setPreferStringKeycapOverImage:(bool)arg1; 114 | - (void)setRenderingContext:(id)arg1; 115 | - (void)setRivenSizeFactor:(double)arg1; 116 | - (void)setScale:(double)arg1; 117 | - (void)setStretchFactor:(CGSize)arg1; 118 | - (void)setupLayoutSegments; 119 | - (id)shiftKeyImageName; 120 | - (id)shiftLockImageName; 121 | - (id)shiftOnKeyImageName; 122 | - (bool)shouldClearBaseDisplayStringForVariants:(id)arg1; 123 | - (double)skinnyKeyThreshold; 124 | - (id)spaceKeyGrabberHandlesImageName; 125 | - (CGSize)stretchFactor; 126 | - (bool)supportsInputTraits:(id)arg1 forKeyplane:(id)arg2; 127 | - (void)suppressLayoutSegments; 128 | - (id)thinKeycapsFontName; 129 | - (id)thinTextFontName; 130 | - (id)traitsForKey:(id)arg1 onKeyplane:(id)arg2; 131 | - (id)traitsHashStringForKey:(id)arg1 withGeometry:(id)arg2 withSymbolStyle:(id)arg3 controlOpacities:(bool)arg4 blurBlending:(bool)arg5; 132 | - (double)translucentGapWidth; 133 | - (id)undoKeyImageName; 134 | - (bool)useBlueThemingForKey:(id)arg1; 135 | 136 | // UIKBRenderFactory (UIKBRenderFactory_Passcode) 137 | 138 | - (id)extraPasscodePaddleTraits; 139 | - (void)modifyKeyTraitsForPasscode:(id)arg1 forKey:(id)arg2 onKeyplane:(id)arg3; 140 | - (id)passcodeActiveControlKeyTraits; 141 | - (id)passcodeBackgroundTraitsForKeyplane:(id)arg1; 142 | - (id)passcodeControlKeyTraits; 143 | - (double)passcodeEdgeWeight; 144 | - (id)passcodeKeyEdgeColorName; 145 | - (id)passcodeShiftedControlKeyTraits; 146 | 147 | @end 148 | -------------------------------------------------------------------------------- /h/UIKBRenderFactoryiPhone.h: -------------------------------------------------------------------------------- 1 | /* Generated by RuntimeBrowser 2 | Image: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore 3 | */ 4 | 5 | @interface UIKBRenderFactoryiPhone : UIKBRenderFactory 6 | 7 | - (CGPoint)ZWNJKeyOffset; 8 | - (void)_configureTraitsForPopupStyle:(id)arg1 withKey:(id)arg2 onKeyplane:(id)arg3; 9 | - (void)_customizeGeometry:(id)arg1 forKey:(id)arg2 contents:(id)arg3; 10 | - (void)_customizePopupTraits:(UIKBRenderTraits *)traits forKey:(UIKBTree *)key onKeyplane:(UIKBTree *)plane; 11 | - (void)_customizeSymbolStyle:(id)arg1 forKey:(id)arg2 contents:(id)arg3; 12 | - (void)_customizeTraits:(id)arg1 forPredictionCellKey:(id)arg2; 13 | - (bool)_popupMenuStyleForKey:(id)arg1; 14 | - (bool)_popupStyleForKey:(id)arg1; 15 | - (double)_row4ControlSegmentWidthLeft; 16 | - (double)_row4ControlSegmentWidthRight; 17 | - (UIKBRenderTraits *)_traitsForKey:(UIKBTree *)key onKeyplane:(UIKBTree *)plane; 18 | - (id)activeControlKeyTraits; 19 | - (double)assistKeyFontSize; 20 | - (CGPoint)boldKeyOffset; 21 | - (id)controlKeyTraits; 22 | - (CGPoint)copyKeyOffset; 23 | - (CGPoint)cutKeyOffset; 24 | - (double)deleteKeyFontSize; 25 | - (id)deleteKeyImageName; 26 | - (CGPoint)deleteKeyOffset; 27 | - (id)deleteOnKeyImageName; 28 | - (id)dictationKeyImageName; 29 | - (CGPoint)dictationKeyOffset; 30 | - (CGPoint)dismissKeyOffset; 31 | - (double)dualStringBottomAdditionalOffsetForDisplayContents:(id)arg1; 32 | - (id)globalEmojiKeyImageName; 33 | - (id)globalKeyImageName; 34 | - (double)hintNoneKeyFontSize; 35 | - (bool)iPadFudgeLayout; 36 | - (bool)iPadSansHomeButtonLayout; 37 | - (CGPoint)internationalKeyOffset; 38 | - (bool)isTallPopup; 39 | - (CGPoint)leftArrowKeyOffset; 40 | - (long long)lightHighQualityEnabledBlendForm; 41 | - (CGPoint)more123KeyOffset; 42 | - (double)moreABCKeyFontSize; 43 | - (CGPoint)moreABCKeyOffset; 44 | - (double)moreABCKeyWideCellFontSize; 45 | - (CGPoint)moreABCKeyWideCellOffset; 46 | - (double)moreKeyFontSize; 47 | - (id)multitapCompleteKeyImageName; 48 | - (id)muttitapReverseKeyImageName; 49 | - (CGPoint)pasteKeyOffset; 50 | - (double)popupFontSize; 51 | - (CGPoint)popupSymbolTextOffset; 52 | - (CGPoint)realEmojiKeyOffset; 53 | - (double)returnKeyFontSize; 54 | - (CGPoint)returnKeyOffset; 55 | - (CGPoint)rightArrowKeyOffset; 56 | - (long long)rowLimitForKey:(id)arg1; 57 | - (CGPoint)secondaryShiftKeyOffset; 58 | - (void)setupLayoutSegments; 59 | - (id)shiftDeleteGlyphTraits; 60 | - (double)shiftKeyFontSize; 61 | - (id)shiftKeyImageName; 62 | - (CGPoint)shiftKeyOffset; 63 | - (id)shiftLockControlKeyTraits; 64 | - (id)shiftLockImageName; 65 | - (id)shiftOnKeyImageName; 66 | - (id)shiftedControlKeyTraits; 67 | - (double)skinnyKeyThreshold; 68 | - (double)stringKeyFontSize; 69 | - (CGPoint)stringKeyOffset; 70 | - (CGPoint)undoKeyOffset; 71 | - (double)variantAnnotationTextFontSize; 72 | - (CGPoint)variantAnnotationTextOffset; 73 | - (UIEdgeInsets)variantDisplayFrameInsets; 74 | - (id)variantGeometriesForGeometry:(id)arg1 variantCount:(unsigned long long)arg2 rowLimit:(long long)arg3 annotationIndex:(unsigned long long)arg4; 75 | - (UIEdgeInsets)variantPaddedFrameInsets; 76 | - (UIEdgeInsets)variantSymbolFrameInsets; 77 | - (CGPoint)variantSymbolTextOffset; 78 | - (double)variantWideShadowWeight; 79 | - (UIEdgeInsets)wideShadowPaddleInsets; 80 | - (UIEdgeInsets)wideShadowPopupMenuInsets; 81 | - (double)zhuyinFirstToneKeyFontSize; 82 | - (CGPoint)zhuyinFirstToneKeyOffset; 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /h/UIKBRenderTraits.h: -------------------------------------------------------------------------------- 1 | /* Generated by RuntimeBrowser 2 | Image: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore 3 | */ 4 | 5 | @interface UIKBRenderTraits : NSObject { 6 | /*UIKBGradient **/id _backgroundGradient; 7 | long long _blendForm; 8 | bool _blurBlending; 9 | bool _controlOpacities; 10 | UIKBTextStyle * _fallbackSymbolStyle; 11 | NSMutableArray * _foregroundRenderEffects; 12 | /*UIKBRenderGeometry **/id _geometry; 13 | NSString * _hashString; 14 | UIKBRenderTraits * _highlightedVariantTraits; 15 | bool _honorControlOpacity; 16 | /*UIKBGradient **/id _layeredBackgroundGradient; 17 | /*UIKBGradient **/id _layeredForegroundGradient; 18 | NSMutableArray * _renderEffects; 19 | NSArray * _renderFlags; 20 | long long _renderFlagsForAboveEffects; 21 | bool _renderSecondarySymbolsSeparately; 22 | NSArray * _secondarySymbolStyles; 23 | UIKBTextStyle * _symbolStyle; 24 | NSArray * _variantGeometries; 25 | UIKBRenderTraits * _variantTraits; 26 | } 27 | 28 | // @property (nonatomic, retain) UIKBGradient *backgroundGradient; 29 | @property (nonatomic) long long blendForm; 30 | @property (nonatomic) bool blurBlending; 31 | @property (nonatomic) bool controlOpacities; 32 | @property (nonatomic, retain) UIKBTextStyle *fallbackSymbolStyle; 33 | @property (nonatomic, readonly) NSArray *foregroundRenderEffects; 34 | // @property (nonatomic, retain) UIKBRenderGeometry *geometry; 35 | @property (nonatomic, retain) NSString *hashString; 36 | @property (nonatomic, retain) UIKBRenderTraits *highlightedVariantTraits; 37 | // @property (nonatomic, retain) UIKBGradient *layeredBackgroundGradient; 38 | // @property (nonatomic, retain) UIKBGradient *layeredForegroundGradient; 39 | @property (nonatomic, readonly) NSArray *renderEffects; 40 | @property (nonatomic, retain) NSArray *renderFlags; 41 | @property (nonatomic) long long renderFlagsForAboveEffects; 42 | @property (nonatomic) bool renderSecondarySymbolsSeparately; 43 | @property (nonatomic, retain) NSArray *secondarySymbolStyles; 44 | @property (nonatomic, retain) UIKBTextStyle *symbolStyle; 45 | @property (nonatomic, retain) NSArray *variantGeometries; 46 | @property (nonatomic, retain) UIKBRenderTraits *variantTraits; 47 | 48 | + (id)emptyTraits; 49 | + (id)traitsWithGeometry:(id)arg1; 50 | + (id)traitsWithSymbolStyle:(id)arg1; 51 | 52 | - (void)addForegroundRenderEffect:(id)arg1; 53 | - (void)addRenderEffect:(id)arg1; 54 | - (id)backgroundGradient; 55 | - (long long)blendForm; 56 | - (bool)blurBlending; 57 | - (bool)controlOpacities; 58 | - (id)copyWithZone:(NSZone *)arg1; 59 | - (void)dealloc; 60 | - (id)description; 61 | - (UIKBTextStyle *)fallbackSymbolStyle; 62 | - (NSArray *)foregroundRenderEffects; 63 | - (id)geometry; 64 | - (NSString *)hashString; 65 | - (UIKBRenderTraits *)highlightedVariantTraits; 66 | - (bool)isEqual:(id)arg1; 67 | - (id)layeredBackgroundGradient; 68 | - (id)layeredForegroundGradient; 69 | - (void)modifyForMasking; 70 | - (void)overlayWithTraits:(id)arg1; 71 | - (void)removeAllRenderEffects; 72 | - (NSArray *)renderEffects; 73 | - (NSArray *)renderFlags; 74 | - (long long)renderFlagsForAboveEffects; 75 | - (bool)renderSecondarySymbolsSeparately; 76 | - (NSArray *)secondarySymbolStyles; 77 | - (void)setBackgroundGradient:(id)arg1; 78 | - (void)setBlendForm:(long long)arg1; 79 | - (void)setBlurBlending:(bool)arg1; 80 | - (void)setControlOpacities:(bool)arg1; 81 | - (void)setFallbackSymbolStyle:(UIKBTextStyle *)arg1; 82 | - (void)setGeometry:(id)arg1; 83 | - (void)setHashString:(NSString *)arg1; 84 | - (void)setHighlightedVariantTraits:(UIKBRenderTraits *)arg1; 85 | - (void)setLayeredBackgroundGradient:(id)arg1; 86 | - (void)setLayeredForegroundGradient:(id)arg1; 87 | - (void)setRenderFlags:(NSArray *)arg1; 88 | - (void)setRenderFlagsForAboveEffects:(long long)arg1; 89 | - (void)setRenderSecondarySymbolsSeparately:(bool)arg1; 90 | - (void)setSecondarySymbolStyles:(NSArray *)arg1; 91 | - (void)setSymbolStyle:(UIKBTextStyle *)arg1; 92 | - (void)setVariantGeometries:(NSArray *)arg1; 93 | - (void)setVariantTraits:(UIKBRenderTraits *)arg1; 94 | - (UIKBTextStyle *)symbolStyle; 95 | - (NSArray *)variantGeometries; 96 | - (UIKBRenderTraits *)variantTraits; 97 | 98 | @end 99 | 100 | -------------------------------------------------------------------------------- /h/UIKBTextStyle.h: -------------------------------------------------------------------------------- 1 | /* Generated by RuntimeBrowser 2 | Image: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore 3 | */ 4 | 5 | @interface UIKBTextStyle : NSObject { 6 | long long _alignment; 7 | unsigned long long _anchorCorner; 8 | NSString * _etchColor; 9 | CGPoint _etchOffset; 10 | NSString * _fontName; 11 | double _fontSize; 12 | double _fontWeight; 13 | bool _ignoreTextMarginOnKey; 14 | double _imageScale; 15 | double _kerning; 16 | double _minFontSize; 17 | double _pathWeight; 18 | long long _selector; 19 | NSString * _textColor; 20 | CGPoint _textOffset; 21 | double _textOpacity; 22 | } 23 | 24 | @property (nonatomic) long long alignment; 25 | @property (nonatomic) unsigned long long anchorCorner; 26 | @property (nonatomic, retain) NSString *etchColor; 27 | @property (nonatomic) CGPoint etchOffset; 28 | @property (nonatomic, retain) NSString *fontName; 29 | @property (nonatomic) double fontSize; 30 | @property (nonatomic) double fontWeight; 31 | @property (nonatomic) bool ignoreTextMarginOnKey; 32 | @property (nonatomic) double imageScale; 33 | @property (nonatomic) double kerning; 34 | @property (nonatomic) double minFontSize; 35 | @property (nonatomic) double pathWeight; 36 | @property (nonatomic) long long selector; 37 | @property (nonatomic, retain) NSString *textColor; 38 | @property (nonatomic) CGPoint textOffset; 39 | @property (nonatomic) double textOpacity; 40 | 41 | + (id)styleWithFontName:(id)arg1 withFontSize:(double)arg2; 42 | + (id)styleWithTextColor:(id)arg1; 43 | 44 | - (long long)alignment; 45 | - (unsigned long long)anchorCorner; 46 | - (id)copyWithZone:(NSZone *)arg1; 47 | - (void)dealloc; 48 | - (NSString *)description; 49 | - (NSString *)etchColor; 50 | - (CGPoint)etchOffset; 51 | - (NSString *)fontName; 52 | - (double)fontSize; 53 | - (double)fontWeight; 54 | - (bool)ignoreTextMarginOnKey; 55 | - (double)imageScale; 56 | - (id)init; 57 | - (bool)isEqual:(id)arg1; 58 | - (double)kerning; 59 | - (double)minFontSize; 60 | - (void)overlayWithStyle:(id)arg1; 61 | - (double)pathWeight; 62 | - (long long)selector; 63 | - (void)setAlignment:(long long)arg1; 64 | - (void)setAnchorCorner:(unsigned long long)arg1; 65 | - (void)setEtchColor:(NSString *)arg1; 66 | - (void)setEtchOffset:(CGPoint)arg1; 67 | - (void)setFontName:(NSString *)arg1; 68 | - (void)setFontSize:(double)arg1; 69 | - (void)setFontWeight:(double)arg1; 70 | - (void)setIgnoreTextMarginOnKey:(bool)arg1; 71 | - (void)setImageScale:(double)arg1; 72 | - (void)setKerning:(double)arg1; 73 | - (void)setMinFontSize:(double)arg1; 74 | - (void)setPathWeight:(double)arg1; 75 | - (void)setSelector:(long long)arg1; 76 | - (void)setTextColor:(NSString *)arg1; 77 | - (void)setTextOffset:(CGPoint)arg1; 78 | - (void)setTextOpacity:(double)arg1; 79 | - (NSString *)textColor; 80 | - (CGPoint)textOffset; 81 | - (double)textOpacity; 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /h/UIKBTouchState.h: -------------------------------------------------------------------------------- 1 | /* Generated by RuntimeBrowser 2 | Image: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore 3 | */ 4 | 5 | @interface UIKBTouchState : NSObject { 6 | } 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /h/UIKBTree.h: -------------------------------------------------------------------------------- 1 | /* Generated by RuntimeBrowser 2 | Image: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore 3 | */ 4 | 5 | @interface UIKBTree : NSObject { 6 | bool _isFloating; 7 | NSMutableDictionary * cache; 8 | NSString * effectiveLayoutTag; 9 | NSString * layoutTag; 10 | NSString * name; 11 | NSMutableDictionary * properties; 12 | NSMutableArray * subtrees; 13 | int type; 14 | } 15 | 16 | @property (nonatomic, retain) NSMutableDictionary *cache; 17 | @property (nonatomic, retain) NSString *effectiveLayoutTag; 18 | @property (nonatomic) bool isFloating; 19 | @property (nonatomic, retain) NSString *layoutTag; 20 | @property (nonatomic, retain) NSString *name; 21 | @property (nonatomic, retain) NSMutableDictionary *properties; 22 | @property (nonatomic, retain) NSMutableArray *subtrees; 23 | @property (nonatomic) int type; 24 | 25 | - (id)alternateKeyplaneName; 26 | - (id)cachedGestureLayout; 27 | - (id)displayString; 28 | - (id)gestureKeyplaneName; 29 | - (id)keySet; 30 | - (id)representedString; 31 | - (int)displayType; 32 | - (int)displayTypeHint; 33 | - (long long)selectedVariantIndex; 34 | - (void)setDisplayTypeHint:(int)arg1; 35 | - (void)setGestureKey:(id)arg1; 36 | - (bool)setObject:(id)arg1 forProperty:(id)arg2; 37 | - (void)setSecondaryDisplayStrings:(id)arg1; 38 | - (void)setSecondaryRepresentedStrings:(id)arg1; 39 | - (id)shiftAlternateKeyplaneName; 40 | - (id)stringForProperty:(id)arg1; 41 | - (id)subtreeWithName:(id)arg1; 42 | @end 43 | -------------------------------------------------------------------------------- /h/UIKeyboardCache.h: -------------------------------------------------------------------------------- 1 | /* Generated by RuntimeBrowser 2 | Image: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore 3 | */ 4 | 5 | @interface UIKeyboardCache : NSObject { 6 | NSMutableSet * _activeRenderers; 7 | // _UIActionWhenIdle * _idleAction; 8 | NSSet * _layouts; 9 | // TIImageCacheClient * _store; 10 | } 11 | 12 | // @property (nonatomic, retain) _UIActionWhenIdle *idleAction; 13 | 14 | + (UIKeyboardCache *)sharedInstance; 15 | 16 | - (void)_didIdle; 17 | - (void)_didIdleAndShouldWait; 18 | // - (CGImage *)cachedCompositeImageForCacheKeys:(id)arg1 fromLayout:(id)arg2 opacities:(id)arg3; 19 | // - (CGImage *)cachedImageForKey:(id)arg1 fromLayout:(id)arg2; 20 | - (void)clearNonPersistentCache; 21 | - (void)commitTransaction; 22 | - (void)dealloc; 23 | - (void)decrementExpectedRender:(id)arg1; 24 | - (id)displayImagesForView:(id)arg1 fromLayout:(id)arg2 imageFlags:(id)arg3; 25 | // - (void)drawCachedImage:(id)arg1 alpha:(double)arg2 inContext:(CGContext *)arg3; 26 | - (id)idleAction; 27 | - (void)incrementExpectedRender:(id)arg1; 28 | - (id)init; 29 | - (void)purge; 30 | - (void)setIdleAction:(id)arg1; 31 | - (NSSet *)uniqueLayoutsFromInputModes:(NSArray *)arg1; 32 | - (void)updateCacheForInputModes:(id)arg1; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /h/UIKeyboardInputMode.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit) (Debug version compiled Oct 15 2018 10:31:50). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2015 by Steve Nygard. 5 | // 6 | 7 | @class NSArray, NSBundle, NSExtension, NSString; 8 | 9 | @interface UIKeyboardInputMode : UITextInputMode 10 | { 11 | _Bool isDisplayed; 12 | _Bool _extensionInputModeHasDictation; 13 | NSString *_primaryLanguage; 14 | NSString *_languageWithRegion; 15 | NSString *identifier; 16 | NSString *normalizedIdentifier; 17 | NSString *softwareLayout; 18 | NSString *hardwareLayout; 19 | NSArray *_multilingualLanguages; 20 | } 21 | 22 | + (_Bool)supportsSecureCoding; 23 | + (id)dictationInputMode; 24 | + (id)autofillSignupInputMode; 25 | + (id)intlInputMode; 26 | + (id)keyboardInputModeWithIdentifier:(id)arg1; 27 | + (id)hardwareLayoutFromIdentifier:(id)arg1; 28 | + (id)softwareLayoutFromIdentifier:(id)arg1; 29 | + (id)canonicalLanguageIdentifierFromIdentifier:(id)arg1; 30 | @property(nonatomic) _Bool extensionInputModeHasDictation; // @synthesize extensionInputModeHasDictation=_extensionInputModeHasDictation; 31 | @property(retain, nonatomic) NSArray *multilingualLanguages; // @synthesize multilingualLanguages=_multilingualLanguages; 32 | @property(nonatomic) _Bool isDisplayed; // @synthesize isDisplayed; 33 | @property(retain, nonatomic) NSString *hardwareLayout; // @synthesize hardwareLayout; 34 | @property(retain, nonatomic) NSString *softwareLayout; // @synthesize softwareLayout; 35 | @property(retain, nonatomic) NSString *normalizedIdentifier; // @synthesize normalizedIdentifier; 36 | @property(retain, nonatomic) NSString *identifier; // @synthesize identifier; 37 | @property(retain, nonatomic) NSString *languageWithRegion; // @synthesize languageWithRegion=_languageWithRegion; 38 | @property(retain, nonatomic) NSString *primaryLanguage; // @synthesize primaryLanguage=_primaryLanguage; 39 | - (void)setLastUsedDictationLanguage; 40 | @property(retain, nonatomic) NSString *dictationLanguage; 41 | @property(readonly, nonatomic) NSString *dictationDisplayName; 42 | - (_Bool)isDesiredForTraits:(id)arg1; 43 | - (_Bool)isAllowedForTraits:(id)arg1; 44 | - (_Bool)includeBarHeight; 45 | @property(readonly, nonatomic) NSString *containingBundleDisplayName; 46 | @property(readonly, nonatomic) NSBundle *containingBundle; 47 | @property(readonly, nonatomic) NSExtension *extension; 48 | @property(readonly, nonatomic) _Bool isExtensionInputMode; 49 | @property(readonly, nonatomic) _Bool isStalledExtensionInputMode; 50 | @property(readonly, nonatomic) NSString *automaticHardwareLayout; 51 | @property(readonly, nonatomic) _Bool defaultLayoutIsASCIICapable; 52 | @property(readonly, nonatomic) _Bool isDefaultRightToLeft; 53 | @property(readonly, nonatomic) NSString *extendedDisplayName; 54 | @property(readonly, nonatomic) NSString *displayName; 55 | - (id)initWithCoder:(id)arg1; 56 | - (void)encodeWithCoder:(id)arg1; 57 | @property(readonly, nonatomic) _Bool isSpecializedInputMode; 58 | @property(readonly, retain, nonatomic) NSArray *normalizedIdentifierLevels; 59 | @property(readonly, nonatomic) NSString *identifierWithLayouts; 60 | - (id)copyWithZone:(struct _NSZone *)arg1; 61 | - (_Bool)isEqual:(id)arg1; 62 | - (void)dealloc; 63 | - (id)initWithIdentifier:(id)arg1; 64 | 65 | @end 66 | 67 | -------------------------------------------------------------------------------- /h/UIKeyboardInputModeController.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit) (Debug version compiled Oct 15 2018 10:31:50). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2015 by Steve Nygard. 5 | // 6 | 7 | #import 8 | 9 | @class NSArray, NSString, UIKeyboardInputMode, UITextInputMode; 10 | @protocol UIKeyboardInputModeControllerDelegate; 11 | 12 | @interface UIKeyboardInputModeController : NSObject 13 | { 14 | UIKeyboardInputMode *_currentInputMode; 15 | NSArray *_inputModesWithoutHardwareSupport; 16 | NSArray *_allExtensions; 17 | NSArray *_allowedExtensions; 18 | _Bool _skipExtensionInputModes; 19 | _Bool _excludeExtensionInputModes; 20 | _Bool _cacheNeedsRefresh; 21 | int _notifyPasscodeChangedToken; 22 | struct __CFUserNotification *_userNotification; 23 | struct __CFRunLoopSource *_userNotificationRunLoopSource; 24 | NSString *_newModeForUserNotification; 25 | NSObject *_keyboardTagForUserNotification; 26 | _Bool _loadingExtensions; 27 | _Bool _needsUpdateExtensions; 28 | _Bool _suppressCurrentPublicInputMode; 29 | _Bool disableFloatingKeyboardFilter; 30 | _Bool _shouldRunContinuousDiscovery; 31 | UITextInputMode *_documentInputMode; 32 | NSArray *keyboardInputModes; 33 | NSArray *keyboardInputModeIdentifiers; 34 | NSArray *enabledInputModes; 35 | NSArray *normalizedInputModes; 36 | NSArray *defaultKeyboardInputModes; 37 | NSArray *defaultRawInputModes; 38 | NSArray *defaultInputModes; 39 | NSArray *defaultNormalizedInputModes; 40 | NSArray *suggestedInputModesForSiriLanguage; 41 | UIKeyboardInputMode *_lastUsedInputMode; 42 | NSString *_inputModeContextIdentifier; 43 | id _delegate; 44 | NSArray *_userSelectableKeyboardInputModes; 45 | NSArray *_userSelectableKeyboardInputModeIdentifiers; 46 | UIKeyboardInputMode *_nextInputModeToUse; 47 | UIKeyboardInputMode *_currentUsedInputMode; 48 | id _extensionMatchingContext; 49 | } 50 | 51 | + (id)ASCIICapableInputModeIdentifierForPreferredLanguages; 52 | + (id)inputModeIdentifierForPreferredLanguages:(id)arg1 passingTest:(id)arg2; 53 | + (id)disallowedDictationLanguagesForDeviceLanguage; 54 | + (id)hardwareInputModeAutomaticHardwareLayout; 55 | + (id)sharedInputModeController; 56 | @property(retain, nonatomic) id extensionMatchingContext; // @synthesize extensionMatchingContext=_extensionMatchingContext; 57 | @property(retain, nonatomic) UIKeyboardInputMode *currentUsedInputMode; // @synthesize currentUsedInputMode=_currentUsedInputMode; 58 | @property(retain, nonatomic) UIKeyboardInputMode *nextInputModeToUse; // @synthesize nextInputModeToUse=_nextInputModeToUse; 59 | @property(retain) NSArray *userSelectableKeyboardInputModeIdentifiers; // @synthesize userSelectableKeyboardInputModeIdentifiers=_userSelectableKeyboardInputModeIdentifiers; 60 | @property(retain) NSArray *userSelectableKeyboardInputModes; // @synthesize userSelectableKeyboardInputModes=_userSelectableKeyboardInputModes; 61 | @property(nonatomic) id delegate; // @synthesize delegate=_delegate; 62 | @property(nonatomic) _Bool shouldRunContinuousDiscovery; // @synthesize shouldRunContinuousDiscovery=_shouldRunContinuousDiscovery; 63 | @property(copy, nonatomic) NSString *inputModeContextIdentifier; // @synthesize inputModeContextIdentifier=_inputModeContextIdentifier; 64 | @property(retain, nonatomic) UIKeyboardInputMode *lastUsedInputMode; // @synthesize lastUsedInputMode=_lastUsedInputMode; 65 | @property(nonatomic) _Bool disableFloatingKeyboardFilter; // @synthesize disableFloatingKeyboardFilter; 66 | @property(retain) NSArray *suggestedInputModesForSiriLanguage; // @synthesize suggestedInputModesForSiriLanguage; 67 | @property(readonly, nonatomic) NSArray *allowedExtensions; // @synthesize allowedExtensions=_allowedExtensions; 68 | @property(retain) NSArray *defaultNormalizedInputModes; // @synthesize defaultNormalizedInputModes; 69 | @property(retain) NSArray *defaultInputModes; // @synthesize defaultInputModes; 70 | @property(copy, nonatomic) NSArray *defaultRawInputModes; // @synthesize defaultRawInputModes; 71 | @property(retain) NSArray *defaultKeyboardInputModes; // @synthesize defaultKeyboardInputModes; 72 | @property(retain) NSArray *normalizedInputModes; // @synthesize normalizedInputModes; 73 | @property(retain) NSArray *enabledInputModes; // @synthesize enabledInputModes; 74 | @property(retain) NSArray *keyboardInputModeIdentifiers; // @synthesize keyboardInputModeIdentifiers; 75 | @property(retain) NSArray *keyboardInputModes; // @synthesize keyboardInputModes; 76 | @property(retain, nonatomic) UITextInputMode *documentInputMode; // @synthesize documentInputMode=_documentInputMode; 77 | - (void)handleSpecificHardwareKeyboard; 78 | - (void)getHardwareKeyboardLanguage:(id *)arg1 countryCode:(id *)arg2; 79 | - (void)releaseAddKeyboardNotification; 80 | - (void)didAcceptAddKeyboardInputMode; 81 | - (void)showAddKeyboardAlertForInputModeIdentifier:(id)arg1; 82 | - (id)inputModeToAddForKeyboardLanguage:(id)arg1 countryCode:(id)arg2 activeModes:(id)arg3; 83 | - (id)hardwareLayoutToUseForInputMode:(id)arg1; 84 | - (void)handleLastUsedInputMode:(id)arg1 withNewInputMode:(id)arg2; 85 | - (id)supportedInputModesFromArray:(id)arg1; 86 | - (void)startConnectionForFileAtURL:(id)arg1 forInputModeIdentifier:(id)arg2; 87 | - (void)startDictationConnectionForFileAtURL:(id)arg1 forInputModeIdentifier:(id)arg2; 88 | - (void)performWithForcedExtensionInputModes:(id)arg1; 89 | - (void)performWithoutExtensionInputModes:(id)arg1; 90 | - (void)stopDictation; 91 | - (void)switchToDictationInputMode; 92 | - (void)switchToCurrentSystemInputMode; 93 | - (void)updateCurrentAndNextInputModes; 94 | - (void)updateLastUsedInputMode:(id)arg1; 95 | - (id)inputModeForASCIIToggleWithTraits:(id)arg1; 96 | - (id)inputModeLastUsedForLanguage:(id)arg1; 97 | - (id)inputModeIdentifierLastUsedForLanguage:(id)arg1; 98 | - (id)nextInputModeInPreferenceListForTraits:(id)arg1; 99 | - (id)nextInputModeInPreferenceListForTraits:(id)arg1 updatePreference:(_Bool)arg2 skipEmoji:(_Bool)arg3; 100 | - (id)nextInputModeInPreferenceListForTraits:(id)arg1 updatePreference:(_Bool)arg2; 101 | - (id)nextInputModeToUseForTraits:(id)arg1; 102 | - (void)clearNextInputModeToUse; 103 | - (id)nextInputModeToUseForTraits:(id)arg1 updatePreference:(_Bool)arg2; 104 | - (void)_setCurrentAndNextInputModePreference; 105 | - (id)nextInputModeFromList:(id)arg1 withFilter:(unsigned long long)arg2 withTraits:(id)arg3; 106 | - (id)extensionInputModes; 107 | - (_Bool)isLockscreenPasscodeKeyboard; 108 | - (_Bool)verifyKeyboardExtensionsWithApp; 109 | - (_Bool)deviceStateIsLocked; 110 | - (id)_MCFilteredExtensionIdentifiers; 111 | - (void)_removeInputModes:(id)arg1; 112 | - (_Bool)_mayContainExtensionInputModes; 113 | - (void)_beginContinuousDiscoveryIfNeeded; 114 | - (id)_allExtensionsFromMatchingExtensions:(id)arg1; 115 | - (void)_clearAllExtensionsIfNeeded; 116 | - (void)_clearAllExtensions; 117 | - (void)extensionsChanged; 118 | - (void)didEnterBackground:(id)arg1; 119 | - (void)keyboardsPreferencesChanged:(id)arg1; 120 | - (void)willEnterForeground:(id)arg1; 121 | - (void)loadSuggestedInputModesForSiriLanguage; 122 | - (id)suggestedInputModesForPreferredLanguages; 123 | - (id)suggestedInputModesForLocales:(id)arg1; 124 | - (id)suggestedInputModesForCurrentLocale; 125 | - (id)suggestedInputModesForCurrentHardwareKeyboardAndSuggestedInputModes:(id)arg1; 126 | - (id)suggestedInputModesForHardwareKeyboardLanguage:(id)arg1 countryCode:(id)arg2 inputModes:(id)arg3; 127 | - (id)suggestedInputModesForCurrentLocale:(_Bool)arg1 fallbackToDefaultInputModes:(_Bool)arg2; 128 | - (id)defaultEnabledInputModesForCurrentLocale:(_Bool)arg1; 129 | - (id)appendPasscodeInputModes:(id)arg1; 130 | - (void)updateDefaultInputModesIfNecessaryForIdiom; 131 | - (id)fallbackCurrentInputModeForFilteredInputModeIdentifier:(id)arg1 fromInputModeIdentifiers:(id)arg2; 132 | - (id)fallbackCurrentInputModeForFilteredInputMode:(id)arg1 fromInputModes:(id)arg2; 133 | - (id)filteredPadInputModesFromInputModes:(id)arg1 withRules:(id)arg2; 134 | - (id)inputModeByReplacingSoftwareLayoutWithSoftwareLayout:(id)arg1 inInputMode:(id)arg2; 135 | - (id)filteredTVInputModesFromInputModes:(id)arg1; 136 | - (id)filteredInputModesForSiriLanguageFromInputModes:(id)arg1; 137 | - (_Bool)currentLocaleRequiresExtendedSetup; 138 | - (void)updateCurrentInputMode:(id)arg1; 139 | - (void)_setCurrentInputMode:(id)arg1 force:(_Bool)arg2; 140 | @property(retain) UIKeyboardInputMode *currentInputMode; 141 | - (id)getDictationSLSLanguagesEnabled; 142 | - (void)setDictationSLSLanguagesEnabled:(id)arg1; 143 | @property(readonly, nonatomic) _Bool containsDictationSupportedInputMode; 144 | - (void)updateEnabledDictationAndSLSLanguagesWithCompletionBlock:(id)arg1; 145 | - (id)updateEnabledDictationLanguages:(_Bool)arg1; 146 | - (_Bool)isDictationLanguageEnabled:(id)arg1; 147 | @property(readonly, nonatomic) NSArray *enabledDictationLanguages; 148 | @property(readonly, nonatomic) NSArray *activeDictationLanguages; 149 | - (id)keyboardLanguageForDictationLanguage:(id)arg1; 150 | - (id)defaultDictationLanguages:(id)arg1; 151 | - (id)suggestedDictationLanguagesForDeviceLanguage; 152 | @property(readonly, nonatomic) NSArray *activeDictationSupportedInputModeIdentifiers; 153 | @property(readonly, nonatomic) UIKeyboardInputMode *lastUsedInputModeForCurrentContext; 154 | @property(readonly, nonatomic) UIKeyboardInputMode *currentLinguisticInputMode; 155 | @property(readonly, nonatomic) UIKeyboardInputMode *currentPublicInputMode; 156 | - (id)textInputModeForResponder:(id)arg1; 157 | - (void)_inputModeChangedWhileContextTracked; 158 | - (void)_trackInputModeIfNecessary:(id)arg1; 159 | - (id)lastUsedInputModeForTextInputMode:(id)arg1; 160 | @property(readonly, nonatomic) UIKeyboardInputMode *currentSystemInputMode; 161 | @property(readonly, nonatomic) UIKeyboardInputMode *hardwareInputMode; 162 | - (id)_systemInputModePassingLanguageTest:(id)arg1; 163 | - (id)_systemInputModePassingTest:(id)arg1; 164 | @property(nonatomic) UIKeyboardInputMode *currentInputModeInPreference; 165 | @property(readonly) NSArray *activeUserSelectableInputModeIdentifiers; 166 | - (id)activeUserSelectableInputModes; 167 | @property(readonly) NSArray *activeInputModeIdentifiers; 168 | - (id)activeInputModes; 169 | - (id)inputModeWithIdentifier:(id)arg1; 170 | - (id)init; 171 | - (void)dealloc; 172 | - (_Bool)identifierIsValidSystemInputMode:(id)arg1; 173 | - (id)inputModesFromIdentifiers:(id)arg1; 174 | - (id)identifiersFromInputModes:(id)arg1; 175 | @property(readonly) NSArray *enabledInputModeLanguages; 176 | @property(readonly) NSArray *normalizedEnabledInputModeIdentifiers; 177 | @property(readonly) NSArray *enabledInputModeIdentifiers; 178 | - (void)updateUserSelectableInputModes; 179 | - (id)userSelectableInputModeIdentifiersFromInputModeIdentifiers:(id)arg1; 180 | - (id)userSelectableInputModesFromInputModes:(id)arg1; 181 | - (id)enabledInputModeIdentifiers:(_Bool)arg1; 182 | - (void)saveDeviceUnlockPasscodeInputModes; 183 | @property(readonly) NSArray *inputModesWithoutHardwareSupport; 184 | @property(readonly) NSArray *supportedInputModeIdentifiers; 185 | 186 | @end 187 | 188 | -------------------------------------------------------------------------------- /h/UIKeyboardLayout.h: -------------------------------------------------------------------------------- 1 | /* Generated by RuntimeBrowser 2 | Image: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore 3 | */ 4 | 5 | @interface UIKeyboardLayout : UIView /*<_UIKBRTRecognizerDelegate, _UIKBRTTouchDriftingDelegate, _UIScreenEdgePanRecognizerDelegate, _UIViewRepresentingKeyboardLayout>*/ { 6 | 7 | } 8 | 9 | @end 10 | -------------------------------------------------------------------------------- /h/UIKeyboardLayoutStar.h: -------------------------------------------------------------------------------- 1 | /* Generated by RuntimeBrowser 2 | Image: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore 3 | */ 4 | 5 | @interface UIKeyboardLayoutStar : UIKeyboardLayout /**/ { 6 | 7 | } 8 | 9 | - (UIKeyboardTouchInfo *)infoForTouch:(UIKBTouchState *)arg1; 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /h/UIKeyboardTaskExecutionContext.h: -------------------------------------------------------------------------------- 1 | /* Generated by RuntimeBrowser 2 | Image: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore 3 | */ 4 | 5 | @interface UIKeyboardTaskExecutionContext : NSObject { 6 | } 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /h/UIKeyboardTouchInfo.h: -------------------------------------------------------------------------------- 1 | /* Generated by RuntimeBrowser 2 | Image: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore 3 | */ 4 | 5 | @interface UIKeyboardTouchInfo : NSObject { 6 | 7 | } 8 | 9 | @property (nonatomic) CGPoint initialDragPoint; 10 | @property (nonatomic) CGPoint initialPoint; 11 | @property (nonatomic, assign) bool fpAllow; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /h/UITextInputMode.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by class-dump 3.5 (64 bit) (Debug version compiled Oct 15 2018 10:31:50). 3 | // 4 | // class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2015 by Steve Nygard. 5 | // 6 | 7 | #import 8 | 9 | @class NSString; 10 | 11 | @interface UITextInputMode : NSObject 12 | { 13 | } 14 | 15 | + (_Bool)supportsSecureCoding; 16 | + (id)activeInputModes; 17 | + (id)currentInputMode; 18 | - (id)initWithCoder:(id)arg1; 19 | - (void)encodeWithCoder:(id)arg1; 20 | @property(readonly, nonatomic) NSString *primaryLanguage; 21 | 22 | @end 23 | 24 | -------------------------------------------------------------------------------- /notes: -------------------------------------------------------------------------------- 1 | UIKBRenderer _drawSingleSymbol draws all "Valid chars for fast drawing" 2 | and returns YES if succeeded, NO if not 3 | 4 | main keyplane: all letters (plus secondary except for those listed below) 5 | numbers and punctuation: all but £, ", , and ' 6 | alternate symbols: none 7 | 8 | symbols in the paddle are not drawn using _drawSingleSymbol 9 | 10 | 11 | _drawKeyString handles all of them, including paddles 12 | ... but is still hit by the textOpacity bug??? 13 | 14 | 15 | // https://iphonedevwiki.net/index.php/UIKBTree 16 | 17 | %hook UIKeyboardLayoutStar 18 | - (void)setLayoutTag:(NSString *)tag { 19 | NSLog(@"UIKeyboardLayoutStar setLayout:%@", tag); 20 | %orig; 21 | } 22 | %end 23 | 24 | %hook UIKBTree 25 | -(void)setLayoutTag:(NSString *)tag passingKeyTest:(id)test { 26 | NSLog(@"UIKBTree %@ sets tag %@", [self description], tag); 27 | %orig; 28 | } 29 | - (void)setGestureKey:(UIKBTree *)key { 30 | NSLog(@"UIKBTree %@ sets gestureKey %@", [self description], [key description]); 31 | %orig; 32 | } 33 | %end 34 | 35 | // dual mode for iPad bottom right keys: 36 | // displayType = 7 (dual string) 37 | // interactionType = 2 (popup?) 38 | // secondaryDisplayStrings, secondaryRepresentedStrings 39 | 40 | supports-continuous-path is a keyplane property 41 | 42 | boolForProperty: 32 = true, other = false?? 43 | 44 | updateFlickKeycapOnKeys is where the gestures are combined 45 | 46 | keyboard { 47 | keyplane* { 48 | keylayout* { 49 | keyset { 50 | list* { 51 | key* 52 | } 53 | } 54 | geometryset 55 | attributeset 56 | } 57 | } 58 | } 59 | 60 | Tree Types: 61 | 1 Keyboard 62 | 2 Keyplane 63 | 3 Keylayout 64 | 4 KeySet 65 | 5 GeometrySet 66 | 6 AttributeSet 67 | 7 List 68 | 8 Key 69 | 9 Shape 70 | 10 Attributes 71 | 11 Identifiers 72 | 12 AdaptiveKey 73 | 13 MergePolicy 74 | 14 Validator 75 | 76 | Interaction Types: 77 | 0 None 78 | 1 String 79 | 2 StringPopup 80 | 3 CandidateList 81 | 4 Delete 82 | 5 Dictation 83 | 6 Dismiss 84 | 7 Drag 85 | 8 Handwriting 86 | 9 International 87 | 10 KeyplaneSwitch 88 | 11 More 89 | 12 Redo 90 | 13 Return 91 | 14 Shift 92 | 15 Space 93 | 16 StringFlick 94 | 17 Undo 95 | 18 EmojiInputView 96 | 19 EmojiCategoryControl 97 | 20 MultitapComplete 98 | 21 MultitapReverse 99 | 22 RecentInput 100 | 23 Clear 101 | 24 RevealHiddenCandidates 102 | 25 SelectNextCandidate 103 | 26 SelectPreviousCandidate 104 | 27 AcceptAutocorrection 105 | 28 Bold 106 | 29 Italic 107 | 30 Underline 108 | 31 Cut 109 | 32 Copy 110 | 33 Paste 111 | 34 LeftArrow 112 | 35 RightArrow 113 | 36 AssertLayoutTag 114 | 37 Tab 115 | 38 CapsLock 116 | 39 DictationDisplay 117 | 40 MessagesWriteboard 118 | 119 | Visual Style 120 | 1 iPhoneStandard 121 | 2 iPhoneDictation 122 | 3 iPhoneAlert 123 | 4 iPhoneEmoji 124 | 5 iPhonePasscode 125 | 126 | 101 Wildcat50On 127 | 102 WildcatStandard 128 | 103 WildcatDictation 129 | 104 WildcatAlert 130 | 105 WildcatPasscode 131 | 106 WildcatSplit 132 | 107 WildcatSplitFullWidth 133 | 108 WildcatEmoji 134 | 109 WildcatEmojiSplit 135 | 201 MonolithStandard 136 | 301 CarStandard 137 | 138 | Display Types 139 | 0 String 140 | 1 CandidateList 141 | 2 Command 142 | 3 Delete 143 | 4 Dictation 144 | 5 Dismiss 145 | 6 Drag 146 | 7 DualString 147 | 8 DynamicString 148 | 9 Emoji 149 | 10 TenKeyKeyplaneSwitchOff 150 | 11 TenKeyKeyplaneSwitchOn 151 | 12 Handwriting 152 | 13 International 153 | 14 KeyplaneSwitch 154 | 15 LeftDarkAndNoRightDivider 155 | 16 LightBottom 156 | 17 LightBottomAndRight 157 | 18 More 158 | 19 NoRightDivider 159 | 20 NumberPad 160 | 21 Return 161 | 22 ReverseVerticalDark 162 | 23 Shift 163 | 24 SmallKana 164 | 25 Space 165 | 26 Tab 166 | 27 TopLevelDomain 167 | 28 TopLevelDomainVariant 168 | 29 TwoVerticalDark 169 | 30 TwoVerticalLight 170 | 31 VoicedKey 171 | 32 MultitapCompleteKey 172 | 33 MultitapReverseKey 173 | 34 WALongVowelSignKey 174 | 35 TenKeyRomanKey 175 | 36 EmojiInputView 176 | 37 EmojiCategoryControl 177 | 38 LetterLine 178 | 39 Bold 179 | 40 Italic 180 | 41 Underline 181 | 42 Cut 182 | 43 Copy 183 | 44 Paste 184 | 45 LeftArrow 185 | 46 RightArrow 186 | 47 PredictionActive 187 | 48 UCBSelectionBackground 188 | 49 BIU 189 | 50 Divider 190 | 51 CapsLock 191 | 52 DictationDisplay 192 | 53 MessagesWriteboard 193 | 194 | Variants Types 195 | 1 Accents 196 | 3 Currency 197 | 4 Email 198 | 5 ImmediateAccents 199 | 6 InputModes 200 | 7 URL 201 | 8 KeyplaneAccents 202 | 9 BIU 203 | 10 SkinToneEmoji 204 | 11 PrepopulatedSkinToneEmoji 205 | 12 ExtendedSkinToneEmoji 206 | 13 PrepopulatedExtendedSkinToneEmoji 207 | 208 | Attribute Value 209 | 1 10Key 210 | 2 Center 211 | 3 Dark 212 | 4 Disabled 213 | 5 Enabled 214 | 6 ExtendedSymbols 215 | 7 Flick 216 | 8 Glyph 217 | 9 Handwriting 218 | 10 Highlighted 219 | 11 Japanese50on 220 | 12 KeyboardTypeASCIICapable 221 | 13 KeyboardTypeDecimalPad 222 | 14 KeyboardTypeDefault 223 | 15 KeyboardTypeEmailAddress 224 | 16 KeyboardTypeNamePhonePad 225 | 17 KeyboardTypeNumberPad 226 | 18 KeyboardTypeNumbersAndPunctuation 227 | 19 KeyboardTypePhonePad 228 | 20 KeyboardTypeURL 229 | 21 Left 230 | 22 Letters 231 | 23 Light 232 | 24 Name 233 | 25 No 234 | 26 Numbers 235 | 27 PhonePad 236 | 28 Pressed 237 | 29 Right 238 | 30 Straight 239 | 31 Symbols 240 | 32 Yes 241 | 33 Chinese10Key 242 | 34 Korean10Key 243 | 35 JapaneseAIU 244 | 36 StrictlyLeft 245 | 37 StrictlyRight 246 | 38 Emoji 247 | 39 Dictation 248 | 40 PopupMenu 249 | 41 High 250 | 42 Linear 251 | 43 FixedLeft 252 | 44 FixedRight 253 | 45 Cased 254 | 46 Literal 255 | 47 None 256 | 257 | 258 | Image flags: 259 | 1: key backgrounds 260 | 2: key dropshadows 261 | 3: popup background, but different, somehow (update: this is prob. the mask) 262 | 4: key labels, all kinds 263 | 16: secondary label *in popup* 264 | 32: 2nd secondary label (for developer gesture mode) 265 | 266 | %hook UIKeyboardCache 267 | - (NSDictionary *)displayImagesForView:(UIView *)view fromLayout:(UIKeyboardLayout *)layout imageFlags:(NSArray *)imageFlags { 268 | NSDictionary *dict = %orig; 269 | NSLog(@"displayImagesForView:"); 270 | [dict enumerateKeysAndObjectsUsingBlock:^(NSObject *key, UIImage *value, BOOL *stop) { 271 | // NSLog(@"IMG: %@ -> %@", key, value); 272 | NSData *png = UIImagePNGRepresentation(value); 273 | NSString *path = [NSString stringWithFormat:@"/private/var/mobile/Containers/Data/Application/7FCDEF14-1CFE-4AD0-A108-B7F49D3616C1/tmp/kb2/%@_%d_%d.png", key, (int)value.size.width, (int)value.size.height]; 274 | NSLog(@"Writing to %@", path); 275 | if ([png writeToFile:path atomically:NO]) 276 | NSLog(@"ok"); 277 | else 278 | NSLog(@"failed"); 279 | }]; 280 | return dict; 281 | } 282 | %end 283 | 284 | 285 | Key States: 286 | 1 = Disabled 287 | 2 = Normal 288 | 4 = Pressed 289 | 8 = ~it is a mystery~ 290 | 16 = Menu active (accent variants OR international menu OR stringflick) 291 | 32 = Shift Lock 292 | 36 = Shift Locked + Touched 293 | 294 | 295 | 'flick' appears to be 10key boards with l/r/u/d buttons like Japanese 296 | uses interaction=16 StringFlick 297 | KBflickDirection represents which subkey user is touching 298 | 299 | fixing key popups is gonna involve UIKBKeyViewAnimator 300 | 301 | UIKeyboardLayoutStar.updatePanAlternativesForTouchInfo is where the 302 | preview animation for the secondary strings is manipulated 303 | so, keyViewAnimator is probably what I need to fix 304 | sets UIKBTree.selectedVariantIndex to -1, 0 or 1 305 | 306 | calling UIKBKeyplaneView.purgeActiveKeyViews gets rid of cached key popups 307 | calling UIKeyboardLayoutStar.reloadCurrentKeyplane does a full 308 | 309 | UIKBKeyplaneView.viewForKey gets the popup view for a key, if that key is pressed 310 | 311 | UIKeyboardLayoutStar contains UIKBKeyplaneView 312 | UIKBKeyplaneView contain three UIKBSplitImageView instances for main keys, and 313 | one UIKBKeyView each for the control keys 314 | 315 | a UIKBKeyView is added to UIInputSetContainerView for the popups 316 | 317 | changing key name may be a cheap way to invalidate caches 318 | 319 | 320 | --- 321 | 322 | 323 | fixing the positions on keycaps requires playing with UIKBKeyViewAnimator 324 | we need two separate versions: one for paddles and one for non-paddles 325 | 326 | initial positions upon tap are applied by: 327 | transitionKeyView:fromState:toState:completion: 328 | handles toState=4 (becoming pressed) 329 | text layer gets keycapPrimaryTransform 330 | for 1-symbol keys: 331 | symbol layer gets keycapAlternateTransform 332 | for 2-symbol keys: 333 | left symbol layer gets keycapLeftTransform 334 | right symbol layer gets keycapRightTransform 335 | symbol layer gets opacity 0.25 for light kb, 0.3 for dark kb 336 | 337 | keycapPrimaryTransform: 338 | from x=0.115 y=0.28 w=0.77 h=0.44 to x=0.115 y=0.45 w=0.77 h=0.44 339 | (moves label down) 340 | 341 | keycapAlternateTransform: 342 | from x=0.115 y=0.28 w=0.77 h=0.44 to x=0.25 y=0.13 w=0.5 h=0.286 343 | or, h=0.2574 if the symbol is a digit 344 | (moves label up and makes it smaller) 345 | 346 | keycapLeftTransform: 347 | from x=0.115 y=0.28 w=0.77 h=0.44 to x=-0.065 y=0.13 w=0.65 h=0.286 348 | (moves label up and left and makes it smaller) 349 | ...hey, wait, isn't this fucking up the aspect ratio? 350 | (yes, it's noticeable on iPad, amazing) 351 | 352 | keycapRightTransform: 353 | from x=0.115 y=0.28 w=0.77 h=0.44 to x=0.415 y=0.13 w=0.65 h=0.286 354 | (same as above really) 355 | 356 | keycapPrimaryExitTransform: 357 | from x=0.115 y=0.28 w=0.77 h=0.44 to x=0.5 y=0.89 w=0 h=0 358 | (moves label to bottom, out of the way) 359 | 360 | keycapNullTransform: 361 | from x=0.115 y=0.28 w=0.77 h=0.44 to x=0.115 y=0.28 w=0.77 h=0.44 362 | (doesn't move anything) 363 | only way to get good rendering on the paddles, by default 364 | 365 | then, animations: 366 | transitionStartedForKeyView:alternateCount:toLeft: 367 | creates missing animations... 368 | for alternateCount=1 (1-symbol keys): 369 | creates "pan transform" animation on text layer: 370 | meshTransform from keycapPrimaryTransform to keycapPrimaryExitTransform 371 | creates "pan opacity" animation on text layer: 372 | opacity animation from 1.0 to 0 373 | creates "pan transform" animation on symbol layer: 374 | meshTransform from keycapAlternateTransform to keycapNullTransform 375 | creates "pan opacity" animation on symbol layer: 376 | opacity animation from 0.25/0.3 to 1.0 377 | for alternateCount=2 (2-symbol keys): 378 | if toLeft: 379 | creates "pan transform left" animation on text layer: 380 | meshTransform from keycapPrimaryTransform to keycapLeftSelectPrimaryTransform 381 | creates "pan transform" animation on symbol layer 1: 382 | meshTransform from keycapLeftTransform to keycapLeftSelectLeftTransform 383 | creates "pan transform" animation on symbol layer 2: 384 | meshTransform from keycapRightTransform to keycapLeftSelectRightTransform 385 | creates "pan opacity" animation on symbol layer 1: 386 | opacity animation from 0.25/0.3 to 1.0 387 | creates "pan opacity" animation on symbol layer 2: 388 | opacity animation from 0.25/0.3 to 0 389 | if not toLeft: 390 | creates "pan transform right" animation on text layer: 391 | meshTransform from keycapPrimaryTransform to keycapRightSelectPrimaryTransform 392 | creates "pan transform" animation on symbol layer 1: 393 | meshTransform from keycapLeftTransform to keycapRightSelectLeftTransform 394 | creates "pan transform" animation on symbol layer 2: 395 | meshTransform from keycapRightTransform to keycapRightSelectRightTransform 396 | creates "pan opacity" animation on symbol layer 1: 397 | opacity animation from 0.25/0.3 to 0 398 | creates "pan opacity" animation on symbol layer 2: 399 | opacity animation from 0.25/0.3 to 1.0 400 | creates "pan opacity" animation on text layer: 401 | opacity animation from 1.0 to 0 402 | 403 | transitionEndedForKeyView:alternateCount: 404 | ...honestly can't be fucked with figuring this one out, it's 3am, it's more of the same 405 | it generates animations, so ofc we need to fuck with it too 406 | 407 | updateTransitionForKeyView:normalizedDragSize: 408 | calls transitionStartedForKeyView:... and setTimeOffset on the layers as appropriate 409 | 410 | endTransitionForKeyView: 411 | calls transitionEndedForKeyView... etc 412 | 413 | ok, now what 414 | paddle is provisionally 108*114 portrait, 123*114 landscape (on i8 simulator) 415 | ...but of course, the position of the text changes *inside* it at the edges 416 | making it work nicely will require some Trickery 417 | 418 | non-paddle is provisionally 35.5*46 portrait, 51*36 landscape (on i8 simulator) 419 | 420 | iPad keys are pretty much square, no paddles, so it's much easier there 421 | 422 | 423 | 424 | 425 | --- 426 | 427 | Default renderconfig: 428 | Light: true 429 | Blur: 30, 0.9 430 | Keycap opacity: 0.96 431 | Light keycap opacity: 1.0 432 | 433 | Dark: 434 | Light: false 435 | Blur: 20, 0.5 436 | Keycap opacity: 1.0 437 | Light keycap opacity: 1.0 438 | 439 | Low Quality Dark: 440 | Same, but forceQuality is 10 441 | 442 | KBStarTypeString(a, b): 443 | a == 2: 444 | _: blank 445 | 4: NumberPad 446 | 5: PhonePad 447 | 6: blank 448 | 7: Email 449 | 8: DecimalPad 450 | 9: blank 451 | 10: AlphaWithURL 452 | 11: NumberPad 453 | 127: PasscodePad 454 | a == 1: 455 | _: blank 456 | 3: URL 457 | 4: Pad 458 | 5: Pad 459 | 6: NamePhonePad 460 | 7: Email 461 | 8: Pad 462 | 9: Twitter 463 | 10: AlphaWithURL 464 | 11: Pad 465 | 127: PasscodePad 466 | else: 467 | _: blank 468 | 3: URL 469 | 4: NumberPad 470 | 5: PhonePad 471 | 6: NamePhonePad 472 | 7: Email 473 | 8: DecimalPad 474 | 9: Twitter 475 | 10: AlphaWithURL 476 | 11: NumberPad 477 | 127: PasscodePad 478 | 479 | 480 | 481 | Enumerating enabled keyboards: 482 | [UIKeyboardInputModeController sharedInputModeController] keeps track of them 483 | 484 | activeInputModes returns NSArray of UIKeyboardInputMode and UIKeyboardExtensionInputMode 485 | enabledInputModes returns NSArray of identifiers: 486 | "en_GB@sw=QWERTY;hw=Automatic", 487 | "es_ES@sw=QWERTY;hw=Automatic", 488 | "emoji@sw=Emoji", 489 | "tr_TR@sw=Turkish-Q;hw=Automatic", 490 | "com.textstarter.PC-Keyboard.Extension" 491 | 492 | displayName and extendedDisplayName give the names to show 493 | -------------------------------------------------------------------------------- /prefs/Makefile: -------------------------------------------------------------------------------- 1 | include $(THEOS)/makefiles/common.mk 2 | 3 | BUNDLE_NAME = FlickPlusPrefs 4 | ARCHS = arm64 arm64e 5 | 6 | FlickPlusPrefs_FILES = NFPRootListController.m NFPKeyboardController.m NFPKeyplaneController.m NFPKeyPropsController.m 7 | FlickPlusPrefs_INSTALL_PATH = /Library/PreferenceBundles 8 | FlickPlusPrefs_FRAMEWORKS = UIKit 9 | FlickPlusPrefs_EXTRA_FRAMEWORKS += Cephei CepheiPrefs 10 | FlickPlusPrefs_PRIVATE_FRAMEWORKS = Preferences 11 | FlickPlusPrefs_CFLAGS = -fobjc-arc 12 | 13 | include $(THEOS_MAKE_PATH)/bundle.mk 14 | 15 | internal-stage:: 16 | $(ECHO_NOTHING)mkdir -p $(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences$(ECHO_END) 17 | $(ECHO_NOTHING)cp entry.plist $(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences/FlickPlusPrefs.plist$(ECHO_END) 18 | -------------------------------------------------------------------------------- /prefs/NFPKeyPropsController.h: -------------------------------------------------------------------------------- 1 | // #import 2 | #import 3 | #import 4 | #import "../h/UIKBTree.h" 5 | 6 | @interface PSTextFieldSpecifier : PSSpecifier 7 | @property (nonatomic, retain) NSString *placeholder; 8 | @end 9 | 10 | enum { 11 | NFPModeNothing = 0, 12 | NFPModeText = 1, 13 | NFPModeDual = 2 14 | }; 15 | 16 | @interface NFPKeyPropsController : PSListController 17 | { 18 | UIKBTree *_key; 19 | UIBarButtonItem *_saveButton; 20 | 21 | int _mode; 22 | NSString *_representedString, *_displayString; 23 | NSString *_leftRepresentedString, *_leftDisplayString; 24 | NSString *_rightRepresentedString, *_rightDisplayString; 25 | 26 | PSSpecifier *_modeSpecNothing, *_modeSpecText, *_modeSpecDual; 27 | 28 | NSArray *_textSpecifierArray; 29 | PSTextFieldSpecifier *_displayStringSpec, *_representedStringSpec; 30 | 31 | NSArray *_dualSpecifierArray; 32 | PSTextFieldSpecifier *_leftDisplayStringSpec, *_leftRepresentedStringSpec; 33 | PSTextFieldSpecifier *_rightDisplayStringSpec, *_rightRepresentedStringSpec; 34 | } 35 | 36 | @property int mode; 37 | @property (nonatomic,retain) NSString *representedString; 38 | @property (nonatomic,retain) NSString *displayString; 39 | @property (nonatomic,retain) NSString *leftRepresentedString; 40 | @property (nonatomic,retain) NSString *leftDisplayString; 41 | @property (nonatomic,retain) NSString *rightRepresentedString; 42 | @property (nonatomic,retain) NSString *rightDisplayString; 43 | @end 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /prefs/NFPKeyPropsController.m: -------------------------------------------------------------------------------- 1 | #include "NFPKeyPropsController.h" 2 | #import "NFPKeyplaneController.h" 3 | #import "../Utils.h" 4 | #include 5 | 6 | @interface PSSetupController : PSViewController 7 | - (void)dismiss; 8 | @end 9 | 10 | @implementation NFPKeyPropsController 11 | 12 | - (void)viewDidLoad { 13 | [super viewDidLoad]; 14 | 15 | self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] 16 | initWithBarButtonSystemItem:UIBarButtonSystemItemCancel 17 | target:self 18 | action:@selector(cancelMe:)]; 19 | 20 | _saveButton = [[UIBarButtonItem alloc] 21 | initWithBarButtonSystemItem:UIBarButtonSystemItemSave 22 | target:self 23 | action:@selector(saveMe:)]; 24 | self.navigationItem.rightBarButtonItem = _saveButton; 25 | } 26 | 27 | - (NSArray *)specifiers { 28 | if (!_specifiers) { 29 | _displayString = @""; 30 | _representedString = @""; 31 | _leftDisplayString = @""; 32 | _leftRepresentedString = @""; 33 | _rightDisplayString = @""; 34 | _rightRepresentedString = @""; 35 | _mode = NFPModeNothing; 36 | 37 | NSArray *config = [self.specifier propertyForKey:@"fp-key-config"]; 38 | if (config) { 39 | if (config.count == 2) { 40 | _mode = NFPModeText; 41 | _representedString = config[0]; 42 | _displayString = config[1]; 43 | } else if (config.count == 4) { 44 | _mode = NFPModeDual; 45 | _leftRepresentedString = config[0]; 46 | _leftDisplayString = config[1]; 47 | _rightRepresentedString = config[2]; 48 | _rightDisplayString = config[3]; 49 | } 50 | } 51 | 52 | NSMutableArray *specs = [NSMutableArray array]; 53 | 54 | _key = [self.specifier propertyForKey:@"fp-key"]; 55 | NSString *niceName = [[_key.name sliceAfterLastUnderscore] hyphensToSpaces]; 56 | self.title = [NSString stringWithFormat:@"%@ (%@)", niceName, _key.displayString]; 57 | 58 | PSSpecifier *group = [PSSpecifier groupSpecifierWithName:@"Action on Swipe Down"]; 59 | [group setProperty:@YES forKey:@"isRadioGroup"]; 60 | [specs addObject:group]; 61 | 62 | _modeSpecNothing = [PSSpecifier 63 | preferenceSpecifierNamed:@"Nothing" 64 | target:self set:nil get:nil detail:Nil 65 | cell:PSListItemCell edit:Nil 66 | ]; 67 | [_modeSpecNothing setProperty:@(NFPModeNothing) forKey:@"fp-mode"]; 68 | _modeSpecText = [PSSpecifier 69 | preferenceSpecifierNamed:@"Text/Character" 70 | target:self set:nil get:nil detail:Nil 71 | cell:PSListItemCell edit:Nil 72 | ]; 73 | [_modeSpecText setProperty:@(NFPModeText) forKey:@"fp-mode"]; 74 | _modeSpecDual = [PSSpecifier 75 | preferenceSpecifierNamed:@"Dual Text/Character (Experimental)" 76 | target:self set:nil get:nil detail:Nil 77 | cell:PSListItemCell edit:Nil 78 | ]; 79 | [_modeSpecDual setProperty:@(NFPModeDual) forKey:@"fp-mode"]; 80 | [specs addObject:_modeSpecNothing]; 81 | [specs addObject:_modeSpecText]; 82 | [specs addObject:_modeSpecDual]; 83 | 84 | id whom = nil; 85 | switch (_mode) { 86 | case NFPModeNothing: whom = _modeSpecNothing; break; 87 | case NFPModeText: whom = _modeSpecText; break; 88 | case NFPModeDual: whom = _modeSpecDual; break; 89 | } 90 | [group setProperty:whom forKey:@"radioGroupCheckedSpecifier"]; 91 | 92 | _specifiers = specs; 93 | 94 | // populate the mode-specific specifiers 95 | group = [PSSpecifier groupSpecifierWithName:@"Text"]; 96 | [group setProperty:@"This text will be typed when you swipe down on this key." forKey:@"footerText"]; 97 | _representedStringSpec = [PSTextFieldSpecifier 98 | preferenceSpecifierNamed:@"Text to Insert" 99 | target:self 100 | set:@selector(setThing:forSpecifier:) 101 | get:@selector(getThingForSpecifier:) 102 | detail:Nil cell:PSEditTextCell edit:Nil]; 103 | _displayStringSpec = [PSTextFieldSpecifier 104 | preferenceSpecifierNamed:@"Text on Keycap" 105 | target:self 106 | set:@selector(setThing:forSpecifier:) 107 | get:@selector(getThingForSpecifier:) 108 | detail:Nil cell:PSEditTextCell edit:Nil]; 109 | _displayStringSpec.placeholder = @"(optional)"; 110 | _textSpecifierArray = @[group, _representedStringSpec, _displayStringSpec]; 111 | 112 | group = [PSSpecifier groupSpecifierWithName:@"Top Left Corner"]; 113 | [group setProperty:@"This text will be typed when you swipe down and to the right on this key." forKey:@"footerText"]; 114 | _leftRepresentedStringSpec = [PSTextFieldSpecifier 115 | preferenceSpecifierNamed:@"Text to Insert" 116 | target:self 117 | set:@selector(setThing:forSpecifier:) 118 | get:@selector(getThingForSpecifier:) 119 | detail:Nil cell:PSEditTextCell edit:Nil]; 120 | _leftDisplayStringSpec = [PSTextFieldSpecifier 121 | preferenceSpecifierNamed:@"Text on Keycap" 122 | target:self 123 | set:@selector(setThing:forSpecifier:) 124 | get:@selector(getThingForSpecifier:) 125 | detail:Nil cell:PSEditTextCell edit:Nil]; 126 | _leftDisplayStringSpec.placeholder = @"(optional)"; 127 | 128 | PSSpecifier *group2 = [PSSpecifier groupSpecifierWithName:@"Top Right Corner"]; 129 | [group2 setProperty:@"This text will be typed when you swipe down and to the left on this key." forKey:@"footerText"]; 130 | _rightRepresentedStringSpec = [PSTextFieldSpecifier 131 | preferenceSpecifierNamed:@"Text to Insert" 132 | target:self 133 | set:@selector(setThing:forSpecifier:) 134 | get:@selector(getThingForSpecifier:) 135 | detail:Nil cell:PSEditTextCell edit:Nil]; 136 | _rightDisplayStringSpec = [PSTextFieldSpecifier 137 | preferenceSpecifierNamed:@"Text on Keycap" 138 | target:self 139 | set:@selector(setThing:forSpecifier:) 140 | get:@selector(getThingForSpecifier:) 141 | detail:Nil cell:PSEditTextCell edit:Nil]; 142 | _rightDisplayStringSpec.placeholder = @"(optional)"; 143 | _dualSpecifierArray = @[group, _leftRepresentedStringSpec, _leftDisplayStringSpec, group2, _rightRepresentedStringSpec, _rightDisplayStringSpec]; 144 | 145 | int startingMode = _mode; 146 | _mode = NFPModeNothing; // we have no specifiers in the array right now 147 | [self _setMode:startingMode]; 148 | } 149 | 150 | return _specifiers; 151 | } 152 | 153 | 154 | - (void)cancelMe:(UIBarButtonItem *)item { 155 | [(PSSetupController *)self.parentController dismiss]; 156 | } 157 | 158 | - (void)saveMe:(UIBarButtonItem *)item { 159 | [self.view endEditing:YES]; 160 | NFPKeyplaneController *kpc = (NFPKeyplaneController *)self.parentController.parentController; 161 | [kpc saveKeyInfoBackFrom:self]; 162 | [(PSSetupController *)self.parentController dismiss]; 163 | } 164 | 165 | - (void)tableView:(UITableView*)view didSelectRowAtIndexPath:(NSIndexPath*)indexPath { 166 | [super tableView:view didSelectRowAtIndexPath:indexPath]; 167 | 168 | PSSpecifier *spec = [self specifierAtIndexPath:indexPath]; 169 | id value = [spec propertyForKey:@"fp-mode"]; 170 | if (value != nil) { 171 | [self _setMode:[value integerValue]]; 172 | } 173 | } 174 | 175 | 176 | - (NSArray *)specsForMode:(int)mode { 177 | switch (mode) { 178 | case NFPModeText: return _textSpecifierArray; 179 | case NFPModeDual: return _dualSpecifierArray; 180 | } 181 | return nil; 182 | } 183 | 184 | - (void)_setMode:(int)newMode { 185 | NSArray *fromArray = [self specsForMode:_mode]; 186 | NSArray *toArray = [self specsForMode:newMode]; 187 | 188 | if (fromArray && toArray) { 189 | [self updateSpecifiers:fromArray withSpecifiers:toArray]; 190 | } else if (fromArray) { 191 | [self removeContiguousSpecifiers:fromArray]; 192 | } else if (toArray) { 193 | [self addSpecifiersFromArray:toArray]; 194 | } 195 | 196 | _mode = newMode; 197 | [self _checkValidity]; 198 | } 199 | 200 | - (id)getThingForSpecifier:(PSSpecifier *)specifier { 201 | if (specifier == _displayStringSpec) 202 | return _displayString; 203 | else if (specifier == _representedStringSpec) 204 | return _representedString; 205 | else if (specifier == _leftDisplayStringSpec) 206 | return _leftDisplayString; 207 | else if (specifier == _leftRepresentedStringSpec) 208 | return _leftRepresentedString; 209 | else if (specifier == _rightDisplayStringSpec) 210 | return _rightDisplayString; 211 | else if (specifier == _rightRepresentedStringSpec) 212 | return _rightRepresentedString; 213 | else 214 | return nil; 215 | } 216 | 217 | - (void)setThing:(id)thing forSpecifier:(PSSpecifier *)specifier { 218 | NSLog(@"setting %@ for %@", thing, specifier); 219 | if (specifier == _displayStringSpec) 220 | _displayString = thing; 221 | else if (specifier == _representedStringSpec) 222 | _representedString = thing; 223 | else if (specifier == _leftDisplayStringSpec) 224 | _leftDisplayString = thing; 225 | else if (specifier == _leftRepresentedStringSpec) 226 | _leftRepresentedString = thing; 227 | else if (specifier == _rightDisplayStringSpec) 228 | _rightDisplayString = thing; 229 | else if (specifier == _rightRepresentedStringSpec) 230 | _rightRepresentedString = thing; 231 | [self _checkValidity]; 232 | } 233 | 234 | - (void)_checkValidity { 235 | // maybe later... 236 | /*BOOL ok = NO; 237 | 238 | switch (_mode) { 239 | case NFPModeNothing: 240 | ok = YES; 241 | break; 242 | case NFPModeText: 243 | ok = (_representedString.length > 0); 244 | break; 245 | case NFPModeDual: 246 | ok = (_leftRepresentedString.length > 0) && (_rightRepresentedString.length > 0); 247 | break; 248 | } 249 | 250 | _saveButton.enabled = ok;*/ 251 | } 252 | 253 | 254 | @end 255 | 256 | 257 | -------------------------------------------------------------------------------- /prefs/NFPKeyboardController.h: -------------------------------------------------------------------------------- 1 | // #import 2 | #import 3 | #import "../h/UIKeyboardInputMode.h" 4 | #import "../h/UIKBTree.h" 5 | #import "../h/TUIKeyboardLayoutFactory.h" 6 | 7 | @interface NFPKeyboardController : PSListController 8 | { 9 | UIKBTree *_keyboard; 10 | 11 | UIKBTree *_smallLettersKeyplane, *_capitalLettersKeyplane; 12 | PSSpecifier *_separateSpecifier; 13 | PSSpecifier *_capitalLettersKeyplaneSpecifier; 14 | } 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /prefs/NFPKeyboardController.m: -------------------------------------------------------------------------------- 1 | #include "NFPKeyboardController.h" 2 | #import "NFPKeyplaneController.h" 3 | #import 4 | #import "../Utils.h" 5 | #include 6 | 7 | @implementation NFPKeyboardController 8 | 9 | - (NSArray *)specifiers { 10 | if (!_specifiers) { 11 | NSMutableArray *specs = [NSMutableArray array]; 12 | 13 | NSString *layoutName = [self.specifier propertyForKey:@"fp-keyboard-layout"]; 14 | NSLog(@"Gonna edit %@", layoutName); 15 | 16 | self.title = layoutName; 17 | 18 | NSString *kbName = [NSString stringWithFormat:@"iPhone-Portrait-%@", layoutName]; 19 | _keyboard = [[objc_getClass("TUIKeyboardLayoutFactory") sharedKeyboardFactory] keyboardWithName:kbName inCache:nil]; 20 | NSLog(@"Found keyboard: %@", _keyboard); 21 | 22 | _smallLettersKeyplane = nil; 23 | _capitalLettersKeyplane = nil; 24 | 25 | NSString *prefBase = [NSString stringWithFormat:@"kb-%@-", layoutName]; 26 | 27 | // Build Keyplanes 28 | PSSpecifier *group = [PSSpecifier groupSpecifierWithName:@"Keyplanes"]; 29 | [group setProperty:@"Each of these is a separate 'page' on the keyboard." forKey:@"footerText"]; 30 | [specs addObject:group]; 31 | 32 | for (UIKBTree *keyplane in _keyboard.subtrees) { 33 | if ([keyplane.name hasSuffix:@"-Small-Display"]) 34 | continue; 35 | else if ([keyplane.name hasSuffix:@"_Capital-Letters"]) 36 | _capitalLettersKeyplane = keyplane; 37 | else if ([keyplane.name hasSuffix:@"_Small-Letters"]) 38 | _smallLettersKeyplane = keyplane; 39 | 40 | NSString *slicedKeyplaneName = [keyplane.name sliceAfterLastUnderscore]; 41 | 42 | PSSpecifier *spec = [PSSpecifier 43 | preferenceSpecifierNamed:[slicedKeyplaneName hyphensToSpaces] 44 | target:self 45 | set:NULL 46 | get:NULL 47 | detail:[NFPKeyplaneController class] 48 | cell:PSLinkCell 49 | edit:Nil]; 50 | [spec setProperty:@YES forKey:@"enabled"]; 51 | [spec setProperty:layoutName forKey:@"fp-layout-name"]; 52 | [spec setProperty:_keyboard forKey:@"fp-keyboard"]; 53 | [spec setProperty:keyplane forKey:@"fp-keyplane"]; 54 | [specs addObject:spec]; 55 | 56 | if ([keyplane.name hasSuffix:@"_Capital-Letters"]) 57 | _capitalLettersKeyplaneSpecifier = spec; 58 | } 59 | 60 | // Niceties 61 | _separateSpecifier = nil; 62 | 63 | if (_capitalLettersKeyplane && _smallLettersKeyplane) { 64 | PSSpecifier *group = [PSSpecifier groupSpecifierWithName:@"Options"]; 65 | [group setProperty:@"Use different shortcuts on the Small Letters and Capital Letters keyboards." forKey:@"footerText"]; 66 | 67 | _separateSpecifier = [PSSpecifier 68 | preferenceSpecifierNamed:@"Separate Small/Capital Letters" 69 | target:self 70 | set:@selector(setPreferenceValue:specifier:) 71 | get:@selector(readPreferenceValue:) 72 | detail:Nil 73 | cell:PSSwitchCell 74 | edit:Nil 75 | ]; 76 | [_separateSpecifier setProperty:[prefBase stringByAppendingString:@"capsAreSeparate"] forKey:@"key"]; 77 | [_separateSpecifier setProperty:@NO forKey:@"default"]; 78 | [_separateSpecifier setProperty:@"org.wuffs.flickplus" forKey:@"defaults"]; 79 | [_separateSpecifier setProperty:@"org.wuffs.flickplus/ReloadPrefs" forKey:@"PostNotification"]; 80 | 81 | [specs addObject:group]; 82 | [specs addObject:_separateSpecifier]; 83 | } 84 | 85 | _specifiers = specs; 86 | } 87 | 88 | [self _refreshSeparateState]; 89 | return _specifiers; 90 | } 91 | 92 | 93 | - (void)_refreshSeparateState { 94 | if (_separateSpecifier) { 95 | id isSeparate = [self readPreferenceValue:_separateSpecifier]; 96 | [_capitalLettersKeyplaneSpecifier setProperty:isSeparate forKey:@"enabled"]; 97 | [self reloadSpecifier:_capitalLettersKeyplaneSpecifier]; 98 | } 99 | } 100 | 101 | - (void)setPreferenceValue:(id)value specifier:(PSSpecifier *)specifier { 102 | [super setPreferenceValue:value specifier:specifier]; 103 | 104 | if (specifier == _separateSpecifier) 105 | [self _refreshSeparateState]; 106 | } 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /prefs/NFPKeyplaneController.h: -------------------------------------------------------------------------------- 1 | // #import 2 | #import 3 | #import "../h/UIKBTree.h" 4 | @class NFPKeyPropsController; 5 | @class HBPreferences; 6 | 7 | @interface NFPKeyplaneController : PSListController 8 | { 9 | UIKBTree *_keyboard, *_keyplane; 10 | NSString *_prefKey; 11 | NSMutableDictionary *_configData; 12 | HBPreferences *_hbPrefs; 13 | } 14 | - (void)saveKeyInfoBackFrom:(NFPKeyPropsController *)kpc; 15 | @end 16 | 17 | 18 | -------------------------------------------------------------------------------- /prefs/NFPKeyplaneController.m: -------------------------------------------------------------------------------- 1 | #include "NFPKeyplaneController.h" 2 | #import 3 | #import "NFPKeyPropsController.h" 4 | #import "../Utils.h" 5 | #import 6 | #include 7 | #import 8 | 9 | // not nice, but Theos is missing this >.< 10 | @interface PSConfirmationSpecifier : PSSpecifier 11 | @property(retain, nonatomic) NSString *prompt; 12 | @property(retain, nonatomic) NSString *title; 13 | @property(retain, nonatomic) NSString *okButton; 14 | @property(retain, nonatomic) NSString *cancelButton; 15 | @end 16 | 17 | @interface PSSpecifier (MissingStuff) 18 | - (id)performGetter; 19 | @end 20 | 21 | @interface PSTableCell (MissingStuff) 22 | - (void)setValue:(id)value; 23 | @end 24 | 25 | @interface NFPForcedValueTableCell : PSTableCell 26 | @end 27 | 28 | @implementation NFPForcedValueTableCell 29 | // because PSLinkCell doesn't get a value by default 30 | - (void)refreshCellContentsWithSpecifier:(PSSpecifier *)specifier { 31 | [super refreshCellContentsWithSpecifier:specifier]; 32 | self.value = [specifier performGetter]; 33 | } 34 | @end 35 | 36 | @interface UIKBTree (FlickPlus) 37 | - (NSDictionary *)nfpGenerateKeylayoutConfigBasedOffKeylayout:(UIKBTree *)subLayout inKeyplane:(UIKBTree *)keyplane rewriteCapitalToSmall:(BOOL)capsToSmall; 38 | @end 39 | 40 | enum { 41 | scClearAll, 42 | scCopyFromPlane 43 | }; 44 | 45 | @implementation NFPKeyplaneController 46 | 47 | - (NSArray *)selectAlternativeKeyplanesFrom:(UIKBTree *)keyboard ignoringPlane:(UIKBTree *)planeToIgnore { 48 | NSMutableArray *results = [NSMutableArray array]; 49 | 50 | for (UIKBTree *plane in keyboard.subtrees) { 51 | if (plane == planeToIgnore) 52 | continue; 53 | if ([plane.name containsString:@"Letters"]) 54 | continue; 55 | 56 | [results addObject:plane]; 57 | } 58 | 59 | return results; 60 | } 61 | 62 | - (NSArray *)specifiers { 63 | if (!_specifiers) { 64 | NSMutableArray *specs = [NSMutableArray array]; 65 | 66 | NSString *layoutName = [self.specifier propertyForKey:@"fp-layout-name"]; 67 | _keyboard = [self.specifier propertyForKey:@"fp-keyboard"]; 68 | _keyplane = [self.specifier propertyForKey:@"fp-keyplane"]; 69 | 70 | NSString *slicedKeyplaneName = [_keyplane.name sliceAfterLastUnderscore]; 71 | self.title = [slicedKeyplaneName hyphensToSpaces]; 72 | 73 | _hbPrefs = [[HBPreferences alloc] initWithIdentifier:@"org.wuffs.flickplus"]; 74 | _prefKey = [NSString stringWithFormat:@"kb-%@--%@--flicks", layoutName, slicedKeyplaneName]; 75 | NSDictionary *storedConfig = [_hbPrefs objectForKey:_prefKey]; 76 | if (storedConfig == nil) { 77 | UIKBTree *keylayout = _keyplane.subtrees[0]; 78 | UIKBTree *gestureKeyplane = [_keyboard subtreeWithName:_keyplane.gestureKeyplaneName]; 79 | if (gestureKeyplane) { 80 | NSLog(@"NFPKeyplaneController creating new default config with gestureKeyplane=%@", gestureKeyplane.name); 81 | UIKBTree *gestureKeylayout = gestureKeyplane.subtrees[0]; 82 | _configData = [[keylayout nfpGenerateKeylayoutConfigBasedOffKeylayout:gestureKeylayout inKeyplane:_keyplane rewriteCapitalToSmall:NO] mutableCopy]; 83 | } else { 84 | NSLog(@"NFPKeyplaneController creating new blank config"); 85 | _configData = [NSMutableDictionary dictionary]; 86 | } 87 | } else { 88 | NSLog(@"NFPKeyplaneController loading existing config"); 89 | _configData = [storedConfig mutableCopy]; 90 | } 91 | 92 | // Spawn some templates 93 | [self addTemplateSpecTo:specs named:@"Clear All Shortcuts" withEnum:scClearAll andExtra:nil]; 94 | 95 | NSArray *alternativeKeyplanes = [self selectAlternativeKeyplanesFrom:_keyboard ignoringPlane:_keyplane]; 96 | if (alternativeKeyplanes.count > 0) { 97 | PSSpecifier *group = [PSSpecifier groupSpecifierWithName:@"Templates"]; 98 | [group setProperty:@"Sets up shortcuts so that flicking a key will give you the corresponding key on the other page, like the default iPad keyboard. A good default starting point." forKey:@"footerText"]; 99 | [specs addObject:group]; 100 | 101 | for (UIKBTree *alternative in alternativeKeyplanes) { 102 | NSString *name = [@"Keys from " stringByAppendingString:[[alternative.name sliceAfterLastUnderscore] hyphensToSpaces]]; 103 | [self addTemplateSpecTo:specs named:name withEnum:scCopyFromPlane andExtra:alternative.name]; 104 | } 105 | } 106 | 107 | // Spawn all keys 108 | for (UIKBTree *keylayout in _keyplane.subtrees) { 109 | if (keylayout.type != 3) 110 | continue; 111 | 112 | NSString *niceKeylayoutName = [keylayout.name sliceAfterLastUnderscore]; 113 | niceKeylayoutName = [niceKeylayoutName hyphensToSpaces]; 114 | niceKeylayoutName = [niceKeylayoutName stringByReplacingOccurrencesOfString:@"iPhone " withString:@""]; 115 | UIKBTree *keySet = [keylayout keySet]; 116 | 117 | for (UIKBTree *list in keySet.subtrees) { 118 | NSString *niceListName = [list.name sliceAfterLastUnderscore]; 119 | niceListName = [niceListName stringByReplacingOccurrencesOfString:@"Row" withString:@"Row "]; 120 | niceListName = [NSString stringWithFormat:@"%@: %@", niceKeylayoutName, niceListName]; 121 | 122 | PSSpecifier *group = [PSSpecifier groupSpecifierWithName:niceListName]; 123 | [specs addObject:group]; 124 | 125 | for (UIKBTree *key in list.subtrees) { 126 | PSSpecifier *keySpec = [PSSpecifier 127 | preferenceSpecifierNamed:[self niceLabelForKey:key] 128 | target:self 129 | set:NULL 130 | get:@selector(shortcutTextForKeySpecifier:) 131 | detail:objc_getClass("PSSetupController") 132 | cell:PSLinkCell 133 | edit:Nil]; 134 | [keySpec setProperty:[NFPForcedValueTableCell class] forKey:@"cellClass"]; 135 | [keySpec setProperty:@"NFPKeyPropsController" forKey:@"customControllerClass"]; 136 | [keySpec setProperty:key forKey:@"fp-key"]; 137 | [keySpec setProperty:_configData[key.name] forKey:@"fp-key-config"]; 138 | [specs addObject:keySpec]; 139 | } 140 | } 141 | 142 | // for now, only show the first keylayout... 143 | break; 144 | } 145 | 146 | _specifiers = specs; 147 | } 148 | 149 | return _specifiers; 150 | } 151 | 152 | 153 | - (NSString *)niceLabelForKey:(UIKBTree *)key { 154 | switch (key.displayType) { 155 | case 0: // String 156 | case 8: // DynamicString 157 | return key.displayString; 158 | default: 159 | return [NSString stringWithFormat:@"", key.displayType]; 160 | } 161 | } 162 | 163 | 164 | - (void)addTemplateSpecTo:(NSMutableArray *)specs named:(NSString *)name withEnum:(int)shortcut andExtra:(NSString *)extra { 165 | PSConfirmationSpecifier *spec = [PSConfirmationSpecifier 166 | preferenceSpecifierNamed:name 167 | target:self 168 | set:NULL 169 | get:NULL 170 | detail:Nil 171 | cell:PSButtonCell 172 | edit:Nil]; 173 | spec.confirmationAction = @selector(processTemplate:); 174 | if (shortcut == scClearAll) 175 | spec.prompt = @"All the existing shortcuts on this page will be removed."; 176 | else 177 | spec.prompt = @"All the existing shortcuts on this page will be removed and replaced with new ones."; 178 | spec.title = @"Continue"; 179 | spec.okButton = @"Continue"; // the fuck does this do...? 180 | spec.cancelButton = @"Cancel"; 181 | [spec setProperty:[NSNumber numberWithInt:shortcut] forKey:@"fp-shortcut"]; 182 | [spec setProperty:extra forKey:@"fp-shortcut-extra"]; 183 | [specs addObject:spec]; 184 | } 185 | 186 | 187 | - (void)processTemplate:(PSSpecifier *)specifier { 188 | int shortcut = [[specifier propertyForKey:@"fp-shortcut"] integerValue]; 189 | 190 | if (shortcut == scClearAll) { 191 | [_configData removeAllObjects]; 192 | } else if (shortcut == scCopyFromPlane) { 193 | NSString *srcKeyplaneName = [specifier propertyForKey:@"fp-shortcut-extra"]; 194 | UIKBTree *srcKeyplane = [_keyboard subtreeWithName:srcKeyplaneName]; 195 | UIKBTree *srcKeylayout = srcKeyplane.subtrees[0]; 196 | UIKBTree *destKeylayout = _keyplane.subtrees[0]; 197 | _configData = [[destKeylayout nfpGenerateKeylayoutConfigBasedOffKeylayout:srcKeylayout inKeyplane:_keyplane rewriteCapitalToSmall:NO] mutableCopy]; 198 | } 199 | 200 | // give all key specifiers back the latest info 201 | for (PSSpecifier *specifier in _specifiers) { 202 | UIKBTree *key = [specifier propertyForKey:@"fp-key"]; 203 | if (key != nil) { 204 | NSArray *keyData = _configData[key.name]; 205 | if (keyData == nil) 206 | [specifier removePropertyForKey:@"fp-key-config"]; 207 | else 208 | [specifier setProperty:keyData forKey:@"fp-key-config"]; 209 | [self reloadSpecifier:specifier]; 210 | } 211 | } 212 | [self writeSettings]; 213 | } 214 | 215 | 216 | - (NSString *)shortcutTextForKeySpecifier:(PSSpecifier *)specifier { 217 | NSArray *info = [specifier propertyForKey:@"fp-key-config"]; 218 | if (info != nil) { 219 | if (info.count == 2) 220 | return info[0]; 221 | else if (info.count == 4) 222 | return [NSString stringWithFormat:@"%@ / %@", info[0], info[2]]; 223 | } 224 | return @""; 225 | } 226 | 227 | 228 | - (void)saveKeyInfoBackFrom:(NFPKeyPropsController *)kpc { 229 | PSSpecifier *specifier = kpc.specifier; 230 | UIKBTree *key = [specifier propertyForKey:@"fp-key"]; 231 | 232 | switch (kpc.mode) { 233 | case NFPModeNothing: 234 | [_configData removeObjectForKey:key.name]; 235 | break; 236 | case NFPModeText: 237 | _configData[key.name] = @[ 238 | kpc.representedString, kpc.displayString 239 | ]; 240 | break; 241 | case NFPModeDual: 242 | _configData[key.name] = @[ 243 | kpc.leftRepresentedString, kpc.leftDisplayString, 244 | kpc.rightRepresentedString, kpc.rightDisplayString 245 | ]; 246 | break; 247 | } 248 | 249 | [specifier setProperty:_configData[key.name] forKey:@"fp-key-config"]; 250 | [self reloadSpecifier:specifier]; 251 | [self writeSettings]; 252 | } 253 | 254 | 255 | - (void)writeSettings { 256 | [_hbPrefs setObject:[NSDictionary dictionaryWithDictionary:_configData] forKey:_prefKey]; 257 | notify_post("org.wuffs.flickplus/ReloadPrefs"); 258 | } 259 | 260 | @end 261 | 262 | -------------------------------------------------------------------------------- /prefs/NFPRootListController.h: -------------------------------------------------------------------------------- 1 | // #import 2 | #import 3 | 4 | // @interface NFPRootListController : HBRootListController 5 | @interface NFPRootListController : PSListController 6 | 7 | @end 8 | -------------------------------------------------------------------------------- /prefs/NFPRootListController.m: -------------------------------------------------------------------------------- 1 | #include "NFPRootListController.h" 2 | #import "NFPKeyboardController.h" 3 | #import 4 | #import 5 | #import 6 | #import 7 | #import 8 | #import "../h/UIKeyboardInputMode.h" 9 | #import "../h/UIKeyboardInputModeController.h" 10 | #import "../h/UIKeyboardCache.h" 11 | #include 12 | 13 | @interface HBRespringController (TerribleHack) 14 | + (NSURL *)_preferencesReturnURL; 15 | @end 16 | 17 | @implementation NFPRootListController 18 | 19 | // + (NSString *)hb_specifierPlist { 20 | // return @"Root"; 21 | // } 22 | 23 | // all of this can be removed once libpackageinfo is updated 24 | // so Cephei works properly again 25 | 26 | - (NSArray *)specifiers { 27 | if (!_specifiers) { 28 | NSMutableArray *specs = [[self loadSpecifiersFromPlistName:@"Root" target:self] mutableCopy]; 29 | 30 | // cephei does this for us once we use its listcontroller 31 | for (PSSpecifier *specifier in specs) { 32 | Class cellClass = specifier.properties[PSCellClassKey]; 33 | if ([cellClass isSubclassOfClass:HBLinkTableCell.class]) { 34 | specifier.cellType = PSLinkCell; 35 | specifier.buttonAction = @selector(hb_openURL:); 36 | } 37 | } 38 | 39 | NSArray *inputModeIDs = [[UIKeyboardInputModeController sharedInputModeController] activeInputModeIdentifiers]; 40 | NSSet *layouts = [[objc_getClass("UIKeyboardCache") sharedInstance] uniqueLayoutsFromInputModes:inputModeIDs]; 41 | int listIndex = 3; 42 | 43 | // this can maybe be made nicer by using PSListController methods 44 | for (NSString *layout in layouts) { 45 | if ([layout isEqualToString:@"Emoji"]) 46 | continue; 47 | 48 | PSSpecifier *spec = [PSSpecifier 49 | preferenceSpecifierNamed:layout 50 | target:self 51 | set:NULL 52 | get:NULL 53 | detail:[NFPKeyboardController class] 54 | cell:PSLinkCell 55 | edit:Nil]; 56 | [spec setProperty:@YES forKey:@"enabled"]; 57 | [spec setProperty:layout forKey:@"fp-keyboard-layout"]; 58 | [specs insertObject:spec atIndex:listIndex++]; 59 | } 60 | 61 | _specifiers = specs; 62 | } 63 | 64 | return _specifiers; 65 | } 66 | 67 | 68 | - (void)resetSettingsTapped:(PSSpecifier *)specifier { 69 | HBPreferences *prefs = [[HBPreferences alloc] initWithIdentifier:@"org.wuffs.flickplus"]; 70 | [prefs removeAllObjects]; 71 | [self reloadSpecifiers]; 72 | } 73 | 74 | 75 | - (void)hb_openURL:(PSSpecifier *)specifier { 76 | NSURL *url = [NSURL URLWithString:specifier.properties[@"url"]]; 77 | [[UIApplication sharedApplication] openURL:url]; 78 | } 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /prefs/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | { 2 | CFBundleDevelopmentRegion = English; 3 | CFBundleExecutable = FlickPlusPrefs; 4 | CFBundleIdentifier = "org.wuffs.flickplus"; 5 | CFBundleInfoDictionaryVersion = "6.0"; 6 | CFBundlePackageType = BNDL; 7 | CFBundleShortVersionString = "1.0.0"; 8 | CFBundleSignature = "????"; 9 | CFBundleVersion = "1.0"; 10 | NSPrincipalClass = NFPRootListController; 11 | } 12 | -------------------------------------------------------------------------------- /prefs/Resources/Root.plist: -------------------------------------------------------------------------------- 1 | { 2 | items = ( 3 | { 4 | cell = PSGroupCell; 5 | label = "Arbitrary Text Field"; 6 | footerText = "Tap above to open a keyboard, which you can conveniently use to preview your settings."; 7 | }, 8 | { 9 | cell = PSEditTextCell; 10 | }, 11 | { 12 | cell = PSGroupCell; 13 | label = "Active Layouts"; 14 | }, 15 | { 16 | cell = PSGroupCell; 17 | label = "Symbol Colours"; 18 | footerText = "Sets the colour of the symbols that appear on the top of the keys."; 19 | }, 20 | { 21 | cell = PSLinkListCell; 22 | label = "Light Keyboard"; 23 | default = "lgrey"; 24 | defaults = "org.wuffs.flickplus"; 25 | key = lightSymbols; 26 | validValues = ("lgrey", "dgrey", "black"); 27 | validTitles = ("Light Grey (iOS Default)", "Dark Grey", "Black"); 28 | shortTitles = ("Light Grey", "Dark Grey", "Black"); 29 | detail = PSListItemsController; 30 | PostNotification = "org.wuffs.flickplus/ReloadPrefs"; 31 | }, 32 | { 33 | cell = PSLinkListCell; 34 | label = "Dark Keyboard"; 35 | default = "lgrey"; 36 | defaults = "org.wuffs.flickplus"; 37 | key = darkSymbols; 38 | validValues = ("white", "lgrey", "dgrey", "black"); 39 | validTitles = ("White", "Light Grey (iOS Default)", "Dark Grey", "Black"); 40 | shortTitles = ("White", "Light Grey", "Dark Grey", "Black"); 41 | detail = PSListItemsController; 42 | PostNotification = "org.wuffs.flickplus/ReloadPrefs"; 43 | }, 44 | 45 | { 46 | cell = PSGroupCell; 47 | label = "Sizing"; 48 | }, 49 | { 50 | cell = PSSwitchCell; 51 | label = "Smaller Symbols"; 52 | default = 0; 53 | defaults = "org.wuffs.flickplus"; 54 | key = smallSymbols; 55 | PostNotification = "org.wuffs.flickplus/ReloadPrefs"; 56 | }, 57 | 58 | { 59 | cell = PSGroupCell; 60 | label = "Haptics"; 61 | footerText = "With this switch on, you will feel a click through the Taptic Engine once you've swiped down enough to activate the shortcut."; 62 | }, 63 | { 64 | cell = PSSwitchCell; 65 | label = "Feedback on Slide"; 66 | default = 1; 67 | defaults = "org.wuffs.flickplus"; 68 | key = hapticFeedback; 69 | PostNotification = "org.wuffs.flickplus/ReloadPrefs"; 70 | }, 71 | 72 | { 73 | cell = PSGroupCell; 74 | label = "Tools"; 75 | footerText = "Use only in case of emergency."; 76 | }, 77 | { 78 | cell = PSButtonCell; 79 | label = "Reset Settings"; 80 | action = "resetSettingsTapped:"; 81 | confirmation = { 82 | prompt = "All of your FlicksForAll settings will be cleared. Are you sure?"; 83 | title = "Yes, do it"; 84 | cancelTitle = "Cancel"; 85 | }; 86 | }, 87 | 88 | { 89 | cell = PSGroupCell; 90 | label = "Donate"; 91 | footerText = "This tweak is free and open-source. If you like it, feel free to throw some money at me (no pressure though!)"; 92 | }, 93 | { 94 | cellClass = HBLinkTableCell; 95 | label = "PayPal.me"; 96 | url = "https://paypal.me/trashcurl"; 97 | }, 98 | { 99 | cellClass = HBLinkTableCell; 100 | label = "Ko-fi"; 101 | url = "https://ko-fi.com/ninji_"; 102 | }, 103 | { 104 | cellClass = HBLinkTableCell; 105 | label = "Monzo (UK only)"; 106 | url = "https://monzo.me/ninji"; 107 | }, 108 | 109 | 110 | { 111 | cell = PSGroupCell; 112 | label = "Twitter"; 113 | footerText = "You'll probably regret following me, but it's there if you really want to."; 114 | }, 115 | { 116 | cellClass = HBTwitterCell; 117 | user = "_Ninji"; 118 | label = "Ninji"; 119 | }, 120 | 121 | 122 | { 123 | cell = PSGroupCell; 124 | label = "Source Code"; 125 | }, 126 | { 127 | cellClass = HBLinkTableCell; 128 | label = "GitHub: Treeki/FlicksForAll"; 129 | url = "https://github.com/Treeki/FlicksForAll"; 130 | } 131 | ); 132 | title = FlicksForAll; 133 | } 134 | -------------------------------------------------------------------------------- /prefs/entry.plist: -------------------------------------------------------------------------------- 1 | { 2 | entry = { 3 | bundle = FlickPlusPrefs; 4 | cell = PSLinkCell; 5 | detail = NFPRootListController; 6 | icon = "icon.png"; 7 | isController = 1; 8 | label = FlicksForAll; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /scripts/frida-fetch-kbcache.js: -------------------------------------------------------------------------------- 1 | var kbcache = null; 2 | 3 | var NSCache = ObjC.classes.NSCache; 4 | var scl = NSCache['- setCountLimit:']; 5 | var oldSCL = scl.implementation; 6 | scl.implementation = ObjC.implement(scl, 7 | function(handle, selector, z) { 8 | console.log(handle, z); 9 | if (z == 50) { 10 | console.log('found kbcache'); 11 | kbcache = new ObjC.Object(handle); 12 | } 13 | oldSCL(handle, selector, z); 14 | }); 15 | 16 | var _img2png = new NativeFunction(Module.findExportByName(null, 'UIImagePNGRepresentation'), 'pointer', ['pointer']); 17 | function img2png(img) { 18 | return new ObjC.Object(_img2png(img)); 19 | } 20 | 21 | var nsfm = ObjC.classes.NSFileManager.defaultManager(); 22 | var path = nsfm.temporaryDirectory().toString().replace('file://', ''); 23 | 24 | function img2pngFile(img, name) { 25 | var png = img2png(img); 26 | console.log('writing ' + path + name); 27 | var result = png.writeToFile_atomically_(path + name, false); 28 | if (result) 29 | console.log('ok'); 30 | else 31 | console.log('failed'); 32 | } 33 | 34 | 35 | function dumpAll() { 36 | var array = kbcache.allObjects(); 37 | for (var i = 0; i < array.count(); i++) { 38 | var img = array.objectAtIndex_(i); 39 | img2pngFile(img, 'kb' + i + '.png'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /scripts/frida-introspect-kb.js: -------------------------------------------------------------------------------- 1 | var UIWindow = ObjC.classes.UIWindow 2 | 3 | var allwindows = UIWindow.allWindowsIncludingInternalWindows_onlyVisibleWindows_(true, true) 4 | var rkbw = allwindows.objectAtIndex_(2) 5 | var it = rkbw.subviews().objectAtIndex_(0) 6 | var it = it.subviews().objectAtIndex_(0) 7 | var UIKBCompatInputView = it.subviews().objectAtIndex_(2) 8 | var UIKeyboardAutomatic = UIKBCompatInputView.subviews().objectAtIndex_(0) 9 | var UIKeyboardImpl = UIKeyboardAutomatic.subviews().objectAtIndex_(0) 10 | var UIKeyboardLayoutStar = UIKeyboardImpl.subviews().objectAtIndex_(0) 11 | var UIKBKeyplaneView = UIKeyboardLayoutStar.subviews().objectAtIndex_(0) 12 | 13 | var keyplane = UIKBKeyplaneView.keyplane() 14 | var r_key = keyplane.subtrees().objectAtIndex_(0).keySet().subtrees().objectAtIndex_(0).subtrees().objectAtIndex_(3) 15 | 16 | var sdkl = keyplane.subtrees().objectAtIndex_(1) 17 | var shiftdeletes = sdkl.keySet().subtrees().objectAtIndex_(0).subtrees() 18 | var shiftk = shiftdeletes.objectAtIndex_(0) 19 | var deletek = shiftdeletes.objectAtIndex_(1) 20 | 21 | var controlkl = keyplane.subtrees().objectAtIndex_(2) 22 | var controlkeys = controlkl.keySet().subtrees().objectAtIndex_(0).subtrees() 23 | var morek = controlkeys.objectAtIndex_(0) 24 | var internationalk = controlkeys.objectAtIndex_(1) 25 | var dictationk = controlkeys.objectAtIndex_(2) 26 | var spacek = controlkeys.objectAtIndex_(3) 27 | var returnk = controlkeys.objectAtIndex_(4) 28 | --------------------------------------------------------------------------------