From 60d4ceb5e67573aa1e263f6bad7ad61894e64729 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Sun, 26 Jun 2022 15:54:05 +1000 Subject: [PATCH 1/2] fix(web): Maintain separate Caps Lock states for touch and physical Fixes #6799. Caps Lock state management for touch layouts was not quite right -- it touched the base Caps state variables rather than just the event Lstates property. This meant that it was impossible to track the physical Caps Lock key separately to the touch layout layer, and that the two states would interfere with each other. --- .../src/text/keyboardProcessor.ts | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/common/web/keyboard-processor/src/text/keyboardProcessor.ts b/common/web/keyboard-processor/src/text/keyboardProcessor.ts index cfbc3da8b8..e42020747b 100644 --- a/common/web/keyboard-processor/src/text/keyboardProcessor.ts +++ b/common/web/keyboard-processor/src/text/keyboardProcessor.ts @@ -190,10 +190,14 @@ namespace com.keyman.text { } setSyntheticEventDefaults(Lkc: text.KeyEvent) { - // Set the flags for the state keys. - Lkc.Lstates |= this.stateKeys['K_CAPS'] ? Codes.modifierCodes['CAPS'] : Codes.modifierCodes['NO_CAPS']; - Lkc.Lstates |= this.stateKeys['K_NUMLOCK'] ? Codes.modifierCodes['NUM_LOCK'] : Codes.modifierCodes['NO_NUM_LOCK']; - Lkc.Lstates |= this.stateKeys['K_SCROLL'] ? Codes.modifierCodes['SCROLL_LOCK'] : Codes.modifierCodes['NO_SCROLL_LOCK']; + // Set the flags for the state keys - for desktop devices. For touch + // devices, the only state key in use currently is Caps Lock, which is set + // when the 'caps' layer is active in ActiveKey::constructBaseKeyEvent. + if(!Lkc.device.touchable) { + Lkc.Lstates |= this.stateKeys['K_CAPS'] ? Codes.modifierCodes['CAPS'] : Codes.modifierCodes['NO_CAPS']; + Lkc.Lstates |= this.stateKeys['K_NUMLOCK'] ? Codes.modifierCodes['NUM_LOCK'] : Codes.modifierCodes['NO_NUM_LOCK']; + Lkc.Lstates |= this.stateKeys['K_SCROLL'] ? Codes.modifierCodes['SCROLL_LOCK'] : Codes.modifierCodes['NO_SCROLL_LOCK']; + } // Set LisVirtualKey to false to ensure that nomatch rule does fire for U_xxxx keys if(Lkc.kName && Lkc.kName.substr(0,2) == 'U_') { @@ -272,7 +276,7 @@ namespace com.keyman.text { matchBehavior.mergeInDefaults(defaultBehavior); } matchBehavior.triggerKeyDefault = false; // We've triggered it successfully. - } // If null, we must rely on something else (like the browser, in DOM-aware code) to fulfill the default. + } // If null, we must rely on something else (like the browser, in DOM-aware code) to fulfill the default. this.keyboardInterface.activeTargetOutput = null; } @@ -688,21 +692,10 @@ namespace com.keyman.text { this.layerId = 'default'; } - this.updateStateKeysFromLayer(); - let baseModifierState = text.KeyboardProcessor.getModifierState(this.layerId); this.modStateFlags = baseModifierState | keyEvent.Lstates; } - public updateStateKeysFromLayer() { - if(this.device.formFactor != utils.FormFactor.Desktop) { - // The caps layer works slightly differently on touch than on desktop. - // It's a single layer with no ability to mix with other modifiers - // We need to make sure that the state is kept in sync with the layer. - this.stateKeys['K_CAPS'] = this.layerId == 'caps'; - } - } - static isModifier(Levent: KeyEvent): boolean { switch(Levent.Lcode) { case 16: //"K_SHIFT":16,"K_CONTROL":17,"K_ALT":18 @@ -748,7 +741,6 @@ namespace com.keyman.text { resetContext() { this.layerId = 'default'; - this.updateStateKeysFromLayer(); this.keyboardInterface.resetContextCache(); this._UpdateVKShift(null); }; @@ -758,7 +750,6 @@ namespace com.keyman.text { let layout = this.activeKeyboard.layout(device.formFactor); if(layout.getLayer('numeric')) { this.layerId = 'numeric'; - this.updateStateKeysFromLayer(); } } }; From aa8730acda8bc3b65dd623c6be5b448f5c52fb77 Mon Sep 17 00:00:00 2001 From: jahorton Date: Mon, 4 Jul 2022 08:54:52 +0700 Subject: [PATCH 2/2] fix(web): properly binds 'suggestionApplied' event handler --- web/source/osk/banner.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/web/source/osk/banner.ts b/web/source/osk/banner.ts index 8bd2b83356..e71a2e8f32 100644 --- a/web/source/osk/banner.ts +++ b/web/source/osk/banner.ts @@ -399,7 +399,7 @@ namespace com.keyman.osk { * @param outputTarget * @returns true */ - suggestionApplied(outputTarget: text.OutputTarget): boolean { + suggestionApplied: (outputTarget: text.OutputTarget) => boolean = function(this: SuggestionBanner, outputTarget: text.OutputTarget) { const keyman = com.keyman.singleton; // Tell the keyboard that the current layer has not changed keyman.core.keyboardProcessor.newLayerStore.set(''); @@ -411,7 +411,7 @@ namespace com.keyman.osk { ?.finalize(keyman.core.keyboardProcessor, outputTarget, true); return true; - }; + }.bind(this); postConfigure() { let keyman = com.keyman.singleton; @@ -427,6 +427,7 @@ namespace com.keyman.osk { keyman.core.languageProcessor.removeListener('suggestionsready', manager.updateSuggestions); keyman.core.languageProcessor.removeListener('tryaccept', manager.tryAccept); keyman.core.languageProcessor.removeListener('tryrevert', manager.tryRevert); + keyman.core.languageProcessor.removeListener('suggestionapplied', this.suggestionApplied); } }