From 803a218cbde95f89b9effb8c7ff5c15f92505489 Mon Sep 17 00:00:00 2001 From: sgschantz Date: Tue, 17 Dec 2024 13:52:09 +0700 Subject: [PATCH 1/4] fix(mac): clear the modifier keys when the OSK window is closed --- .../OnScreenKeyboard/OSKWindowController.m | 5 ++++- .../KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.h | 1 + .../KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m | 11 +++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.m b/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.m index ca4181d11c..19b7ece101 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.m @@ -67,8 +67,11 @@ - (void)windowDidResize:(NSNotification *)notification { } - (void)windowWillClose:(NSNotification *)notification { + os_log_debug([KMLogs oskLog], "OSKWindowController windowWillClose"); [KMSettingsRepository.shared writeShowOskOnActivate:NO]; - os_log_debug([KMLogs oskLog], "OSKWindowController windowWillClose, updating settings writeShowOsk to NO"); + + // whenever the OSK is closed clear all of its modifier keys + [self.oskView clearOskModifiers]; } - (void)helpAction:(id)sender { diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.h b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.h index 082604871e..cc582eca71 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.h +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.h @@ -25,6 +25,7 @@ - (void)setOskOptionState:(BOOL)oskAltState; - (void)setPhysicalControlState:(BOOL)ctrlState; - (void)setOskControlState:(BOOL)oskCtrlState; +- (void)clearOskModifiers; - (void)resetOSK; - (void)resizeOSKLayout; - (int64_t)createOskEventUserData; diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m index 4bf0f6a0e8..91adf05eb7 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m @@ -427,6 +427,17 @@ - (NSArray *)oskDefaultNKeys { return _oskDefaultNKeys; } +/** + * called when closing the OSK + * when the OSK is not visible then modifier state is determined solely by the physical keyboard + */ +- (void)clearOskModifiers { + _oskShiftState = NO; + _oskOptionState = NO; + _oskControlState = NO; + [self displayKeyLabelsForLayer]; +} + - (void)resetOSK { [self setOskShiftState:NO]; [self setOskOptionState:NO]; From e77853720f5953af55fd816fe1a6a3622ecd803d Mon Sep 17 00:00:00 2001 From: sgschantz Date: Tue, 17 Dec 2024 15:13:14 +0700 Subject: [PATCH 2/4] fix(mac): also reset the corresponding keys when closing OSK --- .../KME/OnScreenKeyboard/OSKView.m | 63 ++++++++----------- 1 file changed, 26 insertions(+), 37 deletions(-) diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m index 91adf05eb7..19e0dfcc6a 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m @@ -435,6 +435,7 @@ - (void)clearOskModifiers { _oskShiftState = NO; _oskOptionState = NO; _oskControlState = NO; + [self displayModifierKeysState]; [self displayKeyLabelsForLayer]; } @@ -643,16 +644,9 @@ - (void)setPhysicalShiftState:(BOOL)state { */ _oskShiftState = NO; - if (state) { - os_log_debug([KMELogs oskLog], "hardware shift key pressed"); - [self displayKeyLabelsForLayer]; - [self displaysShiftKeysAsPressed:YES]; - } - else { - os_log_debug([KMELogs oskLog], "hardware shift key released"); - [self displayKeyLabelsForLayer]; - [self displaysShiftKeysAsPressed:NO]; - } + os_log_debug([KMELogs oskLog], "hardware shift key released"); + [self displayKeyLabelsForLayer]; + [self displayShiftKeysState]; } } @@ -662,12 +656,12 @@ - (void)setOskShiftState:(BOOL)state { if (state) { os_log_debug([KMELogs oskLog], "OSK shift key selected"); [self displayKeyLabelsForLayer]; - [self displaysShiftKeysAsPressed:YES]; + [self displayShiftKeysState]; } else if (!self.physicalShiftState) { os_log_debug([KMELogs oskLog], "OSK shift key de-selected"); [self displayKeyLabelsForLayer]; - [self displaysShiftKeysAsPressed:NO]; + [self displayShiftKeysState]; } } } @@ -681,15 +675,8 @@ - (void)setPhysicalOptionState:(BOOL)state { * The state of the physical key overrides the modifier key clicked in the OSK. */ _oskOptionState = NO; - - if (state) { - [self displayKeyLabelsForLayer]; - [self displaysOptionKeysAsPressed:YES]; - } - else { - [self displayKeyLabelsForLayer]; - [self displaysOptionKeysAsPressed:NO]; - } + [self displayKeyLabelsForLayer]; + [self displayOptionKeysState]; } } @@ -698,11 +685,11 @@ - (void)setOskOptionState:(BOOL)state { _oskOptionState = state; if (state) { [self displayKeyLabelsForLayer]; - [self displaysOptionKeysAsPressed:YES]; + [self displayOptionKeysState]; } else if (!self.physicalOptionState) { [self displayKeyLabelsForLayer]; - [self displaysOptionKeysAsPressed:NO]; + [self displayOptionKeysState]; } } } @@ -716,15 +703,8 @@ - (void)setPhysicalControlState:(BOOL)state { * The state of the physical key overrides the modifier key clicked in the OSK. */ _oskControlState = NO; - - if (state) { - [self displayKeyLabelsForLayer]; - [self displaysControlKeysAsPressed:YES]; - } - else { - [self displayKeyLabelsForLayer]; - [self displaysControlKeysAsPressed:NO]; - } + [self displayKeyLabelsForLayer]; + [self displayControlKeysState]; } } @@ -733,30 +713,39 @@ - (void)setOskControlState:(BOOL)state { _oskControlState = state; if (state) { [self displayKeyLabelsForLayer]; - [self displaysControlKeysAsPressed:YES]; + [self displayControlKeysState]; } else if (!self.physicalControlState) { [self displayKeyLabelsForLayer]; - [self displaysControlKeysAsPressed:NO]; + [self displayControlKeysState]; } } } -- (void)displaysShiftKeysAsPressed:(BOOL)pressed { +- (void)displayModifierKeysState { + [self displayShiftKeysState]; + [self displayOptionKeysState]; + [self displayControlKeysState]; +} + +- (void)displayShiftKeysState { + BOOL pressed = self.oskShiftState || self.physicalShiftState; KeyView *leftShiftKey = (KeyView *)[self viewWithTag:MVK_LEFT_SHIFT|0x1000]; KeyView *rightShiftKey = (KeyView *)[self viewWithTag:MVK_RIGHT_SHIFT|0x1000]; [leftShiftKey setKeyPressed:pressed]; [rightShiftKey setKeyPressed:pressed]; } -- (void)displaysOptionKeysAsPressed:(BOOL)pressed { +- (void)displayOptionKeysState { + BOOL pressed = self.oskOptionState || self.physicalOptionState; KeyView *leftOptionKey = (KeyView *)[self viewWithTag:MVK_LEFT_ALT|0x1000]; KeyView *rightOptionKey = (KeyView *)[self viewWithTag:MVK_RIGHT_ALT|0x1000]; [leftOptionKey setKeyPressed:pressed]; [rightOptionKey setKeyPressed:pressed]; } -- (void)displaysControlKeysAsPressed:(BOOL)pressed { +- (void)displayControlKeysState { + BOOL pressed = self.oskControlState || self.physicalControlState; KeyView *leftControlKey = (KeyView *)[self viewWithTag:MVK_LEFT_CTRL|0x1000]; KeyView *rightControlKey = (KeyView *)[self viewWithTag:MVK_RIGHT_CTRL|0x1000]; [leftControlKey setKeyPressed:pressed]; From b9b178698681362816e161280ef91d983aadb4c8 Mon Sep 17 00:00:00 2001 From: sgschantz Date: Wed, 18 Dec 2024 16:51:09 +0700 Subject: [PATCH 3/4] fix(mac): renaming and refactoring --- .../OnScreenKeyboard/OSKWindowController.m | 6 ++ .../KME/OnScreenKeyboard/OSKView.m | 91 ++++++++++--------- 2 files changed, 56 insertions(+), 41 deletions(-) diff --git a/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.m b/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.m index 19b7ece101..69c2c9c15f 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.m @@ -74,6 +74,12 @@ - (void)windowWillClose:(NSNotification *)notification { [self.oskView clearOskModifiers]; } +- (void) showWindow:(id) sender { + [super showWindow:sender]; + + os_log_info([KMLogs oskLog], "OSKWindowController showWindow"); +} + - (void)helpAction:(id)sender { NSString *kvkPath = [self AppDelegate].kvk.filePath; if (!kvkPath) diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m index 19e0dfcc6a..901404c85a 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m @@ -140,7 +140,7 @@ - (void)setKvk:(KVKFile *)kvk { _oskLayout = nil; _oskDefaultNKeys = nil; - [self displayKeyLabelsForLayer]; + [self updateKeyLabelsForState]; } - (void)initOSKKeys { @@ -174,7 +174,7 @@ - (void)initOSKKeys { py += keyHeight; } - [self displayKeyLabelsForLayer]; + [self updateKeyLabelsForState]; } - (NSArray *)oskLayout { @@ -435,8 +435,8 @@ - (void)clearOskModifiers { _oskShiftState = NO; _oskOptionState = NO; _oskControlState = NO; - [self displayModifierKeysState]; - [self displayKeyLabelsForLayer]; + [self updateModifierKeysForState]; + [self updateKeyLabelsForState]; } - (void)resetOSK { @@ -536,22 +536,13 @@ - (void)setKeyPressedOff:(KeyView *)keyView { } /** - * Display the key labels that correspond to the current state of the modifier keys. - * The layer shown depends on both the physical modifier state and the osk modifier state. + * get the modifier flags that represent the combined state of the physical and osk modifiers */ -- (void)displayKeyLabelsForLayer { - os_log_debug([KMELogs oskLog], "OSKView displayKeyLabelsForLayer, phsyical modifiers [shift: %d, option: %d, control: %d]\nosk modifiers [shift: %d, option: %d, control: %d]", self.physicalShiftState, self.physicalOptionState, self.physicalControlState, self.oskShiftState, self.oskOptionState, self.oskControlState); - +- (WORD) getCombinedModifierFlags { BOOL shift = self.physicalShiftState | self.oskShiftState; BOOL option = self.physicalOptionState | self.oskOptionState; BOOL control = self.physicalControlState | self.oskControlState; - - [self resetKeyLabels]; - NSMutableArray *mKeys = [[self keyTags] mutableCopy]; - NSArray *nkeys = [self.kvk keys]; - if (nkeys == nil) - nkeys = self.oskDefaultNKeys; - + WORD flags = 0; if (shift) { flags |= KVKS_SHIFT; @@ -567,6 +558,24 @@ - (void)displayKeyLabelsForLayer { flags |= KVKS_RCTRL; } + return flags; +} + +/** + * Display the key labels that correspond to the current state of the modifier keys. + * The layer shown depends on both the physical modifier state and the osk modifier state. + */ +- (void)updateKeyLabelsForState { + os_log_debug([KMELogs oskLog], "OSKView updateKeyLabelsForState, phsyical modifiers [shift: %d, option: %d, control: %d]\nosk modifiers [shift: %d, option: %d, control: %d]", self.physicalShiftState, self.physicalOptionState, self.physicalControlState, self.oskShiftState, self.oskOptionState, self.oskControlState); + + [self resetKeyLabels]; + NSMutableArray *mKeys = [[self keyTags] mutableCopy]; + NSArray *nkeys = [self.kvk keys]; + if (nkeys == nil) + nkeys = self.oskDefaultNKeys; + + WORD flags = [self getCombinedModifierFlags]; + NSString *ansiFont = [self ansiFont]; NSString *unicodeFont = [self unicodeFont]; unsigned short keyCode; @@ -645,8 +654,8 @@ - (void)setPhysicalShiftState:(BOOL)state { _oskShiftState = NO; os_log_debug([KMELogs oskLog], "hardware shift key released"); - [self displayKeyLabelsForLayer]; - [self displayShiftKeysState]; + [self updateKeyLabelsForState]; + [self updateShiftKeysForState]; } } @@ -655,13 +664,13 @@ - (void)setOskShiftState:(BOOL)state { _oskShiftState = state; if (state) { os_log_debug([KMELogs oskLog], "OSK shift key selected"); - [self displayKeyLabelsForLayer]; - [self displayShiftKeysState]; + [self updateKeyLabelsForState]; + [self updateShiftKeysForState]; } else if (!self.physicalShiftState) { os_log_debug([KMELogs oskLog], "OSK shift key de-selected"); - [self displayKeyLabelsForLayer]; - [self displayShiftKeysState]; + [self updateKeyLabelsForState]; + [self updateShiftKeysForState]; } } } @@ -675,8 +684,8 @@ - (void)setPhysicalOptionState:(BOOL)state { * The state of the physical key overrides the modifier key clicked in the OSK. */ _oskOptionState = NO; - [self displayKeyLabelsForLayer]; - [self displayOptionKeysState]; + [self updateKeyLabelsForState]; + [self updateOptionKeysForState]; } } @@ -684,12 +693,12 @@ - (void)setOskOptionState:(BOOL)state { if (_oskOptionState != state && !self.physicalOptionState) { _oskOptionState = state; if (state) { - [self displayKeyLabelsForLayer]; - [self displayOptionKeysState]; + [self updateKeyLabelsForState]; + [self updateOptionKeysForState]; } else if (!self.physicalOptionState) { - [self displayKeyLabelsForLayer]; - [self displayOptionKeysState]; + [self updateKeyLabelsForState]; + [self updateOptionKeysForState]; } } } @@ -703,8 +712,8 @@ - (void)setPhysicalControlState:(BOOL)state { * The state of the physical key overrides the modifier key clicked in the OSK. */ _oskControlState = NO; - [self displayKeyLabelsForLayer]; - [self displayControlKeysState]; + [self updateKeyLabelsForState]; + [self updateControlKeysForState]; } } @@ -712,23 +721,23 @@ - (void)setOskControlState:(BOOL)state { if (_oskControlState != state && !self.physicalControlState) { _oskControlState = state; if (state) { - [self displayKeyLabelsForLayer]; - [self displayControlKeysState]; + [self updateKeyLabelsForState]; + [self updateControlKeysForState]; } else if (!self.physicalControlState) { - [self displayKeyLabelsForLayer]; - [self displayControlKeysState]; + [self updateKeyLabelsForState]; + [self updateControlKeysForState]; } } } -- (void)displayModifierKeysState { - [self displayShiftKeysState]; - [self displayOptionKeysState]; - [self displayControlKeysState]; +- (void)updateModifierKeysForState { + [self updateShiftKeysForState]; + [self updateOptionKeysForState]; + [self updateControlKeysForState]; } -- (void)displayShiftKeysState { +- (void)updateShiftKeysForState { BOOL pressed = self.oskShiftState || self.physicalShiftState; KeyView *leftShiftKey = (KeyView *)[self viewWithTag:MVK_LEFT_SHIFT|0x1000]; KeyView *rightShiftKey = (KeyView *)[self viewWithTag:MVK_RIGHT_SHIFT|0x1000]; @@ -736,7 +745,7 @@ - (void)displayShiftKeysState { [rightShiftKey setKeyPressed:pressed]; } -- (void)displayOptionKeysState { +- (void)updateOptionKeysForState{ BOOL pressed = self.oskOptionState || self.physicalOptionState; KeyView *leftOptionKey = (KeyView *)[self viewWithTag:MVK_LEFT_ALT|0x1000]; KeyView *rightOptionKey = (KeyView *)[self viewWithTag:MVK_RIGHT_ALT|0x1000]; @@ -744,7 +753,7 @@ - (void)displayOptionKeysState { [rightOptionKey setKeyPressed:pressed]; } -- (void)displayControlKeysState { +- (void)updateControlKeysForState { BOOL pressed = self.oskControlState || self.physicalControlState; KeyView *leftControlKey = (KeyView *)[self viewWithTag:MVK_LEFT_CTRL|0x1000]; KeyView *rightControlKey = (KeyView *)[self viewWithTag:MVK_RIGHT_CTRL|0x1000]; From 31280ecee7c216d8c0a0696f9630ad803c170f84 Mon Sep 17 00:00:00 2001 From: sgschantz Date: Thu, 19 Dec 2024 15:52:19 +0700 Subject: [PATCH 4/4] fix(mac): apply OSK modifiers to typing on physical keyboard Fixes: #12584 --- .../Keyman4MacIM/KMInputMethodAppDelegate.m | 22 +++- .../OnScreenKeyboard/OSKWindowController.h | 2 + .../OnScreenKeyboard/OSKWindowController.m | 22 +++- .../KME/OnScreenKeyboard/OSKView.h | 1 + .../KME/OnScreenKeyboard/OSKView.m | 123 ++++++++++-------- 5 files changed, 108 insertions(+), 62 deletions(-) diff --git a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m index aa2e914371..b938279197 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/KMInputMethodAppDelegate.m @@ -944,6 +944,7 @@ - (void)registerConfigurationWindow:(NSWindowController *)window { } - (void)showOSK { + [self.oskWindow prepareToShowOsk]; [[self.oskWindow window] makeKeyAndOrderFront:nil]; [[self.oskWindow window] setLevel:NSStatusWindowLevel]; [[self.oskWindow window] setTitle:self.oskWindowTitle]; @@ -1242,13 +1243,32 @@ - (NSEventModifierFlags) determineModifiers { NSEventModifierFlags modifierFlags = 0; if (self.receivedKeyDownFromOsk) { + /** + * the event was generated from the OSK, so use the oskEventModifiers in effect at time of event generation + */ modifierFlags = self.oskEventModifiers; os_log_debug([KMLogs eventsLog], "--- use modifiers from OSK, oskEventModifiers: 0x%lX", (unsigned long)modifierFlags); self.oskEventModifiers = 0; - } else { + } else { + /** + * the event originated from the physical keyboard, use the modifiers on kCGEventFlagsChanged events + */ NSEventModifierFlags originalModifiers = self.currentModifiers; modifierFlags = [self.modifierMapping adjustModifiers:originalModifiers]; os_log_debug([KMLogs eventsLog], "--- use adjusted modifiers from current state: 0x%lX", (unsigned long)modifierFlags); + + /** + * If the OSK is open, then we also need to apply its modifiers, if any, to this event originating from the physical keyboard. + * If the OSK is closed, its modifiers will be zero. + */ + NSEventModifierFlags oskModifiers = [self.oskWindow getOskEventModifierFlags]; + if (oskModifiers != 0) { + os_log_debug([KMLogs eventsLog], "--- modifiers from OSK to apply to physical keyboard event: 0x%lX", (unsigned long)oskModifiers); + + // combine osk modifiers with adjusted modifiers + modifierFlags = oskModifiers | modifierFlags; + os_log_debug([KMLogs eventsLog], "--- combined modifiers to apply to physical keyboard event: 0x%lX", (unsigned long)modifierFlags); + } } return modifierFlags; diff --git a/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.h b/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.h index fd3a953a85..ecb2f2566e 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.h +++ b/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.h @@ -13,6 +13,8 @@ @property (nonatomic, weak) IBOutlet OSKView *oskView; +- (void)prepareToShowOsk; - (void)resetOSK; +- (NSEventModifierFlags)getOskEventModifierFlags; @end diff --git a/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.m b/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.m index 69c2c9c15f..b3824fa897 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/OnScreenKeyboard/OSKWindowController.m @@ -66,20 +66,18 @@ - (void)windowDidResize:(NSNotification *)notification { [self.oskView resizeOSKLayout]; } +- (void)prepareToShowOsk { + os_log_info([KMLogs oskLog], "OSKWindowController prepareToShowOsk"); +} + - (void)windowWillClose:(NSNotification *)notification { os_log_debug([KMLogs oskLog], "OSKWindowController windowWillClose"); [KMSettingsRepository.shared writeShowOskOnActivate:NO]; - // whenever the OSK is closed clear all of its modifier keys + // whenever the OSK is closing clear all of its modifier keys [self.oskView clearOskModifiers]; } -- (void) showWindow:(id) sender { - [super showWindow:sender]; - - os_log_info([KMLogs oskLog], "OSKWindowController showWindow"); -} - - (void)helpAction:(id)sender { NSString *kvkPath = [self AppDelegate].kvk.filePath; if (!kvkPath) @@ -106,6 +104,16 @@ - (void)resetOSK { } } +/** + * returns current event flags representing the state of the modifiers on the OSK or zero if OSK is closed + */ +- (NSEventModifierFlags)getOskEventModifierFlags { + if (self.window.isVisible) { + return [self.oskView getOskEventModifierFlags]; + } else { + return 0; + } +} - (void)startTimerWithTimeInterval:(NSTimeInterval)interval { if (_modFlagsTimer == nil) { TimerTarget *timerTarget = [[TimerTarget alloc] init]; diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.h b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.h index cc582eca71..19c3263baa 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.h +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.h @@ -26,6 +26,7 @@ - (void)setPhysicalControlState:(BOOL)ctrlState; - (void)setOskControlState:(BOOL)oskCtrlState; - (void)clearOskModifiers; +- (NSEventModifierFlags)getOskEventModifierFlags; - (void)resetOSK; - (void)resizeOSKLayout; - (int64_t)createOskEventUserData; diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m index 901404c85a..e98fe60663 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/OnScreenKeyboard/OSKView.m @@ -140,7 +140,7 @@ - (void)setKvk:(KVKFile *)kvk { _oskLayout = nil; _oskDefaultNKeys = nil; - [self updateKeyLabelsForState]; + [self updateKeyLabelsForCurrentLayer]; } - (void)initOSKKeys { @@ -174,7 +174,7 @@ - (void)initOSKKeys { py += keyHeight; } - [self updateKeyLabelsForState]; + [self updateKeyLabelsForCurrentLayer]; } - (NSArray *)oskLayout { @@ -436,7 +436,7 @@ - (void)clearOskModifiers { _oskOptionState = NO; _oskControlState = NO; [self updateModifierKeysForState]; - [self updateKeyLabelsForState]; + [self updateKeyLabelsForCurrentLayer]; } - (void)resetOSK { @@ -487,6 +487,47 @@ - (void)keyAction:(id)sender { } } +/** + * get the event modifier flags representing the current state of the osk modifiers + */ +- (NSEventModifierFlags)getOskEventModifierFlags { + return [self getEventModifierFlags:self.oskShiftState optionFlag:self.oskOptionState controlFlag:self.oskControlState]; +} + +/** + * get the event modifier flags that represent the combined state of the physical and osk modifiers + */ +- (NSEventModifierFlags) getCombinedEventModifierFlags { + BOOL shift = self.physicalShiftState | self.oskShiftState; + BOOL option = self.physicalOptionState | self.oskOptionState; + BOOL control = self.physicalControlState | self.oskControlState; + + return [self getEventModifierFlags:shift optionFlag:option controlFlag:control]; +} + +/** + * get the NSEventModifierFlags value that corresponds to the specified modifier states + */ +- (NSEventModifierFlags)getEventModifierFlags:(BOOL)shift optionFlag:(BOOL)option controlFlag:(BOOL)control { + NSEventModifierFlags modifierFlags = 0; + + if (shift) { + modifierFlags = modifierFlags | NSEventModifierFlagShift; + } + /** + * Both left and right option keys on the OSK cause oskOptionState to be true without distinction of left or right. + * However, the generated event is a right alt so that it will trigger the right alt rules in the Keyman keyboard. + */ + if (option) { + modifierFlags = modifierFlags | MK_RIGHT_ALT_MASK; + } + if (control) { + modifierFlags = modifierFlags | NSEventModifierFlagControl; + } + + return modifierFlags; +} + /** * Create the 64-bit value to pass in the kCGEventSourceUserData field of the generated CGEvent * The upper-most bit is set to distinguish it from the default value of zero, and the lower 32 bits @@ -500,22 +541,9 @@ - (void)keyAction:(id)sender { - (int64_t) createOskEventUserData { // set bit to identify this user data as originating from the OSK int64_t oskEventData = OSK_EVENT_FLAG; - - if (self.oskShiftState || self.physicalShiftState) { - oskEventData = oskEventData | kCGEventFlagMaskShift; - } - /** - * Both left and right option keys on the OSK cause oskOptionState to be true without distinction of left or right. - * However, the generated event is a right alt so that it will trigger the right alt rules in the Keyman keyboard. - */ - if (self.oskOptionState || self.physicalOptionState) { - oskEventData = oskEventData | MK_RIGHT_ALT_MASK; - } - if (self.oskControlState || self.oskControlState) { - oskEventData = oskEventData | kCGEventFlagMaskControl; - } - - return oskEventData; + NSEventModifierFlags eventModifierFlags = [self getCombinedEventModifierFlags]; + + return oskEventData | eventModifierFlags; } - (void)handleKeyEvent:(NSEvent *)event { @@ -536,13 +564,20 @@ - (void)setKeyPressedOff:(KeyView *)keyView { } /** - * get the modifier flags that represent the combined state of the physical and osk modifiers + * get the Keyman modifier flags that represent the combined state of the physical and osk modifiers */ -- (WORD) getCombinedModifierFlags { +- (WORD) getKeymanModifierFlagsForCurrentLayer { BOOL shift = self.physicalShiftState | self.oskShiftState; BOOL option = self.physicalOptionState | self.oskOptionState; BOOL control = self.physicalControlState | self.oskControlState; - + + return [self getKeymanModifierFlags:shift optionFlag:option controlFlag:control]; +} + +/** + * get Keyman modifier flags for the specified modifier states + */ +- (WORD)getKeymanModifierFlags:(BOOL)shift optionFlag:(BOOL)option controlFlag:(BOOL)control { WORD flags = 0; if (shift) { flags |= KVKS_SHIFT; @@ -565,7 +600,7 @@ - (WORD) getCombinedModifierFlags { * Display the key labels that correspond to the current state of the modifier keys. * The layer shown depends on both the physical modifier state and the osk modifier state. */ -- (void)updateKeyLabelsForState { +- (void)updateKeyLabelsForCurrentLayer { os_log_debug([KMELogs oskLog], "OSKView updateKeyLabelsForState, phsyical modifiers [shift: %d, option: %d, control: %d]\nosk modifiers [shift: %d, option: %d, control: %d]", self.physicalShiftState, self.physicalOptionState, self.physicalControlState, self.oskShiftState, self.oskOptionState, self.oskControlState); [self resetKeyLabels]; @@ -574,13 +609,13 @@ - (void)updateKeyLabelsForState { if (nkeys == nil) nkeys = self.oskDefaultNKeys; - WORD flags = [self getCombinedModifierFlags]; + WORD keymanFlagsForCurrentLayer = [self getKeymanModifierFlagsForCurrentLayer]; NSString *ansiFont = [self ansiFont]; NSString *unicodeFont = [self unicodeFont]; unsigned short keyCode; for (NKey *nkey in nkeys) { - if (nkey.modifierFlags == flags) { + if (nkey.modifierFlags == keymanFlagsForCurrentLayer) { keyCode = [self MacKeyCode:nkey.keyCode]; os_log_debug([KMELogs keyLog], "keyCode: %d, %x for key: %{public}@", keyCode, keyCode, nkey); if (keyCode < USHRT_MAX) { @@ -654,7 +689,7 @@ - (void)setPhysicalShiftState:(BOOL)state { _oskShiftState = NO; os_log_debug([KMELogs oskLog], "hardware shift key released"); - [self updateKeyLabelsForState]; + [self updateKeyLabelsForCurrentLayer]; [self updateShiftKeysForState]; } } @@ -662,16 +697,8 @@ - (void)setPhysicalShiftState:(BOOL)state { - (void)setOskShiftState:(BOOL)state { if (_oskShiftState != state && !self.physicalShiftState) { _oskShiftState = state; - if (state) { - os_log_debug([KMELogs oskLog], "OSK shift key selected"); - [self updateKeyLabelsForState]; - [self updateShiftKeysForState]; - } - else if (!self.physicalShiftState) { - os_log_debug([KMELogs oskLog], "OSK shift key de-selected"); - [self updateKeyLabelsForState]; - [self updateShiftKeysForState]; - } + [self updateKeyLabelsForCurrentLayer]; + [self updateShiftKeysForState]; } } @@ -684,7 +711,7 @@ - (void)setPhysicalOptionState:(BOOL)state { * The state of the physical key overrides the modifier key clicked in the OSK. */ _oskOptionState = NO; - [self updateKeyLabelsForState]; + [self updateKeyLabelsForCurrentLayer]; [self updateOptionKeysForState]; } } @@ -692,14 +719,8 @@ - (void)setPhysicalOptionState:(BOOL)state { - (void)setOskOptionState:(BOOL)state { if (_oskOptionState != state && !self.physicalOptionState) { _oskOptionState = state; - if (state) { - [self updateKeyLabelsForState]; - [self updateOptionKeysForState]; - } - else if (!self.physicalOptionState) { - [self updateKeyLabelsForState]; - [self updateOptionKeysForState]; - } + [self updateKeyLabelsForCurrentLayer]; + [self updateOptionKeysForState]; } } @@ -712,7 +733,7 @@ - (void)setPhysicalControlState:(BOOL)state { * The state of the physical key overrides the modifier key clicked in the OSK. */ _oskControlState = NO; - [self updateKeyLabelsForState]; + [self updateKeyLabelsForCurrentLayer]; [self updateControlKeysForState]; } } @@ -720,14 +741,8 @@ - (void)setPhysicalControlState:(BOOL)state { - (void)setOskControlState:(BOOL)state { if (_oskControlState != state && !self.physicalControlState) { _oskControlState = state; - if (state) { - [self updateKeyLabelsForState]; - [self updateControlKeysForState]; - } - else if (!self.physicalControlState) { - [self updateKeyLabelsForState]; - [self updateControlKeysForState]; - } + [self updateKeyLabelsForCurrentLayer]; + [self updateControlKeysForState]; } }