mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-08 09:55:32 +00:00
chore(web): Merge branch 'refactor/web/common-layout-typing' into feat/web/base-recognizer-integration
This commit is contained in:
commit
fd71de16e5
9 changed files with 44 additions and 47 deletions
|
|
@ -59,26 +59,17 @@ export abstract class InputEngineBase<HoveredItemType, StateToken = any> extends
|
|||
*/
|
||||
maintainTouchpointsWithIds(identifiers: number[]) {
|
||||
const identifiersToMaintain = identifiers.map((internal_id) => this.identifierMap[internal_id]);
|
||||
const sourcesToDrop: GestureSource<HoveredItemType>[] = [];
|
||||
|
||||
this._activeTouchpoints.forEach((source) => {
|
||||
if(identifiersToMaintain.indexOf(source.rawIdentifier) == -1) {
|
||||
sourcesToDrop.push(source);
|
||||
}
|
||||
});
|
||||
|
||||
sourcesToDrop.forEach((source) => {
|
||||
this._activeTouchpoints
|
||||
.filter((source) => !identifiersToMaintain.includes(source.rawIdentifier))
|
||||
// Will trigger `.dropTouchpoint` later in the event chain.
|
||||
source.terminate(true);
|
||||
});
|
||||
.forEach((source) => source.terminate(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param identifier The identifier number corresponding to the input sequence.
|
||||
*/
|
||||
hasActiveTouchpoint(identifier: number) {
|
||||
const id = this.identifierMap[identifier];
|
||||
return id !== undefined; //this.getTouchpointWithId(id) !== undefined;
|
||||
return this.identifierMap[identifier] !== undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -117,7 +108,7 @@ export abstract class InputEngineBase<HoveredItemType, StateToken = any> extends
|
|||
const id = point.rawIdentifier;
|
||||
|
||||
this._activeTouchpoints = this._activeTouchpoints.filter((pt) => point != pt);
|
||||
for(let key in this.identifierMap) {
|
||||
for(const key of Object.keys(this.identifierMap)) {
|
||||
if(this.identifierMap[key] == id) {
|
||||
delete this.identifierMap[key];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ export class TouchEventEngine<HoveredItemType, StateToken = any> extends InputEv
|
|||
public dropTouchpoint(source: GestureSource<HoveredItemType>) {
|
||||
super.dropTouchpoint(source);
|
||||
|
||||
for(let key in this.safeBoundMaskMap) {
|
||||
for(const key of Object.keys(this.safeBoundMaskMap)) {
|
||||
if(this.getTouchpointWithId(Number.parseInt(key, 10)) == source) {
|
||||
delete this.safeBoundMaskMap[key];
|
||||
}
|
||||
|
|
@ -104,7 +104,10 @@ export class TouchEventEngine<HoveredItemType, StateToken = any> extends InputEv
|
|||
const allTouches = touchListToArray(event.touches);
|
||||
const newTouches = touchListToArray(event.changedTouches);
|
||||
// Maintain all touches in the `.touches` array that are NOT marked as `.changedTouches` (and therefore, new)
|
||||
this.maintainTouchpointsWithIds(allTouches.filter((touch) => (newTouches.indexOf(touch) == -1)).map((touch) => touch.identifier));
|
||||
this.maintainTouchpointsWithIds(allTouches
|
||||
.filter((touch) => (newTouches.indexOf(touch) == -1))
|
||||
.map((touch) => touch.identifier)
|
||||
);
|
||||
|
||||
// Ensure the same timestamp is used for all touches being updated.
|
||||
const timestamp = performance.now();
|
||||
|
|
@ -134,7 +137,9 @@ export class TouchEventEngine<HoveredItemType, StateToken = any> extends InputEv
|
|||
// Ensure the same timestamp is used for all touches being updated.
|
||||
const timestamp = performance.now();
|
||||
|
||||
this.maintainTouchpointsWithIds(touchListToArray(event.touches).map((touch) => touch.identifier));
|
||||
this.maintainTouchpointsWithIds(touchListToArray(event.touches)
|
||||
.map((touch) => touch.identifier)
|
||||
);
|
||||
|
||||
// Do not change to `changedTouches` - we need a sample for all active touches in order
|
||||
// to facilitate path-update synchronization for multi-touch gestures.
|
||||
|
|
|
|||
|
|
@ -87,9 +87,12 @@ export class InputSequenceSimulator<HoveredItemType> {
|
|||
const mappedSample = this.getSampleClientPos(data.sample);
|
||||
|
||||
let touch: Touch;
|
||||
let touchDict = {identifier: data.identifier,
|
||||
target: targetElement || config.targetRoot,
|
||||
...mappedSample};
|
||||
let touchDict = {
|
||||
identifier: data.identifier,
|
||||
target: targetElement || config.targetRoot,
|
||||
...mappedSample
|
||||
};
|
||||
|
||||
if(window['Touch'] !== undefined) {
|
||||
touch = new Touch(touchDict);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import Codes from "../text/codes.js";
|
|||
import KeyEvent, { KeyEventSpec } from "../text/keyEvent.js";
|
||||
import KeyMapping from "../text/keyMapping.js";
|
||||
import type { KeyDistribution } from "../text/keyEvent.js";
|
||||
import { Layouts } from "./defaultLayouts.js";
|
||||
import type { LayoutKey, LayoutSubKey, LayoutRow, LayoutLayer, LayoutFormFactor, ButtonClass } from "./defaultLayouts.js";
|
||||
import type Keyboard from "./keyboard.js";
|
||||
|
||||
|
|
@ -63,7 +64,7 @@ class ActiveKeyBase {
|
|||
|
||||
// While they're only valid on ActiveKey, spec'ing them here makes references more concise within the OSK.
|
||||
sk?: ActiveKey[];
|
||||
multitap?: ActiveSubkey[];
|
||||
multitap?: ActiveSubKey[];
|
||||
flick?: TouchLayout.TouchLayoutFlick;
|
||||
|
||||
// Keeping things simple here, as this was added LATE in 14.0 beta.
|
||||
|
|
@ -96,7 +97,7 @@ class ActiveKeyBase {
|
|||
public get isPadding(): boolean {
|
||||
// Does not include 9 (class: blank) as that may be an intentional 'catch' for misplaced
|
||||
// keystrokes.
|
||||
return this.sp == 10; // Button class: hidden.
|
||||
return this.sp == Layouts.buttonClasses.HIDDEN; // Button class: hidden.
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -233,7 +234,7 @@ class ActiveKeyBase {
|
|||
// Ensure subkeys are also properly extended.
|
||||
if((key as LayoutKey).sk) {
|
||||
for(let subkey of (key as LayoutKey).sk) {
|
||||
ActiveSubkey.polyfill(subkey, keyboard, layout, displayLayer);
|
||||
ActiveSubKey.polyfill(subkey, keyboard, layout, displayLayer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -241,8 +242,6 @@ class ActiveKeyBase {
|
|||
aKey.displayLayer = displayLayer;
|
||||
aKey.layer = aKey.layer || displayLayer;
|
||||
|
||||
aKey.default = (key as LayoutSubKey).default;
|
||||
|
||||
// Compute the key's base KeyEvent properties for use in future event generation
|
||||
aKey.constructBaseKeyEvent(keyboard, layout, displayLayer);
|
||||
}
|
||||
|
|
@ -321,7 +320,7 @@ export class ActiveKey extends ActiveKeyBase implements LayoutKey {
|
|||
}
|
||||
|
||||
|
||||
export class ActiveSubkey extends ActiveKeyBase implements LayoutSubKey {
|
||||
export class ActiveSubKey extends ActiveKeyBase implements LayoutSubKey {
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -372,14 +371,14 @@ export class ActiveRow implements LayoutRow {
|
|||
// to allow the keyboard font to ovveride the SpecialOSK font.
|
||||
// Blank keys are no longer reclassed - can use before/after CSS to add text
|
||||
switch(key['sp']) {
|
||||
case 1:
|
||||
case Layouts.buttonClasses['SHIFT']:
|
||||
if(!ActiveRow.SPECIAL_LABEL.test(key['text']) && key['text'] != '') {
|
||||
key.sp=3;
|
||||
key.sp=Layouts.buttonClasses['SPECIAL'];
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
case Layouts.buttonClasses['SHIFT-ON']:
|
||||
if(!ActiveRow.SPECIAL_LABEL.test(key['text']) && key['text'] != '') {
|
||||
key.sp=4;
|
||||
key.sp=Layouts.buttonClasses['SPECIAL-ON'];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,10 +22,7 @@ export type KLS = {[layerName: string]: string[]};
|
|||
export type ButtonClass = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
|
||||
export type ButtonClassString = "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"|"10";
|
||||
|
||||
export type LayoutLayer = {
|
||||
"id": string,
|
||||
"row": LayoutRow[],
|
||||
|
||||
export interface LayoutLayer extends LayoutLayerBase {
|
||||
// Post-processing elements.
|
||||
shiftKey?: LayoutKey,
|
||||
capsKey?: LayoutKey,
|
||||
|
|
@ -45,6 +42,8 @@ export type LayoutSpec = {
|
|||
"tablet"?: LayoutFormFactor
|
||||
}
|
||||
|
||||
const KEY_102_WIDTH = 200;
|
||||
|
||||
// This class manages default layout construction for consumption by OSKs without a specified layout.
|
||||
export class Layouts {
|
||||
static dfltCodes=[
|
||||
|
|
@ -65,9 +64,9 @@ export class Layouts {
|
|||
// Cross-reference with the ids in osk.setButtonClass.
|
||||
static buttonClasses: {[name: string]: ButtonClass} = {
|
||||
'DEFAULT':0,
|
||||
'SHIFT':1,
|
||||
'SHIFT':1, // special-key / frame key styling: uses our custom, PUA OSK font
|
||||
'SHIFT-ON':2,
|
||||
'SPECIAL':3,
|
||||
'SPECIAL':3, // special-key / frame key styling: uses the keyboard's font
|
||||
'SPECIAL-ON':4,
|
||||
'DEADKEY':8,
|
||||
'BLANK':9,
|
||||
|
|
@ -479,7 +478,7 @@ export class Layouts {
|
|||
if(typeof key102 == 'undefined' || !key102) {
|
||||
if(formFactor == 'desktop') {
|
||||
keys.splice(j--, 1);
|
||||
keys[0]['width']=200;
|
||||
keys[0]['width']=KEY_102_WIDTH;
|
||||
} else {
|
||||
keys[j]['sp']=buttonClasses['HIDDEN'];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { ActiveSubkey } from '@keymanapp/keyboard-processor';
|
||||
import { ActiveSubKey } from '@keymanapp/keyboard-processor';
|
||||
import OSKKey from '../../../keyboard-layout/oskKey.js';
|
||||
import { KeyData, KeyElement, link } from '../../../keyElement.js';
|
||||
import VisualKeyboard from '../../../visualKeyboard.js';
|
||||
|
||||
export default class OSKSubKey extends OSKKey {
|
||||
constructor(spec: ActiveSubkey, layer: string) {
|
||||
constructor(spec: ActiveSubKey, layer: string) {
|
||||
if(typeof(layer) != 'string' || layer == '') {
|
||||
throw "The 'layer' parameter for subkey construction must be properly defined.";
|
||||
}
|
||||
|
|
@ -24,7 +24,7 @@ export default class OSKSubKey extends OSKKey {
|
|||
let tKey = osk.getDefaultKeyObject();
|
||||
let ks=kDiv.style;
|
||||
|
||||
for(var tp in tKey) {
|
||||
for(const tp of Object.keys(tKey)) {
|
||||
// We've already preprocessed the keyboard's version of the subkey. While certain
|
||||
// layout properties are fine to overwrite, certain functional properties must
|
||||
// be preserved.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import OSKBaseKey from '../../../keyboard-layout/oskBaseKey.js';
|
|||
import VisualKeyboard from '../../../visualKeyboard.js';
|
||||
import InputEventCoordinate from '../../../input/inputEventCoordinate.js';
|
||||
|
||||
import { DeviceSpec, KeyEvent, ActiveSubkey } from '@keymanapp/keyboard-processor';
|
||||
import { DeviceSpec, KeyEvent, ActiveSubKey } from '@keymanapp/keyboard-processor';
|
||||
import { InputSample } from '@keymanapp/gesture-recognizer';
|
||||
|
||||
/**
|
||||
|
|
@ -58,7 +58,7 @@ export default class SubkeyPopup implements RealizedGesture {
|
|||
e.key.highlight(true);
|
||||
|
||||
// A tag we directly set on a key element during its construction.
|
||||
let subKeySpec: ActiveSubkey[] = e['subKeys'];
|
||||
let subKeySpec: ActiveSubKey[] = e['subKeys'];
|
||||
|
||||
// The holder is position:fixed, but the keys do not need to be, as no scrolling
|
||||
// is possible while the array is visible. So it is simplest to let the keys have
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { ActiveSubkey } from '@keymanapp/keyboard-processor';
|
||||
import { ActiveSubKey } from '@keymanapp/keyboard-processor';
|
||||
import OSKKey from "./keyboard-layout/oskKey.js";
|
||||
|
||||
export class KeyData {
|
||||
['key']: OSKKey;
|
||||
['keyId']: string;
|
||||
['subKeys']?: ActiveSubkey[];
|
||||
['subKeys']?: ActiveSubKey[];
|
||||
|
||||
constructor(keyData: OSKKey, keyId: string) {
|
||||
this['key'] = keyData;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ActiveKey, ActiveSubkey, ButtonClass, DeviceSpec, LayoutKey } from '@keymanapp/keyboard-processor';
|
||||
import { ActiveKey, ActiveSubKey, ButtonClass, DeviceSpec, LayoutKey } from '@keymanapp/keyboard-processor';
|
||||
import { TouchLayout } from '@keymanapp/common-types';
|
||||
import TouchLayoutFlick = TouchLayout.TouchLayoutFlick;
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ export default abstract class OSKKey {
|
|||
static readonly BUTTON_CLASSES = buttonClassNames;
|
||||
|
||||
static readonly HIGHLIGHT_CLASS = 'kmw-key-touched';
|
||||
readonly spec: ActiveKey | ActiveSubkey;
|
||||
readonly spec: ActiveKey | ActiveSubKey;
|
||||
|
||||
btn: KeyElement;
|
||||
label: HTMLSpanElement;
|
||||
|
|
@ -31,7 +31,7 @@ export default abstract class OSKKey {
|
|||
*/
|
||||
readonly layer: string;
|
||||
|
||||
constructor(spec: ActiveKey | ActiveSubkey, layer: string) {
|
||||
constructor(spec: ActiveKey | ActiveSubKey, layer: string) {
|
||||
this.spec = spec;
|
||||
this.layer = layer;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue