mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-26 17:47:40 +00:00
Merge pull request #3949 from keymanapp/feat/mac/1953-user-controllable-legacy-app-list
feat(mac): user-controllable legacy app list
This commit is contained in:
commit
0c67dbf5dd
3 changed files with 91 additions and 27 deletions
|
|
@ -125,6 +125,8 @@ typedef struct {
|
|||
- (NSString *)oskWindowTitle;
|
||||
- (void)postKeyboardEventWithSource: (CGEventSourceRef)source code:(CGKeyCode) virtualKey postCallback:(PostEventCallback)postEvent;
|
||||
- (KeymanVersionInfo)versionInfo;
|
||||
- (NSString *)keymanDataPath;
|
||||
- (NSArray *)legacyAppsUserDefaults;
|
||||
@end
|
||||
|
||||
#endif /* KMInputMethodAppDelegate_h */
|
||||
|
|
|
|||
|
|
@ -21,11 +21,14 @@
|
|||
#import "ZipArchive.h"
|
||||
@import Sentry;
|
||||
|
||||
/** NSUserDefaults keys */
|
||||
NSString *const kKMSelectedKeyboardKey = @"KMSelectedKeyboardKey";
|
||||
NSString *const kKMActiveKeyboardsKey = @"KMActiveKeyboardsKey";
|
||||
NSString *const kKMSavedStoresKey = @"KMSavedStoresKey";
|
||||
NSString *const kKMAlwaysShowOSKKey = @"KMAlwaysShowOSKKey";
|
||||
NSString *const kKMUseVerboseLogging = @"KMUseVerboseLogging";
|
||||
NSString *const kKMLegacyApps = @"KMLegacyApps";
|
||||
|
||||
NSString *const kKeymanKeyboardDownloadCompletedNotification = @"kKeymanKeyboardDownloadCompletedNotification";
|
||||
|
||||
NSString *const kPackage = @"[Package]";
|
||||
|
|
@ -64,6 +67,7 @@ typedef enum {
|
|||
@synthesize alwaysShowOSK = _alwaysShowOSK;
|
||||
|
||||
id _lastServerWithOSKShowing = nil;
|
||||
NSString* _keymanDataPath = nil;
|
||||
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
|
|
@ -460,14 +464,37 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
|
|||
return [userData boolForKey:kKMUseVerboseLogging];
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate and create the Keyman data path; currently in ~/Documents/Keyman-Keyboards
|
||||
*/
|
||||
- (NSString *)keymanDataPath {
|
||||
if(_keymanDataPath == nil) {
|
||||
NSString *documentDirPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
|
||||
_keymanDataPath = [documentDirPath stringByAppendingPathComponent:@"Keyman-Keyboards"];
|
||||
|
||||
NSFileManager *fm = [NSFileManager defaultManager];
|
||||
if (![fm fileExistsAtPath:_keymanDataPath]) {
|
||||
[fm createDirectoryAtPath:_keymanDataPath withIntermediateDirectories:YES attributes:nil error:nil];
|
||||
}
|
||||
}
|
||||
return _keymanDataPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of user-default legacy apps
|
||||
*/
|
||||
- (NSArray *)legacyAppsUserDefaults {
|
||||
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
|
||||
return [userData arrayForKey:kKMLegacyApps];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root folder where keyboards are stored; currently the same
|
||||
* as the keymanDataPath, but may diverge in future versions (possibly a sub-folder)
|
||||
*/
|
||||
- (NSString *)keyboardsPath {
|
||||
if (_keyboardsPath == nil) {
|
||||
NSString *documentDirPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
|
||||
_keyboardsPath = [documentDirPath stringByAppendingPathComponent:@"Keyman-Keyboards"];
|
||||
NSFileManager *fm = [NSFileManager defaultManager];
|
||||
if (![fm fileExistsAtPath:_keyboardsPath]) {
|
||||
[fm createDirectoryAtPath:_keyboardsPath withIntermediateDirectories:YES attributes:nil error:nil];
|
||||
}
|
||||
_keyboardsPath = [self keymanDataPath];
|
||||
}
|
||||
|
||||
return _keyboardsPath;
|
||||
|
|
|
|||
|
|
@ -42,22 +42,33 @@ NSRange _previousSelRange;
|
|||
return self;
|
||||
}
|
||||
|
||||
// This is the public initializer.
|
||||
- (instancetype)initWithClient:(NSString *)clientAppId client:(id) sender {
|
||||
self.senderForDeleteBack = sender;
|
||||
// TODO: Pages and Keynote (and possibly lots of other undiscovered apps that are otherwise compliant
|
||||
// with Apple's IM framework) have a problem in that if the user selects a different font (or other
|
||||
// formatting) and then types a sequence that causes characters to be added to the document and then
|
||||
// subsequently replaced, the replacement causes the formatting decision to be forgotten. This can be
|
||||
// "fixed" by treating them as legacy apps, but it causes other problems.
|
||||
BOOL legacy = ([clientAppId isEqual: @"com.github.atom"] ||
|
||||
/**
|
||||
* Checks if the client app requires legacy input mode, first by checking the user defaults, if they exist,
|
||||
* then, by our hard-coded list.
|
||||
*/
|
||||
- (BOOL)isClientAppLegacy:(NSString *)clientAppId {
|
||||
NSArray *legacyAppsUserDefaults = [self.AppDelegate legacyAppsUserDefaults];
|
||||
|
||||
BOOL result = NO;
|
||||
|
||||
if(legacyAppsUserDefaults != nil) {
|
||||
result = [self isClientAppLegacy:clientAppId fromArray:legacyAppsUserDefaults];
|
||||
}
|
||||
|
||||
if(!result) {
|
||||
// TODO: Pages and Keynote (and possibly lots of other undiscovered apps that are otherwise compliant
|
||||
// with Apple's IM framework) have a problem in that if the user selects a different font (or other
|
||||
// formatting) and then types a sequence that causes characters to be added to the document and then
|
||||
// subsequently replaced, the replacement causes the formatting decision to be forgotten. This can be
|
||||
// "fixed" by treating them as legacy apps, but it causes other problems.
|
||||
result = ([clientAppId isEqual: @"com.github.atom"] ||
|
||||
[clientAppId isEqual: @"com.collabora.libreoffice-free"] ||
|
||||
[clientAppId isEqual: @"org.libreoffice.script"] ||
|
||||
[clientAppId isEqual: @"com.axosoft.gitkraken"] ||
|
||||
[clientAppId isEqual: @"org.sil.app.builder.scripture.ScriptureAppBuilder"] ||
|
||||
[clientAppId isEqual: @"org.sil.app.builder.reading.ReadingAppBuilder"] ||
|
||||
[clientAppId isEqual: @"org.sil.app.builder.dictionary.DictionaryAppBuilder"] ||
|
||||
[clientAppId isEqual: @"com.microsoft.Word"] ||
|
||||
//[clientAppId isEqual: @"com.microsoft.Word"] || // 2020-11-24[mcd]: Appears to work well in Word 16.43, disable legacy by default
|
||||
[clientAppId isEqual: @"org.openoffice.script"] ||
|
||||
[clientAppId isEqual: @"com.adobe.illustrator"] ||
|
||||
[clientAppId isEqual: @"com.adobe.InDesign"] ||
|
||||
|
|
@ -67,19 +78,43 @@ NSRange _previousSelRange;
|
|||
[clientAppId isEqual: @"com.google.Chrome"] ||
|
||||
[clientAppId hasPrefix: @"net.java"] ||
|
||||
[clientAppId isEqual: @"com.Keyman.test.legacyInput"]
|
||||
/*||[clientAppId isEqual: @"ro.sync.exml.Oxygen"] - Oxygen has worse problems */);
|
||||
/*||[clientAppId isEqual: @"ro.sync.exml.Oxygen"] - Oxygen has worse problems */
|
||||
);
|
||||
}
|
||||
|
||||
// We used to default to NO, so these were the obvious exceptions. But then we realized that
|
||||
// in any app, command keys can change the selection, so now we default to YES, and only have
|
||||
// a few situations where we pretend it can't. This flag should probably be renamed to something
|
||||
// like "disregardPossibleSelectionChanges".
|
||||
// if ([clientAppId isEqual: @"com.google.Chrome"] ||
|
||||
// [clientAppId isEqual: @"com.apple.Terminal"] ||
|
||||
// [clientAppId isEqual: @"com.apple.dt.Xcode"]) {
|
||||
// _clientSelectionCanChangeUnexpectedly = YES;
|
||||
// }
|
||||
return result;
|
||||
}
|
||||
|
||||
// In Xcode, if Keyman is the active IM and is in "debugMode" and "English plus Spanish" is the current keyboard and you type "Sentry force now", it will force a simulated crash to test reporting to sentry.keyman.com
|
||||
/**
|
||||
* Checks user defaults array for a list of possible regexes to match a client app id
|
||||
*/
|
||||
- (BOOL)isClientAppLegacy:(NSString *)clientAppId fromArray:(NSArray *)legacyApps {
|
||||
for(id legacyApp in legacyApps) {
|
||||
if(![legacyApp isKindOfClass:[NSString class]]) {
|
||||
NSLog(@"isClientAppLegacy:fromArray: LegacyApps user defaults array should contain only strings");
|
||||
} else {
|
||||
NSError *error = nil;
|
||||
NSRange range = NSMakeRange(0, clientAppId.length);
|
||||
|
||||
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern: (NSString *) legacyApp options: 0 error: &error];
|
||||
if([regex matchesInString:clientAppId options:0 range:range]) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
// This is the public initializer.
|
||||
- (instancetype)initWithClient:(NSString *)clientAppId client:(id) sender {
|
||||
self.senderForDeleteBack = sender;
|
||||
|
||||
BOOL legacy = [self isClientAppLegacy:clientAppId];
|
||||
|
||||
// In Xcode, if Keyman is the active IM and is in "debugMode" and "English plus Spanish" is
|
||||
// the current keyboard and you type "Sentry force now", it will force a simulated crash to
|
||||
// test reporting to sentry.keyman.com
|
||||
if ([self.AppDelegate debugMode] && [clientAppId isEqual: @"com.apple.dt.Xcode"]) {
|
||||
NSLog(@"Sentry - Preparing to detect Easter egg.");
|
||||
_easterEggForSentry = [[NSMutableString alloc] init];
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue