TeaWeb/shared/js/PPTListener.ts

333 lines
7.9 KiB
TypeScript

import { tr } from "./i18n/localize";
import {LogCategory, logTrace} from "tc-shared/log";
export enum KeyCode {
KEY_CANCEL = 3,
KEY_HELP = 6,
KEY_BACK_SPACE = 8,
KEY_TAB = 9,
KEY_CLEAR = 12,
KEY_RETURN = 13,
KEY_ENTER = 14,
KEY_SHIFT = 16,
KEY_CONTROL = 17,
KEY_ALT = 18,
KEY_PAUSE = 19,
KEY_CAPS_LOCK = 20,
KEY_ESCAPE = 27,
KEY_SPACE = 32,
KEY_PAGE_UP = 33,
KEY_PAGE_DOWN = 34,
KEY_END = 35,
KEY_HOME = 36,
KEY_LEFT = 37,
KEY_UP = 38,
KEY_RIGHT = 39,
KEY_DOWN = 40,
KEY_PRINTSCREEN = 44,
KEY_INSERT = 45,
KEY_DELETE = 46,
KEY_0 = 48,
KEY_1 = 49,
KEY_2 = 50,
KEY_3 = 51,
KEY_4 = 52,
KEY_5 = 53,
KEY_6 = 54,
KEY_7 = 55,
KEY_8 = 56,
KEY_9 = 57,
KEY_SEMICOLON = 59,
KEY_EQUALS = 61,
KEY_A = 65,
KEY_B = 66,
KEY_C = 67,
KEY_D = 68,
KEY_E = 69,
KEY_F = 70,
KEY_G = 71,
KEY_H = 72,
KEY_I = 73,
KEY_J = 74,
KEY_K = 75,
KEY_L = 76,
KEY_M = 77,
KEY_N = 78,
KEY_O = 79,
KEY_P = 80,
KEY_Q = 81,
KEY_R = 82,
KEY_S = 83,
KEY_T = 84,
KEY_U = 85,
KEY_V = 86,
KEY_W = 87,
KEY_X = 88,
KEY_Y = 89,
KEY_Z = 90,
KEY_LEFT_CMD = 91,
KEY_RIGHT_CMD = 93,
KEY_CONTEXT_MENU = 93,
KEY_NUMPAD0 = 96,
KEY_NUMPAD1 = 97,
KEY_NUMPAD2 = 98,
KEY_NUMPAD3 = 99,
KEY_NUMPAD4 = 100,
KEY_NUMPAD5 = 101,
KEY_NUMPAD6 = 102,
KEY_NUMPAD7 = 103,
KEY_NUMPAD8 = 104,
KEY_NUMPAD9 = 105,
KEY_MULTIPLY = 106,
KEY_ADD = 107,
KEY_SEPARATOR = 108,
KEY_SUBTRACT = 109,
KEY_DECIMAL = 110,
KEY_DIVIDE = 111,
KEY_F1 = 112,
KEY_F2 = 113,
KEY_F3 = 114,
KEY_F4 = 115,
KEY_F5 = 116,
KEY_F6 = 117,
KEY_F7 = 118,
KEY_F8 = 119,
KEY_F9 = 120,
KEY_F10 = 121,
KEY_F11 = 122,
KEY_F12 = 123,
KEY_F13 = 124,
KEY_F14 = 125,
KEY_F15 = 126,
KEY_F16 = 127,
KEY_F17 = 128,
KEY_F18 = 129,
KEY_F19 = 130,
KEY_F20 = 131,
KEY_F21 = 132,
KEY_F22 = 133,
KEY_F23 = 134,
KEY_F24 = 135,
KEY_NUM_LOCK = 144,
KEY_SCROLL_LOCK = 145,
KEY_COMMA = 188,
KEY_PERIOD = 190,
KEY_SLASH = 191,
KEY_BACK_QUOTE = 192,
KEY_OPEN_BRACKET = 219,
KEY_BACK_SLASH = 220,
KEY_CLOSE_BRACKET = 221,
KEY_QUOTE = 222,
KEY_META = 224
}
export enum EventType {
KEY_PRESS,
KEY_RELEASE,
KEY_TYPED
}
export enum SpecialKey {
CTRL,
WINDOWS,
SHIFT,
ALT
}
export interface KeyDescriptor {
keyCode: string;
keyCtrl: boolean;
keyWindows: boolean;
keyShift: boolean;
keyAlt: boolean;
}
export interface KeyEvent extends KeyDescriptor {
readonly type: EventType;
readonly key: string;
}
export interface KeyHook extends KeyDescriptor {
callbackPress: () => any;
callbackRelease: () => any;
}
export interface KeyBoardBackend {
registerListener(listener: (event: KeyEvent) => void);
unregisterListener(listener: (event: KeyEvent) => void);
registerHook(hook: KeyHook);
unregisterHook(hook: KeyHook);
isKeyPressed(key: string | SpecialKey) : boolean;
}
export class AbstractKeyBoard implements KeyBoardBackend {
protected readonly registeredListener: ((event: KeyEvent) => void)[];
protected readonly activeSpecialKeys: { [key: number] : boolean };
protected readonly activeKeys;
protected registeredKeyHooks: KeyHook[] = [];
protected activeKeyHooks: KeyHook[] = [];
constructor() {
this.activeSpecialKeys = {};
this.activeKeys = {};
this.registeredListener = [];
}
protected destroy() {}
isKeyPressed(key: string | SpecialKey): boolean {
if(typeof(key) === 'string') {
return typeof this.activeKeys[key] !== "undefined";
}
return this.activeSpecialKeys[key];
}
registerHook(hook: KeyHook) {
this.registeredKeyHooks.push(hook);
}
unregisterHook(hook: KeyHook) {
this.registeredKeyHooks.remove(hook);
this.activeKeyHooks.remove(hook);
}
registerListener(listener: (event: KeyEvent) => void) {
this.registeredListener.push(listener);
}
unregisterListener(listener: (event: KeyEvent) => void) {
this.registeredListener.remove(listener);
}
protected fireKeyEvent(event: KeyEvent) {
//console.debug("Trigger key event %o", key_event);
for(const listener of this.registeredListener) {
listener(event);
}
if(event.type == EventType.KEY_TYPED) {
return;
}
let oldHooks = [...this.activeKeyHooks];
let newHooks = [];
this.activeSpecialKeys[SpecialKey.ALT] = event.keyAlt;
this.activeSpecialKeys[SpecialKey.CTRL] = event.keyCtrl;
this.activeSpecialKeys[SpecialKey.SHIFT] = event.keyShift;
this.activeSpecialKeys[SpecialKey.WINDOWS] = event.keyWindows;
delete this.activeKeys[event.keyCode];
if(event.type == EventType.KEY_PRESS) {
this.activeKeys[event.keyCode] = event;
for(const hook of this.registeredKeyHooks) {
if(hook.keyCode !== event.keyCode) {
continue;
}
if(hook.keyAlt != event.keyAlt) {
continue;
}
if(hook.keyCtrl != event.keyCtrl) {
continue;
}
if(hook.keyShift != event.keyShift) {
continue;
}
if(hook.keyWindows != event.keyWindows) {
continue;
}
newHooks.push(hook);
if(!oldHooks.remove(hook) && hook.callbackPress) {
hook.callbackPress();
logTrace(LogCategory.GENERAL, tr("Trigger key press for %o!"), hook);
}
}
}
//We have a new situation
for(const hook of oldHooks) {
//Do not test for meta key states because they could differ in a key release event
if(hook.keyCode === event.keyCode) {
if(hook.callbackRelease) {
hook.callbackRelease();
logTrace(LogCategory.GENERAL, tr("Trigger key release for %o!"), hook);
}
} else {
newHooks.push(hook);
}
}
this.activeKeyHooks = newHooks;
}
protected resetKeyboardState() {
this.activeSpecialKeys[SpecialKey.ALT] = false;
this.activeSpecialKeys[SpecialKey.CTRL] = false;
this.activeSpecialKeys[SpecialKey.SHIFT] = false;
this.activeSpecialKeys[SpecialKey.WINDOWS] = false;
for(const code of Object.keys(this.activeKeys)) {
delete this.activeKeys[code];
}
for(const hook of this.activeKeyHooks) {
hook.callbackRelease();
}
this.activeKeyHooks = [];
}
}
let keyBoardBackend: KeyBoardBackend;
export function getKeyBoard() : KeyBoardBackend {
return keyBoardBackend;
}
export function setKeyBoardBackend(newBackend: KeyBoardBackend) {
keyBoardBackend = newBackend;
}
export function getKeyDescription(key: KeyDescriptor) {
let result = "";
if(key.keyShift) {
result += " + " + tr("Shift");
}
if(key.keyAlt) {
result += " + " + tr("Alt");
}
if(key.keyCtrl) {
result += " + " + tr("CTRL");
}
if(key.keyWindows) {
result += " + " + tr("Win");
}
if(key.keyCode) {
let keyName;
if(key.keyCode.startsWith("Key")) {
keyName = key.keyCode.substr(3);
} else if(key.keyCode.startsWith("Digit")) {
keyName = key.keyCode.substr(5);
} else if(key.keyCode.startsWith("Numpad")) {
keyName = "Numpad " + key.keyCode.substr(6);
} else {
keyName = key.keyCode;
}
result += " + " + keyName;
}
return result ? result.substr(3) : tr("unset");
}