mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-05 00:15:32 +00:00
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:
commit
eae49ed211
13 changed files with 158 additions and 10 deletions
|
|
@ -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];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
@property (strong, nonatomic) NSString *string;
|
||||
|
||||
- (void)setDwSystemID:(DWORD)dwID;
|
||||
- (id)copyWithZone:(NSZone *)zone;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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: {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue