mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-06 17:05:34 +00:00
The Caps Lock change I made in the previous commit broke desktop Caps Lock handling. The fix was a little more convoluted. Turns out that _UpdateVKShift is also pretty crufty. I simplified it, removing dead code.
119 lines
No EOL
3.6 KiB
TypeScript
119 lines
No EOL
3.6 KiB
TypeScript
/// <reference path="../pendingGesture.interface.ts" />
|
|
/// <reference path="../visualKeyboard.ts" />
|
|
|
|
namespace com.keyman.osk {
|
|
|
|
export enum PendingMultiTapState { Waiting, Realized, Cancelled };
|
|
/**
|
|
* Implements the multi-tap gesture, which is a series of taps on a single key
|
|
* (based on key id substring in the case of the shift key), within a
|
|
* specified timeout period.
|
|
*/
|
|
export class PendingMultiTap implements PendingGesture {
|
|
public readonly vkbd: VisualKeyboard;
|
|
public readonly baseKey: KeyElement;
|
|
public readonly count: number;
|
|
private timerId;
|
|
private _touches = 1; // we start the multitap with a single touch
|
|
private _state: PendingMultiTapState = PendingMultiTapState.Waiting;
|
|
private _timeout: Promise<void>;
|
|
private cancelDelayFactor = 125; // 125msec * count
|
|
|
|
public get timeout() {
|
|
return this._timeout;
|
|
}
|
|
public get realized() {
|
|
return this._state == PendingMultiTapState.Realized;
|
|
}
|
|
public get cancelled() {
|
|
return this._state == PendingMultiTapState.Cancelled;
|
|
}
|
|
|
|
/**
|
|
* Construct a record of a potential multitap gesture
|
|
* @param vkbd
|
|
* @param baseKey key which is being tapped
|
|
* @param count number of taps required to finalize this gesture
|
|
*/
|
|
constructor(vkbd: VisualKeyboard, baseKey: KeyElement, count: number) {
|
|
this.vkbd = vkbd;
|
|
this.count = count;
|
|
this.baseKey = baseKey;
|
|
|
|
const _this = this;
|
|
this._timeout = new Promise<void>(function(resolve) {
|
|
// If multiple taps do not occur within the timeout window,
|
|
// then we will abandon the gesture
|
|
_this.timerId = window.setTimeout(() => {
|
|
_this.cancel();
|
|
resolve();
|
|
}, _this.cancelDelayFactor * _this.count);
|
|
});
|
|
}
|
|
|
|
public static isValidTarget(vkbd: VisualKeyboard, baseKey: KeyElement) {
|
|
return (
|
|
baseKey['keyId'].includes('K_SHIFT') &&
|
|
vkbd.layerGroup.layers['caps'] &&
|
|
!baseKey['subKeys'] &&
|
|
vkbd.touchCount == 1
|
|
);
|
|
}
|
|
|
|
private cleanup(): void {
|
|
if(this.timerId) {
|
|
window.clearTimeout(this.timerId);
|
|
}
|
|
this.timerId = null;
|
|
}
|
|
|
|
/**
|
|
* Cancel a pending multitap gesture
|
|
*/
|
|
public cancel(): void {
|
|
this._state = PendingMultiTapState.Cancelled;
|
|
this.cleanup();
|
|
}
|
|
|
|
/**
|
|
* Increments the touch counter for the gesture, and
|
|
* if the touch count is reached, realize the gesture
|
|
* @returns new state of the gesture
|
|
*/
|
|
public incrementTouch(newKey: KeyElement): PendingMultiTapState {
|
|
// TODO: support for any key
|
|
if(this._state == PendingMultiTapState.Waiting) {
|
|
if(!newKey['keyId'].includes('K_SHIFT')) {
|
|
this.cancel();
|
|
}
|
|
else if(++this._touches == this.count) {
|
|
this.realize();
|
|
}
|
|
}
|
|
return this._state;
|
|
}
|
|
|
|
/**
|
|
* Realize the gesture. In Keyman 15, this supports only
|
|
* the Caps double-tap gesture on the Shift key.
|
|
*/
|
|
public realize(): void {
|
|
if(this._state != PendingMultiTapState.Waiting) {
|
|
return;
|
|
}
|
|
this._state = PendingMultiTapState.Realized;
|
|
this.cleanup();
|
|
|
|
// In Keyman 15, only the K_SHIFT key supports multi-tap, so we can hack
|
|
// in the switch to the caps layer.
|
|
//
|
|
// TODO: generalize this with double-tap key properties in touch layout
|
|
// description.
|
|
let e = text.KeyEvent.constructNullKeyEvent(this.vkbd.device);
|
|
e.kNextLayer = 'caps';
|
|
e.Lstates = text.Codes.stateBitmasks.CAPS;
|
|
e.LmodifierChange = true;
|
|
PreProcessor.raiseKeyEvent(e);
|
|
}
|
|
}
|
|
} |