From 4c0ab7ab1a7f665a528771e33a1879c1bbbd873c Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Wed, 6 Jul 2022 12:11:30 +0700 Subject: [PATCH 1/9] fix(web): set(layer) should not trigger for hardware keystrokes --- common/web/keyboard-processor/src/text/kbdInterface.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/web/keyboard-processor/src/text/kbdInterface.ts b/common/web/keyboard-processor/src/text/kbdInterface.ts index bf8dad08d7..5bb27e1841 100644 --- a/common/web/keyboard-processor/src/text/kbdInterface.ts +++ b/common/web/keyboard-processor/src/text/kbdInterface.ts @@ -882,7 +882,8 @@ namespace com.keyman.text { */ setStore(systemId: number, strValue: string, outputTarget: OutputTarget): boolean { this.resetContextCache(); - if(systemId == KeyboardInterface.TSS_LAYER) { + // Unique case: we only allow set-store ops from keyboard rules triggered by touch OSKs. + if(systemId == KeyboardInterface.TSS_LAYER && this.activeDevice.touchable) { // Denote the changed store as part of the matched rule's behavior. this.ruleBehavior.setStore[systemId] = strValue; } else { From 4489337cd64c50893b2fbb283dbb89273b391388 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Wed, 6 Jul 2022 12:25:08 +0700 Subject: [PATCH 2/9] change(web): disables touch OSK auto-shift on hardware shift --- common/web/input-processor/src/text/inputProcessor.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/common/web/input-processor/src/text/inputProcessor.ts b/common/web/input-processor/src/text/inputProcessor.ts index 4b5580cc81..ce3b1a7983 100644 --- a/common/web/input-processor/src/text/inputProcessor.ts +++ b/common/web/input-processor/src/text/inputProcessor.ts @@ -102,8 +102,9 @@ 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. `doModifierPress` must always run. - if(this.keyboardProcessor.doModifierPress(keyEvent, outputTarget, !fromOSK)) { + // of state management. `doModifierPress` must always run for desktop-mode contexts. + // In standard Web integration, `contextDevice` indicates what type of OSK is visible. + if(!this.contextDevice.touchable && this.keyboardProcessor.doModifierPress(keyEvent, outputTarget, !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) { From a1a43f80c125c9a355396fdafb92812e84bdd187 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Wed, 6 Jul 2022 13:20:14 +0700 Subject: [PATCH 3/9] fix(web): doModifierPress layer handling --- common/web/input-processor/src/text/inputProcessor.ts | 5 ++--- common/web/keyboard-processor/src/text/keyboardProcessor.ts | 6 ++++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/common/web/input-processor/src/text/inputProcessor.ts b/common/web/input-processor/src/text/inputProcessor.ts index ce3b1a7983..4b5580cc81 100644 --- a/common/web/input-processor/src/text/inputProcessor.ts +++ b/common/web/input-processor/src/text/inputProcessor.ts @@ -102,9 +102,8 @@ 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. `doModifierPress` must always run for desktop-mode contexts. - // In standard Web integration, `contextDevice` indicates what type of OSK is visible. - if(!this.contextDevice.touchable && this.keyboardProcessor.doModifierPress(keyEvent, outputTarget, !fromOSK)) { + // of state management. `doModifierPress` must always run. + if(this.keyboardProcessor.doModifierPress(keyEvent, outputTarget, !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) { diff --git a/common/web/keyboard-processor/src/text/keyboardProcessor.ts b/common/web/keyboard-processor/src/text/keyboardProcessor.ts index 6249d85bc4..f53431c671 100644 --- a/common/web/keyboard-processor/src/text/keyboardProcessor.ts +++ b/common/web/keyboard-processor/src/text/keyboardProcessor.ts @@ -728,7 +728,7 @@ namespace com.keyman.text { } else if(KeyboardProcessor.isModifier(Levent)) { this.activeKeyboard.notify(Levent.Lcode, outputTarget, isKeyDown ? 1 : 0); // For eventual integration - we bypass an OSK update for physical keystrokes when in touch mode. - if(!Levent.device.touchable) { + if(!this.contextDevice.touchable) { return this._UpdateVKShift(Levent); // I2187 } else { return true; @@ -737,7 +737,9 @@ namespace com.keyman.text { if(Levent.LmodifierChange) { this.activeKeyboard.notify(0, outputTarget, 1); - this._UpdateVKShift(Levent); + if(!this.contextDevice.touchable) { + this._UpdateVKShift(Levent); + } } // No modifier keypresses detected. From 620cbb54ab983c47db2a08d0c326e1d622c2e69d Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Thu, 7 Jul 2022 08:39:28 +0700 Subject: [PATCH 4/9] chore(web): applies code suggestion Co-authored-by: Marc Durdin --- common/web/keyboard-processor/src/text/kbdInterface.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/web/keyboard-processor/src/text/kbdInterface.ts b/common/web/keyboard-processor/src/text/kbdInterface.ts index 5bb27e1841..497565914b 100644 --- a/common/web/keyboard-processor/src/text/kbdInterface.ts +++ b/common/web/keyboard-processor/src/text/kbdInterface.ts @@ -882,7 +882,7 @@ namespace com.keyman.text { */ setStore(systemId: number, strValue: string, outputTarget: OutputTarget): boolean { this.resetContextCache(); - // Unique case: we only allow set-store ops from keyboard rules triggered by touch OSKs. + // Unique case: we only allow set(&layer) ops from keyboard rules triggered by touch OSKs. if(systemId == KeyboardInterface.TSS_LAYER && this.activeDevice.touchable) { // Denote the changed store as part of the matched rule's behavior. this.ruleBehavior.setStore[systemId] = strValue; From f085c60ac1e081b13c2db276cf6f854e4020dd23 Mon Sep 17 00:00:00 2001 From: jahorton Date: Fri, 8 Jul 2022 09:52:40 +0700 Subject: [PATCH 5/9] fix(web): reset context on page focus loss --- web/source/keymanweb.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/web/source/keymanweb.ts b/web/source/keymanweb.ts index 61d523f6fa..36b30e5b32 100644 --- a/web/source/keymanweb.ts +++ b/web/source/keymanweb.ts @@ -118,12 +118,13 @@ if(!window['keyman']['initialized']) { util.attachDOMEvent(document, 'keyup', keymanweb.hotkeyManager._Process, false); /** - * Reset OSK shift states when entering or exiting the active element + * Reset context when entering or exiting the active element. + * Will also trigger OSK shift state / layer reset. **/ function resetVKShift() { let keyman = com.keyman.singleton; if(!keyman.uiManager.isActivating && keyman.osk?.vkbd) { - keyman.core.keyboardProcessor._UpdateVKShift(null); //this should be enabled !!!!! TODO + keyman.core.resetContext(null); } } From 648acc927361d20373d7be78d17f1c1cb58b88c0 Mon Sep 17 00:00:00 2001 From: jahorton Date: Fri, 8 Jul 2022 10:14:35 +0700 Subject: [PATCH 6/9] chore(web): extra check for robustness --- common/web/keyboard-processor/src/text/keyboardProcessor.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common/web/keyboard-processor/src/text/keyboardProcessor.ts b/common/web/keyboard-processor/src/text/keyboardProcessor.ts index f53431c671..516b236a43 100644 --- a/common/web/keyboard-processor/src/text/keyboardProcessor.ts +++ b/common/web/keyboard-processor/src/text/keyboardProcessor.ts @@ -749,7 +749,9 @@ namespace com.keyman.text { resetContext() { this.layerId = 'default'; this.keyboardInterface.resetContextCache(); - this._UpdateVKShift(null); + if(this.contextDevice.touchable) { + this._UpdateVKShift(null); + } }; setNumericLayer(device: utils.DeviceSpec) { From 7342f7f9e6c95ac8befdd6bf066c5214204c4dcd Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Tue, 12 Jul 2022 11:01:14 +0700 Subject: [PATCH 7/9] fix(web): applies PR suggestions --- .../web/keyboard-processor/src/text/keyboardProcessor.ts | 2 +- web/source/keymanweb.ts | 7 +++---- web/source/kmwbase.ts | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/common/web/keyboard-processor/src/text/keyboardProcessor.ts b/common/web/keyboard-processor/src/text/keyboardProcessor.ts index 516b236a43..2cc3015179 100644 --- a/common/web/keyboard-processor/src/text/keyboardProcessor.ts +++ b/common/web/keyboard-processor/src/text/keyboardProcessor.ts @@ -749,7 +749,7 @@ namespace com.keyman.text { resetContext() { this.layerId = 'default'; this.keyboardInterface.resetContextCache(); - if(this.contextDevice.touchable) { + if(!this.contextDevice.touchable) { this._UpdateVKShift(null); } }; diff --git a/web/source/keymanweb.ts b/web/source/keymanweb.ts index 36b30e5b32..5864eb8aa0 100644 --- a/web/source/keymanweb.ts +++ b/web/source/keymanweb.ts @@ -121,7 +121,7 @@ if(!window['keyman']['initialized']) { * Reset context when entering or exiting the active element. * Will also trigger OSK shift state / layer reset. **/ - function resetVKShift() { + keymanweb.pageFocusHandler = function() { let keyman = com.keyman.singleton; if(!keyman.uiManager.isActivating && keyman.osk?.vkbd) { keyman.core.resetContext(null); @@ -129,9 +129,8 @@ if(!window['keyman']['initialized']) { } // We need to track this handler, as it causes... interesting... interactions during testing in certain browsers. - keymanweb['pageFocusHandler'] = resetVKShift; - util.attachDOMEvent(window, 'focus', keymanweb['pageFocusHandler'], false); // I775 - util.attachDOMEvent(window, 'blur', keymanweb['pageFocusHandler'], false); // I775 + util.attachDOMEvent(window, 'focus', keymanweb.pageFocusHandler, false); // I775 + util.attachDOMEvent(window, 'blur', keymanweb.pageFocusHandler, false); // I775 // Initialize supplementary plane string extensions String.kmwEnableSupplementaryPlane(true); diff --git a/web/source/kmwbase.ts b/web/source/kmwbase.ts index 71414c5efc..c168e07983 100644 --- a/web/source/kmwbase.ts +++ b/web/source/kmwbase.ts @@ -183,8 +183,8 @@ namespace com.keyman { */ ['shutdown']() { // Disable page focus/blur events, which can sometimes trigger and cause parallel KMW instances in testing. - this.util.detachDOMEvent(window, 'focus', this['pageFocusHandler'], false); - this.util.detachDOMEvent(window, 'blur', this['pageFocusHandler'], false); + this.util.detachDOMEvent(window, 'focus', (this as any).pageFocusHandler, false); + this.util.detachDOMEvent(window, 'blur', (this as any).pageFocusHandler, false); this.domManager.shutdown(); this.osk.shutdown(); From 53578a114f9e4a4cd608528f9dd061cc325d0d11 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Wed, 13 Jul 2022 08:22:48 +0700 Subject: [PATCH 8/9] change(web): relocates pageFocusHandler def'n --- web/source/keymanweb.ts | 11 ----------- web/source/kmwbase.ts | 15 +++++++++++++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/web/source/keymanweb.ts b/web/source/keymanweb.ts index 5864eb8aa0..88cef3e2b1 100644 --- a/web/source/keymanweb.ts +++ b/web/source/keymanweb.ts @@ -117,17 +117,6 @@ if(!window['keyman']['initialized']) { util.attachDOMEvent(document, 'keyup', keymanweb.hotkeyManager._Process, false); - /** - * Reset context when entering or exiting the active element. - * Will also trigger OSK shift state / layer reset. - **/ - keymanweb.pageFocusHandler = function() { - let keyman = com.keyman.singleton; - if(!keyman.uiManager.isActivating && keyman.osk?.vkbd) { - keyman.core.resetContext(null); - } - } - // We need to track this handler, as it causes... interesting... interactions during testing in certain browsers. util.attachDOMEvent(window, 'focus', keymanweb.pageFocusHandler, false); // I775 util.attachDOMEvent(window, 'blur', keymanweb.pageFocusHandler, false); // I775 diff --git a/web/source/kmwbase.ts b/web/source/kmwbase.ts index c168e07983..e89c2e44f6 100644 --- a/web/source/kmwbase.ts +++ b/web/source/kmwbase.ts @@ -176,6 +176,17 @@ namespace com.keyman { this.touchAliasing = this.util.device.touchable ? this.domManager.touchHandlers : this.domManager.nonTouchHandlers; } + /** + * Reset context when entering or exiting the active element. + * Will also trigger OSK shift state / layer reset. + **/ + pageFocusHandler: () => boolean = function(this: KeymanBase) { + if(!this.uiManager.isActivating && this.osk?.vkbd) { + this.core.resetContext(null); + } + return false; + }.bind(this); + /** * Triggers a KeymanWeb engine shutdown to facilitate a full system reset. * This function is designed for use with KMW unit-testing, which reloads KMW @@ -183,8 +194,8 @@ namespace com.keyman { */ ['shutdown']() { // Disable page focus/blur events, which can sometimes trigger and cause parallel KMW instances in testing. - this.util.detachDOMEvent(window, 'focus', (this as any).pageFocusHandler, false); - this.util.detachDOMEvent(window, 'blur', (this as any).pageFocusHandler, false); + this.util.detachDOMEvent(window, 'focus', this.pageFocusHandler, false); + this.util.detachDOMEvent(window, 'blur', this.pageFocusHandler, false); this.domManager.shutdown(); this.osk.shutdown(); From 5476c7b1c321c62e02bbef736e7295db2ea7d595 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Thu, 14 Jul 2022 08:42:04 +0700 Subject: [PATCH 9/9] chore(web): applies PR suggestion (manually) --- web/source/kmwbase.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/source/kmwbase.ts b/web/source/kmwbase.ts index e89c2e44f6..d1ccd15c6a 100644 --- a/web/source/kmwbase.ts +++ b/web/source/kmwbase.ts @@ -180,12 +180,12 @@ namespace com.keyman { * Reset context when entering or exiting the active element. * Will also trigger OSK shift state / layer reset. **/ - pageFocusHandler: () => boolean = function(this: KeymanBase) { + pageFocusHandler = () => { if(!this.uiManager.isActivating && this.osk?.vkbd) { this.core.resetContext(null); } return false; - }.bind(this); + } /** * Triggers a KeymanWeb engine shutdown to facilitate a full system reset.