From 69b309104acbc808f8fede1e2fd6cf080d957ec4 Mon Sep 17 00:00:00 2001 From: jahorton Date: Sat, 21 Mar 2020 21:40:40 +0700 Subject: [PATCH] refactor(web/engine): moves CJK, RTL, chiral checks to Keyboard wrapper --- web/source/keyboards/keyboard.ts | 31 +++++++++++ web/source/keyboards/kmwkeyboards.ts | 79 +++------------------------- web/source/kmwbase.ts | 22 ++++++-- web/source/kmwdom.ts | 5 +- web/source/kmwdomevents.ts | 2 +- web/source/osk/banner.ts | 6 ++- web/source/osk/defaultLayouts.ts | 13 +++-- web/source/osk/oskManager.ts | 6 +-- web/source/osk/visualKeyboard.ts | 8 +-- web/source/text/kbdInterface.ts | 3 +- web/source/text/processor.ts | 14 ++--- 11 files changed, 89 insertions(+), 100 deletions(-) diff --git a/web/source/keyboards/keyboard.ts b/web/source/keyboards/keyboard.ts index 95b20608b1..776b14fe65 100644 --- a/web/source/keyboards/keyboard.ts +++ b/web/source/keyboards/keyboard.ts @@ -64,6 +64,37 @@ namespace com.keyman.keyboards { return this.scriptObject['KCSS']; } + /** + * true if this keyboard uses a (legacy) pick list (Chinese, Japanese, Korean, etc.) + */ + get isCJK(): boolean { // I3363 (Build 301) + var lg: string; + if(typeof(this.scriptObject['KLC']) != 'undefined') { + lg = this.scriptObject['KLC']; + } else if(typeof(this.scriptObject['LanguageCode']) != 'undefined') { + lg = this.scriptObject['LanguageCode']; + } + + // While some of these aren't proper BCP-47 language codes, the CJK keyboards predate our use of BCP-47. + // So, we preserve the old ISO 639-3 codes, as that's what the keyboards are matching against. + return ((lg == 'cmn') || (lg == 'jpn') || (lg == 'kor')); + } + + get isRTL(): boolean { + return !!this.scriptObject['KRTL']; + } + + /** + * Obtains the currently-active modifier bitmask for the active keyboard. + */ + get modifierBitmask(): number { + return this.scriptObject['KMBM'] || text.Codes.modifierBitmasks['NON_CHIRAL']; + } + + get isChiral(): boolean { + return !!(this.modifierBitmask & text.Codes.modifierBitmasks['IS_CHIRAL']); + } + // TODO: Provide public property-retrieving methods on this class, rather than as part of // the KeyboardManager object. } diff --git a/web/source/keyboards/kmwkeyboards.ts b/web/source/keyboards/kmwkeyboards.ts index 9f8de89b86..f70a608a47 100644 --- a/web/source/keyboards/kmwkeyboards.ts +++ b/web/source/keyboards/kmwkeyboards.ts @@ -796,85 +796,20 @@ namespace com.keyman.keyboards { * Scope Public * @param {Object=} k0 * @return {boolean} - * Description Tests if active keyboard (or optional argument) uses a pick list (Chinese, Japanese, Korean, etc.) + * Description Tests if the keyboard stub uses a pick list (Chinese, Japanese, Korean, etc.) * (This function accepts either keyboard structure.) */ - isCJK(k0?: any|KeyboardStub) { // I3363 (Build 301) - let textProcessor = com.keyman.singleton.textProcessor; - var k; - if(textProcessor.activeKeyboard) { - k = textProcessor.activeKeyboard.scriptObject; - } - var lg=''; - - if(arguments.length > 0) { - k = k0; - } - - if(k) { - if(typeof(k['KLC']) != 'undefined') { - lg = k['KLC']; - } else if(typeof(k['LanguageCode']) != 'undefined') { - lg = k['LanguageCode']; - } + isCJK(k: KeyboardStub) { // I3363 (Build 301) + var lg: string; + if(typeof(k['KLC']) != 'undefined') { + lg = k['KLC']; + } else if(typeof(k['LanguageCode']) != 'undefined') { + lg = k['LanguageCode']; } return ((lg == 'cmn') || (lg == 'jpn') || (lg == 'kor')); } - isRTL(k0?): boolean { - let textProcessor = com.keyman.singleton.textProcessor - var k = k0; - if(!k && textProcessor.activeKeyboard) { - k = textProcessor.activeKeyboard.scriptObject; - } - return (k != null) && (k['KRTL']); - } - - /** - * Function isChiral - * Scope Public - * @param {string|Object=} k0 - * @return {boolean} - * Description Tests if the active keyboard (or optional argument) uses chiral modifiers. - */ - isChiral(k0?) { - if(typeof(k0) == "string") { - k0 = this.getKeyboardByID(k0); - } - - return !!(this.getKeyboardModifierBitmask(k0) & text.Codes.modifierBitmasks.IS_CHIRAL); - } - - /** - * Function getKeyboardModifierBitmask - * Scope Private - * @param {Object=} k0 - * @return {number} - * Description Obtains the currently-active modifier bitmask for the active keyboard. - */ - getKeyboardModifierBitmask(k0?) { - let textProcessor = com.keyman.singleton.textProcessor - var k=textProcessor.activeKeyboard; - if(k) { - k = k.scriptObject; - } - - if(arguments.length > 0 && typeof k0 != 'undefined') { - k = k0; - } - - if(!k) { - return 0x0000; - } - - if(k['KMBM']) { - return k['KMBM']; - } - - return text.Codes.modifierBitmasks['NON_CHIRAL']; - } - getFont(k0?) { let textProcessor = com.keyman.singleton.textProcessor var k = k0; diff --git a/web/source/kmwbase.ts b/web/source/kmwbase.ts index 120ddccb05..174dacc1d6 100644 --- a/web/source/kmwbase.ts +++ b/web/source/kmwbase.ts @@ -343,11 +343,19 @@ namespace com.keyman { * Scope Public * @param {Object=} k0 * @return {boolean} - * Description Tests if active keyboard (or optional argument) uses a pick list (Chinese, Japanese, Korean, etc.) + * Description Tests if active keyboard (or specified keyboard script object, as optional argument) + * uses a pick list (Chinese, Japanese, Korean, etc.) * (This function accepts either keyboard structure.) */ - ['isCJK'](k0) { - return this.keyboardManager.isCJK(k0); + ['isCJK'](k0?) { + var kbd: keyboards.Keyboard; + if(k0) { + kbd = new keyboards.Keyboard(kbd); + } else { + kbd = this.textProcessor.activeKeyboard; + } + + return kbd && kbd.isCJK; } /** @@ -358,7 +366,13 @@ namespace com.keyman { * Description Tests if the active keyboard (or optional argument) uses chiral modifiers. */ ['isChiral'](k0?) { - return this.keyboardManager.isChiral(k0); + var kbd: keyboards.Keyboard; + if(k0) { + kbd = new keyboards.Keyboard(k0); + } else { + kbd = this.textProcessor.activeKeyboard; + } + return kbd.isChiral; } /** diff --git a/web/source/kmwdom.ts b/web/source/kmwdom.ts index c8e1a99dcd..2da71b8554 100644 --- a/web/source/kmwdom.ts +++ b/web/source/kmwdom.ts @@ -774,8 +774,9 @@ namespace com.keyman { * * @param {Object} Ptarg Target element */ - _SetTargDir(Ptarg: HTMLElement) { - var elDir=(this.keyman.keyboardManager.isRTL()) ? 'rtl' : 'ltr'; + _SetTargDir(Ptarg: HTMLElement) { + let activeKeyboard = com.keyman.singleton.textProcessor.activeKeyboard; + var elDir=(activeKeyboard && activeKeyboard.isRTL) ? 'rtl' : 'ltr'; if(Ptarg) { if(this.keyman.util.device.touchable) { diff --git a/web/source/kmwdomevents.ts b/web/source/kmwdomevents.ts index 866204eb81..1271fa3844 100644 --- a/web/source/kmwdomevents.ts +++ b/web/source/kmwdomevents.ts @@ -154,7 +154,7 @@ namespace com.keyman { } else { // Conditionally show the OSK when control receives the focus if(osk.ready) { - if(this.keyman.keyboardManager.isCJK()) { + if(this.keyman.isCJK()) { osk._Enabled = true; } if(osk._Enabled) { diff --git a/web/source/osk/banner.ts b/web/source/osk/banner.ts index 4a7b6e7605..db1e802e7d 100644 --- a/web/source/osk/banner.ts +++ b/web/source/osk/banner.ts @@ -324,7 +324,8 @@ namespace com.keyman.osk { suggestionText = '\xa0'; // default: nbsp. } else { // Default the LTR ordering to match that of the active keyboard. - let rtl = keyman.keyboardManager.isRTL(); + let activeKeyboard = keyman.textProcessor.activeKeyboard; + let rtl = activeKeyboard && activeKeyboard.isRTL; let orderCode = rtl ? 0x202e /* RTL */ : 0x202d /* LTR */; suggestionText = String.fromCharCode(orderCode) + suggestion.displayAs; } @@ -372,7 +373,8 @@ namespace com.keyman.osk { * the elements are inserted for RTL. This allows the banner to be RTL * for visuals/UI while still being internally LTR. */ - let rtl = com.keyman.singleton.keyboardManager.isRTL(); + let activeKeyboard = com.keyman.singleton.textProcessor.activeKeyboard; + let rtl = activeKeyboard && activeKeyboard.isRTL; for (var i=0; i window['keyman']; + var activeKeyboard = keyman.textProcessor.activeKeyboard; let modifierCodes = Codes.modifierCodes; + if(!activeKeyboard) { + // No Alt-Gr emulation if there's not actually a keyboard loaded. + return false; + } + // If we're not chiral, we're not emulating. - if(!keyman.keyboardManager.isChiral()) { + if(!activeKeyboard.isChiral) { return false; } if(!keyLabels) { - var activeKeyboard = keyman.textProcessor.activeKeyboard; - if(activeKeyboard == null || activeKeyboard.legacyLayoutSpec == null) { + if(activeKeyboard.legacyLayoutSpec == null) { return false; } @@ -402,7 +407,7 @@ namespace com.keyman.osk { // It's technically possible for the OSK to not specify anything while allowing chiral input. A last-ditch catch: - var bitmask = keyman.keyboardManager.getKeyboardModifierBitmask(); + var bitmask = activeKeyboard.modifierBitmask; if((bitmask & emulationMask) != emulationMask) { // At least one of the emulation modifiers is never used by the keyboard! We can confirm everything's safe. return true; diff --git a/web/source/osk/oskManager.ts b/web/source/osk/oskManager.ts index db9f2dd1aa..e59ce1fc59 100644 --- a/web/source/osk/oskManager.ts +++ b/web/source/osk/oskManager.ts @@ -271,7 +271,7 @@ namespace com.keyman.osk { Lviskbd={'F':'Tahoma', 'BK': Layouts.dfltText}; //DDOSK } - this._GenerateVisualKeyboard(Lviskbd, Lhelp, layout, keymanweb.keyboardManager.getKeyboardModifierBitmask()); + this._GenerateVisualKeyboard(Lviskbd, Lhelp, layout, activeKeyboard.modifierBitmask); } else { //The following code applies only to preformatted 'help' such as European Latin //osk.ddOSK = false; Ldiv=util._CreateElement('div'); @@ -779,7 +779,7 @@ namespace com.keyman.osk { this._VMoveX = Lposx - this._Box.offsetLeft; this._VMoveY = Lposy - this._Box.offsetTop; - if(keymanweb.keyboardManager.isCJK()) { + if(keymanweb.isCJK()) { this.pinImg.style.left='15px'; } @@ -1402,7 +1402,7 @@ namespace com.keyman.osk { if(hiddenByUser) { //osk.loadCookie(); // preserve current offset and userlocated state - this._Enabled = ((keymanweb.keyboardManager.isCJK() || device.touchable)? true : false); // I3363 (Build 301) + this._Enabled = ((keymanweb.isCJK() || device.touchable)? true : false); // I3363 (Build 301) this.saveCookie(); // Save current OSK state, size and position (desktop only) } else if(device.formFactor == 'desktop') { //Allow desktop OSK to remain visible on blur if body class set diff --git a/web/source/osk/visualKeyboard.ts b/web/source/osk/visualKeyboard.ts index ec2e5450e8..b55becae68 100644 --- a/web/source/osk/visualKeyboard.ts +++ b/web/source/osk/visualKeyboard.ts @@ -210,7 +210,7 @@ namespace com.keyman.osk { ts.fontSize=spec['fontsize']; } - let keyboardManager = (window['keyman']).keyboardManager; + let activeKeyboard = com.keyman.singleton.textProcessor.activeKeyboard; // For some reason, fonts will sometimes 'bug out' for the embedded iOS page if we // instead assign fontFamily to the existing style 'ts'. (Occurs in iOS 12.) @@ -228,7 +228,7 @@ namespace com.keyman.osk { // Add the Unicode 'empty circle' as a base support for needy diacritics. keyText = '\u25cc' + keyText; - if(keyboardManager.isRTL()) { + if(activeKeyboard && activeKeyboard.isRTL) { // Add the RTL marker to ensure it displays properly. keyText = '\u200f' + keyText; } @@ -2216,7 +2216,7 @@ namespace com.keyman.osk { // Else get a default layout for the device for this keyboard if(layout == null && PVK != null) { let kbdDevVersion = PKbd.compilerVersion; - layout=Layouts.buildDefaultLayout(PVK, kbdDevVersion, keymanweb.keyboardManager.getKeyboardModifierBitmask(PKbd),formFactor); + layout=Layouts.buildDefaultLayout(PVK, kbdDevVersion, PKbd.modifierBitmask, formFactor); } // Cannot create an OSK if no layout defined, just return empty DIV @@ -2228,7 +2228,7 @@ namespace com.keyman.osk { } } - let kbdObj = new VisualKeyboard(PVK, null, layout, keymanweb.keyboardManager.getKeyboardModifierBitmask(), device, true); + let kbdObj = new VisualKeyboard(PVK, null, layout, PKbd.modifierBitmask, device, true); let kbd = kbdObj.kbdDiv.childNodes[0] as HTMLDivElement; // Gets the layer group. // Select the layer to display, and adjust sizes diff --git a/web/source/text/kbdInterface.ts b/web/source/text/kbdInterface.ts index 2aac917061..a0e2cbf34b 100644 --- a/web/source/text/kbdInterface.ts +++ b/web/source/text/kbdInterface.ts @@ -600,8 +600,7 @@ namespace com.keyman.text { var retVal = false; // I3318 var keyCode = (e.Lcode == 173 ? 189 : e.Lcode); //I3555 (Firefox hyphen issue) - let keyman = com.keyman.singleton; - let bitmask = keyman.keyboardManager.getKeyboardModifierBitmask(); + let bitmask = this.activeKeyboard.modifierBitmask; let Codes = com.keyman.text.Codes; var modifierBitmask = bitmask & Codes.modifierBitmasks["ALL"]; var stateBitmask = bitmask & Codes.stateBitmasks["ALL"]; diff --git a/web/source/text/processor.ts b/web/source/text/processor.ts index 5f57405168..4d6a8e9da7 100644 --- a/web/source/text/processor.ts +++ b/web/source/text/processor.ts @@ -712,13 +712,17 @@ namespace com.keyman.text { var lockNames = ['CAPS', 'NUM_LOCK', 'SCROLL_LOCK']; var lockKeys = ['K_CAPS', 'K_NUMLOCK', 'K_SCROLL']; + if(!this.activeKeyboard) { + return true; + } + if(e) { // read shift states from Pevent keyShiftState = e.Lmodifiers; lockStates = e.Lstates; // Are we simulating AltGr? If it's a simulation and not real, time to un-simulate for the OSK. - if(keyman.keyboardManager.isChiral() && osk.Layouts.emulatesAltGr() && + if(this.activeKeyboard.isChiral && osk.Layouts.emulatesAltGr() && (this.modStateFlags & Codes.modifierBitmasks['ALT_GR_SIM']) == Codes.modifierBitmasks['ALT_GR_SIM']) { keyShiftState |= Codes.modifierBitmasks['ALT_GR_SIM']; keyShiftState &= ~Codes.modifierCodes['RALT']; @@ -774,8 +778,7 @@ namespace com.keyman.text { */ selectLayer(keyName: string, nextLayerIn?: number | string): boolean { var nextLayer = arguments.length < 2 ? null : nextLayerIn; - let keyman = com.keyman.singleton; - var isChiral = keyman.keyboardManager.isChiral(); + var isChiral = this.activeKeyboard && this.activeKeyboard.isChiral; // Layer must be identified by name, not number (27/08/2015) if(typeof nextLayer == 'number') { @@ -1125,7 +1128,8 @@ namespace com.keyman.text { let modifierBitmasks = Codes.modifierBitmasks; // Stage 4 - map the modifier set to the appropriate keystroke's modifiers. - if(keyman.keyboardManager.isChiral()) { + var activeKeyboard = this.activeKeyboard; + if(activeKeyboard && activeKeyboard.isChiral) { s.Lmodifiers = curModState & modifierBitmasks.CHIRAL; // Note for future - embedding a kill switch here or in keymanweb.osk.emulatesAltGr would facilitate disabling @@ -1143,8 +1147,6 @@ namespace com.keyman.text { } // Mnemonic handling. - var activeKeyboard = this.activeKeyboard; - if(activeKeyboard && activeKeyboard.isMnemonic) { // The following will never set a code corresponding to a modifier key, so it's fine to do this, // which may change the value of Lcode, here.