From 5e506cf1aa4075129e03c79a245b43e36683afc5 Mon Sep 17 00:00:00 2001 From: jahorton Date: Fri, 9 Jul 2021 15:24:11 +0700 Subject: [PATCH 1/7] fix(common/core/web): state-key toggle as part of key event --- .../src/keyboards/activeLayout.ts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/common/core/web/keyboard-processor/src/keyboards/activeLayout.ts b/common/core/web/keyboard-processor/src/keyboards/activeLayout.ts index ae8d65cafb1..0765c9a1309 100644 --- a/common/core/web/keyboard-processor/src/keyboards/activeLayout.ts +++ b/common/core/web/keyboard-processor/src/keyboards/activeLayout.ts @@ -217,6 +217,26 @@ namespace com.keyman.keyboards { // This part depends on the keyboard processor's active state. if(keyboardProcessor) { keyboardProcessor.setSyntheticEventDefaults(Lkc); + + // If it's a state key modifier, trigger its effects as part of the + // keystroke. + let bitmask = 0; + switch(Lkc.kName) { + case 'K_CAPS': + bitmask = text.Codes.stateBitmasks.CAPS; + break; + case 'K_NUMLOCK': + bitmask = text.Codes.stateBitmasks.NUM_LOCK; + break; + case 'K_SCROLL': + bitmask = text.Codes.stateBitmasks.SCROLL_LOCK; + break; + } + + if(bitmask) { + Lkc.Lstates ^= bitmask; + Lkc.LmodifierChange = true; + } } return Lkc; From 8b9066e109ecd46d1e669de05e88de1a10a88f11 Mon Sep 17 00:00:00 2001 From: jahorton Date: Mon, 12 Jul 2021 05:27:44 +0700 Subject: [PATCH 2/7] fix(web): uninitialized layer index before OSK load --- web/source/osk/visualKeyboard.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/source/osk/visualKeyboard.ts b/web/source/osk/visualKeyboard.ts index 03d4e525dd6..f1e0840a006 100644 --- a/web/source/osk/visualKeyboard.ts +++ b/web/source/osk/visualKeyboard.ts @@ -602,7 +602,7 @@ namespace com.keyman.osk { layers: keyboards.LayoutLayer[]; private layerId: string = "default"; readonly isRTL: boolean; - layerIndex: number; + layerIndex: number = 0; // the index of the default layer device: Device; isStatic: boolean = false; From 9933b76ea3ca88dc0894772223d5e81d097c2cf0 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Mon, 12 Jul 2021 05:29:37 +0700 Subject: [PATCH 3/7] chore(web): applies PR suggestion Co-authored-by: Marc Durdin --- .../src/keyboards/activeLayout.ts | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/common/core/web/keyboard-processor/src/keyboards/activeLayout.ts b/common/core/web/keyboard-processor/src/keyboards/activeLayout.ts index 0765c9a1309..3f5e804139a 100644 --- a/common/core/web/keyboard-processor/src/keyboards/activeLayout.ts +++ b/common/core/web/keyboard-processor/src/keyboards/activeLayout.ts @@ -220,18 +220,12 @@ namespace com.keyman.keyboards { // If it's a state key modifier, trigger its effects as part of the // keystroke. - let bitmask = 0; - switch(Lkc.kName) { - case 'K_CAPS': - bitmask = text.Codes.stateBitmasks.CAPS; - break; - case 'K_NUMLOCK': - bitmask = text.Codes.stateBitmasks.NUM_LOCK; - break; - case 'K_SCROLL': - bitmask = text.Codes.stateBitmasks.SCROLL_LOCK; - break; - } + const bitmap = { + 'K_CAPS': text.Codes.stateBitmasks.CAPS, + 'K_NUMLOCK': text.Codes.stateBitmasks.NUM_LOCK, + 'K_SCROLL': text.Codes.stateBitmasks.SCROLL_LOCK + }; + const bitmask = bitmap[Lkc.kName]; if(bitmask) { Lkc.Lstates ^= bitmask; @@ -690,4 +684,4 @@ namespace com.keyman.keyboards { return aLayout; } } -} \ No newline at end of file +} From 018016907defe00bf2e9531e75a77c33fb370ed3 Mon Sep 17 00:00:00 2001 From: jahorton Date: Mon, 12 Jul 2021 05:32:13 +0700 Subject: [PATCH 4/7] chore(web): another PR suggestion --- .../web/input-processor/src/text/inputProcessor.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/common/core/web/input-processor/src/text/inputProcessor.ts b/common/core/web/input-processor/src/text/inputProcessor.ts index 314d1e8c5ef..e2607cfd7dc 100644 --- a/common/core/web/input-processor/src/text/inputProcessor.ts +++ b/common/core/web/input-processor/src/text/inputProcessor.ts @@ -78,9 +78,13 @@ namespace com.keyman.text { } // Will handle keystroke-based non-layer change modifier & state keys, mapping them through the physical keyboard's version - // of state management. - if(!fromOSK && this.keyboardProcessor.doModifierPress(keyEvent, !fromOSK)) { - return new RuleBehavior(); + // of state management. `doModifierPress` must always run. + if(this.keyboardProcessor.doModifierPress(keyEvent, !fromOSK)) { + // If run on a desktop platform, we know that modifier & state key presses may not + // produce output, so we may make an immediate return safely. + if(!fromOSK) { + return new RuleBehavior(); + } } // If suggestions exist AND space is pressed, accept the suggestion and do not process the keystroke. From 71f0b2c300ed3c8d6b9cf16428ed5815c812b556 Mon Sep 17 00:00:00 2001 From: jahorton Date: Wed, 21 Jul 2021 15:29:26 +0700 Subject: [PATCH 5/7] fix(common/core/web): mnemonic layer tracking with caps --- .../src/text/keyboardProcessor.ts | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/common/core/web/keyboard-processor/src/text/keyboardProcessor.ts b/common/core/web/keyboard-processor/src/text/keyboardProcessor.ts index 6ee5d2b9bfc..76e66193366 100644 --- a/common/core/web/keyboard-processor/src/text/keyboardProcessor.ts +++ b/common/core/web/keyboard-processor/src/text/keyboardProcessor.ts @@ -406,7 +406,7 @@ namespace com.keyman.text { for(i=0; i < lockNames.length; i++) { if(lockStates & Codes.stateBitmasks[lockNames[i]]) { - this.stateKeys[lockKeys[i]] = lockStates & Codes.modifierCodes[lockNames[i]]; + this.stateKeys[lockKeys[i]] = !!(lockStates & Codes.modifierCodes[lockNames[i]]); } } } else if(d) { @@ -427,10 +427,44 @@ namespace com.keyman.text { } } + this.updateStates(); + + if(this.activeKeyboard.isMnemonic && this.stateKeys['K_CAPS']) { + // Modifier keypresses doesn't trigger mnemonic manipulation of modifier state. + // Only an output key does; active use of Caps will also flip the SHIFT flag. + if(!e || !KeyboardProcessor.isModifier(e)) { + // Mnemonic keystrokes manipulate the SHIFT property based on CAPS state. + // We need to unflip them when tracking the OSK layer. + keyShiftState ^= Codes.modifierCodes['SHIFT']; + } + } + this.layerId = this.getLayerId(keyShiftState); return true; } + private updateStates(): void { + var lockNames = ['CAPS', 'NUM_LOCK', 'SCROLL_LOCK']; + var lockKeys = ['K_CAPS', 'K_NUMLOCK', 'K_SCROLL']; + + for(let i=0; i < lockKeys.length; i++) { + const key = lockKeys[i]; + const flag = this.stateKeys[key]; + const onBit = lockNames[i]; + const offBit = 'NO_' + lockNames[i]; + + // Ensures that the current mod-state info properly matches the currently-simulated + // state key states. + if(flag) { + this.modStateFlags |= Codes.modifierCodes[onBit]; + this.modStateFlags &= ~Codes.modifierCodes[offBit]; + } else { + this.modStateFlags &= ~Codes.modifierCodes[onBit]; + this.modStateFlags |= Codes.modifierCodes[offBit]; + } + } + } + getLayerId(modifier: number): string { return keyboards.Layouts.getLayerId(modifier); } From 1730ef6315931b67123749f5babf0495b280cf0a Mon Sep 17 00:00:00 2001 From: jahorton Date: Tue, 27 Jul 2021 11:46:21 +0700 Subject: [PATCH 6/7] fix(web): restores code lost due to cherrypick rebase conflicts --- web/source/osk/visualKeyboard.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/web/source/osk/visualKeyboard.ts b/web/source/osk/visualKeyboard.ts index f1e0840a006..26fffd92e61 100644 --- a/web/source/osk/visualKeyboard.ts +++ b/web/source/osk/visualKeyboard.ts @@ -1022,6 +1022,12 @@ namespace com.keyman.osk { layerChangeHandler: text.SystemStoreMutationHandler = function(this: VisualKeyboard, source: text.MutableSystemStore, newValue: string) { + // This handler is also triggered on state-key state changes (K_CAPS) that + // may not actually change the layer. + if(this) { + this._UpdateVKShiftStyle(); + } + if(source.value != newValue) { this.layerId = newValue; let keyman = com.keyman.singleton; From 3bcf3039aa9606addf60ae08520f66af5e3d536e Mon Sep 17 00:00:00 2001 From: jahorton Date: Tue, 27 Jul 2021 11:48:23 +0700 Subject: [PATCH 7/7] fix(web): restores another change lost during rebase merge conflicts --- web/source/osk/preProcessor.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/web/source/osk/preProcessor.ts b/web/source/osk/preProcessor.ts index e8174a05cb9..edcbc0ac3a6 100644 --- a/web/source/osk/preProcessor.ts +++ b/web/source/osk/preProcessor.ts @@ -9,14 +9,6 @@ namespace com.keyman.osk { // First check the virtual key, and process shift, control, alt or function keys let Lkc = e.constructKeyEvent(core.keyboardProcessor, dom.Utils.getOutputTarget(Lelem), keyman.util.device.coreSpec); - // If it's actually a state key modifier, trigger its effects immediately, as KeyboardEvents would do the same. - switch(Lkc.kName) { - case 'K_CAPS': - case 'K_NUMLOCK': - case 'K_SCROLL': - core.keyboardProcessor.stateKeys[Lkc.kName] = ! core.keyboardProcessor.stateKeys[Lkc.kName]; - } - // End - mirrors _GetKeyEventProperties return Lkc; }