mirror of
https://github.com/keymanapp/keyman.git
synced 2026-10-15 10:27:31 +00:00
Merge pull request #2893 from keymanapp/refactor/web/osk-preprocessing
refactor(web): starts OSK preprocessor
This commit is contained in:
commit
9cea778a7b
5 changed files with 119 additions and 117 deletions
|
|
@ -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
|
||||
|
|
|
|||
105
web/source/osk/preProcessor.ts
Normal file
105
web/source/osk/preProcessor.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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='';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue