better-xcloud/src/modules/mkb/key-helper.ts
2024-12-07 16:48:58 +07:00

151 lines
4.3 KiB
TypeScript
Executable File

import { MouseButtonCode, WheelCode, type KeyCode } from "@/enums/mkb";
export const enum KeyModifier {
CTRL = 1,
SHIFT = 2,
ALT = 4,
};
export type KeyEventInfo = {
code: KeyCode | MouseButtonCode | WheelCode;
modifiers?: number;
};
export class KeyHelper {
private static readonly NON_PRINTABLE_KEYS = {
Backquote: '`',
Minus: '-',
Equal: '=',
BracketLeft: '[',
BracketRight: ']',
Backslash: '\\',
Semicolon: ';',
Quote: '\'',
Comma: ',',
Period: '.',
Slash: '/',
NumpadMultiply: 'Numpad *',
NumpadAdd: 'Numpad +',
NumpadSubtract: 'Numpad -',
NumpadDecimal: 'Numpad .',
NumpadDivide: 'Numpad /',
NumpadEqual: 'Numpad =',
// Mouse buttons
[MouseButtonCode.LEFT_CLICK]: 'Left Click',
[MouseButtonCode.RIGHT_CLICK]: 'Right Click',
[MouseButtonCode.MIDDLE_CLICK]: 'Middle Click',
[WheelCode.SCROLL_UP]: 'Scroll Up',
[WheelCode.SCROLL_DOWN]: 'Scroll Down',
[WheelCode.SCROLL_LEFT]: 'Scroll Left',
[WheelCode.SCROLL_RIGHT]: 'Scroll Right',
};
static getKeyFromEvent(e: Event): KeyEventInfo | null {
let code: KeyEventInfo['code'] | null = null;
let modifiers;
if (e instanceof KeyboardEvent) {
code = (e.code || e.key) as KeyCode;
// Modifiers
modifiers = 0;
modifiers ^= e.ctrlKey ? KeyModifier.CTRL : 0;
modifiers ^= e.shiftKey ? KeyModifier.SHIFT : 0;
modifiers ^= e.altKey ? KeyModifier.ALT : 0;
} else if (e instanceof WheelEvent) {
if (e.deltaY < 0) {
code = WheelCode.SCROLL_UP;
} else if (e.deltaY > 0) {
code = WheelCode.SCROLL_DOWN;
} else if (e.deltaX < 0) {
code = WheelCode.SCROLL_LEFT;
} else if (e.deltaX > 0) {
code = WheelCode.SCROLL_RIGHT;
}
} else if (e instanceof MouseEvent) {
code = 'Mouse' + e.button as MouseButtonCode;
}
if (code) {
const results: KeyEventInfo = { code };
if (modifiers) {
results.modifiers = modifiers;
}
return results;
}
return null;
}
static getFullKeyCodeFromEvent(e: KeyboardEvent): string {
const key = KeyHelper.getKeyFromEvent(e);
return key ? `${key.code}:${key.modifiers || 0}` : '';
}
static parseFullKeyCode(str: string | undefined | null): KeyEventInfo | null {
if (!str) {
return null;
}
const tmp = str.split(':');
const code = tmp[0] as KeyEventInfo['code'];
const modifiers = parseInt(tmp[1] as string);
return {
code,
modifiers,
} as KeyEventInfo;
}
static codeToKeyName(key: KeyEventInfo): string {
const { code, modifiers } = key;
const text = [(
KeyHelper.NON_PRINTABLE_KEYS[code as keyof typeof KeyHelper.NON_PRINTABLE_KEYS]
||
(code.startsWith('Key') && code.substring(3))
||
(code.startsWith('Digit') && code.substring(5))
||
(code.startsWith('Numpad') && ('Numpad ' + code.substring(6)))
||
(code.startsWith('Arrow') && ('Arrow ' + code.substring(5)))
||
(code.endsWith('Lock') && (code.replace('Lock', ' Lock')))
||
(code.endsWith('Left') && ('Left ' + code.replace('Left', '')))
||
(code.endsWith('Right') && ('Right ' + code.replace('Right', '')))
||
code
)];
if (modifiers && modifiers !== 0) {
if (!code.startsWith('Control') && !code.startsWith('Shift') && !code.startsWith('Alt')) {
// Shift
if (modifiers & KeyModifier.SHIFT) {
text.unshift('Shift');
}
// Alt
if (modifiers & KeyModifier.ALT) {
text.unshift('Alt');
}
// Ctrl
if (modifiers & KeyModifier.CTRL) {
text.unshift('Ctrl');
}
}
}
return text.join(' + ');
}
}