Merge pull request #1863 from keymanapp/mac-cherrypick-1838-1839-1840-fixes-stable-11.0

[mac] [cherry-pick] [11.0] Merge fixes for #1838, #1839, #1840 into 11.0
This commit is contained in:
Marc Durdin 2019-07-19 10:32:55 +10:00 committed by GitHub
commit eae49ed211
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 158 additions and 10 deletions

View file

@ -41,7 +41,7 @@ NSMutableArray *servers;
}
- (NSUInteger)recognizedEvents:(id)sender {
return (NSEventMaskKeyDown);
return NSEventMaskKeyDown | NSEventMaskFlagsChanged;
}
- (BOOL)handleEvent:(NSEvent *)event client:(id)sender {
@ -223,6 +223,7 @@ NSMutableArray *servers;
[self.AppDelegate setKeyboardIcon:[kmxInfo objectForKey:kKMKeyboardIconKey]];
[self.AppDelegate setContextBuffer:nil];
[self.AppDelegate setSelectedKeyboard:path];
[self.AppDelegate loadSavedStores];
if (kvk != nil && self.AppDelegate.alwaysShowOSK)
[self.AppDelegate showOSK];
}

View file

@ -89,6 +89,8 @@ extern NSString *const kWebSite;
- (NSMenu *)menu;
- (void)saveActiveKeyboards;
- (void)loadSavedStores;
- (void)saveStore:(NSNumber *)storeKey withValue:(NSString* )value;
- (void)showAboutWindow;
- (void)showOSK;
- (void)showConfigurationWindow;

View file

@ -24,6 +24,7 @@
NSString *const kKMSelectedKeyboardKey = @"KMSelectedKeyboardKey";
NSString *const kKMActiveKeyboardsKey = @"KMActiveKeyboardsKey";
NSString *const kKMSavedStoresKey = @"KMSavedStoresKey";
NSString *const kKMAlwaysShowOSKKey = @"KMAlwaysShowOSKKey";
NSString *const kKMUseVerboseLogging = @"KMUseVerboseLogging";
NSString *const kKeymanKeyboardDownloadCompletedNotification = @"kKeymanKeyboardDownloadCompletedNotification";
@ -81,7 +82,7 @@ id _lastServerWithOSKShowing = nil;
forEventClass:kInternetEventClass
andEventID:kAEGetURL];
self.lowLevelEventTap = CGEventTapCreate(kCGAnnotatedSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionListenOnly, NSFlagsChangedMask | NSLeftMouseDown | NSLeftMouseUp, (CGEventTapCallBack)eventTapFunction, nil);
self.lowLevelEventTap = CGEventTapCreate(kCGAnnotatedSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionListenOnly, CGEventMaskBit(kCGEventFlagsChanged) | CGEventMaskBit(kCGEventLeftMouseDown) | CGEventMaskBit(kCGEventLeftMouseUp), (CGEventTapCallBack)eventTapFunction, nil);
if (!self.lowLevelEventTap) {
NSLog(@"Can't tap into low level events!");
@ -308,6 +309,53 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
[_oskWindow.window setTitle:self.oskWindowTitle];
}
- (void)loadSavedStores {
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
NSDictionary *allSavedStores = [userData dictionaryForKey:kKMSavedStoresKey];
if (!allSavedStores) return;
NSDictionary *savedStores = [allSavedStores objectForKey:_selectedKeyboard];
if (!savedStores) return;
NSNumberFormatter *fmt = [[NSNumberFormatter alloc] init];
fmt.numberStyle = NSNumberFormatterDecimalStyle;
for (NSString *key in savedStores) {
NSString *value = [savedStores objectForKey:key];
NSUInteger storeID = [[fmt numberFromString:key] unsignedIntegerValue];
[self.kme setStore:(DWORD)storeID withValue:value];
}
}
- (void)saveStore:(NSNumber *)storeKey withValue:(NSString* )value {
NSString *storeKeyStr = [storeKey stringValue];
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
NSDictionary *allSavedStores = [userData dictionaryForKey:kKMSavedStoresKey];
NSDictionary *savedStores;
if (allSavedStores) {
savedStores = [allSavedStores objectForKey:_selectedKeyboard];
}
if (savedStores) {
NSMutableDictionary *newSavedStores = [savedStores mutableCopy];
[newSavedStores setObject:value forKey:storeKeyStr];
savedStores = newSavedStores;
} else {
savedStores = [[NSDictionary alloc] initWithObjectsAndKeys:value, storeKeyStr, nil];
}
if (allSavedStores) {
NSMutableDictionary *newAllSavedStores = [allSavedStores mutableCopy];
[newAllSavedStores setObject:savedStores forKey:_selectedKeyboard];
allSavedStores = newAllSavedStores;
} else {
allSavedStores = [[NSDictionary alloc] initWithObjectsAndKeys:savedStores, _selectedKeyboard, nil];
}
[userData setObject:allSavedStores forKey:kKMSavedStoresKey];
[userData synchronize];
}
- (NSString *)oskWindowTitle {
if (_keyboardName == nil || !_keyboardName.length)
return [NSString stringWithFormat:@"Keyman"];
@ -765,6 +813,7 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
[self setKvk:kvk];
[self setKeyboardName:[kmxInfo objectForKey:kKMKeyboardNameKey]];
[self setKeyboardIcon:[kmxInfo objectForKey:kKMKeyboardIconKey]];
[self loadSavedStores];
didSetKeyboard = YES;
}
@ -800,6 +849,7 @@ CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef
[self setKeyboardName:[kmxInfo objectForKey:kKMKeyboardNameKey]];
[self setKeyboardIcon:[kmxInfo objectForKey:kKMKeyboardIconKey]];
[self setContextBuffer:nil];
[self loadSavedStores];
[self setSelectedKeyboard:path];
}
}

