mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-05 00:15:32 +00:00
refactor(web): add abstract Keyboard base class
Also rename `JSKeyboardData` → `KeyboardData`. Test-bot: skip
This commit is contained in:
parent
945556201e
commit
115ab18d71
24 changed files with 180 additions and 71 deletions
|
|
@ -689,18 +689,14 @@ export class KeymanEngine extends KeymanEngineBase<BrowserConfiguration, Context
|
|||
argFormFactor?: DeviceSpec.FormFactor,
|
||||
argLayerId?: string
|
||||
): HTMLElement {
|
||||
let PKbd: Keyboard = null;
|
||||
const PKbd = (PInternalName != null ? this.keyboardRequisitioner.cache.getKeyboard(PInternalName) : null) || this.core.activeKeyboard;
|
||||
|
||||
if(PInternalName != null) {
|
||||
PKbd = this.keyboardRequisitioner.cache.getKeyboard(PInternalName);
|
||||
}
|
||||
|
||||
PKbd = PKbd || this.core.activeKeyboard;
|
||||
if (PKbd instanceof KMXKeyboard) {
|
||||
// TODO-web-core: implement for KMX keyboards (epic/embed-osk-in-kmx)
|
||||
// TODO-embed-osk-in-kmx: implement for KMX keyboards
|
||||
return null;
|
||||
}
|
||||
const Pstub = this.keyboardRequisitioner.cache.getStub(PKbd);
|
||||
const jsKbd = PKbd as JSKeyboard;
|
||||
const Pstub = this.keyboardRequisitioner.cache.getStub(jsKbd);
|
||||
|
||||
// help.keyman.com will set this function in place to specify the desired
|
||||
// dimensions for the documentation-keyboards, so we'll give it priority. One of those
|
||||
|
|
@ -712,7 +708,7 @@ export class KeymanEngine extends KeymanEngineBase<BrowserConfiguration, Context
|
|||
const targetHeight = (typeof getOskHeight == 'function' ? getOskHeight() : null) || this.osk.computedHeight || 200;
|
||||
|
||||
return VisualKeyboard.buildDocumentationKeyboard(
|
||||
PKbd,
|
||||
jsKbd,
|
||||
Pstub,
|
||||
this.config.paths,
|
||||
argFormFactor,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { ModifierKeyConstants } from '@keymanapp/common-types';
|
|||
import {
|
||||
Codes,
|
||||
JSKeyboard,
|
||||
Keyboard,
|
||||
KeyboardHarness,
|
||||
KeyboardKeymanGlobal,
|
||||
KeyMapping,
|
||||
|
|
@ -194,11 +195,15 @@ export class JSKeyboardInterface extends KeyboardHarness {
|
|||
_AnyIndices: number[] = []; // AnyIndex - array of any/index match indices
|
||||
|
||||
// Must be accessible to some of the keyboard API methods.
|
||||
activeKeyboard: JSKeyboard;
|
||||
activeKeyboard: Keyboard;
|
||||
activeDevice: DeviceSpec;
|
||||
|
||||
variableStoreSerializer: VariableStoreSerializer;
|
||||
|
||||
private get activeJSKeyboard(): JSKeyboard {
|
||||
return this.activeKeyboard as JSKeyboard;
|
||||
}
|
||||
|
||||
// A 'reference point' that debug keyboards may use to access KMW's code constants.
|
||||
public get Codes(): typeof Codes {
|
||||
return Codes;
|
||||
|
|
@ -569,7 +574,7 @@ export class JSKeyboardInterface extends KeyboardHarness {
|
|||
let retVal = false; // I3318
|
||||
let keyCode = (e.Lcode == 173 ? 189 : e.Lcode); //I3555 (Firefox hyphen issue)
|
||||
|
||||
const bitmask = this.activeKeyboard.modifierBitmask;
|
||||
const bitmask = this.activeJSKeyboard.modifierBitmask;
|
||||
const modifierBitmask = bitmask & Codes.modifierBitmasks["ALL"];
|
||||
const stateBitmask = bitmask & Codes.stateBitmasks["ALL"];
|
||||
|
||||
|
|
@ -649,7 +654,7 @@ export class JSKeyboardInterface extends KeyboardHarness {
|
|||
|
||||
_ExplodeStore(store: KeyboardStore): ComplexKeyboardStore {
|
||||
if(typeof(store) == 'string') {
|
||||
const cachedStores = this.activeKeyboard.explodedStores;
|
||||
const cachedStores = this.activeJSKeyboard.explodedStores;
|
||||
|
||||
// Is the result cached?
|
||||
if(cachedStores[store]) {
|
||||
|
|
@ -1005,7 +1010,7 @@ export class JSKeyboardInterface extends KeyboardHarness {
|
|||
if(!this.activeKeyboard) {
|
||||
throw "No active keyboard for keystroke processing!";
|
||||
}
|
||||
return this.process(this.activeKeyboard.processNewContextEvent.bind(this.activeKeyboard), textStore, keystroke, true);
|
||||
return this.process(this.activeJSKeyboard.processNewContextEvent.bind(this.activeKeyboard), textStore, keystroke, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1020,7 +1025,7 @@ export class JSKeyboardInterface extends KeyboardHarness {
|
|||
if(!this.activeKeyboard) {
|
||||
throw "No active keyboard for keystroke processing!";
|
||||
}
|
||||
return this.process(this.activeKeyboard.processPostKeystroke.bind(this.activeKeyboard), textStore, keystroke, true);
|
||||
return this.process(this.activeJSKeyboard.processPostKeystroke.bind(this.activeKeyboard), textStore, keystroke, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1035,7 +1040,7 @@ export class JSKeyboardInterface extends KeyboardHarness {
|
|||
if(!this.activeKeyboard) {
|
||||
throw "No active keyboard for keystroke processing!";
|
||||
}
|
||||
return this.process(this.activeKeyboard.process.bind(this.activeKeyboard), textStore, keystroke, false);
|
||||
return this.process(this.activeJSKeyboard.process.bind(this.activeKeyboard), textStore, keystroke, false);
|
||||
}
|
||||
|
||||
private process(callee: (textStore: TextStore, keystroke: KeyEvent) => boolean, textStore: TextStore, keystroke: KeyEvent, readonly: boolean): ProcessorAction {
|
||||
|
|
@ -1057,7 +1062,7 @@ export class JSKeyboardInterface extends KeyboardHarness {
|
|||
const preInput = SyntheticTextStore.from(textStore, true);
|
||||
|
||||
// Capture the initial state of any variable stores
|
||||
const cachedVariableStores = this.activeKeyboard.variableStores;
|
||||
const cachedVariableStores = this.activeJSKeyboard.variableStores;
|
||||
|
||||
// Establishes the results object, allowing corresponding commands to set values here as appropriate.
|
||||
this.ruleBehavior = new ProcessorAction();
|
||||
|
|
@ -1077,8 +1082,8 @@ export class JSKeyboardInterface extends KeyboardHarness {
|
|||
// We always backup the changes to variable stores to the ProcessorAction, to
|
||||
// be applied during finalization, then restore them to the cached initial
|
||||
// values to avoid side-effects with predictive text mocks.
|
||||
this.ruleBehavior.variableStores = this.activeKeyboard.variableStores;
|
||||
this.activeKeyboard.variableStores = cachedVariableStores;
|
||||
this.ruleBehavior.variableStores = this.activeJSKeyboard.variableStores;
|
||||
this.activeJSKeyboard.variableStores = cachedVariableStores;
|
||||
|
||||
// `matched` refers to whether or not the FINAL rule (from any group) matched, rather than
|
||||
// whether or not ANY rule matched. If the final rule doesn't match, we trigger the key's
|
||||
|
|
@ -1104,7 +1109,7 @@ export class JSKeyboardInterface extends KeyboardHarness {
|
|||
* keyboard
|
||||
*/
|
||||
applyVariableStores(stores: VariableStoreDictionary): void {
|
||||
this.activeKeyboard.variableStores = stores;
|
||||
this.activeJSKeyboard.variableStores = stores;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ export class JSKeyboardProcessor extends EventEmitter<EventMap> implements Keybo
|
|||
}
|
||||
|
||||
public get activeKeyboard(): JSKeyboard {
|
||||
return this.keyboardInterface.activeKeyboard;
|
||||
return this.keyboardInterface.activeKeyboard as JSKeyboard;
|
||||
}
|
||||
|
||||
public set activeKeyboard(keyboard: JSKeyboard) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { type Keyboard, JSKeyboard, KeyboardLoaderBase as KeyboardLoader, KMXKeyboard } from "keyman/engine/keyboard";
|
||||
import { Keyboard, JSKeyboard, KeyboardLoaderBase as KeyboardLoader, KMXKeyboard } from "keyman/engine/keyboard";
|
||||
import { EventEmitter } from "eventemitter3";
|
||||
|
||||
import { KeyboardStub } from "./keyboardStub.js";
|
||||
|
|
@ -152,7 +152,7 @@ export class StubAndKeyboardCache extends EventEmitter<EventMap> {
|
|||
keyboardID = toPrefixedKeyboardId(keyboardID);
|
||||
|
||||
const cachedEntry = this.keyboardTable[keyboardID];
|
||||
if(cachedEntry instanceof JSKeyboard) {
|
||||
if(cachedEntry instanceof Keyboard) {
|
||||
return Promise.resolve(cachedEntry);
|
||||
} else if(cachedEntry instanceof Promise) {
|
||||
return cachedEntry;
|
||||
|
|
@ -172,6 +172,7 @@ export class StubAndKeyboardCache extends EventEmitter<EventMap> {
|
|||
|
||||
promise.then((kbd) => {
|
||||
// Overrides the built-in ID in case of keyboard namespacing.
|
||||
// TODO-web-core: what do we have to do for KMX keyboards here?
|
||||
if (kbd instanceof JSKeyboard) {
|
||||
kbd.scriptObject["KI"] = keyboardID;
|
||||
}
|
||||
|
|
@ -197,12 +198,12 @@ export class StubAndKeyboardCache extends EventEmitter<EventMap> {
|
|||
}
|
||||
|
||||
getStub(keyboardID: string, languageID: string): KeyboardStub;
|
||||
getStub(keyboard: JSKeyboard, languageID?: string): KeyboardStub;
|
||||
getStub(arg0: string | JSKeyboard, arg1?: string): KeyboardStub {
|
||||
getStub(keyboard: Keyboard, languageID?: string): KeyboardStub;
|
||||
getStub(arg0: string | Keyboard, arg1?: string): KeyboardStub {
|
||||
let keyboardID: string;
|
||||
const languageID = arg1 || '---';
|
||||
|
||||
if(arg0 instanceof JSKeyboard) {
|
||||
if(arg0 instanceof Keyboard) {
|
||||
keyboardID = arg0.id;
|
||||
} else {
|
||||
keyboardID = arg0;
|
||||
|
|
@ -229,12 +230,12 @@ export class StubAndKeyboardCache extends EventEmitter<EventMap> {
|
|||
/**
|
||||
* Removes all metadata (stubs) associated with a specific keyboard from the cache, optionally
|
||||
* removing the cached keyboard as well.
|
||||
* @param keyboard Either the keyboard ID or `JSKeyboard` instance
|
||||
* @param purge If `true`, will also purge the `JSKeyboard` instance itself from the cache.
|
||||
* @param keyboard Either the keyboard ID or `Keyboard` instance
|
||||
* @param purge If `true`, will also purge the `Keyboard` instance itself from the cache.
|
||||
* If `false`, only forgets the metadata (stubs).
|
||||
*/
|
||||
forgetKeyboard(keyboard: string | JSKeyboard, purge: boolean = false) {
|
||||
const id: string = (keyboard instanceof JSKeyboard) ? keyboard.id : toPrefixedKeyboardId(keyboard);
|
||||
forgetKeyboard(keyboard: string | Keyboard, purge: boolean = false) {
|
||||
const id: string = (keyboard instanceof Keyboard) ? keyboard.id : toPrefixedKeyboardId(keyboard);
|
||||
|
||||
if(this.stubSetTable[id]) {
|
||||
delete this.stubSetTable[id];
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
export { ActiveKeyBase, ActiveKey, ActiveSubKey, ActiveRow, ActiveLayer, ActiveLayout } from "./keyboards/activeLayout.js";
|
||||
export { ButtonClass, ButtonClasses, LayoutLayer, LayoutFormFactor, LayoutRow, LayoutKey, LayoutSubKey, Layouts } from "./keyboards/defaultLayouts.js";
|
||||
export { JSKeyboard, LayoutState } from "./keyboards/jsKeyboard.js";
|
||||
export { Keyboard } from './keyboards/keyboard.js';
|
||||
export { KeyboardMinimalInterface } from './keyboards/keyboardMinimalInterface.js';
|
||||
export { KMXKeyboard } from './keyboards/kmxKeyboard.js';
|
||||
export { KeyboardHarness, KeyboardKeymanGlobal, MinimalCodesInterface, MinimalKeymanGlobal } from "./keyboards/keyboardHarness.js";
|
||||
export { NotifyEventCode, Keyboard, KeyboardLoaderBase } from "./keyboards/keyboardLoaderBase.js";
|
||||
export { NotifyEventCode, KeyboardLoaderBase } from "./keyboards/keyboardLoaderBase.js";
|
||||
export { KeyboardLoadErrorBuilder, KeyboardMissingError, KeyboardScriptError, KeyboardDownloadError, InvalidKeyboardError } from './keyboards/keyboardLoadError.js'
|
||||
export { BeepHandler, EventMap, KeyboardProcessor } from "./keyboards/keyboardProcessor.js";
|
||||
export {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { type DeviceSpec } from "keyman/common/web-utils";
|
|||
import { Codes } from './codes.js';
|
||||
import { DefaultOutputRules } from "./defaultOutputRules.js";
|
||||
import { ActiveKeyBase } from './keyboards/activeLayout.js';
|
||||
import { type Keyboard } from "./keyboards/keyboardLoaderBase.js";
|
||||
import { type Keyboard } from "./keyboards/keyboard.js";
|
||||
|
||||
// Represents a probability distribution over a keyboard's keys.
|
||||
// Defined here to avoid compilation issues.
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ type TouchLayoutSpec = TouchLayout.TouchLayoutPlatform & { isDefault?: boolean};
|
|||
import { Version, DeviceSpec } from "keyman/common/web-utils";
|
||||
import { StateKeyMap } from "./stateKeyMap.js";
|
||||
import { NotifyEventCode } from './keyboardLoaderBase.js';
|
||||
import { Keyboard } from './keyboard.js';
|
||||
|
||||
/**
|
||||
* Stores preprocessed properties of a keyboard for quick retrieval later.
|
||||
|
|
@ -49,7 +50,7 @@ type KmwKeyboardObject = KeyboardObject & {
|
|||
* and keyboard-centered functionality in an object-oriented way without modifying the
|
||||
* wrapped keyboard itself.
|
||||
*/
|
||||
export class JSKeyboard {
|
||||
export class JSKeyboard extends Keyboard {
|
||||
public static DEFAULT_SCRIPT_OBJECT: KmwKeyboardObject = {
|
||||
'gs': function(textStore: TextStore, keystroke: KeyEvent) { return false; }, // no matching rules; rely on defaultRuleOutput entirely
|
||||
'KI': '', // The currently-existing default keyboard ID; we already have checks that focus against this.
|
||||
|
|
@ -68,6 +69,7 @@ export class JSKeyboard {
|
|||
private layoutStates: {[layout: string]: LayoutState};
|
||||
|
||||
constructor(keyboardScript: any) {
|
||||
super();
|
||||
if(keyboardScript) {
|
||||
this.scriptObject = keyboardScript;
|
||||
} else {
|
||||
|
|
|
|||
89
web/src/engine/src/keyboard/keyboards/keyboard.ts
Normal file
89
web/src/engine/src/keyboard/keyboards/keyboard.ts
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Keyman is copyright (C) SIL Global. MIT License.
|
||||
*/
|
||||
import { DeviceSpec } from 'keyman/common/web-utils';
|
||||
import { ActiveKey, ActiveLayout, ActiveSubKey } from './activeLayout.js';
|
||||
import { StateKeyMap } from './stateKeyMap.js';
|
||||
import { KeyEvent } from '../keyEvent.js';
|
||||
import { TextStore } from '../textStore.js';
|
||||
import { NotifyEventCode } from './keyboardLoaderBase.js';
|
||||
|
||||
/**
|
||||
* Abstract base class for Keyman keyboards, providing common interface
|
||||
* for JSKeyboard and KMXKeyboard.
|
||||
*/
|
||||
export abstract class Keyboard {
|
||||
/**
|
||||
* Unique identifier for the keyboard.
|
||||
*/
|
||||
abstract get id(): string;
|
||||
|
||||
/**
|
||||
* Gets the name of the keyboard.
|
||||
*/
|
||||
abstract get name(): string;
|
||||
|
||||
/**
|
||||
* Version string of the keyboard.
|
||||
*/
|
||||
abstract get version(): string;
|
||||
|
||||
/**
|
||||
* Indicates whether the keyboard uses mnemonic layout.
|
||||
*/
|
||||
abstract get isMnemonic(): boolean;
|
||||
|
||||
/**
|
||||
* Indicates whether the keyboard is chiral (distinguishes left/right modifiers).
|
||||
*/
|
||||
abstract get isChiral(): boolean;
|
||||
|
||||
/**
|
||||
* Indicates whether the keyboard emulates AltGr.
|
||||
*/
|
||||
abstract get emulatesAltGr(): boolean;
|
||||
|
||||
/**
|
||||
* Indicates whether the keyboard is right-to-left.
|
||||
*/
|
||||
abstract get isRTL(): boolean;
|
||||
|
||||
/**
|
||||
* true if this keyboard uses a (legacy) pick list (Chinese, Japanese, Korean, etc.)
|
||||
*/
|
||||
abstract get isCJK(): boolean;
|
||||
|
||||
/**
|
||||
* CSS styling for the on-screen keyboard.
|
||||
*/
|
||||
abstract get oskStyling(): string;
|
||||
|
||||
/**
|
||||
* Returns an ActiveLayout object representing the keyboard's layout for this form factor.
|
||||
* May return null if a custom desktop "help" OSK is defined.
|
||||
* @param formFactor The desired form factor for the layout.
|
||||
*/
|
||||
abstract layout(formFactor: DeviceSpec.FormFactor): ActiveLayout;
|
||||
|
||||
/**
|
||||
* Indicates whether the keyboard's desktop layout should be used for the specified device.
|
||||
* @param device The device specification to check.
|
||||
*/
|
||||
abstract usesDesktopLayoutOnDevice(device: DeviceSpec): boolean;
|
||||
|
||||
/**
|
||||
* Notifies keyboard of keystroke or other event.
|
||||
* @param eventCode Event code (16-18: Shift, Control or Alt), or 0 for focus.
|
||||
* @param textStore Text store.
|
||||
* @param data 1 for KeyDown or FocusReceived, 0 for KeyUp or FocusLost.
|
||||
*/
|
||||
abstract notify(eventCode: NotifyEventCode, textStore: TextStore, data: number): void;
|
||||
|
||||
/**
|
||||
* Constructs a KeyEvent from an ActiveKey or ActiveSubKey.
|
||||
* @param key The key to construct the event for.
|
||||
* @param device The device specification.
|
||||
* @param stateKeys The current state of modifier keys.
|
||||
*/
|
||||
abstract constructKeyEvent(key: ActiveKey | ActiveSubKey, device: DeviceSpec, stateKeys: StateKeyMap): KeyEvent;
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import { JSKeyboard } from "./jsKeyboard.js";
|
||||
import { Codes } from "../codes.js";
|
||||
import { DeviceSpec } from 'keyman/common/web-utils';
|
||||
import { Keyboard } from './keyboard.js';
|
||||
|
||||
/**
|
||||
* Defines members of the top-level `keyman` global object necessary to guarantee
|
||||
|
|
@ -64,7 +65,7 @@ export class KeyboardHarness {
|
|||
/**
|
||||
* This field serves as the receptacle for a successfully-loaded Keyboard.
|
||||
*/
|
||||
public loadedKeyboard: JSKeyboard = null;
|
||||
public loadedKeyboard: Keyboard = null;
|
||||
|
||||
/**
|
||||
* Keyman keyboards register themselves into the Keyman Engine for Web by directly
|
||||
|
|
@ -85,6 +86,7 @@ export class KeyboardHarness {
|
|||
throw new Error("Unexpected state: the most-recently loaded keyboard field was not properly reset.");
|
||||
}
|
||||
this.loadedKeyboard = new JSKeyboard(scriptObject);
|
||||
// TODO-web-core: do we have to do something similar for KMX keyboards?
|
||||
}
|
||||
|
||||
// Is evaluated on script-load for some keyboards using variable stores.
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { KM_Core, KM_CORE_STATUS } from 'keyman/engine/core-adapter';
|
||||
import { JSKeyboard } from "./jsKeyboard.js";
|
||||
import { KMXKeyboard } from './kmxKeyboard.js';
|
||||
import { KeyboardHarness } from "./keyboardHarness.js";
|
||||
import { KeyboardProperties } from "./keyboardProperties.js";
|
||||
import { KeyboardLoadErrorBuilder, StubBasedErrorBuilder, UriBasedErrorBuilder } from './keyboardLoadError.js';
|
||||
import { Codes } from '../codes.js';
|
||||
import { Keyboard } from './keyboard.js';
|
||||
|
||||
export enum NotifyEventCode {
|
||||
FocusEvent = 0,
|
||||
|
|
@ -14,7 +14,6 @@ export enum NotifyEventCode {
|
|||
};
|
||||
|
||||
export type KeyboardStub = KeyboardProperties & { filename: string };
|
||||
export type Keyboard = JSKeyboard | KMXKeyboard;
|
||||
|
||||
export abstract class KeyboardLoaderBase {
|
||||
private _harness: KeyboardHarness;
|
||||
|
|
@ -63,7 +62,7 @@ export abstract class KeyboardLoaderBase {
|
|||
const name = this.extractIdFromUrl(uri);
|
||||
const result = KM_Core.instance.keyboard_load_from_blob(name, byteArray);
|
||||
if (result.status == KM_CORE_STATUS.OK) {
|
||||
return new KMXKeyboard(result.object);
|
||||
return new KMXKeyboard(name, result.object);
|
||||
}
|
||||
throw errorBuilder.invalidKeyboard(new Error(`Loading KMX keyboard from ${uri} failed with status ${result.status}`));
|
||||
}
|
||||
|
|
@ -86,5 +85,5 @@ export abstract class KeyboardLoaderBase {
|
|||
|
||||
protected abstract loadKeyboardBlob(uri: string, errorBuilder: KeyboardLoadErrorBuilder): Promise<Uint8Array>;
|
||||
|
||||
protected abstract loadKeyboardFromScript(scriptSrc: string, errorBuilder: KeyboardLoadErrorBuilder): Promise<JSKeyboard>;
|
||||
protected abstract loadKeyboardFromScript(scriptSrc: string, errorBuilder: KeyboardLoadErrorBuilder): Promise<Keyboard>;
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { VariableStoreSerializer } from '../variableStore.js';
|
||||
import { Keyboard } from './keyboardLoaderBase.js';
|
||||
import { Keyboard } from './keyboard.js';
|
||||
|
||||
export interface KeyboardMinimalInterface {
|
||||
activeKeyboard: Keyboard;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { EventEmitter } from 'eventemitter3';
|
|||
import { DeviceSpec } from 'keyman/common/web-utils';
|
||||
import { KeyEvent } from '../keyEvent.js';
|
||||
import { type MutableSystemStore } from "../systemStore.js";
|
||||
import { Keyboard } from './keyboardLoaderBase.js';
|
||||
import { Keyboard } from './keyboard.js';
|
||||
import { KeyboardMinimalInterface } from './keyboardMinimalInterface.js';
|
||||
import { ProcessorAction } from './processorAction.js';
|
||||
import { StateKeyMap } from './stateKeyMap.js';
|
||||
|
|
|
|||
|
|
@ -8,14 +8,16 @@ import { StateKeyMap } from './stateKeyMap.js';
|
|||
import { KeyEvent } from '../keyEvent.js';
|
||||
import { TextStore } from '../textStore.js';
|
||||
import { NotifyEventCode } from './keyboardLoaderBase.js';
|
||||
import { Keyboard } from './keyboard.js';
|
||||
|
||||
/**
|
||||
* Acts as a wrapper class for KMX(+) Keyman keyboards
|
||||
*/
|
||||
export class KMXKeyboard {
|
||||
private _state: km_core_state;
|
||||
export class KMXKeyboard extends Keyboard {
|
||||
private _state: km_core_state | null = null;
|
||||
|
||||
public constructor(private _keyboard: km_core_keyboard) {
|
||||
public constructor(private _name: string, private _keyboard: km_core_keyboard) {
|
||||
super();
|
||||
const environment_opts =
|
||||
[
|
||||
{
|
||||
|
|
@ -77,6 +79,10 @@ export class KMXKeyboard {
|
|||
return id;
|
||||
}
|
||||
|
||||
public get name(): string {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
public get keyboard(): km_core_keyboard {
|
||||
return this._keyboard;
|
||||
}
|
||||
|
|
@ -124,6 +130,15 @@ export class KMXKeyboard {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns always false because (legacy) pick lists (Chinese, Japanese, Korean, etc.)
|
||||
* are not supported when using KMX keyboards.
|
||||
*/
|
||||
public get isCJK(): boolean {
|
||||
// always return false
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an ActiveLayout object representing the keyboard's layout for this
|
||||
* form factor. May return null if a custom desktop "help" OSK is defined,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
///<reference lib="dom" />
|
||||
|
||||
import { JSKeyboard } from '../jsKeyboard.js';
|
||||
import { Keyboard } from '../keyboard.js';
|
||||
import { KeyboardHarness, MinimalKeymanGlobal } from '../keyboardHarness.js';
|
||||
import { KeyboardLoaderBase } from '../keyboardLoaderBase.js';
|
||||
import { KeyboardLoadErrorBuilder } from '../keyboardLoadError.js';
|
||||
|
|
@ -54,7 +54,7 @@ export class DOMKeyboardLoader extends KeyboardLoaderBase {
|
|||
return new Uint8Array(buffer);
|
||||
}
|
||||
|
||||
protected async loadKeyboardFromScript(script: string, errorBuilder: KeyboardLoadErrorBuilder): Promise<JSKeyboard> {
|
||||
protected async loadKeyboardFromScript(script: string, errorBuilder: KeyboardLoadErrorBuilder): Promise<Keyboard> {
|
||||
try {
|
||||
this.evalScriptInContext(script, this.harness._jsGlobal);
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -9,14 +9,14 @@ import { CoreKeyboardProcessor } from 'keyman/engine/core-processor';
|
|||
|
||||
import {
|
||||
Codes,
|
||||
JSKeyboard, // TODO-web-core: huh? why is this here
|
||||
JSKeyboard, // required to be able to distinguish between JS and Core kbd processor
|
||||
Keyboard,
|
||||
KeyboardMinimalInterface,
|
||||
SyntheticTextStore,
|
||||
TextStore,
|
||||
ProcessorAction,
|
||||
SystemStoreIDs,
|
||||
type Alternate,
|
||||
type Keyboard,
|
||||
type KeyEvent,
|
||||
KeyboardProcessor,
|
||||
VariableStoreSerializer
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { ProcessorInitOptions } from 'keyman/engine/js-processor';
|
|||
import { DOMKeyboardLoader } from "keyman/engine/keyboard";
|
||||
import { WorkerFactory } from "@keymanapp/lexical-model-layer/web"
|
||||
import { InputProcessor } from './headless/inputProcessor.js';
|
||||
import { OSKView, JSKeyboardData } from "keyman/engine/osk";
|
||||
import { OSKView, KeyboardData } from "keyman/engine/osk";
|
||||
import { KeyboardRequisitioner, ModelCache, toUnprefixedKeyboardId, DOMCloudRequester } from "keyman/engine/keyboard-storage";
|
||||
import { ModelSpec, PredictionContext } from "keyman/engine/interfaces";
|
||||
|
||||
|
|
@ -386,7 +386,7 @@ export class KeymanEngineBase<
|
|||
this.core.keyboardProcessor.contextDevice = value?.targetDevice ?? this.config.softDevice;
|
||||
if(value) {
|
||||
// Don't build an OSK if no keyboard is available yet; avoid the extra flash.
|
||||
if (this.contextManager.activeKeyboard && this.contextManager.activeKeyboard instanceof JSKeyboardData) { // TODO-embed-osk-in-kmx: add support for OSK for KMX keyboards
|
||||
if (this.contextManager.activeKeyboard && this.contextManager.activeKeyboard instanceof KeyboardData) { // TODO-embed-osk-in-kmx: add support for OSK for KMX keyboards
|
||||
value.activeKeyboard = this.contextManager.activeKeyboard;
|
||||
}
|
||||
value.on('keyevent', this.keyEventListener);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { EventEmitter } from 'eventemitter3';
|
||||
|
||||
import { JSKeyboard } from 'keyman/engine/keyboard';
|
||||
import { Keyboard } from 'keyman/engine/keyboard';
|
||||
|
||||
import { OSKViewComponent } from './oskViewComponent.interface.js';
|
||||
import { ParsedLengthStyle } from '../lengthStyle.js';
|
||||
|
|
@ -102,7 +102,7 @@ export class TitleBar extends EventEmitter<EventMap, TitleBar> implements OSKVie
|
|||
this._caption.innerHTML = str;
|
||||
}
|
||||
|
||||
public setTitleFromKeyboard(keyboard: JSKeyboard) {
|
||||
public setTitleFromKeyboard(keyboard: Keyboard) {
|
||||
const title = "<span style='font-weight:bold'>" + keyboard?.name + '</span>'; // I1972 // I2186
|
||||
this._caption.innerHTML = title;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
export { DeviceSpec } from 'keyman/common/web-utils';
|
||||
export { Codes, JSKeyboard, KeyboardProperties, SpacebarText } from 'keyman/engine/keyboard';
|
||||
|
||||
export { OSKView, JSKeyboardData } from './views/oskView.js';
|
||||
export { OSKView, KeyboardData } from './views/oskView.js';
|
||||
export { FloatingOSKView, FloatingOSKViewConfiguration } from './views/floatingOskView.js';
|
||||
export { AnchoredOSKView } from './views/anchoredOskView.js';
|
||||
export { InlinedOSKView } from './views/inlinedOskView.js';
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import { DeviceSpec, ManagedPromise } from 'keyman/common/web-utils';
|
|||
import {
|
||||
Codes,
|
||||
JSKeyboard,
|
||||
Keyboard,
|
||||
KeyboardProperties,
|
||||
type MinimalCodesInterface,
|
||||
type MutableSystemStore, type SystemStoreMutationHandler,
|
||||
|
|
@ -58,8 +59,8 @@ export interface LegacyOSKEventMap {
|
|||
}): void;
|
||||
}
|
||||
|
||||
export class JSKeyboardData {
|
||||
keyboard: JSKeyboard;
|
||||
export class KeyboardData {
|
||||
keyboard: Keyboard;
|
||||
metadata: KeyboardProperties;
|
||||
};
|
||||
|
||||
|
|
@ -172,7 +173,7 @@ export abstract class OSKView
|
|||
private _boxBaseTouchStart: (e: TouchEvent) => boolean;
|
||||
private _boxBaseTouchEventCancel: (e: TouchEvent) => boolean;
|
||||
|
||||
private keyboardData: JSKeyboardData;
|
||||
private keyboardData: KeyboardData;
|
||||
|
||||
/**
|
||||
* Provides the current parameterization for timings and distances used by
|
||||
|
|
@ -553,11 +554,11 @@ export abstract class OSKView
|
|||
}
|
||||
}
|
||||
|
||||
public get activeKeyboard(): JSKeyboardData {
|
||||
public get activeKeyboard(): KeyboardData {
|
||||
return this.keyboardData;
|
||||
}
|
||||
|
||||
public set activeKeyboard(keyboardData: JSKeyboardData) {
|
||||
public set activeKeyboard(keyboardData: KeyboardData) {
|
||||
this.keyboardData = keyboardData;
|
||||
this.loadActiveKeyboard();
|
||||
|
||||
|
|
@ -765,7 +766,7 @@ export abstract class OSKView
|
|||
|
||||
// Create new ones for the new, incoming kbd.
|
||||
this.kbdStyleSheetManager = new StylesheetManager(this._Box, this.config.doCacheBusting || false);
|
||||
const kbdView = this.keyboardView = this._GenerateKeyboardView(this.keyboardData?.keyboard, this.keyboardData?.metadata);
|
||||
const kbdView = this.keyboardView = this._GenerateKeyboardView(this.keyboardData?.keyboard as JSKeyboard, this.keyboardData?.metadata);
|
||||
|
||||
// Perform the replacement.
|
||||
this._Box.replaceChild(kbdView.element, oldKbd.element);
|
||||
|
|
|
|||
|
|
@ -1356,7 +1356,7 @@ export class VisualKeyboard extends EventEmitter<EventMap> implements KeyboardVi
|
|||
* @return {Object} DIV object with filled keyboard layer content
|
||||
*/
|
||||
static buildDocumentationKeyboard(
|
||||
PKbd: JSKeyboard,
|
||||
PKbd: JSKeyboard, // TODO-web-core: do we have to do anything for KMX keyboards?
|
||||
kbdProperties: KeyboardProperties,
|
||||
pathConfig: OSKResourcePathConfiguration,
|
||||
argFormFactor: DeviceSpec.FormFactor,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
import {
|
||||
DOMKeyboardLoader
|
||||
} from 'keyman/engine/keyboard';
|
||||
|
||||
import {
|
||||
DOMKeyboardLoader,
|
||||
JSKeyboard,
|
||||
Keyboard,
|
||||
KeyboardProperties,
|
||||
MinimalKeymanGlobal
|
||||
} from 'keyman/engine/keyboard';
|
||||
|
|
@ -18,13 +16,13 @@ export function loadKeyboardFromPath(path: string) {
|
|||
}
|
||||
|
||||
export type KeyboardMap = {
|
||||
[key: string]: KeyboardInfoPair & { keyboard: JSKeyboard }
|
||||
[key: string]: KeyboardInfoPair & { keyboard: Keyboard }
|
||||
};
|
||||
|
||||
export function loadKeyboardsFromStubs(apiStubs: any, baseDir: string) {
|
||||
baseDir = baseDir || './';
|
||||
const keyboards: KeyboardMap = {};
|
||||
let priorPromise: Promise<void | JSKeyboard> = Promise.resolve();
|
||||
let priorPromise: Promise<void | Keyboard> = Promise.resolve();
|
||||
for(const stub of apiStubs) {
|
||||
// We are keeping this strictly sequential because we don't have sandboxed
|
||||
// loading yet; lack of sandboxing means that all loading keyboards compete
|
||||
|
|
|
|||
|
|
@ -520,7 +520,7 @@ describe('CoreKeyboardProcessor', function () {
|
|||
keyEvent.source = { type: eventType };
|
||||
|
||||
const coreKeyboard = loadKeyboard('/common/test/resources/keyboards/test_8568_deadkeys.kmx');
|
||||
const kmxKeyboard = new KMXKeyboard(coreKeyboard);
|
||||
const kmxKeyboard = new KMXKeyboard('test_8568_deadkeys', coreKeyboard);
|
||||
sandbox.replaceGetter(coreProcessor, 'activeKeyboard', () => { return kmxKeyboard; });
|
||||
// We return a non-ok value just so that we can return early from
|
||||
// processKeyStroke()
|
||||
|
|
@ -546,7 +546,7 @@ describe('CoreKeyboardProcessor', function () {
|
|||
context = KM_Core.instance.state_context(state);
|
||||
sandbox = sinon.createSandbox();
|
||||
const coreKeyboard = loadKeyboard('/common/test/resources/keyboards/test_8568_deadkeys.kmx');
|
||||
coreProcessor.activeKeyboard = new KMXKeyboard(coreKeyboard);
|
||||
coreProcessor.activeKeyboard = new KMXKeyboard('test_8568_deadkeys', coreKeyboard);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { createRequire } from 'module';
|
|||
const require = createRequire(import.meta.url);
|
||||
|
||||
import { DeviceSpec, KMWString } from 'keyman/common/web-utils';
|
||||
import { Codes, DefaultOutputRules, JSKeyboard, KeyEvent, MinimalKeymanGlobal, SyntheticTextStore } from 'keyman/engine/keyboard';
|
||||
import { Codes, DefaultOutputRules, KeyEvent, MinimalKeymanGlobal, SyntheticTextStore } from 'keyman/engine/keyboard';
|
||||
import { JSKeyboardInterface, JSKeyboardProcessor } from 'keyman/engine/js-processor';
|
||||
import { NodeKeyboardLoader } from 'keyman/test/resources';
|
||||
import { ModifierKeyConstants } from '@keymanapp/common-types';
|
||||
|
|
@ -103,7 +103,7 @@ describe('Engine - specialized backspace handling', function() {
|
|||
// This part provides extra assurance that the keyboard properly loaded.
|
||||
assert.equal(keyboard.id, "Keyboard_sil_ipa");
|
||||
|
||||
harness.activeKeyboard = keyboard as JSKeyboard;
|
||||
harness.activeKeyboard = keyboard;
|
||||
ipaWithHarness = harness;
|
||||
|
||||
// --------------
|
||||
|
|
@ -117,7 +117,7 @@ describe('Engine - specialized backspace handling', function() {
|
|||
// This part provides extra assurance that the keyboard properly loaded.
|
||||
assert.equal(keyboard.id, "Keyboard_khmer_angkor");
|
||||
|
||||
harness.activeKeyboard = keyboard as JSKeyboard;
|
||||
harness.activeKeyboard = keyboard;
|
||||
angkorWithHarness = harness;
|
||||
|
||||
// --------------
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { readFile } from 'node:fs/promises';
|
|||
|
||||
import { globalObject } from 'keyman/common/web-utils';
|
||||
|
||||
import { JSKeyboard, KeyboardHarness, MinimalKeymanGlobal, KeyboardLoaderBase, KeyboardLoadErrorBuilder } from 'keyman/engine/keyboard';
|
||||
import { Keyboard, KeyboardHarness, MinimalKeymanGlobal, KeyboardLoaderBase, KeyboardLoadErrorBuilder } from 'keyman/engine/keyboard';
|
||||
|
||||
export class NodeKeyboardLoader extends KeyboardLoaderBase {
|
||||
constructor()
|
||||
|
|
@ -38,7 +38,7 @@ export class NodeKeyboardLoader extends KeyboardLoaderBase {
|
|||
return Uint8Array.from(buffer);
|
||||
}
|
||||
|
||||
protected async loadKeyboardFromScript(scriptSrc: string, errorBuilder: KeyboardLoadErrorBuilder): Promise<JSKeyboard> {
|
||||
protected async loadKeyboardFromScript(scriptSrc: string, errorBuilder: KeyboardLoadErrorBuilder): Promise<Keyboard> {
|
||||
let script;
|
||||
try {
|
||||
script = new vm.Script(scriptSrc);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue