From d488f22fd9590c55af7fd1c97ac6b8b3f792f5fb Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Mon, 21 Aug 2023 10:42:06 +0700 Subject: [PATCH 1/6] feat(web): browser-KMW support for default subkeys --- .../src/keyboards/activeLayout.ts | 6 + .../src/keyboards/defaultLayouts.ts | 1 + .../src/input/gestures/browser/subkeyPopup.ts | 13 +- .../engine/osk/src/keyboard-layout/oskKey.ts | 1 + .../web/default-subkey/default_subkey.js | 1 + .../test/manual/web/default-subkey/index.html | 99 +++ .../web/default-subkey/kbd_source/HISTORY.md | 6 + .../web/default-subkey/kbd_source/LICENSE.md | 21 + .../web/default-subkey/kbd_source/README.md | 30 + .../kbd_source/default_subkey.keyboard_info | 7 + .../kbd_source/default_subkey.kpj | 110 +++ .../kbd_source/source/default_subkey.ico | Bin 0 -> 1150 bytes .../source/default_subkey.keyman-touch-layout | 717 ++++++++++++++++++ .../kbd_source/source/default_subkey.kmn | 16 + .../kbd_source/source/default_subkey.kps | 65 ++ .../kbd_source/source/default_subkey.kvks | 8 + .../kbd_source/source/readme.htm | 24 + .../kbd_source/source/welcome.htm | 26 + web/src/test/manual/web/index.html | 1 + 19 files changed, 1145 insertions(+), 7 deletions(-) create mode 100644 web/src/test/manual/web/default-subkey/default_subkey.js create mode 100644 web/src/test/manual/web/default-subkey/index.html create mode 100644 web/src/test/manual/web/default-subkey/kbd_source/HISTORY.md create mode 100644 web/src/test/manual/web/default-subkey/kbd_source/LICENSE.md create mode 100644 web/src/test/manual/web/default-subkey/kbd_source/README.md create mode 100644 web/src/test/manual/web/default-subkey/kbd_source/default_subkey.keyboard_info create mode 100644 web/src/test/manual/web/default-subkey/kbd_source/default_subkey.kpj create mode 100644 web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.ico create mode 100644 web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.keyman-touch-layout create mode 100644 web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kmn create mode 100644 web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kps create mode 100644 web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kvks create mode 100644 web/src/test/manual/web/default-subkey/kbd_source/source/readme.htm create mode 100644 web/src/test/manual/web/default-subkey/kbd_source/source/welcome.htm diff --git a/common/web/keyboard-processor/src/keyboards/activeLayout.ts b/common/web/keyboard-processor/src/keyboards/activeLayout.ts index e6d2ab9f157..9050d393a19 100644 --- a/common/web/keyboard-processor/src/keyboards/activeLayout.ts +++ b/common/web/keyboard-processor/src/keyboards/activeLayout.ts @@ -48,6 +48,12 @@ export class ActiveKey implements LayoutKey { _baseKeyEvent: KeyEvent; isMnemonic: boolean = false; + /** + * Only available on subkeys, but we don't distinguish between base keys and subkeys + * at this level yet in KMW. + */ + default?: boolean; + proportionalPad: number; proportionalX: number; proportionalWidth: number; diff --git a/common/web/keyboard-processor/src/keyboards/defaultLayouts.ts b/common/web/keyboard-processor/src/keyboards/defaultLayouts.ts index 8d187ac8544..7e0153d0a52 100644 --- a/common/web/keyboard-processor/src/keyboards/defaultLayouts.ts +++ b/common/web/keyboard-processor/src/keyboards/defaultLayouts.ts @@ -22,6 +22,7 @@ export type LayoutKey = { "nextlayer"?: string, "pad"?: string | number, "sk"?: LayoutKey[] + "default"?: boolean } export type LayoutRow = { diff --git a/web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts b/web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts index e36b24b0e82..9d7f0030002 100644 --- a/web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts +++ b/web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts @@ -219,25 +219,24 @@ export default class SubkeyPopup implements RealizedGesture { let skElement = popupBase.childNodes[i].firstChild; // Preference order: - // #1: if a default subkey has been specified, select it. (pending, for 15.0+) + // #1: if a default subkey has been specified, select it. // #2: if no default subkey is specified, default to a subkey with the same // key ID and layer / modifier spec. - //if(skSpec.isDefault) { TODO for 15.0 - // bk = skElement; - // break; - //} else - if(!baseKey.key || !baseKey.key.spec) { + if(skSpec.default) { + bk = skElement; + break; + } else if(!baseKey.key || !baseKey.key.spec) { continue; } if(skSpec.elementID == baseKey.key.spec.elementID) { bk = skElement; - break; // Best possible match has been found. (Disable 'break' once above block is implemented.) } } if(bk) { vkbd.keyPending = bk; + this.currentSelection = bk; // Subkeys never get key previews, so we can directly highlight the subkey. bk.key.highlight(true); } diff --git a/web/src/engine/osk/src/keyboard-layout/oskKey.ts b/web/src/engine/osk/src/keyboard-layout/oskKey.ts index b99d2076253..77d8927b60a 100644 --- a/web/src/engine/osk/src/keyboard-layout/oskKey.ts +++ b/web/src/engine/osk/src/keyboard-layout/oskKey.ts @@ -25,6 +25,7 @@ export class OSKKeySpec implements LayoutKey { nextlayer?: string; pad?: number; sk?: OSKKeySpec[]; + default?: boolean; constructor(id: string, text?: string, width?: number, sp?: ButtonClass, nextlayer?: string, pad?: number) { this.id = id; diff --git a/web/src/test/manual/web/default-subkey/default_subkey.js b/web/src/test/manual/web/default-subkey/default_subkey.js new file mode 100644 index 00000000000..1d656018754 --- /dev/null +++ b/web/src/test/manual/web/default-subkey/default_subkey.js @@ -0,0 +1 @@ +if(typeof keyman === 'undefined') {console.log('Keyboard requires KeymanWeb 10.0 or later');if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later");} else {KeymanWeb.KR(new Keyboard_default_subkey());}function Keyboard_default_subkey(){this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;this.KI="Keyboard_default_subkey";this.KN="default-subkey";this.KMINVER="10.0";this.KV={F:' 1em "Arial"',K102:0};this.KV.KLS={};this.KV.BK=(function(x){var e=Array.apply(null,Array(65)).map(String.prototype.valueOf,""),r=[],v,i,m=['default','shift','ctrl','shift-ctrl','alt','shift-alt','ctrl-alt','shift-ctrl-alt'];for(i=m.length-1;i>=0;i--)if((v=x[m[i]])||r.length)r=(v?v:e).slice().concat(r);return r})(this.KV.KLS);this.KDU=0;this.KH='';this.KM=0;this.KBVER="1.0";this.KMBM=0x0000;this.KVKD="T_d_default";this.KVKL={"tablet":{"font":"Tahoma","displayUnderlying":false,"layer":[{"id":"default","row":[{"id":"1","key":[{"id":"K_Q","text":"q"},{"id":"K_W","text":"w"},{"id":"K_E","text":"e"},{"id":"K_R","text":"r"},{"id":"K_T","text":"t"},{"id":"K_Y","text":"y"},{"id":"K_U","text":"u"},{"id":"K_I","text":"i"},{"id":"K_O","text":"o"},{"id":"K_P","text":"p"}]},{"id":"2","key":[{"id":"K_A","pad":"70","text":"a","sk":[{"id":"U_00E1","text":"\u00E1"},{"id":"U_00E0","text":"\u00E0"},{"id":"K_A","text":"a"},{"id":"U_00E4","text":"\u00E4"},{"id":"U_00E5","text":"\u00E5"},{"id":"U_00E2","text":"\u00E2"},{"id":"U_00E3","text":"\u00E3"}]},{"id":"K_S","text":"s"},{"id":"K_D","text":"d","sk":[{"id":"U_010F","text":"\u010F"},{"id":"U_0111","text":"\u0111"},{"id":"U_0257","text":"\u0257"},{"id":"T_d_default","text":"default","default":true},{"id":"U_0221","text":"\u0221"}]},{"id":"K_F","text":"f"},{"id":"K_G","text":"g"},{"id":"K_H","text":"h"},{"id":"K_J","text":"j"},{"id":"K_K","text":"k"},{"id":"K_L","text":"l"},{"width":"10","id":"T_new_88","sp":"10"}]},{"id":"3","key":[{"nextlayer":"shift","width":"110","id":"K_SHIFT","sp":"1","text":"*Shift*"},{"id":"K_Z","text":"z"},{"id":"K_X","text":"x"},{"id":"K_C","text":"c"},{"id":"K_V","text":"v"},{"id":"K_B","text":"b"},{"id":"K_N","text":"n"},{"id":"K_M","text":"m"},{"id":"K_PERIOD","text":".","sk":[{"id":"K_COMMA","text":","},{"layer":"shift","id":"K_1","text":"!"},{"layer":"shift","id":"K_SLASH","text":"?"},{"id":"K_QUOTE","text":"'"},{"layer":"shift","id":"K_QUOTE","text":"\""},{"id":"K_BKSLASH","text":"\\"},{"layer":"shift","id":"K_COLON","text":":"},{"id":"K_COLON","text":";"}]},{"width":"90","id":"K_BKSP","sp":"1","text":"*BkSp*"}]},{"id":"4","key":[{"nextlayer":"numeric","width":"140","id":"K_NUMLOCK","sp":"1","text":"*123*"},{"width":"120","id":"K_LOPT","sp":"1","text":"*Menu*"},{"width":"630","id":"K_SPACE"},{"width":"140","id":"K_ENTER","sp":"1","text":"*Enter*"}]}]},{"id":"shift","row":[{"id":"1","key":[{"id":"K_Q","text":"Q"},{"id":"K_W","text":"W"},{"id":"K_E","text":"E"},{"id":"K_R","text":"R"},{"id":"K_T","text":"T"},{"id":"K_Y","text":"Y"},{"id":"K_U","text":"U"},{"id":"K_I","text":"I"},{"id":"K_O","text":"O"},{"id":"K_P","text":"P"}]},{"id":"2","key":[{"id":"K_A","pad":"70","text":"A"},{"id":"K_S","text":"S"},{"id":"K_D","text":"D"},{"id":"K_F","text":"F"},{"id":"K_G","text":"G"},{"id":"K_H","text":"H"},{"id":"K_J","text":"J"},{"id":"K_K","text":"K"},{"id":"K_L","text":"L"},{"width":"10","sp":"10"}]},{"id":"3","key":[{"nextlayer":"default","width":"110","id":"K_SHIFT","sp":"2","text":"*Shift*"},{"id":"K_Z","text":"Z"},{"id":"K_X","text":"X"},{"id":"K_C","text":"C"},{"id":"K_V","text":"V"},{"id":"K_B","text":"B"},{"id":"K_N","text":"N"},{"id":"K_M","text":"M"},{"layer":"default","id":"K_PERIOD","text":".","sk":[{"layer":"default","id":"K_COMMA","text":","},{"layer":"shift","id":"K_1","text":"!"},{"layer":"shift","id":"K_SLASH","text":"?"},{"layer":"default","id":"K_QUOTE","text":"'"},{"layer":"shift","id":"K_QUOTE","text":"\""},{"layer":"default","id":"K_BKSLASH","text":"\\"},{"layer":"shift","id":"K_COLON","text":":"},{"layer":"default","id":"K_COLON","text":";"}]},{"width":"90","id":"K_BKSP","sp":"1","text":"*BkSp*"}]},{"id":"4","key":[{"nextlayer":"numeric","width":"140","id":"K_NUMLOCK","sp":"1","text":"*123*"},{"width":"120","id":"K_LOPT","sp":"1","text":"*Menu*"},{"width":"630","id":"K_SPACE"},{"width":"140","id":"K_ENTER","sp":"1","text":"*Enter*"}]}]},{"id":"numeric","row":[{"id":"1","key":[{"id":"K_1","text":"1"},{"id":"K_2","text":"2"},{"id":"K_3","text":"3"},{"id":"K_4","text":"4"},{"id":"K_5","text":"5"},{"id":"K_6","text":"6"},{"id":"K_7","text":"7"},{"id":"K_8","text":"8"},{"id":"K_9","text":"9"},{"id":"K_0","text":"0"}]},{"id":"2","key":[{"layer":"shift","id":"K_4","pad":"70","text":"$"},{"layer":"shift","id":"K_2","text":"@"},{"layer":"shift","id":"K_3","text":"#"},{"layer":"shift","id":"K_5","text":"%"},{"layer":"shift","id":"K_7","text":"&"},{"layer":"shift","id":"K_HYPHEN","text":"_"},{"layer":"default","id":"K_EQUAL","text":"="},{"layer":"shift","id":"K_BKSLASH","text":"|"},{"layer":"default","id":"K_BKSLASH","text":"\\"},{"width":"10","sp":"10"}]},{"id":"3","key":[{"width":"110","id":"K_SHIFT","sp":"1","text":"*Shift*"},{"id":"K_LBRKT","text":"[","sk":[{"id":"U_00AB","text":"\u00AB"},{"layer":"shift","id":"K_COMMA","text":"<"},{"layer":"shift","id":"K_LBRKT","text":"{"}]},{"layer":"shift","id":"K_9","text":"("},{"layer":"shift","id":"K_0","text":")"},{"id":"K_RBRKT","text":"]","sk":[{"id":"U_00BB","text":"\u00BB"},{"layer":"shift","id":"K_PERIOD","text":">"},{"layer":"shift","id":"K_RBRKT","text":"}"}]},{"layer":"shift","id":"K_EQUAL","text":"+"},{"layer":"default","id":"K_HYPHEN","text":"-"},{"layer":"shift","id":"K_8","text":"*"},{"layer":"default","id":"K_SLASH","text":"\/"},{"width":"90","id":"K_BKSP","sp":"1","text":"*BkSp*"}]},{"id":"4","key":[{"nextlayer":"default","width":"140","id":"K_LOWER","sp":"1","text":"*abc*"},{"width":"120","id":"K_LOPT","sp":"1","text":"*Menu*"},{"width":"630","id":"K_SPACE"},{"width":"140","id":"K_ENTER","sp":"1","text":"*Enter*"}]}]}]}};this.KVER="17.0.162.0";this.KVS=[];this.gs=function(t,e) {return this.g0(t,e);};this.gs=function(t,e) {return this.g0(t,e);};this.g0=function(t,e) {var k=KeymanWeb,r=0,m=0;if(k.KKM(e,16384,256)) {if(1){r=m=1;k.KDC(0,t);k.KO(-1,t,"default");}}return r;};} \ No newline at end of file diff --git a/web/src/test/manual/web/default-subkey/index.html b/web/src/test/manual/web/default-subkey/index.html new file mode 100644 index 00000000000..728355c43b4 --- /dev/null +++ b/web/src/test/manual/web/default-subkey/index.html @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + KeymanWeb Testing Page - Predictive Text: robust testing + + + + + + + + + + + + + + + + +

KeymanWeb Sample Page - default subkey bootstrap-testing

+

Note: the intended tests require use of a touch-form-factor device or emulation thereof. +

+

+ The primary test is held on the default layer's 'd' key - the key labeled 'default' should + be autoselected. +

+

+ A secondary test is held on the default layer's 'a' key - the key labeled 'a', matching the + base key, should be autoselected. +

+
+ +
+ +

Type in your language in this text area:

+ + +

or in this input field:

+ + +

Return to testing home page

+
+ + + + + diff --git a/web/src/test/manual/web/default-subkey/kbd_source/HISTORY.md b/web/src/test/manual/web/default-subkey/kbd_source/HISTORY.md new file mode 100644 index 00000000000..cbd807699c4 --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/HISTORY.md @@ -0,0 +1,6 @@ +default-subkey Change History +==================== + +1.0 (2023-08-21) +---------------- +* Created by SIL International diff --git a/web/src/test/manual/web/default-subkey/kbd_source/LICENSE.md b/web/src/test/manual/web/default-subkey/kbd_source/LICENSE.md new file mode 100644 index 00000000000..b582b3f9086 --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +© 2023 SIL International + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/web/src/test/manual/web/default-subkey/kbd_source/README.md b/web/src/test/manual/web/default-subkey/kbd_source/README.md new file mode 100644 index 00000000000..9fb82bd00ba --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/README.md @@ -0,0 +1,30 @@ +default-subkey keyboard +============== + +Version 1.0 + +Description +----------- +default-subkey generated from template + +Links +----- + +Copyright +--------- +See [LICENSE.md](LICENSE.md) + +Supported Platforms +------------------- + * Windows + * macOS + * Linux + * Web + * iPhone + * iPad + * Android phone + * Android tablet + * Mobile devices + * Desktop devices + * Tablet devices + diff --git a/web/src/test/manual/web/default-subkey/kbd_source/default_subkey.keyboard_info b/web/src/test/manual/web/default-subkey/kbd_source/default_subkey.keyboard_info new file mode 100644 index 00000000000..1677ce4c2f4 --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/default_subkey.keyboard_info @@ -0,0 +1,7 @@ +{ + "license": "mit", + "languages": [ + + ], + "description": "default-subkey generated from template" +} diff --git a/web/src/test/manual/web/default-subkey/kbd_source/default_subkey.kpj b/web/src/test/manual/web/default-subkey/kbd_source/default_subkey.kpj new file mode 100644 index 00000000000..4de714dbd3b --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/default_subkey.kpj @@ -0,0 +1,110 @@ + + + + $PROJECTPATH\build + True + True + True + keyboard + + + + id_8305ac63cf6c1388736030b6b94f996d + default_subkey.kmn + source\default_subkey.kmn + 1.0 + .kmn +
+ default-subkey + © SIL International +
+
+ + id_f586f51f683bde64c75f566e643e59bd + default_subkey.kps + source\default_subkey.kps + + .kps +
+ default-subkey + © SIL International +
+
+ + id_ede98e4633e239f933cbfd1f4e1b766c + HISTORY.md + HISTORY.md + + .md + + + id_53e892b8b41cc4caece1cfd5ef21d6e7 + LICENSE.md + LICENSE.md + + .md + + + id_0730bb7c2e8f9ea2438b52e419dd86c9 + README.md + README.md + + .md + + + id_9cc75be74cee7f9a4937893e80b91b5f + default_subkey.keyboard_info + default_subkey.keyboard_info + + .keyboard_info + + + id_d8483af80632f8b611983c11137efccd + default_subkey.ico + source\default_subkey.ico + + .ico + id_8305ac63cf6c1388736030b6b94f996d + + + id_5086f2e8ef1d731c015a78f418aba1e8 + default_subkey.kmx + source\..\build\default_subkey.kmx + + .kmx + id_f586f51f683bde64c75f566e643e59bd + + + id_c8c9acd9c28010e45856034bff6c9d90 + default_subkey.js + source\..\build\default_subkey.js + + .js + id_f586f51f683bde64c75f566e643e59bd + + + id_7b38ddd4f3836ebf9365696475ade08a + default_subkey.kvk + source\..\build\default_subkey.kvk + + .kvk + id_f586f51f683bde64c75f566e643e59bd + + + id_356e5d149c1e539356d72698c1e401a6 + welcome.htm + source\welcome.htm + + .htm + id_f586f51f683bde64c75f566e643e59bd + + + id_8da344c4cea6f467013357fe099006f5 + readme.htm + source\readme.htm + + .htm + id_f586f51f683bde64c75f566e643e59bd + +
+
diff --git a/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.ico b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.ico new file mode 100644 index 0000000000000000000000000000000000000000..e3628ccc9b2823958484107ff80fed06c5a02228 GIT binary patch literal 1150 zcmZQzU<5(|0R;vS$Y5b$5ChU0Kr8^n3P8*VCV>o~96C5~=orH&9{4bbXx+$=mmkd# zkzd3xqcs{FCor)*pxBz$B8EJmngi=Pu*Mg%T;438e`aB-M^=L#=g4x+>yCl#L$QBW v2Ln1E*$ia;", + "layer": "shift" + }, + { + "id": "K_RBRKT", + "text": "}", + "layer": "shift" + } + ] + }, + { + "id": "K_EQUAL", + "text": "+", + "layer": "shift" + }, + { + "id": "K_HYPHEN", + "text": "-", + "layer": "default" + }, + { + "id": "K_8", + "text": "*", + "layer": "shift" + }, + { + "id": "K_SLASH", + "text": "/", + "layer": "default" + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": 90, + "sp": 1 + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_LOWER", + "text": "*abc*", + "width": 140, + "sp": 1, + "nextlayer": "default" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": 120, + "sp": 1 + }, + { + "id": "K_SPACE", + "text": "", + "width": 630, + "sp": 0 + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": 140, + "sp": 1 + } + ] + } + ] + } + ] + } +} \ No newline at end of file diff --git a/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kmn b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kmn new file mode 100644 index 00000000000..f1ac06ea5e9 --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kmn @@ -0,0 +1,16 @@ +c default_subkey generated from template at 2023-08-21 10:14:50 +c with name "default-subkey" +store(&VERSION) '10.0' +store(&NAME) 'default-subkey' +store(©RIGHT) '© SIL International' +store(&KEYBOARDVERSION) '1.0' +store(&TARGETS) 'any' +store(&BITMAP) 'default_subkey.ico' +store(&VISUALKEYBOARD) 'default_subkey.kvks' +store(&LAYOUTFILE) 'default_subkey.keyman-touch-layout' + +begin Unicode > use(main) + +group(main) using keys + ++ [ T_d_default ] > "default" diff --git a/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kps b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kps new file mode 100644 index 00000000000..291e349d760 --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kps @@ -0,0 +1,65 @@ + + + + 17.0.162.0 + 7.0 + + + + readme.htm + + + + + + + + + + default-subkey + © SIL International + SIL International + + + + + ..\build\default_subkey.kmx + + 0 + .kmx + + + ..\build\default_subkey.js + + 0 + .js + + + ..\build\default_subkey.kvk + + 0 + .kvk + + + welcome.htm + + 0 + .htm + + + readme.htm + + 0 + .htm + + + + + default-subkey + default_subkey + 1.0 + + + + + diff --git a/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kvks b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kvks new file mode 100644 index 00000000000..830237b17e9 --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kvks @@ -0,0 +1,8 @@ + + +
+ 10.0 + default_subkey + +
+
diff --git a/web/src/test/manual/web/default-subkey/kbd_source/source/readme.htm b/web/src/test/manual/web/default-subkey/kbd_source/source/readme.htm new file mode 100644 index 00000000000..8bce21ff5d7 --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/source/readme.htm @@ -0,0 +1,24 @@ + + + + + + default-subkey + + + + +

default-subkey

+ +

+ default-subkey 1.0 generated from template. +

+ +

© SIL International

+ + + diff --git a/web/src/test/manual/web/default-subkey/kbd_source/source/welcome.htm b/web/src/test/manual/web/default-subkey/kbd_source/source/welcome.htm new file mode 100644 index 00000000000..cdf7e1e234b --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/source/welcome.htm @@ -0,0 +1,26 @@ + + + + + + Start Using default-subkey + + + + +

Start Using default-subkey

+ +

+ default-subkey 1.0 generated from template. +

+ +

Keyboard Layout

+ + + + + \ No newline at end of file diff --git a/web/src/test/manual/web/index.html b/web/src/test/manual/web/index.html index 9931e3998ba..fce84d11a68 100644 --- a/web/src/test/manual/web/index.html +++ b/web/src/test/manual/web/index.html @@ -64,6 +64,7 @@

Test Caps Lock Layer (#3620)

Test Start of Sentence (#3621)

Test start of sentence keyboard rules (#5963)

Tests predictive text & other handling of rule matching when the final rule group does not match (#6005)

+

Tests handling of new default-subkey feature (#9430)

Other

Keystroke processing regression test engine.

Return to main index. From dc033b98bf5430f1d9963088aad6c9194443bfed Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Mon, 21 Aug 2023 10:57:51 +0700 Subject: [PATCH 2/6] docs(android): markers for sites to add default subkey handling code --- .../KMEA/app/src/main/java/com/keyman/engine/KMKeyboard.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboard.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboard.java index bc0aed1d049..cf299230d02 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboard.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboard.java @@ -397,6 +397,7 @@ public boolean onTouchEvent(MotionEvent event) { if (action == MotionEvent.ACTION_UP) { // Cleanup popups. #6636 dismissKeyPreview(0); + // TODO: default subkey handling dismissSubKeysWindow(); } @@ -970,6 +971,7 @@ public void onDismiss() { @SuppressLint({"InflateParams", "ClickableViewAccessibility"}) private void showSubKeys(Context context) { + // TODO: we'll need to pre-select the default key if it exists here! if (subKeysList == null || subKeysWindow != null) { return; } @@ -1060,6 +1062,7 @@ private void showSubKeys(Context context) { // Helps keep things from totally breaking when the event handler triggering subkey menu // generation and the menu's event handler stop talking to each other. final ArrayList> subkeyList = subKeysList; + // NOTE: keys are currently only executed from an actual 'click'. button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { @@ -1117,6 +1120,7 @@ public boolean onTouch(View v, MotionEvent event) { break; } } + // TODO: Is there a default subkey? If so, and we're still within the key-grid or similar, trigger it. dismissSubKeysWindow(); return true; } else if (action == MotionEvent.ACTION_MOVE) { From 3adf4dc6ebbbb7de6f569047fd9b93107bc6cddd Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Mon, 21 Aug 2023 11:41:44 +0700 Subject: [PATCH 3/6] fix(web): stuck base-key highlighting upon default selection --- web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts | 2 ++ web/src/test/manual/web/default-subkey/default_subkey.js | 2 +- .../kbd_source/source/default_subkey.keyman-touch-layout | 4 ++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts b/web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts index 9d7f0030002..94dcf2a65cd 100644 --- a/web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts +++ b/web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts @@ -235,6 +235,8 @@ export default class SubkeyPopup implements RealizedGesture { } if(bk) { + // Prevent sticky-highlighting should the default key be selected. + vkbd.keyPending?.key.highlight(false); vkbd.keyPending = bk; this.currentSelection = bk; // Subkeys never get key previews, so we can directly highlight the subkey. diff --git a/web/src/test/manual/web/default-subkey/default_subkey.js b/web/src/test/manual/web/default-subkey/default_subkey.js index 1d656018754..556acda19a2 100644 --- a/web/src/test/manual/web/default-subkey/default_subkey.js +++ b/web/src/test/manual/web/default-subkey/default_subkey.js @@ -1 +1 @@ -if(typeof keyman === 'undefined') {console.log('Keyboard requires KeymanWeb 10.0 or later');if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later");} else {KeymanWeb.KR(new Keyboard_default_subkey());}function Keyboard_default_subkey(){this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;this.KI="Keyboard_default_subkey";this.KN="default-subkey";this.KMINVER="10.0";this.KV={F:' 1em "Arial"',K102:0};this.KV.KLS={};this.KV.BK=(function(x){var e=Array.apply(null,Array(65)).map(String.prototype.valueOf,""),r=[],v,i,m=['default','shift','ctrl','shift-ctrl','alt','shift-alt','ctrl-alt','shift-ctrl-alt'];for(i=m.length-1;i>=0;i--)if((v=x[m[i]])||r.length)r=(v?v:e).slice().concat(r);return r})(this.KV.KLS);this.KDU=0;this.KH='';this.KM=0;this.KBVER="1.0";this.KMBM=0x0000;this.KVKD="T_d_default";this.KVKL={"tablet":{"font":"Tahoma","displayUnderlying":false,"layer":[{"id":"default","row":[{"id":"1","key":[{"id":"K_Q","text":"q"},{"id":"K_W","text":"w"},{"id":"K_E","text":"e"},{"id":"K_R","text":"r"},{"id":"K_T","text":"t"},{"id":"K_Y","text":"y"},{"id":"K_U","text":"u"},{"id":"K_I","text":"i"},{"id":"K_O","text":"o"},{"id":"K_P","text":"p"}]},{"id":"2","key":[{"id":"K_A","pad":"70","text":"a","sk":[{"id":"U_00E1","text":"\u00E1"},{"id":"U_00E0","text":"\u00E0"},{"id":"K_A","text":"a"},{"id":"U_00E4","text":"\u00E4"},{"id":"U_00E5","text":"\u00E5"},{"id":"U_00E2","text":"\u00E2"},{"id":"U_00E3","text":"\u00E3"}]},{"id":"K_S","text":"s"},{"id":"K_D","text":"d","sk":[{"id":"U_010F","text":"\u010F"},{"id":"U_0111","text":"\u0111"},{"id":"U_0257","text":"\u0257"},{"id":"T_d_default","text":"default","default":true},{"id":"U_0221","text":"\u0221"}]},{"id":"K_F","text":"f"},{"id":"K_G","text":"g"},{"id":"K_H","text":"h"},{"id":"K_J","text":"j"},{"id":"K_K","text":"k"},{"id":"K_L","text":"l"},{"width":"10","id":"T_new_88","sp":"10"}]},{"id":"3","key":[{"nextlayer":"shift","width":"110","id":"K_SHIFT","sp":"1","text":"*Shift*"},{"id":"K_Z","text":"z"},{"id":"K_X","text":"x"},{"id":"K_C","text":"c"},{"id":"K_V","text":"v"},{"id":"K_B","text":"b"},{"id":"K_N","text":"n"},{"id":"K_M","text":"m"},{"id":"K_PERIOD","text":".","sk":[{"id":"K_COMMA","text":","},{"layer":"shift","id":"K_1","text":"!"},{"layer":"shift","id":"K_SLASH","text":"?"},{"id":"K_QUOTE","text":"'"},{"layer":"shift","id":"K_QUOTE","text":"\""},{"id":"K_BKSLASH","text":"\\"},{"layer":"shift","id":"K_COLON","text":":"},{"id":"K_COLON","text":";"}]},{"width":"90","id":"K_BKSP","sp":"1","text":"*BkSp*"}]},{"id":"4","key":[{"nextlayer":"numeric","width":"140","id":"K_NUMLOCK","sp":"1","text":"*123*"},{"width":"120","id":"K_LOPT","sp":"1","text":"*Menu*"},{"width":"630","id":"K_SPACE"},{"width":"140","id":"K_ENTER","sp":"1","text":"*Enter*"}]}]},{"id":"shift","row":[{"id":"1","key":[{"id":"K_Q","text":"Q"},{"id":"K_W","text":"W"},{"id":"K_E","text":"E"},{"id":"K_R","text":"R"},{"id":"K_T","text":"T"},{"id":"K_Y","text":"Y"},{"id":"K_U","text":"U"},{"id":"K_I","text":"I"},{"id":"K_O","text":"O"},{"id":"K_P","text":"P"}]},{"id":"2","key":[{"id":"K_A","pad":"70","text":"A"},{"id":"K_S","text":"S"},{"id":"K_D","text":"D"},{"id":"K_F","text":"F"},{"id":"K_G","text":"G"},{"id":"K_H","text":"H"},{"id":"K_J","text":"J"},{"id":"K_K","text":"K"},{"id":"K_L","text":"L"},{"width":"10","sp":"10"}]},{"id":"3","key":[{"nextlayer":"default","width":"110","id":"K_SHIFT","sp":"2","text":"*Shift*"},{"id":"K_Z","text":"Z"},{"id":"K_X","text":"X"},{"id":"K_C","text":"C"},{"id":"K_V","text":"V"},{"id":"K_B","text":"B"},{"id":"K_N","text":"N"},{"id":"K_M","text":"M"},{"layer":"default","id":"K_PERIOD","text":".","sk":[{"layer":"default","id":"K_COMMA","text":","},{"layer":"shift","id":"K_1","text":"!"},{"layer":"shift","id":"K_SLASH","text":"?"},{"layer":"default","id":"K_QUOTE","text":"'"},{"layer":"shift","id":"K_QUOTE","text":"\""},{"layer":"default","id":"K_BKSLASH","text":"\\"},{"layer":"shift","id":"K_COLON","text":":"},{"layer":"default","id":"K_COLON","text":";"}]},{"width":"90","id":"K_BKSP","sp":"1","text":"*BkSp*"}]},{"id":"4","key":[{"nextlayer":"numeric","width":"140","id":"K_NUMLOCK","sp":"1","text":"*123*"},{"width":"120","id":"K_LOPT","sp":"1","text":"*Menu*"},{"width":"630","id":"K_SPACE"},{"width":"140","id":"K_ENTER","sp":"1","text":"*Enter*"}]}]},{"id":"numeric","row":[{"id":"1","key":[{"id":"K_1","text":"1"},{"id":"K_2","text":"2"},{"id":"K_3","text":"3"},{"id":"K_4","text":"4"},{"id":"K_5","text":"5"},{"id":"K_6","text":"6"},{"id":"K_7","text":"7"},{"id":"K_8","text":"8"},{"id":"K_9","text":"9"},{"id":"K_0","text":"0"}]},{"id":"2","key":[{"layer":"shift","id":"K_4","pad":"70","text":"$"},{"layer":"shift","id":"K_2","text":"@"},{"layer":"shift","id":"K_3","text":"#"},{"layer":"shift","id":"K_5","text":"%"},{"layer":"shift","id":"K_7","text":"&"},{"layer":"shift","id":"K_HYPHEN","text":"_"},{"layer":"default","id":"K_EQUAL","text":"="},{"layer":"shift","id":"K_BKSLASH","text":"|"},{"layer":"default","id":"K_BKSLASH","text":"\\"},{"width":"10","sp":"10"}]},{"id":"3","key":[{"width":"110","id":"K_SHIFT","sp":"1","text":"*Shift*"},{"id":"K_LBRKT","text":"[","sk":[{"id":"U_00AB","text":"\u00AB"},{"layer":"shift","id":"K_COMMA","text":"<"},{"layer":"shift","id":"K_LBRKT","text":"{"}]},{"layer":"shift","id":"K_9","text":"("},{"layer":"shift","id":"K_0","text":")"},{"id":"K_RBRKT","text":"]","sk":[{"id":"U_00BB","text":"\u00BB"},{"layer":"shift","id":"K_PERIOD","text":">"},{"layer":"shift","id":"K_RBRKT","text":"}"}]},{"layer":"shift","id":"K_EQUAL","text":"+"},{"layer":"default","id":"K_HYPHEN","text":"-"},{"layer":"shift","id":"K_8","text":"*"},{"layer":"default","id":"K_SLASH","text":"\/"},{"width":"90","id":"K_BKSP","sp":"1","text":"*BkSp*"}]},{"id":"4","key":[{"nextlayer":"default","width":"140","id":"K_LOWER","sp":"1","text":"*abc*"},{"width":"120","id":"K_LOPT","sp":"1","text":"*Menu*"},{"width":"630","id":"K_SPACE"},{"width":"140","id":"K_ENTER","sp":"1","text":"*Enter*"}]}]}]}};this.KVER="17.0.162.0";this.KVS=[];this.gs=function(t,e) {return this.g0(t,e);};this.gs=function(t,e) {return this.g0(t,e);};this.g0=function(t,e) {var k=KeymanWeb,r=0,m=0;if(k.KKM(e,16384,256)) {if(1){r=m=1;k.KDC(0,t);k.KO(-1,t,"default");}}return r;};} \ No newline at end of file +if(typeof keyman === 'undefined') {console.log('Keyboard requires KeymanWeb 10.0 or later');if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later");} else {KeymanWeb.KR(new Keyboard_default_subkey());}function Keyboard_default_subkey(){this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;this.KI="Keyboard_default_subkey";this.KN="default-subkey";this.KMINVER="10.0";this.KV={F:' 1em "Arial"',K102:0};this.KV.KLS={};this.KV.BK=(function(x){var e=Array.apply(null,Array(65)).map(String.prototype.valueOf,""),r=[],v,i,m=['default','shift','ctrl','shift-ctrl','alt','shift-alt','ctrl-alt','shift-ctrl-alt'];for(i=m.length-1;i>=0;i--)if((v=x[m[i]])||r.length)r=(v?v:e).slice().concat(r);return r})(this.KV.KLS);this.KDU=0;this.KH='';this.KM=0;this.KBVER="1.0";this.KMBM=0x0000;this.KVKD="T_d_default";this.KVKL={"tablet":{"font":"Tahoma","displayUnderlying":false,"layer":[{"id":"default","row":[{"id":"1","key":[{"id":"K_Q","text":"q"},{"id":"K_W","text":"w"},{"id":"K_E","text":"e"},{"id":"K_R","text":"r"},{"id":"K_T","text":"t"},{"id":"K_Y","text":"y"},{"id":"K_U","text":"u"},{"id":"K_I","text":"i"},{"id":"K_O","text":"o"},{"id":"K_P","text":"p"}]},{"id":"2","key":[{"id":"K_A","pad":"70","text":"a","sk":[{"id":"U_00E1","text":"\u00E1"},{"id":"U_00E0","text":"\u00E0"},{"id":"K_A","text":"a"},{"id":"U_00E4","text":"\u00E4"},{"id":"U_00E5","text":"\u00E5"},{"id":"U_00E2","text":"\u00E2"},{"id":"U_00E3","text":"\u00E3"}]},{"id":"K_S","text":"s"},{"id":"K_D","text":"d","sk":[{"id":"K_D","text":"d"},{"id":"U_010F","text":"\u010F"},{"id":"U_0111","text":"\u0111"},{"id":"U_0257","text":"\u0257"},{"id":"T_d_default","text":"default","default":true},{"id":"U_0221","text":"\u0221"}]},{"id":"K_F","text":"f"},{"id":"K_G","text":"g"},{"id":"K_H","text":"h"},{"id":"K_J","text":"j"},{"id":"K_K","text":"k"},{"id":"K_L","text":"l"},{"width":"10","id":"T_new_88","sp":"10"}]},{"id":"3","key":[{"nextlayer":"shift","width":"110","id":"K_SHIFT","sp":"1","text":"*Shift*"},{"id":"K_Z","text":"z"},{"id":"K_X","text":"x"},{"id":"K_C","text":"c"},{"id":"K_V","text":"v"},{"id":"K_B","text":"b"},{"id":"K_N","text":"n"},{"id":"K_M","text":"m"},{"id":"K_PERIOD","text":".","sk":[{"id":"K_COMMA","text":","},{"layer":"shift","id":"K_1","text":"!"},{"layer":"shift","id":"K_SLASH","text":"?"},{"id":"K_QUOTE","text":"'"},{"layer":"shift","id":"K_QUOTE","text":"\""},{"id":"K_BKSLASH","text":"\\"},{"layer":"shift","id":"K_COLON","text":":"},{"id":"K_COLON","text":";"}]},{"width":"90","id":"K_BKSP","sp":"1","text":"*BkSp*"}]},{"id":"4","key":[{"nextlayer":"numeric","width":"140","id":"K_NUMLOCK","sp":"1","text":"*123*"},{"width":"120","id":"K_LOPT","sp":"1","text":"*Menu*"},{"width":"630","id":"K_SPACE"},{"width":"140","id":"K_ENTER","sp":"1","text":"*Enter*"}]}]},{"id":"shift","row":[{"id":"1","key":[{"id":"K_Q","text":"Q"},{"id":"K_W","text":"W"},{"id":"K_E","text":"E"},{"id":"K_R","text":"R"},{"id":"K_T","text":"T"},{"id":"K_Y","text":"Y"},{"id":"K_U","text":"U"},{"id":"K_I","text":"I"},{"id":"K_O","text":"O"},{"id":"K_P","text":"P"}]},{"id":"2","key":[{"id":"K_A","pad":"70","text":"A"},{"id":"K_S","text":"S"},{"id":"K_D","text":"D"},{"id":"K_F","text":"F"},{"id":"K_G","text":"G"},{"id":"K_H","text":"H"},{"id":"K_J","text":"J"},{"id":"K_K","text":"K"},{"id":"K_L","text":"L"},{"width":"10","sp":"10"}]},{"id":"3","key":[{"nextlayer":"default","width":"110","id":"K_SHIFT","sp":"2","text":"*Shift*"},{"id":"K_Z","text":"Z"},{"id":"K_X","text":"X"},{"id":"K_C","text":"C"},{"id":"K_V","text":"V"},{"id":"K_B","text":"B"},{"id":"K_N","text":"N"},{"id":"K_M","text":"M"},{"layer":"default","id":"K_PERIOD","text":".","sk":[{"layer":"default","id":"K_COMMA","text":","},{"layer":"shift","id":"K_1","text":"!"},{"layer":"shift","id":"K_SLASH","text":"?"},{"layer":"default","id":"K_QUOTE","text":"'"},{"layer":"shift","id":"K_QUOTE","text":"\""},{"layer":"default","id":"K_BKSLASH","text":"\\"},{"layer":"shift","id":"K_COLON","text":":"},{"layer":"default","id":"K_COLON","text":";"}]},{"width":"90","id":"K_BKSP","sp":"1","text":"*BkSp*"}]},{"id":"4","key":[{"nextlayer":"numeric","width":"140","id":"K_NUMLOCK","sp":"1","text":"*123*"},{"width":"120","id":"K_LOPT","sp":"1","text":"*Menu*"},{"width":"630","id":"K_SPACE"},{"width":"140","id":"K_ENTER","sp":"1","text":"*Enter*"}]}]},{"id":"numeric","row":[{"id":"1","key":[{"id":"K_1","text":"1"},{"id":"K_2","text":"2"},{"id":"K_3","text":"3"},{"id":"K_4","text":"4"},{"id":"K_5","text":"5"},{"id":"K_6","text":"6"},{"id":"K_7","text":"7"},{"id":"K_8","text":"8"},{"id":"K_9","text":"9"},{"id":"K_0","text":"0"}]},{"id":"2","key":[{"layer":"shift","id":"K_4","pad":"70","text":"$"},{"layer":"shift","id":"K_2","text":"@"},{"layer":"shift","id":"K_3","text":"#"},{"layer":"shift","id":"K_5","text":"%"},{"layer":"shift","id":"K_7","text":"&"},{"layer":"shift","id":"K_HYPHEN","text":"_"},{"layer":"default","id":"K_EQUAL","text":"="},{"layer":"shift","id":"K_BKSLASH","text":"|"},{"layer":"default","id":"K_BKSLASH","text":"\\"},{"width":"10","sp":"10"}]},{"id":"3","key":[{"width":"110","id":"K_SHIFT","sp":"1","text":"*Shift*"},{"id":"K_LBRKT","text":"[","sk":[{"id":"U_00AB","text":"\u00AB"},{"layer":"shift","id":"K_COMMA","text":"<"},{"layer":"shift","id":"K_LBRKT","text":"{"}]},{"layer":"shift","id":"K_9","text":"("},{"layer":"shift","id":"K_0","text":")"},{"id":"K_RBRKT","text":"]","sk":[{"id":"U_00BB","text":"\u00BB"},{"layer":"shift","id":"K_PERIOD","text":">"},{"layer":"shift","id":"K_RBRKT","text":"}"}]},{"layer":"shift","id":"K_EQUAL","text":"+"},{"layer":"default","id":"K_HYPHEN","text":"-"},{"layer":"shift","id":"K_8","text":"*"},{"layer":"default","id":"K_SLASH","text":"\/"},{"width":"90","id":"K_BKSP","sp":"1","text":"*BkSp*"}]},{"id":"4","key":[{"nextlayer":"default","width":"140","id":"K_LOWER","sp":"1","text":"*abc*"},{"width":"120","id":"K_LOPT","sp":"1","text":"*Menu*"},{"width":"630","id":"K_SPACE"},{"width":"140","id":"K_ENTER","sp":"1","text":"*Enter*"}]}]}]}};this.KVER="17.0.162.0";this.KVS=[];this.gs=function(t,e) {return this.g0(t,e);};this.gs=function(t,e) {return this.g0(t,e);};this.g0=function(t,e) {var k=KeymanWeb,r=0,m=0;if(k.KKM(e,16384,256)) {if(1){r=m=1;k.KDC(0,t);k.KO(-1,t,"default");}}return r;};} \ No newline at end of file diff --git a/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.keyman-touch-layout b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.keyman-touch-layout index a0641c40791..41cbf16e1d9 100644 --- a/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.keyman-touch-layout +++ b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.keyman-touch-layout @@ -96,6 +96,10 @@ "id": "K_D", "text": "d", "sk": [ + { + "text": "d", + "id": "K_D" + }, { "text": "ď", "id": "U_010F" From bf713d10439fd56f31cff273f60933cacaf2ac89 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Mon, 21 Aug 2023 12:16:22 +0700 Subject: [PATCH 4/6] fix(web): test resource package compilation --- .../web/default-subkey/kbd_source/source/default_subkey.kps | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kps b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kps index 291e349d760..97cbafecd72 100644 --- a/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kps +++ b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kps @@ -58,7 +58,9 @@ default-subkey default_subkey 1.0 - + + English + From 909331df62734410c11741c60d0b321632082430 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Mon, 21 Aug 2023 12:22:52 +0700 Subject: [PATCH 5/6] feat(web): allows small fudge-factor before cancelling default --- .../src/input/gestures/browser/subkeyPopup.ts | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts b/web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts index 94dcf2a65cd..8482aa85e85 100644 --- a/web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts +++ b/web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts @@ -36,6 +36,9 @@ export default class SubkeyPopup implements RealizedGesture { public readonly baseKey: KeyElement; public readonly promise: Promise; + private initialX: number; + private initialY: number; + // Resolves the promise that generated this SubkeyPopup. private resolver: (keyEvent: KeyEvent) => void; @@ -269,7 +272,33 @@ export default class SubkeyPopup implements RealizedGesture { } updateTouch(input: InputEventCoordinate) { - this.currentSelection = null; + // For 'default' subkey handling, we want a small fudge factor. + if(this.initialX === undefined || this.initialY === undefined) { + this.initialX = input.x; + this.initialY = input.y; + } + + const deltaX = this.initialX - input.x; + const deltaY = this.initialY - input.y; + const dist = Math.sqrt(deltaX * deltaX + deltaY * deltaY); + + if(dist > 5) { + this.initialX = Number.MAX_SAFE_INTEGER; // it'll always exceed the threshold hereafter. + this.currentSelection = null; + } else { + // The function that calls this to perform subkey updates auto-unhighlights the active selection; + // make sure that highlighting is maintained if no new key was selected, but we haven't cancelled + // default-selection mode yet. + this.currentSelection.key.highlight(true); + + // Even if we technically have a different subkey underneath the touchpoint, we're still in + // default-selection mode. Require more movement before cancelling default-selection mode. + // + // Can occur for large subkey menus or when subkey menus are "constrained" within OSK bounds, + // as with the iOS app. + return; + } + this.baseKey.key.highlight(false); for(let i=0; i < this.baseKey['subKeys'].length; i++) { From a5cbf6aab864b822a3a589f30cee96c33bd2fc41 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Thu, 28 Sep 2023 16:40:29 +0700 Subject: [PATCH 6/6] fix(web): test page path on the index page --- web/src/test/manual/web/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/test/manual/web/index.html b/web/src/test/manual/web/index.html index 6d5c4bb4660..2597d8caac5 100644 --- a/web/src/test/manual/web/index.html +++ b/web/src/test/manual/web/index.html @@ -64,7 +64,7 @@

Test Caps Lock Layer (#3620)

Test Start of Sentence (#3621)

Test start of sentence keyboard rules (#5963)

Tests predictive text & other handling of rule matching when the final rule group does not match (#6005)

-

Tests handling of new default-subkey feature (#9430)

+

Tests handling of new default-subkey feature (#9430)

Test special characters rendering with keymanweb-osk.ttf (#9469)

Other

Keystroke processing regression test engine.