Improved the keyboad hook listener
This commit is contained in:
parent
c68c217eaf
commit
8d25697e98
1 changed files with 67 additions and 53 deletions
|
@ -148,16 +148,20 @@ export interface KeyEvent extends KeyDescriptor {
|
||||||
readonly key: string;
|
readonly key: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface KeyHook extends KeyDescriptor {
|
export interface KeyHook extends Partial<KeyDescriptor> {
|
||||||
callbackPress: () => any;
|
callbackPress: () => any;
|
||||||
callbackRelease: () => any;
|
callbackRelease: () => any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface RegisteredKeyHook extends KeyHook {
|
||||||
|
triggered: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export interface KeyBoardBackend {
|
export interface KeyBoardBackend {
|
||||||
registerListener(listener: (event: KeyEvent) => void);
|
registerListener(listener: (event: KeyEvent) => void);
|
||||||
unregisterListener(listener: (event: KeyEvent) => void);
|
unregisterListener(listener: (event: KeyEvent) => void);
|
||||||
|
|
||||||
registerHook(hook: KeyHook);
|
registerHook(hook: KeyHook) : () => void;
|
||||||
unregisterHook(hook: KeyHook);
|
unregisterHook(hook: KeyHook);
|
||||||
|
|
||||||
isKeyPressed(key: string | SpecialKey) : boolean;
|
isKeyPressed(key: string | SpecialKey) : boolean;
|
||||||
|
@ -168,8 +172,7 @@ export class AbstractKeyBoard implements KeyBoardBackend {
|
||||||
protected readonly activeSpecialKeys: { [key: number] : boolean };
|
protected readonly activeSpecialKeys: { [key: number] : boolean };
|
||||||
protected readonly activeKeys;
|
protected readonly activeKeys;
|
||||||
|
|
||||||
protected registeredKeyHooks: KeyHook[] = [];
|
protected registeredKeyHooks: RegisteredKeyHook[] = [];
|
||||||
protected activeKeyHooks: KeyHook[] = [];
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.activeSpecialKeys = {};
|
this.activeSpecialKeys = {};
|
||||||
|
@ -188,12 +191,26 @@ export class AbstractKeyBoard implements KeyBoardBackend {
|
||||||
}
|
}
|
||||||
|
|
||||||
registerHook(hook: KeyHook) {
|
registerHook(hook: KeyHook) {
|
||||||
this.registeredKeyHooks.push(hook);
|
const registeredHook: RegisteredKeyHook = {
|
||||||
|
triggered: false,
|
||||||
|
...hook
|
||||||
|
};
|
||||||
|
|
||||||
|
this.registeredKeyHooks.push(registeredHook);
|
||||||
|
if(this.shouldHookBeActive(registeredHook)) {
|
||||||
|
registeredHook.triggered = true;
|
||||||
|
registeredHook.callbackPress();
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => this.unregisterHook(hook);
|
||||||
}
|
}
|
||||||
|
|
||||||
unregisterHook(hook: KeyHook) {
|
unregisterHook(hook: KeyHook) {
|
||||||
|
if(!("triggered" in hook)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.registeredKeyHooks.remove(hook);
|
this.registeredKeyHooks.remove(hook);
|
||||||
this.activeKeyHooks.remove(hook);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
registerListener(listener: (event: KeyEvent) => void) {
|
registerListener(listener: (event: KeyEvent) => void) {
|
||||||
|
@ -204,6 +221,26 @@ export class AbstractKeyBoard implements KeyBoardBackend {
|
||||||
this.registeredListener.remove(listener);
|
this.registeredListener.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private shouldHookBeActive(hook: KeyHook) {
|
||||||
|
if(typeof hook.keyAlt !== "undefined" && hook.keyAlt != this.activeSpecialKeys[SpecialKey.ALT]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof hook.keyCtrl !== "undefined" && hook.keyCtrl != this.activeSpecialKeys[SpecialKey.CTRL]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof hook.keyShift !== "undefined" && hook.keyShift != this.activeSpecialKeys[SpecialKey.SHIFT]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof hook.keyWindows !== "undefined" && hook.keyWindows != this.activeSpecialKeys[SpecialKey.WINDOWS]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeof hook.keyCode === "undefined" || typeof this.activeKeys[hook.keyCode] !== "undefined";
|
||||||
|
}
|
||||||
|
|
||||||
protected fireKeyEvent(event: KeyEvent) {
|
protected fireKeyEvent(event: KeyEvent) {
|
||||||
//console.debug("Trigger key event %o", key_event);
|
//console.debug("Trigger key event %o", key_event);
|
||||||
for(const listener of this.registeredListener) {
|
for(const listener of this.registeredListener) {
|
||||||
|
@ -214,61 +251,34 @@ export class AbstractKeyBoard implements KeyBoardBackend {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let oldHooks = [...this.activeKeyHooks];
|
|
||||||
let newHooks = [];
|
|
||||||
|
|
||||||
this.activeSpecialKeys[SpecialKey.ALT] = event.keyAlt;
|
this.activeSpecialKeys[SpecialKey.ALT] = event.keyAlt;
|
||||||
this.activeSpecialKeys[SpecialKey.CTRL] = event.keyCtrl;
|
this.activeSpecialKeys[SpecialKey.CTRL] = event.keyCtrl;
|
||||||
this.activeSpecialKeys[SpecialKey.SHIFT] = event.keyShift;
|
this.activeSpecialKeys[SpecialKey.SHIFT] = event.keyShift;
|
||||||
this.activeSpecialKeys[SpecialKey.WINDOWS] = event.keyWindows;
|
this.activeSpecialKeys[SpecialKey.WINDOWS] = event.keyWindows;
|
||||||
|
|
||||||
delete this.activeKeys[event.keyCode];
|
|
||||||
if(event.type == EventType.KEY_PRESS) {
|
if(event.type == EventType.KEY_PRESS) {
|
||||||
this.activeKeys[event.keyCode] = event;
|
this.activeKeys[event.keyCode] = event;
|
||||||
|
} else {
|
||||||
|
delete this.activeKeys[event.keyCode];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for(const hook of this.registeredKeyHooks) {
|
for(const hook of this.registeredKeyHooks) {
|
||||||
if(hook.keyCode !== event.keyCode) {
|
const hookActive = this.shouldHookBeActive(hook);
|
||||||
|
if(hookActive === hook.triggered) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hook.keyAlt != event.keyAlt) {
|
hook.triggered = hookActive;
|
||||||
continue;
|
if(hookActive) {
|
||||||
}
|
if(hook.callbackPress) {
|
||||||
|
|
||||||
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();
|
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 {
|
} else {
|
||||||
newHooks.push(hook);
|
if(hook.callbackRelease) {
|
||||||
|
hook.callbackRelease();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.activeKeyHooks = newHooks;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected resetKeyboardState() {
|
protected resetKeyboardState() {
|
||||||
|
@ -281,11 +291,15 @@ export class AbstractKeyBoard implements KeyBoardBackend {
|
||||||
delete this.activeKeys[code];
|
delete this.activeKeys[code];
|
||||||
}
|
}
|
||||||
|
|
||||||
for(const hook of this.activeKeyHooks) {
|
for(const hook of this.registeredKeyHooks) {
|
||||||
|
if(hook.triggered) {
|
||||||
|
if(hook.callbackRelease) {
|
||||||
hook.callbackRelease();
|
hook.callbackRelease();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.activeKeyHooks = [];
|
hook.triggered = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue