2022-04-21 18:01:54 +02:00
|
|
|
import * as plugins from './domtools.plugins.js';
|
|
|
|
|
|
2022-04-20 23:56:09 +02:00
|
|
|
export enum Key {
|
|
|
|
|
Backspace = 8,
|
|
|
|
|
Tab = 9,
|
|
|
|
|
Enter = 13,
|
|
|
|
|
Shift = 16,
|
|
|
|
|
Ctrl = 17,
|
|
|
|
|
Alt = 18,
|
|
|
|
|
PauseBreak = 19,
|
|
|
|
|
CapsLock = 20,
|
|
|
|
|
Escape = 27,
|
|
|
|
|
Space = 32,
|
|
|
|
|
PageUp = 33,
|
|
|
|
|
PageDown = 34,
|
|
|
|
|
End = 35,
|
|
|
|
|
Home = 36,
|
|
|
|
|
|
|
|
|
|
LeftArrow = 37,
|
|
|
|
|
UpArrow = 38,
|
|
|
|
|
RightArrow = 39,
|
|
|
|
|
DownArrow = 40,
|
|
|
|
|
|
|
|
|
|
Insert = 45,
|
|
|
|
|
Delete = 46,
|
|
|
|
|
|
|
|
|
|
Zero = 48,
|
|
|
|
|
ClosedParen = Zero,
|
|
|
|
|
One = 49,
|
|
|
|
|
ExclamationMark = One,
|
|
|
|
|
Two = 50,
|
|
|
|
|
AtSign = Two,
|
|
|
|
|
Three = 51,
|
|
|
|
|
PoundSign = Three,
|
|
|
|
|
Hash = PoundSign,
|
|
|
|
|
Four = 52,
|
|
|
|
|
DollarSign = Four,
|
|
|
|
|
Five = 53,
|
|
|
|
|
PercentSign = Five,
|
|
|
|
|
Six = 54,
|
|
|
|
|
Caret = Six,
|
|
|
|
|
Hat = Caret,
|
|
|
|
|
Seven = 55,
|
|
|
|
|
Ampersand = Seven,
|
|
|
|
|
Eight = 56,
|
|
|
|
|
Star = Eight,
|
|
|
|
|
Asterik = Star,
|
|
|
|
|
Nine = 57,
|
|
|
|
|
OpenParen = Nine,
|
|
|
|
|
|
|
|
|
|
A = 65,
|
|
|
|
|
B = 66,
|
|
|
|
|
C = 67,
|
|
|
|
|
D = 68,
|
|
|
|
|
E = 69,
|
|
|
|
|
F = 70,
|
|
|
|
|
G = 71,
|
|
|
|
|
H = 72,
|
|
|
|
|
I = 73,
|
|
|
|
|
J = 74,
|
|
|
|
|
K = 75,
|
|
|
|
|
L = 76,
|
|
|
|
|
M = 77,
|
|
|
|
|
N = 78,
|
|
|
|
|
O = 79,
|
|
|
|
|
P = 80,
|
|
|
|
|
Q = 81,
|
|
|
|
|
R = 82,
|
|
|
|
|
S = 83,
|
|
|
|
|
T = 84,
|
|
|
|
|
U = 85,
|
|
|
|
|
V = 86,
|
|
|
|
|
W = 87,
|
|
|
|
|
X = 88,
|
|
|
|
|
Y = 89,
|
|
|
|
|
Z = 90,
|
|
|
|
|
|
|
|
|
|
LeftWindowKey = 91,
|
|
|
|
|
RightWindowKey = 92,
|
|
|
|
|
SelectKey = 93,
|
|
|
|
|
|
|
|
|
|
Numpad0 = 96,
|
|
|
|
|
Numpad1 = 97,
|
|
|
|
|
Numpad2 = 98,
|
|
|
|
|
Numpad3 = 99,
|
|
|
|
|
Numpad4 = 100,
|
|
|
|
|
Numpad5 = 101,
|
|
|
|
|
Numpad6 = 102,
|
|
|
|
|
Numpad7 = 103,
|
|
|
|
|
Numpad8 = 104,
|
|
|
|
|
Numpad9 = 105,
|
|
|
|
|
|
|
|
|
|
Multiply = 106,
|
|
|
|
|
Add = 107,
|
|
|
|
|
Subtract = 109,
|
|
|
|
|
DecimalPoint = 110,
|
|
|
|
|
Divide = 111,
|
|
|
|
|
|
|
|
|
|
F1 = 112,
|
|
|
|
|
F2 = 113,
|
|
|
|
|
F3 = 114,
|
|
|
|
|
F4 = 115,
|
|
|
|
|
F5 = 116,
|
|
|
|
|
F6 = 117,
|
|
|
|
|
F7 = 118,
|
|
|
|
|
F8 = 119,
|
|
|
|
|
F9 = 120,
|
|
|
|
|
F10 = 121,
|
|
|
|
|
F11 = 122,
|
|
|
|
|
F12 = 123,
|
|
|
|
|
|
|
|
|
|
NumLock = 144,
|
|
|
|
|
ScrollLock = 145,
|
|
|
|
|
|
|
|
|
|
SemiColon = 186,
|
|
|
|
|
Equals = 187,
|
|
|
|
|
Comma = 188,
|
|
|
|
|
Dash = 189,
|
|
|
|
|
Period = 190,
|
|
|
|
|
UnderScore = Dash,
|
|
|
|
|
PlusSign = Equals,
|
|
|
|
|
ForwardSlash = 191,
|
|
|
|
|
Tilde = 192,
|
|
|
|
|
GraveAccent = Tilde,
|
|
|
|
|
|
|
|
|
|
OpenBracket = 219,
|
|
|
|
|
ClosedBracket = 221,
|
2022-04-21 18:01:54 +02:00
|
|
|
Quote = 222,
|
2022-04-20 23:56:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class Keyboard {
|
2026-04-24 04:54:40 +00:00
|
|
|
private mapCombosToHandlers = new Map<
|
|
|
|
|
string,
|
|
|
|
|
{
|
|
|
|
|
keys: Key[];
|
|
|
|
|
subjects: plugins.smartrx.rxjs.Subject<KeyboardEvent>[];
|
|
|
|
|
}
|
|
|
|
|
>();
|
2022-04-20 23:56:09 +02:00
|
|
|
private pressedKeys = new Set<Key>();
|
2026-04-24 04:54:40 +00:00
|
|
|
private listening = false;
|
2022-04-20 23:56:09 +02:00
|
|
|
|
2022-04-21 18:01:54 +02:00
|
|
|
constructor(private domNode: Element | Document) {
|
|
|
|
|
this.startListening();
|
2022-04-20 23:56:09 +02:00
|
|
|
}
|
|
|
|
|
|
2022-04-21 19:16:06 +02:00
|
|
|
public keyEnum = Key;
|
|
|
|
|
|
2022-04-21 23:52:45 +02:00
|
|
|
public on(keys: Key[]) {
|
2022-04-21 18:01:54 +02:00
|
|
|
const subject = new plugins.smartrx.rxjs.Subject<KeyboardEvent>();
|
2022-04-21 23:52:45 +02:00
|
|
|
this.registerKeys(keys, subject);
|
2022-04-21 19:05:52 +02:00
|
|
|
return subject;
|
2022-04-20 23:56:09 +02:00
|
|
|
}
|
|
|
|
|
|
2022-04-22 10:39:34 +02:00
|
|
|
public triggerKeyPress(keysArg: Key[]) {
|
2026-04-24 04:54:40 +00:00
|
|
|
const normalizedKeys = this.normalizeKeys(keysArg);
|
|
|
|
|
for (const key of normalizedKeys) {
|
2022-04-22 10:39:34 +02:00
|
|
|
this.pressedKeys.add(key);
|
|
|
|
|
}
|
2026-04-24 04:54:40 +00:00
|
|
|
this.checkMatchingKeyboardSubjects(this.createKeyboardEvent(normalizedKeys));
|
|
|
|
|
for (const key of normalizedKeys) {
|
2022-04-22 10:39:34 +02:00
|
|
|
this.pressedKeys.delete(key);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-21 18:01:54 +02:00
|
|
|
public startListening() {
|
2026-04-24 04:54:40 +00:00
|
|
|
if (this.listening) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2026-03-27 16:32:24 +00:00
|
|
|
this.domNode.addEventListener('keydown', this.handleKeyDown as EventListener);
|
|
|
|
|
this.domNode.addEventListener('keyup', this.handleKeyUp as EventListener);
|
2026-04-24 04:54:40 +00:00
|
|
|
this.listening = true;
|
2022-04-20 23:56:09 +02:00
|
|
|
}
|
|
|
|
|
|
2022-04-21 18:01:54 +02:00
|
|
|
public stopListening() {
|
2026-04-24 04:54:40 +00:00
|
|
|
if (!this.listening) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2026-03-27 16:32:24 +00:00
|
|
|
this.domNode.removeEventListener('keydown', this.handleKeyDown as EventListener);
|
|
|
|
|
this.domNode.removeEventListener('keyup', this.handleKeyUp as EventListener);
|
2026-04-24 04:54:40 +00:00
|
|
|
this.listening = false;
|
2022-04-20 23:56:09 +02:00
|
|
|
}
|
|
|
|
|
|
2022-04-21 18:01:54 +02:00
|
|
|
public clear() {
|
|
|
|
|
this.stopListening();
|
2026-04-24 04:54:40 +00:00
|
|
|
for (const comboEntry of this.mapCombosToHandlers.values()) {
|
|
|
|
|
for (const subject of comboEntry.subjects) {
|
|
|
|
|
subject.complete();
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-04-21 18:01:54 +02:00
|
|
|
this.mapCombosToHandlers.clear();
|
|
|
|
|
this.pressedKeys.clear();
|
2022-04-20 23:56:09 +02:00
|
|
|
}
|
|
|
|
|
|
2026-04-24 04:54:40 +00:00
|
|
|
public dispose() {
|
|
|
|
|
this.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-20 23:56:09 +02:00
|
|
|
private handleKeyDown = (event: KeyboardEvent) => {
|
2026-04-24 04:54:40 +00:00
|
|
|
const resolvedKey = this.resolveKey(event);
|
|
|
|
|
if (resolvedKey === null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
this.pressedKeys.add(resolvedKey);
|
2022-04-22 10:39:34 +02:00
|
|
|
this.checkMatchingKeyboardSubjects(event);
|
|
|
|
|
};
|
2022-04-20 23:56:09 +02:00
|
|
|
|
2026-04-24 04:54:40 +00:00
|
|
|
private checkMatchingKeyboardSubjects(payloadArg: KeyboardEvent) {
|
|
|
|
|
this.mapCombosToHandlers.forEach((comboEntry) => {
|
|
|
|
|
if (this.areAllKeysPressed(comboEntry.keys)) {
|
|
|
|
|
for (const subjectArg of comboEntry.subjects) {
|
|
|
|
|
subjectArg.next(payloadArg);
|
|
|
|
|
}
|
2022-04-21 18:01:54 +02:00
|
|
|
}
|
|
|
|
|
});
|
2022-04-22 10:39:34 +02:00
|
|
|
}
|
2022-04-20 23:56:09 +02:00
|
|
|
|
|
|
|
|
private handleKeyUp = (event: KeyboardEvent) => {
|
2026-04-24 04:54:40 +00:00
|
|
|
const resolvedKey = this.resolveKey(event);
|
|
|
|
|
if (resolvedKey === null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
this.pressedKeys.delete(resolvedKey);
|
2022-04-21 18:01:54 +02:00
|
|
|
};
|
2022-04-20 23:56:09 +02:00
|
|
|
|
2022-04-22 09:25:10 +02:00
|
|
|
private areAllKeysPressed(keysArg: Key[]) {
|
2022-04-21 18:01:54 +02:00
|
|
|
let result = true;
|
2022-04-20 23:56:09 +02:00
|
|
|
|
2022-04-22 09:25:10 +02:00
|
|
|
keysArg.forEach((key) => {
|
2022-04-21 18:01:54 +02:00
|
|
|
if (!this.pressedKeys.has(key)) {
|
|
|
|
|
result = false;
|
2022-04-20 23:56:09 +02:00
|
|
|
}
|
2022-04-21 18:01:54 +02:00
|
|
|
});
|
2022-04-20 23:56:09 +02:00
|
|
|
|
2022-04-21 18:01:54 +02:00
|
|
|
return result;
|
|
|
|
|
}
|
2022-04-20 23:56:09 +02:00
|
|
|
|
2022-04-21 23:52:45 +02:00
|
|
|
private registerKeys(
|
|
|
|
|
keysArg: Array<Key>,
|
2022-04-21 18:01:54 +02:00
|
|
|
subjectArg: plugins.smartrx.rxjs.Subject<KeyboardEvent>
|
|
|
|
|
) {
|
2026-04-24 04:54:40 +00:00
|
|
|
const normalizedKeys = this.normalizeKeys(keysArg);
|
|
|
|
|
const comboKey = normalizedKeys.join('+');
|
|
|
|
|
const existingEntry = this.mapCombosToHandlers.get(comboKey);
|
|
|
|
|
if (!existingEntry) {
|
|
|
|
|
this.mapCombosToHandlers.set(comboKey, {
|
|
|
|
|
keys: normalizedKeys,
|
|
|
|
|
subjects: [subjectArg],
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
existingEntry.subjects.push(subjectArg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private normalizeKeys(keysArg: Key[]) {
|
|
|
|
|
return [...new Set(keysArg)].sort((leftKey, rightKey) => leftKey - rightKey);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private resolveKey(event: KeyboardEvent): Key | null {
|
|
|
|
|
return this.resolveKeyFromCode(event.code)
|
|
|
|
|
?? this.resolveKeyFromKey(event.key)
|
|
|
|
|
?? this.resolveKeyFromKeyCode(event.keyCode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private resolveKeyFromCode(codeArg: string): Key | null {
|
|
|
|
|
if (!codeArg) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (codeArg.startsWith('Key') && codeArg.length === 4) {
|
|
|
|
|
return Key[codeArg.slice(3) as keyof typeof Key] ?? null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (codeArg.startsWith('Digit') && codeArg.length === 6) {
|
|
|
|
|
return this.resolveKeyFromKey(codeArg.slice(5));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (codeArg) {
|
|
|
|
|
case 'Backspace':
|
|
|
|
|
return Key.Backspace;
|
|
|
|
|
case 'Tab':
|
|
|
|
|
return Key.Tab;
|
|
|
|
|
case 'Enter':
|
|
|
|
|
case 'NumpadEnter':
|
|
|
|
|
return Key.Enter;
|
|
|
|
|
case 'ShiftLeft':
|
|
|
|
|
case 'ShiftRight':
|
|
|
|
|
return Key.Shift;
|
|
|
|
|
case 'ControlLeft':
|
|
|
|
|
case 'ControlRight':
|
|
|
|
|
return Key.Ctrl;
|
|
|
|
|
case 'AltLeft':
|
|
|
|
|
case 'AltRight':
|
|
|
|
|
return Key.Alt;
|
|
|
|
|
case 'Pause':
|
|
|
|
|
return Key.PauseBreak;
|
|
|
|
|
case 'CapsLock':
|
|
|
|
|
return Key.CapsLock;
|
|
|
|
|
case 'Escape':
|
|
|
|
|
return Key.Escape;
|
|
|
|
|
case 'Space':
|
|
|
|
|
return Key.Space;
|
|
|
|
|
case 'PageUp':
|
|
|
|
|
return Key.PageUp;
|
|
|
|
|
case 'PageDown':
|
|
|
|
|
return Key.PageDown;
|
|
|
|
|
case 'End':
|
|
|
|
|
return Key.End;
|
|
|
|
|
case 'Home':
|
|
|
|
|
return Key.Home;
|
|
|
|
|
case 'ArrowLeft':
|
|
|
|
|
return Key.LeftArrow;
|
|
|
|
|
case 'ArrowUp':
|
|
|
|
|
return Key.UpArrow;
|
|
|
|
|
case 'ArrowRight':
|
|
|
|
|
return Key.RightArrow;
|
|
|
|
|
case 'ArrowDown':
|
|
|
|
|
return Key.DownArrow;
|
|
|
|
|
case 'Insert':
|
|
|
|
|
return Key.Insert;
|
|
|
|
|
case 'Delete':
|
|
|
|
|
return Key.Delete;
|
|
|
|
|
case 'MetaLeft':
|
|
|
|
|
return Key.LeftWindowKey;
|
|
|
|
|
case 'MetaRight':
|
|
|
|
|
return Key.RightWindowKey;
|
|
|
|
|
case 'ContextMenu':
|
|
|
|
|
return Key.SelectKey;
|
|
|
|
|
case 'Numpad0':
|
|
|
|
|
return Key.Numpad0;
|
|
|
|
|
case 'Numpad1':
|
|
|
|
|
return Key.Numpad1;
|
|
|
|
|
case 'Numpad2':
|
|
|
|
|
return Key.Numpad2;
|
|
|
|
|
case 'Numpad3':
|
|
|
|
|
return Key.Numpad3;
|
|
|
|
|
case 'Numpad4':
|
|
|
|
|
return Key.Numpad4;
|
|
|
|
|
case 'Numpad5':
|
|
|
|
|
return Key.Numpad5;
|
|
|
|
|
case 'Numpad6':
|
|
|
|
|
return Key.Numpad6;
|
|
|
|
|
case 'Numpad7':
|
|
|
|
|
return Key.Numpad7;
|
|
|
|
|
case 'Numpad8':
|
|
|
|
|
return Key.Numpad8;
|
|
|
|
|
case 'Numpad9':
|
|
|
|
|
return Key.Numpad9;
|
|
|
|
|
case 'NumpadMultiply':
|
|
|
|
|
return Key.Multiply;
|
|
|
|
|
case 'NumpadAdd':
|
|
|
|
|
return Key.Add;
|
|
|
|
|
case 'NumpadSubtract':
|
|
|
|
|
return Key.Subtract;
|
|
|
|
|
case 'NumpadDecimal':
|
|
|
|
|
return Key.DecimalPoint;
|
|
|
|
|
case 'NumpadDivide':
|
|
|
|
|
return Key.Divide;
|
|
|
|
|
case 'F1':
|
|
|
|
|
return Key.F1;
|
|
|
|
|
case 'F2':
|
|
|
|
|
return Key.F2;
|
|
|
|
|
case 'F3':
|
|
|
|
|
return Key.F3;
|
|
|
|
|
case 'F4':
|
|
|
|
|
return Key.F4;
|
|
|
|
|
case 'F5':
|
|
|
|
|
return Key.F5;
|
|
|
|
|
case 'F6':
|
|
|
|
|
return Key.F6;
|
|
|
|
|
case 'F7':
|
|
|
|
|
return Key.F7;
|
|
|
|
|
case 'F8':
|
|
|
|
|
return Key.F8;
|
|
|
|
|
case 'F9':
|
|
|
|
|
return Key.F9;
|
|
|
|
|
case 'F10':
|
|
|
|
|
return Key.F10;
|
|
|
|
|
case 'F11':
|
|
|
|
|
return Key.F11;
|
|
|
|
|
case 'F12':
|
|
|
|
|
return Key.F12;
|
|
|
|
|
case 'NumLock':
|
|
|
|
|
return Key.NumLock;
|
|
|
|
|
case 'ScrollLock':
|
|
|
|
|
return Key.ScrollLock;
|
|
|
|
|
case 'Semicolon':
|
|
|
|
|
return Key.SemiColon;
|
|
|
|
|
case 'Equal':
|
|
|
|
|
return Key.Equals;
|
|
|
|
|
case 'Comma':
|
|
|
|
|
return Key.Comma;
|
|
|
|
|
case 'Minus':
|
|
|
|
|
return Key.Dash;
|
|
|
|
|
case 'Period':
|
|
|
|
|
return Key.Period;
|
|
|
|
|
case 'Slash':
|
|
|
|
|
return Key.ForwardSlash;
|
|
|
|
|
case 'Backquote':
|
|
|
|
|
return Key.Tilde;
|
|
|
|
|
case 'BracketLeft':
|
|
|
|
|
return Key.OpenBracket;
|
|
|
|
|
case 'BracketRight':
|
|
|
|
|
return Key.ClosedBracket;
|
|
|
|
|
case 'Quote':
|
|
|
|
|
return Key.Quote;
|
|
|
|
|
default:
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private resolveKeyFromKey(keyArg: string): Key | null {
|
|
|
|
|
if (!keyArg) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (keyArg.length === 1) {
|
|
|
|
|
const upperKey = keyArg.toUpperCase();
|
|
|
|
|
if (upperKey >= 'A' && upperKey <= 'Z') {
|
|
|
|
|
return Key[upperKey as keyof typeof Key] ?? null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (keyArg) {
|
|
|
|
|
case '0':
|
|
|
|
|
return Key.Zero;
|
|
|
|
|
case '1':
|
|
|
|
|
return Key.One;
|
|
|
|
|
case '2':
|
|
|
|
|
return Key.Two;
|
|
|
|
|
case '3':
|
|
|
|
|
return Key.Three;
|
|
|
|
|
case '4':
|
|
|
|
|
return Key.Four;
|
|
|
|
|
case '5':
|
|
|
|
|
return Key.Five;
|
|
|
|
|
case '6':
|
|
|
|
|
return Key.Six;
|
|
|
|
|
case '7':
|
|
|
|
|
return Key.Seven;
|
|
|
|
|
case '8':
|
|
|
|
|
return Key.Eight;
|
|
|
|
|
case '9':
|
|
|
|
|
return Key.Nine;
|
|
|
|
|
case ' ':
|
|
|
|
|
return Key.Space;
|
|
|
|
|
case ';':
|
|
|
|
|
return Key.SemiColon;
|
|
|
|
|
case '=':
|
|
|
|
|
return Key.Equals;
|
|
|
|
|
case ',':
|
|
|
|
|
return Key.Comma;
|
|
|
|
|
case '-':
|
|
|
|
|
return Key.Dash;
|
|
|
|
|
case '.':
|
|
|
|
|
return Key.Period;
|
|
|
|
|
case '/':
|
|
|
|
|
return Key.ForwardSlash;
|
|
|
|
|
case '`':
|
|
|
|
|
return Key.Tilde;
|
|
|
|
|
case '[':
|
|
|
|
|
return Key.OpenBracket;
|
|
|
|
|
case ']':
|
|
|
|
|
return Key.ClosedBracket;
|
|
|
|
|
case '\'':
|
|
|
|
|
return Key.Quote;
|
|
|
|
|
default:
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (keyArg) {
|
|
|
|
|
case 'Backspace':
|
|
|
|
|
return Key.Backspace;
|
|
|
|
|
case 'Tab':
|
|
|
|
|
return Key.Tab;
|
|
|
|
|
case 'Enter':
|
|
|
|
|
return Key.Enter;
|
|
|
|
|
case 'Shift':
|
|
|
|
|
return Key.Shift;
|
|
|
|
|
case 'Control':
|
|
|
|
|
return Key.Ctrl;
|
|
|
|
|
case 'Alt':
|
|
|
|
|
return Key.Alt;
|
|
|
|
|
case 'Pause':
|
|
|
|
|
return Key.PauseBreak;
|
|
|
|
|
case 'CapsLock':
|
|
|
|
|
return Key.CapsLock;
|
|
|
|
|
case 'Escape':
|
|
|
|
|
return Key.Escape;
|
|
|
|
|
case 'PageUp':
|
|
|
|
|
return Key.PageUp;
|
|
|
|
|
case 'PageDown':
|
|
|
|
|
return Key.PageDown;
|
|
|
|
|
case 'End':
|
|
|
|
|
return Key.End;
|
|
|
|
|
case 'Home':
|
|
|
|
|
return Key.Home;
|
|
|
|
|
case 'ArrowLeft':
|
|
|
|
|
return Key.LeftArrow;
|
|
|
|
|
case 'ArrowUp':
|
|
|
|
|
return Key.UpArrow;
|
|
|
|
|
case 'ArrowRight':
|
|
|
|
|
return Key.RightArrow;
|
|
|
|
|
case 'ArrowDown':
|
|
|
|
|
return Key.DownArrow;
|
|
|
|
|
case 'Insert':
|
|
|
|
|
return Key.Insert;
|
|
|
|
|
case 'Delete':
|
|
|
|
|
return Key.Delete;
|
|
|
|
|
case 'Meta':
|
|
|
|
|
return Key.LeftWindowKey;
|
|
|
|
|
case 'ContextMenu':
|
|
|
|
|
return Key.SelectKey;
|
|
|
|
|
case 'NumLock':
|
|
|
|
|
return Key.NumLock;
|
|
|
|
|
case 'ScrollLock':
|
|
|
|
|
return Key.ScrollLock;
|
|
|
|
|
default:
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private resolveKeyFromKeyCode(keyCodeArg: number): Key | null {
|
|
|
|
|
if (typeof keyCodeArg !== 'number') {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return typeof Key[keyCodeArg as Key] !== 'undefined' ? (keyCodeArg as Key) : null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private createKeyboardEvent(keysArg: Key[]) {
|
|
|
|
|
const triggerKey = keysArg[keysArg.length - 1] ?? Key.Enter;
|
|
|
|
|
const keyDescriptor = this.getKeyDescriptor(triggerKey);
|
|
|
|
|
return new KeyboardEvent('keydown', {
|
|
|
|
|
key: keyDescriptor.key,
|
|
|
|
|
code: keyDescriptor.code,
|
|
|
|
|
ctrlKey: keysArg.includes(Key.Ctrl),
|
|
|
|
|
shiftKey: keysArg.includes(Key.Shift),
|
|
|
|
|
altKey: keysArg.includes(Key.Alt),
|
|
|
|
|
metaKey: keysArg.includes(Key.LeftWindowKey) || keysArg.includes(Key.RightWindowKey),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private getKeyDescriptor(keyArg: Key): { key: string; code: string } {
|
|
|
|
|
switch (keyArg) {
|
|
|
|
|
case Key.Ctrl:
|
|
|
|
|
return { key: 'Control', code: 'ControlLeft' };
|
|
|
|
|
case Key.Shift:
|
|
|
|
|
return { key: 'Shift', code: 'ShiftLeft' };
|
|
|
|
|
case Key.Alt:
|
|
|
|
|
return { key: 'Alt', code: 'AltLeft' };
|
|
|
|
|
case Key.Enter:
|
|
|
|
|
return { key: 'Enter', code: 'Enter' };
|
|
|
|
|
case Key.Space:
|
|
|
|
|
return { key: ' ', code: 'Space' };
|
|
|
|
|
default: {
|
|
|
|
|
const keyName = Key[keyArg];
|
|
|
|
|
if (keyName && keyName.length === 1) {
|
|
|
|
|
if (keyName >= 'A' && keyName <= 'Z') {
|
|
|
|
|
return { key: keyName.toLowerCase(), code: `Key${keyName}` };
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (keyArg >= Key.Zero && keyArg <= Key.Nine) {
|
|
|
|
|
const digit = String(keyArg - Key.Zero);
|
|
|
|
|
return { key: digit, code: `Digit${digit}` };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return { key: keyName ?? 'Unidentified', code: 'Unidentified' };
|
|
|
|
|
}
|
2022-04-21 18:01:54 +02:00
|
|
|
}
|
2022-04-20 23:56:09 +02:00
|
|
|
}
|
2022-04-21 18:01:54 +02:00
|
|
|
}
|