Merge pull request #2893 from keymanapp/refactor/web/osk-preprocessing

refactor(web): starts OSK preprocessor
This commit is contained in:
Joshua Horton 2020-03-30 08:41:26 +07:00 • committed by GitHub
commit 9cea778a7b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 119 additions and 117 deletions

View file

@ -429,7 +429,7 @@ namespace com.keyman.text {
// While we can't source the base KeyEvent properties for embedded subkeys the same way as native,
// we can handle many other pre-processing steps the same way with this common method.
processor.commonClickEventPreprocessing(Lkc);
processor.setSyntheticEventDefaults(Lkc);
//if(!Lkc.Lcode) return false; // Value is now zero if not known (Build 347)
//Build 353: revert to prior test to try to fix lack of KMEI output, May 1, 2014

View file

@ -0,0 +1,105 @@
namespace com.keyman.osk {
export class PreProcessor {
static _GetClickEventProperties(e: osk.ActiveKey, Lelem: HTMLElement): text.KeyEvent {
let keyman = com.keyman.singleton;
let processor = keyman.textProcessor;
var activeKeyboard = processor.activeKeyboard;
let formFactor = keyman.util.device.formFactor;
// Get key name and keyboard shift state (needed only for default layouts and physical keyboard handling)
// Note - virtual keys should be treated case-insensitive, so we force uppercasing here.
var layer = e.layer || e.displayLayer || '', keyName=e.id.toUpperCase();
// Start: mirrors _GetKeyEventProperties
// Override key shift state if specified for key in layout (corrected for popup keys KMEW-93)
var keyShiftState = processor.getModifierState(layer);
// First check the virtual key, and process shift, control, alt or function keys
var Lkc: text.KeyEvent = {
Ltarg: text.Processor.getOutputTarget(Lelem),
Lmodifiers: keyShiftState,
Lstates: 0,
Lcode: text.Codes.keyCodes[keyName],
LisVirtualKey: true,
vkCode: 0,
kName: keyName,
kLayer: layer,
kbdLayer: e.displayLayer,
kNextLayer: e.nextlayer
};
// If it's actually a state key modifier, trigger its effects immediately, as KeyboardEvents would do the same.
switch(keyName) {
case 'K_CAPS':
case 'K_NUMLOCK':
case 'K_SCROLL':
processor.stateKeys[keyName] = ! processor.stateKeys[keyName];
}
// Performs common pre-analysis for both 'native' and 'embedded' OSK key & subkey input events.
processor.setSyntheticEventDefaults(Lkc);
// End - mirrors _GetKeyEventProperties
// Include *limited* support for mnemonic keyboards (Sept 2012)
// If a touch layout has been defined for a mnemonic keyout, do not perform mnemonic mapping for rules on touch devices.
if(activeKeyboard && activeKeyboard.isMnemonic && !(activeKeyboard.layouts && formFactor != 'desktop')) {
if(Lkc.Lcode != text.Codes.keyCodes['K_SPACE']) { // exception required, March 2013
// Jan 2019 - interesting that 'K_SPACE' also affects the caps-state check...
Lkc.vkCode = Lkc.Lcode;
text.Processor.setMnemonicCode(Lkc, layer.indexOf('shift') != -1, processor.stateKeys['K_CAPS']);
}
} else {
Lkc.vkCode=Lkc.Lcode;
}
// Support version 1.0 KeymanWeb keyboards that do not define positional vs mnemonic
if(!activeKeyboard.definesPositionalOrMnemonic) {
Lkc.Lcode = KeyMapping._USKeyCodeToCharCode(Lkc);
Lkc.LisVirtualKey=false;
}
return Lkc;
}
/**
* Simulate a keystroke according to the touched keyboard button element
*
* 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, touch?: Touch, layerId?: string, keyDistribution?: text.KeyDistribution) {
let keyman = com.keyman.singleton;
var Lelem = keyman.domManager.getLastActiveElement();
if(Lelem != null) {
// Handle any DOM state management related to click inputs.
let outputTarget = text.Processor.getOutputTarget(Lelem);
keyman.domManager.initActiveElement(Lelem);
// Turn off key highlighting (or preview)
keyman['osk'].vkbd.highlightKey(e,false);
// Clear any cached codepoint data; we can rebuild it if it's unchanged.
outputTarget.invalidateSelection();
// Deadkey matching continues to be troublesome.
// Deleting matched deadkeys here seems to correct some of the issues. (JD 6/6/14)
outputTarget.deadkeys().deleteMatched(); // Delete any matched deadkeys before continuing
let Lkc = PreProcessor._GetClickEventProperties(e['key'].spec as osk.ActiveKey, Lelem);
if(keyman.modelManager.enabled) {
Lkc.source = touch;
Lkc.keyDistribution = keyDistribution;
}
return keyman.textProcessor.processKeyEvent(Lkc, e);
} else {
return true;
}
}
}
}

View file

@ -1,5 +1,6 @@
/// <reference path="activeLayout.ts" />
/// <reference path="../utils/version.ts" />
/// <reference path="preProcessor.ts" />
namespace com.keyman.osk {
let Codes = com.keyman.text.Codes;
@ -911,7 +912,6 @@ namespace com.keyman.osk {
*
*/
touch: (e: TouchEvent) => void = function(this: VisualKeyboard, e: TouchEvent) {
let Processor = com.keyman.singleton.textProcessor;
// Identify the key touched
var t = <HTMLElement> e.changedTouches[0].target, key = this.keyTarget(t);
@ -952,7 +952,7 @@ namespace com.keyman.osk {
// Special function keys need immediate action
if(keyName == 'K_LOPT' || keyName == 'K_ROPT') {
window.setTimeout(function(this: VisualKeyboard){
Processor.clickKey(key);
PreProcessor.clickKey(key);
}.bind(this),0);
this.keyPending = null;
this.touchPending = null;
@ -962,7 +962,7 @@ namespace com.keyman.osk {
let touchProbabilities = this.getTouchProbabilities(e.changedTouches[0]);
// While we could inline the execution of the delete key here, we lose the ability to
// record the backspace key if we do so.
Processor.clickKey(key, e.changedTouches[0], this.layerId, touchProbabilities);
PreProcessor.clickKey(key, e.changedTouches[0], this.layerId, touchProbabilities);
this.deleteKey = key;
this.deleting = window.setTimeout(this.repeatDelete,500);
this.keyPending = null;
@ -971,7 +971,7 @@ namespace com.keyman.osk {
if(this.keyPending) {
this.highlightKey(this.keyPending, false);
let touchProbabilities = this.getTouchProbabilities(this.touchPending);
Processor.clickKey(this.keyPending, this.touchPending, this.layerId, touchProbabilities);
PreProcessor.clickKey(this.keyPending, this.touchPending, this.layerId, touchProbabilities);
this.clearPopup();
// Decrement the number of unreleased touch points to prevent
// sending the keystroke again when the key is actually released
@ -1047,7 +1047,7 @@ namespace com.keyman.osk {
// Output character unless moved off key
if(this.keyPending.className.indexOf('hidden') < 0 && tc > 0 && !beyondEdge) {
let touchProbabilities = this.getTouchProbabilities(e.changedTouches[0]);
Processor.clickKey(this.keyPending, e.changedTouches[0], this.layerId, touchProbabilities);
PreProcessor.clickKey(this.keyPending, e.changedTouches[0], this.layerId, touchProbabilities);
}
this.clearPopup();
this.keyPending = null;
@ -1321,10 +1321,8 @@ namespace com.keyman.osk {
* Repeat backspace as long as the backspace key is held down
**/
repeatDelete: () => void = function(this: VisualKeyboard) {
let Processor = com.keyman.singleton.textProcessor;
if(this.deleting) {
Processor.clickKey(this.deleteKey);
PreProcessor.clickKey(this.deleteKey);
this.deleting = window.setTimeout(this.repeatDelete,100);
}
}.bind(this);
@ -1763,7 +1761,7 @@ namespace com.keyman.osk {
// Process as click if mouse button released anywhere over key
if(util.eventType(e) == 'mouseup') {
if(key.id == this.currentKey) {
keyman.textProcessor.clickKey(key);
PreProcessor.clickKey(key);
}
this.currentKey='';
}

View file

@ -127,15 +127,15 @@ copyTestDefinition = function() {
alert("Unable to copy successfully.");
}
var _ock = com.keyman.text.Processor.prototype.clickKey; //.bind(keyman.osk);
com.keyman.text.Processor.prototype.clickKey = function(e) {
var _ock = com.keyman.osk.PreProcessor.clickKey; //.bind(keyman.osk);
com.keyman.osk.PreProcessor.clickKey = function(e) {
if(com.keyman.dom.DOMEventHandlers.states.activeElement != in_output &&
com.keyman.dom.DOMEventHandlers.states.activeElement != in_output['kmw_ip']) {
return _ock.call(com.keyman.singleton.textProcessor, e);
return _ock(e);
}
var event = new KMWRecorder.OSKInputEvent(e);
var retVal = _ock.call(com.keyman.singleton.textProcessor, e);
var retVal = _ock(e);
// Record the click/touch as part of a test sequence!
addInputRecord(event);

View file

@ -178,70 +178,7 @@ namespace com.keyman.text {
}
}
_GetClickEventProperties(e: osk.ActiveKey, Lelem: HTMLElement): KeyEvent {
let keyman = com.keyman.singleton;
var activeKeyboard = this.activeKeyboard;
let formFactor = keyman.util.device.formFactor;
// Get key name and keyboard shift state (needed only for default layouts and physical keyboard handling)
// Note - virtual keys should be treated case-insensitive, so we force uppercasing here.
var layer = e.layer || e.displayLayer || '', keyName=e.id.toUpperCase();
// Start: mirrors _GetKeyEventProperties
// Override key shift state if specified for key in layout (corrected for popup keys KMEW-93)
var keyShiftState = this.getModifierState(layer);
// First check the virtual key, and process shift, control, alt or function keys
var Lkc: KeyEvent = {
Ltarg: Processor.getOutputTarget(Lelem),
Lmodifiers: keyShiftState,
Lstates: 0,
Lcode: Codes.keyCodes[keyName],
LisVirtualKey: true,
vkCode: 0,
kName: keyName,
kLayer: layer,
kbdLayer: e.displayLayer,
kNextLayer: e.nextlayer
};
// If it's actually a state key modifier, trigger its effects immediately, as KeyboardEvents would do the same.
switch(keyName) {
case 'K_CAPS':
case 'K_NUMLOCK':
case 'K_SCROLL':
this.stateKeys[keyName] = ! this.stateKeys[keyName];
}
// Performs common pre-analysis for both 'native' and 'embedded' OSK key & subkey input events.
this.commonClickEventPreprocessing(Lkc);
// End - mirrors _GetKeyEventProperties
// Include *limited* support for mnemonic keyboards (Sept 2012)
// If a touch layout has been defined for a mnemonic keyout, do not perform mnemonic mapping for rules on touch devices.
if(activeKeyboard && activeKeyboard.isMnemonic && !(activeKeyboard.layouts && formFactor != 'desktop')) {
if(Lkc.Lcode != Codes.keyCodes['K_SPACE']) { // exception required, March 2013
// Jan 2019 - interesting that 'K_SPACE' also affects the caps-state check...
Lkc.vkCode = Lkc.Lcode;
Processor.setMnemonicCode(Lkc, layer.indexOf('shift') != -1, this.stateKeys['K_CAPS']);
}
} else {
Lkc.vkCode=Lkc.Lcode;
}
// Support version 1.0 KeymanWeb keyboards that do not define positional vs mnemonic
if(!activeKeyboard.definesPositionalOrMnemonic) {
Lkc.Lcode = KeyMapping._USKeyCodeToCharCode(Lkc);
Lkc.LisVirtualKey=false;
}
return Lkc;
}
commonClickEventPreprocessing(Lkc: KeyEvent) {
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'];
@ -433,7 +370,7 @@ namespace com.keyman.text {
continue;
}
let altEvent = this._GetClickEventProperties(altKey, keyEvent.Ltarg.getElement());
let altEvent = osk.PreProcessor._GetClickEventProperties(altKey, keyEvent.Ltarg.getElement());
altEvent.Ltarg = mock;
let alternateBehavior = this.processKeystroke(altEvent, mock, fromOSK);
if(alternateBehavior) {
@ -518,44 +455,6 @@ namespace com.keyman.text {
return ruleBehavior == null;
}
/**
* Simulate a keystroke according to the touched keyboard button element
*
* 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)
*/
clickKey(e: osk.KeyElement, touch?: Touch, layerId?: string, keyDistribution?: KeyDistribution) {
let keyman = com.keyman.singleton;
var Lelem = keyman.domManager.getLastActiveElement();
if(Lelem != null) {
// Handle any DOM state management related to click inputs.
let outputTarget = Processor.getOutputTarget(Lelem);
keyman.domManager.initActiveElement(Lelem);
// Turn off key highlighting (or preview)
keyman['osk'].vkbd.highlightKey(e,false);
// Clear any cached codepoint data; we can rebuild it if it's unchanged.
outputTarget.invalidateSelection();
// Deadkey matching continues to be troublesome.
// Deleting matched deadkeys here seems to correct some of the issues. (JD 6/6/14)
outputTarget.deadkeys().deleteMatched(); // Delete any matched deadkeys before continuing
let Lkc = this._GetClickEventProperties(e['key'].spec as osk.ActiveKey, Lelem);
if(keyman.modelManager.enabled) {
Lkc.source = touch;
Lkc.keyDistribution = keyDistribution;
}
return this.processKeyEvent(Lkc, e);
} else {
return true;
}
}
// FIXME: makes some bad assumptions.
static setMnemonicCode(Lkc: KeyEvent, shifted: boolean, capsActive: boolean) {
// K_SPACE is not handled by defaultKeyOutput for physical keystrokes unless using touch-aliased elements.