View file

@ -425,6 +425,12 @@ NSRange _previousSelRange;
else if ([actionType isEqualToString:Q_BEEP]) {
[[NSSound soundNamed:@"Tink"] play];
}
else if ([actionType isEqualToString:Q_SAVEOPT]) {
NSDictionary *save = [action objectForKey:actionType];
NSNumber *storeKey = [save allKeys][0];
NSString *value = [save objectForKey:storeKey];
[self.AppDelegate saveStore:storeKey withValue:value];
}
}
return YES;
}
@ -489,6 +495,11 @@ NSRange _previousSelRange;
/*if (event.type == NSKeyDown)
[self.AppDelegate handleKeyEvent:event];*/
if (event.type == NSFlagsChanged) {
_contextOutOfDate = YES;
return NO;
}
if ((event.modifierFlags & NSEventModifierFlagCommand) == NSEventModifierFlagCommand) {
[self handleCommand:event];
return NO; // We let the client app handle all Command-key events.

View file

@ -36,6 +36,9 @@
[self removeLastObject];
[self addObject:mAction];
}
else {
[self addObject:newAction];
}
}
else if ([preActionType isEqualToString:Q_STR] && [newActionType isEqualToString:Q_BACK]) {
NSString *preStr = [preAction objectForKey:preActionType];

View file

@ -356,7 +356,7 @@
@implementation NSMutableString (XString)
- (void)appendDeadkey:(NSUInteger)index {
NSString *dk = [NSString stringWithFormat:@"%C%C%lu", UC_SENTINEL, CODE_DEADKEY, index];
NSString *dk = [NSString stringWithFormat:@"%C%C%C", UC_SENTINEL, CODE_DEADKEY, index];
[self appendString:dk];
}

View file

@ -20,6 +20,7 @@
@property (strong, nonatomic) NSString *string;
- (void)setDwSystemID:(DWORD)dwID;
- (id)copyWithZone:(NSZone *)zone;
@end

View file

@ -21,6 +21,18 @@
return self;
}
- (id)copyWithZone:(NSZone *)zone {
KMCompStore *newStore = [[[self class] allocWithZone:zone] init];
if (newStore) {
[newStore setDwSystemID:[self dwSystemID]];
if ([self name]) newStore.name = [[NSString alloc] initWithString:[self name]];
if ([self string]) newStore.string = [[NSString alloc] initWithString:[self string]];
}
return newStore;
}
- (NSString *)description {
NSString *format = @"<%@:%p ID:0x%X DN:%@ N:%@ S:%@>";
NSString *str = [NSString stringWithFormat:format,

View file

@ -20,6 +20,7 @@ extern NSString *const Q_DEADKEY;
extern NSString *const Q_NUL;
extern NSString *const Q_BEEP;
extern NSString *const Q_RETURN;
extern NSString *const Q_SAVEOPT;
extern DWORD VKMap[0x80];
@ -31,6 +32,7 @@ extern DWORD VKMap[0x80];
- (id)initWithKMX:(KMXFile *)kmx contextBuffer:(NSString *)ctxBuf;
- (void)setContextBuffer:(NSString *)ctxBuf;
- (NSString *)contextBuffer;
- (void)setStore:(DWORD)storeID withValue:(NSString *)value;
- (NSArray *)processEvent:(NSEvent *)event;
- (void)setUseVerboseLogging:(BOOL)useVerboseLogging;

View file

@ -23,6 +23,7 @@ NSString *const Q_DEADKEY = @"Q_DEADKEY";
NSString *const Q_NUL = @"Q_NUL";
NSString *const Q_BEEP = @"Q_BEEP";
NSString *const Q_RETURN = @"Q_RETURN";
NSString *const Q_SAVEOPT = @"Q_SAVEOPT";
DWORD VKMap[0x80];
@ -103,6 +104,13 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx";
return _tmpCtxBuf;
}
- (void)setStore:(DWORD)storeID withValue:(NSString *)value {
KMCompStore *store = [self.kmx.store objectAtIndex:storeID];
KMCompStore *storeSaved = [self.kmx.storeSaved objectAtIndex:storeID];
store.string = [[NSString alloc] initWithString:value];
storeSaved.string = [[NSString alloc] initWithString:value];
}
- (NSArray *)processEvent:(NSEvent *)event {
NSArray *actions = nil;
@ -408,6 +416,8 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx";
if (!outKey || !outKey.length)
return nil;
BOOL handledWithoutActions = NO;
for (int i = 0; i < outKey.length;) {
unichar c = [outKey characterAtIndex:i];
if (c == UC_SENTINEL) {
@ -517,6 +527,42 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx";
i+=2;
break;
}
case CODE_SETOPT: {
DWORD x1 = [outKey characterAtIndex:i+2]-1;
DWORD x2 = [outKey characterAtIndex:i+3]-1;
KMCompStore *store1 = [self.kmx.store objectAtIndex:x1];
KMCompStore *store2 = [self.kmx.store objectAtIndex:x2];
store1.string = [[NSString alloc] initWithString:store2.string];
handledWithoutActions = YES;
i+=4;
break;
}
case CODE_RESETOPT: {
DWORD x1 = [outKey characterAtIndex:i+2]-1;
KMCompStore *store = [self.kmx.store objectAtIndex:x1];
KMCompStore *storeSaved = [self.kmx.storeSaved objectAtIndex:x1];
store.string = [[NSString alloc] initWithString:storeSaved.string];
handledWithoutActions = YES;
i+=3;
break;
}
case CODE_SAVEOPT: {
DWORD x1 = [outKey characterAtIndex:i+2]-1;
KMCompStore *store = [self.kmx.store objectAtIndex:x1];
KMCompStore *storeSaved = [self.kmx.storeSaved objectAtIndex:x1];
storeSaved.string = [[NSString alloc] initWithString:store.string];
NSDictionary *actionObj = [[NSDictionary alloc] initWithObjectsAndKeys:[[NSString alloc] initWithString:store.string], [NSNumber numberWithUnsignedInteger:x1], nil];
NSDictionary *action = [[NSDictionary alloc] initWithObjectsAndKeys:actionObj, Q_SAVEOPT, nil];
if (!actions)
actions = [[NSMutableArray alloc] initWithObjects:action, nil];
else
[actions addAction:action];
i+=3;
break;
}
default:
i+=2;
break;
@ -538,6 +584,11 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx";
NSLog(@"tmpCtxBuf = \"%@\"", [self.tmpCtxBuf codeString]);
}
if (!actions && handledWithoutActions) {
NSDictionary *action = [[NSDictionary alloc] initWithObjectsAndKeys:@"", Q_NUL, nil];
actions = [[NSMutableArray alloc] initWithObjects:action, nil];
}
return actions;
}
@ -770,7 +821,7 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx";
DWORD index = [keyCtx characterAtIndex:i+2];
if ([ctx characterAtIndex:px] == UC_SENTINEL && [ctx characterAtIndex:px+1] == CODE_DEADKEY) {
px+=2;
c = [[NSString stringWithFormat:@"%d", index] characterAtIndex:0];
c = [[NSString stringWithFormat:@"%C", index] characterAtIndex:0];
unichar c2 = [ctx characterAtIndex:px];
if (c != c2)
return 0;
@ -784,13 +835,21 @@ const NSString* kEasterEggKmxName = @"EnglishSpanish.kmx";
break;
}
case CODE_IFOPT: {
//DWORD x1 = [keyCtx characterAtIndex:i+2]-1;
//DWORD x2 = [keyCtx characterAtIndex:i+3]-1;
//DWORD x3 = [keyCtx characterAtIndex:i+4]-1;
//KMCompStore *store = [self.kmx.store objectAtIndex:x3];
//i+=5;
DWORD x1 = [keyCtx characterAtIndex:i+2]-1;
DWORD x2 = [keyCtx characterAtIndex:i+3]-1;
DWORD x3 = [keyCtx characterAtIndex:i+4]-1;
KMCompStore *store1 = [self.kmx.store objectAtIndex:x1];
KMCompStore *store2 = [self.kmx.store objectAtIndex:x3];
BOOL match = [store1.string isEqualToString:store2.string];
if ((match && x2 == EQUAL) || (!match && x2 == NOT_EQUAL)) {
cx+=1000;
}
else {
return 0;
}
return 0; // CODE_IFOPT is not supported
i+=5;
break;
}
case CODE_IFSYSTEMSTORE: {

View file

@ -29,6 +29,7 @@ extern NSString *const kKMVisualKeyboardKey;
@property (assign, nonatomic, readonly) BOOL isMnemonic;
@property (assign, nonatomic, readonly) DWORD version;
@property (strong, nonatomic, readonly) NSArray *store;
@property (strong, nonatomic, readonly) NSArray *storeSaved;
@property (strong, nonatomic, readonly) NSArray *group;
@property (strong, nonatomic, readonly) NSArray *startGroup;
@property (assign, nonatomic, readonly) DWORD flags;

View file

@ -95,6 +95,7 @@ NSString *const kKMVisualKeyboardKey = @"KMVisualKeyboardKey";
}
_store = [[NSArray alloc] initWithArray:mStore];
_storeSaved = [[NSArray alloc] initWithArray:mStore copyItems:YES];
struct COMP_GROUP cmp_grp[cmp_kb.cxGroupArray];
[file seekToFileOffset:cmp_kb.dpGroupArray];

View file

@ -1,5 +1,10 @@
# Keyman for macOS Version History
## 2019-02-26 11.0.221 stable
* Add support for option stores (if/set/reset/save statements) (#1838)
* Fix bug where keyboards with more than nine deadkeys did not operate correctly (#1839)
* Fix out of date context buffer when using command keys (#1840)
## 2019-02-25 11.0.220 stable
* 11.0 Stable release