diff --git a/web/source/text/defaultOutput.ts b/web/source/text/defaultOutput.ts
new file mode 100644
index 0000000000..c330e9ba58
--- /dev/null
+++ b/web/source/text/defaultOutput.ts
@@ -0,0 +1,109 @@
+// Establishes key-code definitions.
+///
+// Defines our generalized "KeyEvent" class.
+///
+
+namespace com.keyman.text {
+ /**
+ * Defines a collection of static library functions that define KeymanWeb's default (implied) keyboard rule behaviors.
+ */
+ export class DefaultOutput {
+ private constructor() {
+ }
+
+ /**
+ * This function is designed for future migration into a separate, explicitly-DOM-aware module.
+ * It would then be assigned to this class via classic JS method extension practices as an 'override'
+ * of `commandEmulation`, reusing the base version of that name seen in this class, which is
+ * designed for web-core.
+ */
+ public static domCommandEmulation(outputTarget: OutputTarget, code: number, keyShiftState: number) {
+ let quiet = outputTarget instanceof Mock;
+
+ let domManager = com.keyman.singleton.domManager;
+
+ switch(code) {
+ case Codes.keyCodes['K_TAB']:
+ if(!quiet) {
+ domManager.moveToNext(keyShiftState);
+ }
+ break;
+ case Codes.keyCodes['K_TABBACK']:
+ if(!quiet) {
+ domManager.moveToNext(true);
+ }
+ break;
+ case Codes.keyCodes['K_TABFWD']:
+ if(!quiet) {
+ domManager.moveToNext(false);
+ }
+ break;
+ }
+ }
+
+ public static commandEmulation(Lkc: KeyEvent, keyShiftState: number) {
+ let keyName = Lkc.kName;
+ let n = Lkc.Lcode;
+ let outputTarget = Lkc.Ltarg;
+
+ let keyman = com.keyman.singleton;
+
+ let quiet = outputTarget instanceof Mock;
+
+ var code = Codes.keyCodes[keyName];
+ if(!code) {
+ code = n;
+ }
+
+ DefaultOutput.domCommandEmulation(outputTarget, code, keyShiftState);
+
+ switch(code) {
+ case Codes.keyCodes['K_BKSP']: //Only desktop UI, not touch devices. TODO: add repeat while mouse down for desktop UI
+ if(quiet) {
+ // TODO: Remove need for this clause via refactoring. It's currently needed for predictive text Mocks.
+ return '\b'; // the escape sequence for backspace.
+ } else {
+ keyman.interface.defaultBackspace(outputTarget);
+ }
+ return '';
+ case Codes.keyCodes['K_ENTER']:
+ outputTarget.handleNewlineAtCaret();
+
+ return '\n'; // We still return this, as it ensures we generate a rule-match.
+ case Codes.keyCodes['K_SPACE']:
+ return ' ';
+ //
+ // // Problem: clusters, and doing them right.
+ // // The commented-out code below should be a decent starting point, but clusters make it complex.
+ // // Mostly based on pre-12.0 code, but the general idea should be relatively clear.
+ //
+ // case Codes.keyCodes['K_LEFT']:
+ // if(touchAlias) {
+ // var caretPos = keymanweb.getTextCaret(Lelem);
+ // keymanweb.setTextCaret(Lelem, caretPos - 1 >= 0 ? caretPos - 1 : 0);
+ // }
+ // break;
+ // case Codes.keyCodes['K_RIGHT']:
+ // if(touchAlias) {
+ // var caretPos = keymanweb.getTextCaret(Lelem);
+ // keymanweb.setTextCaret(Lelem, caretPos + 1);
+ // }
+ // if(code == VisualKeyboard.keyCodes['K_RIGHT']) {
+ // break;
+ // }
+ // // Should we include this? It could be tricky to do correctly...
+ // case Codes.keyCodes['K_DEL']:
+ // // Move caret right one unit, then backspace.
+ // if(touchAlias) {
+ // var caretPos = keymanweb.getTextCaret(Lelem);
+ // keymanweb.setTextCaret(Lelem, caretPos + 1);
+ // if(caretPos == keymanweb.getTextCaret(Lelem)) {
+ // // Failed to move right - there's nothing to delete.
+ // break;
+ // }
+ // kbdInterface.defaultBackspace();
+ // }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/web/source/text/processor.ts b/web/source/text/processor.ts
index 77b403fde1..43d13a7498 100644
--- a/web/source/text/processor.ts
+++ b/web/source/text/processor.ts
@@ -2,6 +2,8 @@
///
// Defines our generalized "KeyEvent" class.
///
+// Defines default key handling behaviors.
+///
namespace com.keyman.text {
export class LegacyKeyEvent {
@@ -65,81 +67,11 @@ namespace com.keyman.text {
// If this was triggered by the OSK -or- if it was triggered by a 'synthetic' OutputTarget (TouchAlias, Mock)
// that lacks default key processing behavior.
if(usingOSK || outputTarget.isSynthetic) {
- var code = Codes.keyCodes[keyName];
- if(!code) {
- code = n;
+ let result = DefaultOutput.commandEmulation(Lkc, keyShiftState);
+
+ if(result) {
+ return result;
}
-
- switch(code) {
- case Codes.keyCodes['K_BKSP']: //Only desktop UI, not touch devices. TODO: add repeat while mouse down for desktop UI
- if(quiet) {
- // TODO: Remove need for this clause via refactoring. It's currently needed for predictive text Mocks.
- return '\b'; // the escape sequence for backspace.
- } else {
- keyman.interface.defaultBackspace(outputTarget);
- }
- return '';
- case Codes.keyCodes['K_TAB']:
- if(!quiet) {
- domManager.moveToNext(keyShiftState);
- }
- break;
- case Codes.keyCodes['K_TABBACK']:
- if(!quiet) {
- domManager.moveToNext(true);
- }
- break;
- case Codes.keyCodes['K_TABFWD']:
- if(!quiet) {
- domManager.moveToNext(false);
- }
- break;
- case Codes.keyCodes['K_ENTER']:
- outputTarget.handleNewlineAtCaret();
-
- return '\n'; // We still return this, as it ensures we generate a rule-match.
- case Codes.keyCodes['K_SPACE']:
- return ' ';
- // break;
- //
- // // Problem: clusters, and doing them right.
- // // The commented-out code below should be a decent starting point, but clusters make it complex.
- //
- // case VisualKeyboard.keyCodes['K_LEFT']:
- // if(touchAlias) {
- // var caretPos = keymanweb.getTextCaret(Lelem);
- // keymanweb.setTextCaret(Lelem, caretPos - 1 >= 0 ? caretPos - 1 : 0);
- // }
- // break;
- // case VisualKeyboard.keyCodes['K_RIGHT']:
- // if(touchAlias) {
- // var caretPos = keymanweb.getTextCaret(Lelem);
- // keymanweb.setTextCaret(Lelem, caretPos + 1);
- // }
- // if(code == VisualKeyboard.keyCodes['K_RIGHT']) {
- // break;
- // }
- // // Should we include this? It could be tricky to do correctly...
- // case VisualKeyboard.keyCodes['K_DEL']:
- // // Move caret right one unit, then backspace.
- // if(touchAlias) {
- // var caretPos = keymanweb.getTextCaret(Lelem);
- // keymanweb.setTextCaret(Lelem, caretPos + 1);
- // if(caretPos == keymanweb.getTextCaret(Lelem)) {
- // // Failed to move right - there's nothing to delete.
- // break;
- // }
- // kbdInterface.defaultBackspace();
- // }
- }
-
- // Only desktop UI, not touch devices. TODO: add repeat while mouse down for desktop UI
- //
- // Can easily occur from mnemonic keyboards, which create synthetic events without
- // the appropriate kName value.
- //
- // Not strictly if `Lkc.vkCode` is properly maintained, but it's good to have an
- // extra safety; this would have blocked the backspace bug as well.
} else if(Lkc.Lcode == 8) {
keyman.interface.defaultBackspace();
return '';