mirror of
https://github.com/keymanapp/keyman.git
synced 2026-10-07 14:37:29 +00:00
Merge pull request #7543 from keymanapp/fix/web/oskEvent-keyboard-synch
fix(web): ensures keyboard does not change underneath OSK keystroke
This commit is contained in:
commit
a060ccb6fd
4 changed files with 58 additions and 9 deletions
|
|
@ -89,6 +89,32 @@ namespace com.keyman.text {
|
|||
* all matched keyboard rules.
|
||||
*/
|
||||
processKeyEvent(keyEvent: KeyEvent, outputTarget: OutputTarget): RuleBehavior {
|
||||
const kbdMismatch = keyEvent.srcKeyboard && this.activeKeyboard != keyEvent.srcKeyboard;
|
||||
const trueActiveKeyboard = this.activeKeyboard;
|
||||
|
||||
try {
|
||||
if(kbdMismatch) {
|
||||
// This will force-reset the context per our setter above.
|
||||
this.activeKeyboard = keyEvent.srcKeyboard;
|
||||
}
|
||||
|
||||
return this._processKeyEvent(keyEvent, outputTarget);
|
||||
} finally {
|
||||
if(kbdMismatch) {
|
||||
// Restore our "current" activeKeyboard to its setting before the mismatching KeyEvent.
|
||||
this.activeKeyboard = trueActiveKeyboard;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Acts as the core of `processKeyEvent` once we're comfortable asserting that the incoming
|
||||
* keystroke matches the current `activeKeyboard`.
|
||||
* @param keyEvent
|
||||
* @param outputTarget
|
||||
* @returns
|
||||
*/
|
||||
private _processKeyEvent(keyEvent: KeyEvent, outputTarget: OutputTarget): RuleBehavior {
|
||||
let formFactor = keyEvent.device.formFactor;
|
||||
let fromOSK = keyEvent.isSynthetic;
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,16 @@ namespace com.keyman.text {
|
|||
kbdLayer?: string; // The virtual keyboard's active layer
|
||||
kNextLayer?: string;
|
||||
|
||||
/**
|
||||
* Marks the active keyboard at the time that this KeyEvent was generated by the user.
|
||||
*
|
||||
* Note: this is NOT equivalent to the active keyboard at the time that the event handler begins
|
||||
* processing! It should be set via closure (or similar) on the event handler that can 100%
|
||||
* guarantee that the keyboard instance known to the handler has not changed during JS execution
|
||||
* since the user's interaction that raised the event.
|
||||
*/
|
||||
srcKeyboard?: keyboards.Keyboard;
|
||||
|
||||
// Holds relevant event properties leading to construction of this KeyEvent.
|
||||
source?: any; // Technically, KeyEvent|MouseEvent|Touch - but those are DOM types that must be kept out of headless mode.
|
||||
// Holds a generated fat-finger distribution (when appropriate)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace com.keyman.osk {
|
|||
* Note that the test-case oriented 'recorder' stubs this method to facilitate OSK-based input
|
||||
* recording for use in test cases. If changing this function, please ensure the recorder is
|
||||
* not affected.
|
||||
*
|
||||
*
|
||||
* @param {Object} e element touched (or clicked)
|
||||
*/
|
||||
static clickKey(e: osk.KeyElement, input?: InputEventCoordinate) {
|
||||
|
|
@ -27,7 +27,7 @@ namespace com.keyman.osk {
|
|||
// Handle any DOM state management related to click inputs.
|
||||
let outputTarget = dom.Utils.getOutputTarget(Lelem);
|
||||
keyman.domManager.initActiveElement(Lelem);
|
||||
|
||||
|
||||
// Clear any cached codepoint data; we can rebuild it if it's unchanged.
|
||||
outputTarget.invalidateSelection();
|
||||
// Deadkey matching continues to be troublesome.
|
||||
|
|
@ -51,8 +51,8 @@ namespace com.keyman.osk {
|
|||
}
|
||||
}
|
||||
|
||||
// Serves to hold DOM-dependent code that affects both 'native' and 'embedded' mode OSK use
|
||||
// after the KeyEvent object has been properly instantiated. This should help catch any
|
||||
// Serves to hold DOM-dependent code that affects both 'native' and 'embedded' mode OSK use
|
||||
// after the KeyEvent object has been properly instantiated. This should help catch any
|
||||
// mutual last-minute DOM-side interactions before passing control to the processor... such as
|
||||
// the UI-control command keys as seen below.
|
||||
static handleClick(Lkc: text.KeyEvent, outputTarget: text.OutputTarget, e: osk.KeyElement) {
|
||||
|
|
|
|||
|
|
@ -102,6 +102,9 @@ namespace com.keyman.osk {
|
|||
// Multi-tap gesture management
|
||||
pendingMultiTap: PendingMultiTap;
|
||||
|
||||
// The keyboard object corresponding to this VisualKeyboard.
|
||||
private layoutKeyboard: keyboards.Keyboard;
|
||||
|
||||
get layerId(): string {
|
||||
return this._layerId;
|
||||
}
|
||||
|
|
@ -172,19 +175,19 @@ namespace com.keyman.osk {
|
|||
|
||||
// Now to build the actual layout.
|
||||
const formFactor = device.formFactor as utils.FormFactor;
|
||||
let layoutKeyboard = keyboard;
|
||||
if (!layoutKeyboard) {
|
||||
this.layoutKeyboard = keyboard;
|
||||
if (!this.layoutKeyboard) {
|
||||
// May occasionally be null in embedded contexts; have seen this when iOS engine sets
|
||||
// keyboard height during change of keyboards.
|
||||
layoutKeyboard = new keyboards.Keyboard(null);
|
||||
this.layoutKeyboard = new keyboards.Keyboard(null);
|
||||
}
|
||||
|
||||
this.layerGroup = new OSKLayerGroup(this, layoutKeyboard, formFactor);
|
||||
this.layerGroup = new OSKLayerGroup(this, this.layoutKeyboard, formFactor);
|
||||
|
||||
// Now that we've properly processed the keyboard's layout, mark it as calibrated.
|
||||
// TODO: drop the whole 'calibration' thing. The newer layout system supersedes the
|
||||
// need for it. (Is no longer really used, so the drop ought be clean.)
|
||||
layoutKeyboard.markLayoutCalibrated(formFactor);
|
||||
this.layoutKeyboard.markLayoutCalibrated(formFactor);
|
||||
|
||||
// Append the OSK layer group container element to the containing element
|
||||
//osk.keyMap = divLayerContainer;
|
||||
|
|
@ -1005,6 +1008,16 @@ namespace com.keyman.osk {
|
|||
// First check the virtual key, and process shift, control, alt or function keys
|
||||
let Lkc = keySpec.constructKeyEvent(core.keyboardProcessor, this.device);
|
||||
|
||||
/* In case of "fun" edge cases caused by JS's single-threadedness & event processing queue.
|
||||
*
|
||||
* Should a touch occur on an OSK key during active JS execution that results in a change
|
||||
* of the active keyboard, it's possible for an OSK key to be evaluated against an
|
||||
* unexpected, non-matching keyboard - one that could even be `null`!
|
||||
*
|
||||
* So, we mark the keyboard backing the OSK as the 'correct' keyboard for this key.
|
||||
*/
|
||||
Lkc.srcKeyboard = this.layoutKeyboard;
|
||||
|
||||
// End - mirrors _GetKeyEventProperties
|
||||
|
||||
if (core.languageProcessor.isActive && input) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue