From efe7e95b3ea93959279bebe207a39162c0d031be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zsef=20Farkas?= Date: Sun, 11 Jun 2017 12:11:12 +0200 Subject: [PATCH] Media key support (#294) * Introduce type for KeystrokeAction * Increment dataModelVersion New property 'type' for KeystrokeAction * Mapping for media keys * Media key selecting support for KeypressTab * refactor: Use more meaningful name (selectedScancodeOption) * Store the keystroke type in key action type instead of a new field --- shared/res/presets/QTY.json | 300 +++++++++++------ shared/res/presets/VIM.json | 3 +- .../tab/keypress/keypress-tab.component.html | 4 +- .../tab/keypress/keypress-tab.component.ts | 107 ++++-- .../popover/tab/keypress/scancodes.json | 8 +- .../svg-keyboard-key.component.ts | 2 +- .../svg-keystroke-key.component.ts | 2 +- .../svg/wrap/svg-keyboard-wrap.component.ts | 3 +- .../config-items/key-action/KeyAction.ts | 15 +- .../key-action/KeystrokeAction.ts | 86 ++++- .../config-items/key-action/keystroke-type.ts | 6 + shared/src/config-serializer/user-config.json | 308 ++++++++++++------ shared/src/services/mapper.service.ts | 268 +++++++-------- 13 files changed, 724 insertions(+), 388 deletions(-) create mode 100644 shared/src/config-serializer/config-items/key-action/keystroke-type.ts diff --git a/shared/res/presets/QTY.json b/shared/res/presets/QTY.json index 5c5d8c40..a7edfd56 100644 --- a/shared/res/presets/QTY.json +++ b/shared/res/presets/QTY.json @@ -12,119 +12,148 @@ "keyActions": [ { "keyActionType": "keystroke", - "scancode": 36 + "scancode": 36, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 37 + "scancode": 37, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 38 + "scancode": 38, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 39 + "scancode": 39, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 45 + "scancode": 45, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 46 + "scancode": 46, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 42 + "scancode": 42, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 28 + "scancode": 28, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 24 + "scancode": 24, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 12 + "scancode": 12, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 18 + "scancode": 18, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 19 + "scancode": 19, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 47 + "scancode": 47, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 48 + "scancode": 48, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 49 + "scancode": 49, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 11 + "scancode": 11, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 13 + "scancode": 13, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 14 + "scancode": 14, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 15 + "scancode": 15, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 51 + "scancode": 51, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 52 + "scancode": 52, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 40 + "scancode": 40, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 17 + "scancode": 17, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 16 + "scancode": 16, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 54 + "scancode": 54, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 55 + "scancode": 55, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 56 + "scancode": 56, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 32 + "modifierMask": 32, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 44 + "scancode": 44, + "type": "basic" }, { "keyActionType": "switchLayer", @@ -133,15 +162,18 @@ }, { "keyActionType": "keystroke", - "modifierMask": 64 + "modifierMask": 64, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 128 + "modifierMask": 128, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 16 + "modifierMask": 16, + "type": "basic" }, { "keyActionType": "switchLayer", @@ -156,55 +188,68 @@ "keyActions": [ { "keyActionType": "keystroke", - "scancode": 53 + "scancode": 53, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 30 + "scancode": 30, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 31 + "scancode": 31, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 32 + "scancode": 32, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 33 + "scancode": 33, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 34 + "scancode": 34, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 35 + "scancode": 35, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 43 + "scancode": 43, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 20 + "scancode": 20, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 26 + "scancode": 26, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 8 + "scancode": 8, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 21 + "scancode": 21, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 23 + "scancode": 23, + "type": "basic" }, { "keyActionType": "switchLayer", @@ -213,59 +258,73 @@ }, { "keyActionType": "keystroke", - "scancode": 4 + "scancode": 4, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 22 + "scancode": 22, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 7 + "scancode": 7, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 9 + "scancode": 9, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 10 + "scancode": 10, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 2 + "modifierMask": 2, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 29 + "scancode": 29, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 27 + "scancode": 27, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 6 + "scancode": 6, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 25 + "scancode": 25, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 5 + "scancode": 5, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 1 + "modifierMask": 1, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 8 + "modifierMask": 8, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 4 + "modifierMask": 4, + "type": "basic" }, { "keyActionType": "switchLayer", @@ -279,7 +338,8 @@ }, { "keyActionType": "keystroke", - "scancode": 44 + "scancode": 44, + "type": "basic" } ] }, @@ -305,19 +365,23 @@ null, { "keyActionType": "keystroke", - "scancode": 75 + "scancode": 75, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 74 + "scancode": 74, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 82 + "scancode": 82, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 77 + "scancode": 77, + "type": "basic" }, null, null, @@ -325,19 +389,23 @@ null, { "keyActionType": "keystroke", - "scancode": 78 + "scancode": 78, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 80 + "scancode": 80, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 81 + "scancode": 81, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 79 + "scancode": 79, + "type": "basic" }, null, null, @@ -351,11 +419,13 @@ null, { "keyActionType": "keystroke", - "scancode": 118 + "scancode": 118, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 32 + "modifierMask": 32, + "type": "basic" }, null, { @@ -365,15 +435,18 @@ }, { "keyActionType": "keystroke", - "modifierMask": 64 + "modifierMask": 64, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 128 + "modifierMask": 128, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 16 + "modifierMask": 16, + "type": "basic" }, { "keyActionType": "switchLayer", @@ -411,7 +484,8 @@ null, { "keyActionType": "keystroke", - "modifierMask": 2 + "modifierMask": 2, + "type": "basic" }, null, null, @@ -420,15 +494,18 @@ null, { "keyActionType": "keystroke", - "modifierMask": 1 + "modifierMask": 1, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 8 + "modifierMask": 8, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 4 + "modifierMask": 4, + "type": "basic" }, { "keyActionType": "switchLayer", @@ -451,11 +528,7 @@ "id": 0, "pointerRole": "move", "keyActions": [ - { - "keyActionType": "switchLayer", - "layer": "fn", - "toggle": true - }, + null, null, null, null, @@ -465,15 +538,18 @@ null, { "keyActionType": "keystroke", - "scancode": 232 + "scancode": 232, + "type": "media" }, { "keyActionType": "keystroke", - "scancode": 237 + "scancode": 237, + "type": "media" }, { "keyActionType": "keystroke", - "scancode": 233 + "scancode": 233, + "type": "media" }, null, null, @@ -482,15 +558,18 @@ null, { "keyActionType": "keystroke", - "scancode": 234 + "scancode": 234, + "type": "media" }, { "keyActionType": "keystroke", - "scancode": 238 + "scancode": 238, + "type": "media" }, { "keyActionType": "keystroke", - "scancode": 235 + "scancode": 235, + "type": "media" }, null, null, @@ -499,13 +578,15 @@ null, { "keyActionType": "keystroke", - "scancode": 239 + "scancode": 226, + "type": "media" }, null, null, { "keyActionType": "keystroke", - "modifierMask": 32 + "modifierMask": 32, + "type": "basic" }, null, { @@ -515,15 +596,18 @@ }, { "keyActionType": "keystroke", - "modifierMask": 64 + "modifierMask": 64, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 128 + "modifierMask": 128, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 16 + "modifierMask": 16, + "type": "basic" }, { "keyActionType": "switchLayer", @@ -569,7 +653,8 @@ null, { "keyActionType": "keystroke", - "modifierMask": 2 + "modifierMask": 2, + "type": "basic" }, null, null, @@ -578,15 +663,18 @@ null, { "keyActionType": "keystroke", - "modifierMask": 1 + "modifierMask": 1, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 8 + "modifierMask": 8, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 4 + "modifierMask": 4, + "type": "basic" }, { "keyActionType": "switchLayer", @@ -659,15 +747,18 @@ null, { "keyActionType": "keystroke", - "modifierMask": 64 + "modifierMask": 64, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 128 + "modifierMask": 128, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 16 + "modifierMask": 16, + "type": "basic" }, null ] @@ -716,15 +807,18 @@ null, { "keyActionType": "keystroke", - "modifierMask": 1 + "modifierMask": 1, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 8 + "modifierMask": 8, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 4 + "modifierMask": 4, + "type": "basic" }, null, { diff --git a/shared/res/presets/VIM.json b/shared/res/presets/VIM.json index a740f0b1..8286bd5b 100644 --- a/shared/res/presets/VIM.json +++ b/shared/res/presets/VIM.json @@ -95,7 +95,8 @@ "keyActions": [ { "keyActionType": "keystroke", - "scancode": 111 + "scancode": 111, + "type": "basic" } ] } diff --git a/shared/src/components/popover/tab/keypress/keypress-tab.component.html b/shared/src/components/popover/tab/keypress/keypress-tab.component.html index 8afd46b8..0d65bd13 100644 --- a/shared/src/components/popover/tab/keypress/keypress-tab.component.html +++ b/shared/src/components/popover/tab/keypress/keypress-tab.component.html @@ -2,7 +2,7 @@ Scancode: When a key is configured as layer switcher key, you can't assign other functions to it. To assign a scancode to the key, set the Layer action to None. - \ No newline at end of file + diff --git a/shared/src/components/popover/tab/keypress/keypress-tab.component.ts b/shared/src/components/popover/tab/keypress/keypress-tab.component.ts index ec989cb0..5b2d15da 100644 --- a/shared/src/components/popover/tab/keypress/keypress-tab.component.ts +++ b/shared/src/components/popover/tab/keypress/keypress-tab.component.ts @@ -6,6 +6,7 @@ import { KeyAction, KeystrokeAction } from '../../../../config-serializer/config import { Tab } from '../tab'; import { MapperService } from '../../../../services/mapper.service'; +import { KeystrokeType } from '../../../../config-serializer/config-items/key-action/keystroke-type'; @Component({ selector: 'keypress-tab', @@ -16,18 +17,18 @@ export class KeypressTabComponent extends Tab implements OnChanges { @Input() defaultKeyAction: KeyAction; @Input() longPressEnabled: boolean; - private leftModifiers: string[]; - private rightModifiers: string[]; + leftModifiers: string[]; + rightModifiers: string[]; - private leftModifierSelects: boolean[]; - private rightModifierSelects: boolean[]; + leftModifierSelects: boolean[]; + rightModifierSelects: boolean[]; - private scanCodeGroups: Array; - private longPressGroups: Array; - private options: Select2Options; + scanCodeGroups: Array; + longPressGroups: Array; + options: Select2Options; - private scanCode: number; - private selectedLongPressIndex: number; + selectedScancodeOption: Select2OptionData; + selectedLongPressIndex: number; constructor(private mapper: MapperService) { super(); @@ -41,7 +42,7 @@ export class KeypressTabComponent extends Tab implements OnChanges { this.longPressGroups = require('json-loader!./longPress.json'); this.leftModifierSelects = Array(this.leftModifiers.length).fill(false); this.rightModifierSelects = Array(this.rightModifiers.length).fill(false); - this.scanCode = 0; + this.selectedScancodeOption = this.scanCodeGroups[0]; this.selectedLongPressIndex = -1; this.options = { templateResult: this.scanCodeTemplateResult, @@ -70,11 +71,11 @@ export class KeypressTabComponent extends Tab implements OnChanges { return (keystrokeAction) ? (keystrokeAction.scancode > 0 || keystrokeAction.modifierMask > 0) : false; } - onKeysCapture(event: {code: number, left: boolean[], right: boolean[]}) { + onKeysCapture(event: { code: number, left: boolean[], right: boolean[] }) { if (event.code) { - this.scanCode = event.code; + this.selectedScancodeOption = this.findScancodeOptionByScancode(event.code, KeystrokeType.basic); } else { - this.scanCode = 0; + this.selectedScancodeOption = this.scanCodeGroups[0]; } this.leftModifierSelects = event.left; @@ -87,8 +88,8 @@ export class KeypressTabComponent extends Tab implements OnChanges { return false; } const keystrokeAction: KeystrokeAction = keyAction; - // Restore scancode - this.scanCode = keystrokeAction.scancode || 0; + // Restore selectedScancodeOption + this.selectedScancodeOption = this.findScancodeOptionByScancode(keystrokeAction.scancode || 0, keystrokeAction.type); const leftModifiersLength: number = this.leftModifiers.length; @@ -112,8 +113,13 @@ export class KeypressTabComponent extends Tab implements OnChanges { toKeyAction(): KeystrokeAction { const keystrokeAction: KeystrokeAction = new KeystrokeAction(); - keystrokeAction.scancode = this.scanCode; - + const scTypePair = this.toScancodeTypePair(this.selectedScancodeOption); + keystrokeAction.scancode = scTypePair[0]; + if (scTypePair[1] === 'media') { + keystrokeAction.type = KeystrokeType.shortMedia; + } else { + keystrokeAction.type = KeystrokeType[scTypePair[1]]; + } keystrokeAction.modifierMask = 0; const modifiers = this.leftModifierSelects.concat(this.rightModifierSelects).map(x => x ? 1 : 0); for (let i = 0; i < modifiers.length; ++i) { @@ -137,10 +143,10 @@ export class KeypressTabComponent extends Tab implements OnChanges { if (state.additional && state.additional.explanation) { return jQuery( '' - + '' + state.text + '' - + ' ' - + state.additional.explanation - + '' + + + '' + state.text + '' + + ' ' + + state.additional.explanation + + '' + '' ); } else { @@ -155,12 +161,65 @@ export class KeypressTabComponent extends Tab implements OnChanges { this.validAction.emit(this.keyActionValid()); } - onLongpressChange(event: {value: string}) { + onLongpressChange(event: { value: string }) { this.selectedLongPressIndex = +event.value; } - onScancodeChange(event: {value: string}) { - this.scanCode = +event.value; + onScancodeChange(event: { value: string }) { + const id: string = event.value; + + // ng2-select2 should provide the selectedOption in an upcoming release + // TODO: change this when it has become available + this.selectedScancodeOption = this.findScancodeOptionById(id); + this.validAction.emit(this.keyActionValid()); } + + private findScancodeOptionBy(predicate: (option: Select2OptionData) => boolean): Select2OptionData { + let selectedOption: Select2OptionData; + + const scanCodeGroups: Select2OptionData[] = [...this.scanCodeGroups]; + while (scanCodeGroups.length > 0) { + const scanCodeGroup = scanCodeGroups.shift(); + if (predicate(scanCodeGroup)) { + selectedOption = scanCodeGroup; + break; + } + scanCodeGroups.push(...scanCodeGroup.children); + } + return selectedOption; + } + + private findScancodeOptionById(id: string): Select2OptionData { + return this.findScancodeOptionBy(option => option.id === id); + } + + private findScancodeOptionByScancode(scancode: number, type: KeystrokeType): Select2OptionData { + const typeToFind: string = type === KeystrokeType.shortMedia || KeystrokeType.longMedia ? 'media' : KeystrokeType[type]; + return this.findScancodeOptionBy((option: Select2OptionData) => { + const additional = option.additional; + if (additional && additional.scancode === scancode && additional.type === typeToFind) { + return true; + } else if (+option.id === scancode) { + return true; + } else { + return false; + } + }); + } + + private toScancodeTypePair(option: Select2OptionData): [number, string] { + let scanCode: number; + let type: string; + if (option.additional) { + scanCode = option.additional.scancode ? option.additional.scancode : 0; + type = option.additional.type || 'basic'; + } else { + scanCode = +option.id; + type = 'basic'; + } + + return [scanCode, type]; + } + } diff --git a/shared/src/components/popover/tab/keypress/scancodes.json b/shared/src/components/popover/tab/keypress/scancodes.json index 0f060c1c..f46527f1 100644 --- a/shared/src/components/popover/tab/keypress/scancodes.json +++ b/shared/src/components/popover/tab/keypress/scancodes.json @@ -559,7 +559,11 @@ "children": [ { "id": "127", - "text": "Mute" + "text": "Mute", + "additional": { + "type": "media", + "scancode": 226 + } }, { "id": "128", @@ -591,4 +595,4 @@ } ] } -] \ No newline at end of file +] diff --git a/shared/src/components/svg/keys/svg-keyboard-key/svg-keyboard-key.component.ts b/shared/src/components/svg/keys/svg-keyboard-key/svg-keyboard-key.component.ts index 4142ef87..0f209e0d 100644 --- a/shared/src/components/svg/keys/svg-keyboard-key/svg-keyboard-key.component.ts +++ b/shared/src/components/svg/keys/svg-keyboard-key/svg-keyboard-key.component.ts @@ -220,7 +220,7 @@ export class SvgKeyboardKeyComponent implements OnInit, OnChanges, OnDestroy { if (!keyAction.hasActiveModifier() && keyAction.hasScancode()) { const scancode: number = keyAction.scancode; - newLabelSource = this.mapper.scanCodeToText(scancode); + newLabelSource = this.mapper.scanCodeToText(scancode, keyAction.type); if (this.mapper.hasScancodeIcon(scancode)) { this.labelSource = this.mapper.scanCodeToSvgImagePath(scancode); this.labelType = LabelTypes.SingleIcon; diff --git a/shared/src/components/svg/keys/svg-keystroke-key/svg-keystroke-key.component.ts b/shared/src/components/svg/keys/svg-keystroke-key/svg-keystroke-key.component.ts index 4d83ea0b..b0a3364e 100644 --- a/shared/src/components/svg/keys/svg-keystroke-key/svg-keystroke-key.component.ts +++ b/shared/src/components/svg/keys/svg-keystroke-key/svg-keystroke-key.component.ts @@ -131,7 +131,7 @@ export class SvgKeystrokeKeyComponent implements OnInit, OnChanges { let newLabelSource: string[]; if (this.keystrokeAction.hasScancode()) { const scancode: number = this.keystrokeAction.scancode; - newLabelSource = this.mapper.scanCodeToText(scancode); + newLabelSource = this.mapper.scanCodeToText(scancode, this.keystrokeAction.type); if (newLabelSource) { if (newLabelSource.length === 1) { this.labelSource = newLabelSource[0]; diff --git a/shared/src/components/svg/wrap/svg-keyboard-wrap.component.ts b/shared/src/components/svg/wrap/svg-keyboard-wrap.component.ts index 00608e22..ae114ccc 100644 --- a/shared/src/components/svg/wrap/svg-keyboard-wrap.component.ts +++ b/shared/src/components/svg/wrap/svg-keyboard-wrap.component.ts @@ -245,7 +245,8 @@ export class SvgKeyboardWrapComponent implements OnInit, OnChanges { if (keystrokeAction.hasScancode()) { let value: string = keystrokeAction.scancode.toString(); - const scanCodeTexts: string = (this.mapper.scanCodeToText(keystrokeAction.scancode) || []).join(', '); + const scanCodeTexts: string = (this.mapper.scanCodeToText(keystrokeAction.scancode, keystrokeAction.type) || []) + .join(', '); if (scanCodeTexts.length > 0) { value += ' (' + scanCodeTexts + ')'; } diff --git a/shared/src/config-serializer/config-items/key-action/KeyAction.ts b/shared/src/config-serializer/config-items/key-action/KeyAction.ts index 2f0d43e8..0ab05c16 100644 --- a/shared/src/config-serializer/config-items/key-action/KeyAction.ts +++ b/shared/src/config-serializer/config-items/key-action/KeyAction.ts @@ -7,17 +7,18 @@ export enum KeyActionId { NoneAction = 0, KeystrokeAction = 1, /* - 1 - 7 are reserved for KeystrokeAction - 3 bits: + 1 - 31 are reserved for KeystrokeAction + 5 bits: 1: Do we have scancode? 2: Do we have modifiers? 3: Do we have longpress? + 4-5: What kind of keystroke? (basic, short/long media, system) */ - LastKeystrokeAction = 7, // TODO: remove this after refactoring the keyActionId check - SwitchLayerAction = 8, - SwitchKeymapAction = 9, - MouseAction = 10, - PlayMacroAction = 11 + LastKeystrokeAction = 31, // TODO: remove this after refactoring the keyActionId check + SwitchLayerAction = 32, + SwitchKeymapAction = 33, + MouseAction = 34, + PlayMacroAction = 35 } export let keyActionType = { diff --git a/shared/src/config-serializer/config-items/key-action/KeystrokeAction.ts b/shared/src/config-serializer/config-items/key-action/KeystrokeAction.ts index 69c76e5c..df4d2cc8 100644 --- a/shared/src/config-serializer/config-items/key-action/KeystrokeAction.ts +++ b/shared/src/config-serializer/config-items/key-action/KeystrokeAction.ts @@ -3,6 +3,7 @@ import { UhkBuffer } from '../../UhkBuffer'; import { KeyModifiers } from '../KeyModifiers'; import { LongPressAction } from '../LongPressAction'; import { KeyAction, KeyActionId, keyActionType } from './KeyAction'; +import { KeystrokeType } from './keystroke-type'; export enum KeystrokeActionFlag { scancode = 1 << 0, @@ -10,19 +11,31 @@ export enum KeystrokeActionFlag { longPressAction = 1 << 2 } +const KEYSTROKE_ACTION_FLAG_LENGTH = 3; + interface JsonObjectKeystrokeAction { keyActionType: string; scancode?: number; modifierMask?: number; longPressAction?: string; + type?: string; } -const MODIFIERS = ['LCtrl', 'LShift', 'LAlt', 'LSuper', 'RCtrl', 'RShift', 'RAlt', 'RSuper']; +const MODIFIERS = ['LCtrl', 'LShift', 'LAlt', 'LSuper', 'RCtrl', 'RShift', 'RAlt', 'RSuper']; export class KeystrokeAction extends KeyAction { - @assertUInt8 - scancode: number; + set scancode(scancode: number) { + this._scancode = scancode; + if (this.type !== KeystrokeType.shortMedia && this.type !== KeystrokeType.longMedia) { + return; + } + this.type = scancode < 256 ? KeystrokeType.shortMedia : KeystrokeType.longMedia; + } + + get scancode() { + return this._scancode; + } @assertUInt8 modifierMask: number; @@ -30,19 +43,41 @@ export class KeystrokeAction extends KeyAction { @assertEnum(LongPressAction) longPressAction: LongPressAction; + set type(type: KeystrokeType) { + if (type === KeystrokeType.shortMedia || type === KeystrokeType.longMedia) { + type = this.scancode < 256 ? KeystrokeType.shortMedia : KeystrokeType.longMedia; + } + this._type = type; + } + + get type() { + return this._type; + } + + private _scancode: number; + + @assertEnum(KeystrokeType) + private _type: KeystrokeType; + constructor(other?: KeystrokeAction) { super(); if (!other) { return; } - this.scancode = other.scancode; + this.type = other.type; + this._scancode = other._scancode; this.modifierMask = other.modifierMask; this.longPressAction = other.longPressAction; } fromJsonObject(jsonObject: JsonObjectKeystrokeAction): KeystrokeAction { this.assertKeyActionType(jsonObject); - this.scancode = jsonObject.scancode; + if (jsonObject.type === 'media') { + this.type = jsonObject.scancode < 256 ? KeystrokeType.shortMedia : KeystrokeType.longMedia; + } else { + this.type = KeystrokeType[jsonObject.type]; + } + this._scancode = jsonObject.scancode; this.modifierMask = jsonObject.modifierMask; this.longPressAction = LongPressAction[jsonObject.longPressAction]; return this; @@ -51,8 +86,9 @@ export class KeystrokeAction extends KeyAction { fromBinary(buffer: UhkBuffer): KeystrokeAction { const keyActionId: KeyActionId = this.readAndAssertKeyActionId(buffer); const flags: number = keyActionId - KeyActionId.KeystrokeAction; + this.type = (flags >> 3) & 0b11; if (flags & KeystrokeActionFlag.scancode) { - this.scancode = buffer.readUInt8(); + this._scancode = this.type === KeystrokeType.longMedia ? buffer.readUInt16() : buffer.readUInt8(); } if (flags & KeystrokeActionFlag.modifierMask) { this.modifierMask = buffer.readUInt8(); @@ -68,8 +104,14 @@ export class KeystrokeAction extends KeyAction { keyActionType: keyActionType.KeystrokeAction }; + if (this.type === KeystrokeType.shortMedia || this.type === KeystrokeType.longMedia) { + jsonObject.type = 'media'; + } else { + jsonObject.type = KeystrokeType[this.type]; + } + if (this.hasScancode()) { - jsonObject.scancode = this.scancode; + jsonObject.scancode = this._scancode; } if (this.hasActiveModifier()) { @@ -85,33 +127,45 @@ export class KeystrokeAction extends KeyAction { toBinary(buffer: UhkBuffer) { let flags = 0; - const bufferData: number[] = []; + const toWrite: { + data: number, + long: boolean + }[] = []; if (this.hasScancode()) { flags |= KeystrokeActionFlag.scancode; - bufferData.push(this.scancode); + toWrite.push({ data: this._scancode, long: this.type === KeystrokeType.longMedia }); } if (this.hasActiveModifier()) { flags |= KeystrokeActionFlag.modifierMask; - bufferData.push(this.modifierMask); + toWrite.push({ data: this.modifierMask, long: false }); } if (this.hasLongPressAction()) { flags |= KeystrokeActionFlag.longPressAction; - bufferData.push(this.longPressAction); + toWrite.push({ data: this.longPressAction, long: false }); } - buffer.writeUInt8(KeyActionId.KeystrokeAction + flags); - for (let i = 0; i < bufferData.length; ++i) { - buffer.writeUInt8(bufferData[i]); + const TYPE_OFFSET = flags + (this.type << KEYSTROKE_ACTION_FLAG_LENGTH); + + buffer.writeUInt8(KeyActionId.KeystrokeAction + TYPE_OFFSET); + for (let i = 0; i < toWrite.length; ++i) { + if (toWrite[i].long) { + buffer.writeUInt16(toWrite[i].data); + } else { + buffer.writeUInt8(toWrite[i].data); + } } + } toString(): string { const properties: string[] = []; + properties.push(`type="${KeystrokeType[this.type]}"`); + if (this.hasScancode()) { - properties.push(`scancode="${this.scancode}"`); + properties.push(`scancode="${this._scancode}"`); } if (this.hasActiveModifier()) { properties.push(`modifierMask="${this.modifierMask}"`); @@ -136,7 +190,7 @@ export class KeystrokeAction extends KeyAction { } hasScancode(): boolean { - return !!this.scancode; + return !!this._scancode; } hasOnlyOneActiveModifier(): boolean { diff --git a/shared/src/config-serializer/config-items/key-action/keystroke-type.ts b/shared/src/config-serializer/config-items/key-action/keystroke-type.ts new file mode 100644 index 00000000..d17d6fb4 --- /dev/null +++ b/shared/src/config-serializer/config-items/key-action/keystroke-type.ts @@ -0,0 +1,6 @@ +export enum KeystrokeType { + basic, + shortMedia, + longMedia, + system +} diff --git a/shared/src/config-serializer/user-config.json b/shared/src/config-serializer/user-config.json index 8ddff9fa..425a8a6b 100644 --- a/shared/src/config-serializer/user-config.json +++ b/shared/src/config-serializer/user-config.json @@ -1,5 +1,5 @@ { - "dataModelVersion": 3, + "dataModelVersion": 4, "moduleConfigurations": [ { "id": 1, @@ -23,119 +23,148 @@ "keyActions": [ { "keyActionType": "keystroke", - "scancode": 36 + "scancode": 36, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 37 + "scancode": 37, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 38 + "scancode": 38, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 39 + "scancode": 39, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 45 + "scancode": 45, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 46 + "scancode": 46, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 42 + "scancode": 42, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 28 + "scancode": 28, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 24 + "scancode": 24, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 12 + "scancode": 12, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 18 + "scancode": 18, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 19 + "scancode": 19, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 47 + "scancode": 47, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 48 + "scancode": 48, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 49 + "scancode": 49, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 11 + "scancode": 11, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 13 + "scancode": 13, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 14 + "scancode": 14, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 15 + "scancode": 15, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 51 + "scancode": 51, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 52 + "scancode": 52, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 40 + "scancode": 40, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 17 + "scancode": 17, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 16 + "scancode": 16, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 54 + "scancode": 54, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 55 + "scancode": 55, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 56 + "scancode": 56, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 32 + "modifierMask": 32, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 44 + "scancode": 44, + "type": "basic" }, { "keyActionType": "switchLayer", @@ -144,15 +173,18 @@ }, { "keyActionType": "keystroke", - "modifierMask": 64 + "modifierMask": 64, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 128 + "modifierMask": 128, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 16 + "modifierMask": 16, + "type": "basic" }, { "keyActionType": "switchLayer", @@ -167,55 +199,68 @@ "keyActions": [ { "keyActionType": "keystroke", - "scancode": 53 + "scancode": 53, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 30 + "scancode": 30, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 31 + "scancode": 31, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 32 + "scancode": 32, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 33 + "scancode": 33, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 34 + "scancode": 34, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 35 + "scancode": 35, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 43 + "scancode": 43, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 20 + "scancode": 20, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 26 + "scancode": 26, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 8 + "scancode": 8, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 21 + "scancode": 21, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 23 + "scancode": 23, + "type": "basic" }, { "keyActionType": "switchLayer", @@ -224,59 +269,73 @@ }, { "keyActionType": "keystroke", - "scancode": 4 + "scancode": 4, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 22 + "scancode": 22, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 7 + "scancode": 7, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 9 + "scancode": 9, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 10 + "scancode": 10, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 2 + "modifierMask": 2, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 29 + "scancode": 29, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 27 + "scancode": 27, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 6 + "scancode": 6, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 25 + "scancode": 25, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 5 + "scancode": 5, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 1 + "modifierMask": 1, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 8 + "modifierMask": 8, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 4 + "modifierMask": 4, + "type": "basic" }, { "keyActionType": "switchLayer", @@ -290,7 +349,8 @@ }, { "keyActionType": "keystroke", - "scancode": 44 + "scancode": 44, + "type": "basic" } ] }, @@ -316,19 +376,23 @@ null, { "keyActionType": "keystroke", - "scancode": 75 + "scancode": 75, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 74 + "scancode": 74, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 82 + "scancode": 82, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 77 + "scancode": 77, + "type": "basic" }, null, null, @@ -336,19 +400,23 @@ null, { "keyActionType": "keystroke", - "scancode": 78 + "scancode": 78, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 80 + "scancode": 80, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 81 + "scancode": 81, + "type": "basic" }, { "keyActionType": "keystroke", - "scancode": 79 + "scancode": 79, + "type": "basic" }, null, null, @@ -362,11 +430,13 @@ null, { "keyActionType": "keystroke", - "scancode": 118 + "scancode": 118, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 32 + "modifierMask": 32, + "type": "basic" }, null, { @@ -376,15 +446,18 @@ }, { "keyActionType": "keystroke", - "modifierMask": 64 + "modifierMask": 64, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 128 + "modifierMask": 128, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 16 + "modifierMask": 16, + "type": "basic" }, { "keyActionType": "switchLayer", @@ -422,7 +495,8 @@ null, { "keyActionType": "keystroke", - "modifierMask": 2 + "modifierMask": 2, + "type": "basic" }, null, null, @@ -431,15 +505,18 @@ null, { "keyActionType": "keystroke", - "modifierMask": 1 + "modifierMask": 1, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 8 + "modifierMask": 8, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 4 + "modifierMask": 4, + "type": "basic" }, { "keyActionType": "switchLayer", @@ -472,15 +549,18 @@ null, { "keyActionType": "keystroke", - "scancode": 232 + "scancode": 232, + "type": "media" }, { "keyActionType": "keystroke", - "scancode": 237 + "scancode": 237, + "type": "media" }, { "keyActionType": "keystroke", - "scancode": 233 + "scancode": 233, + "type": "media" }, null, null, @@ -489,15 +569,18 @@ null, { "keyActionType": "keystroke", - "scancode": 234 + "scancode": 234, + "type": "media" }, { "keyActionType": "keystroke", - "scancode": 238 + "scancode": 238, + "type": "media" }, { "keyActionType": "keystroke", - "scancode": 235 + "scancode": 235, + "type": "media" }, null, null, @@ -506,13 +589,15 @@ null, { "keyActionType": "keystroke", - "scancode": 239 + "scancode": 226, + "type": "media" }, null, null, { "keyActionType": "keystroke", - "modifierMask": 32 + "modifierMask": 32, + "type": "basic" }, null, { @@ -522,15 +607,18 @@ }, { "keyActionType": "keystroke", - "modifierMask": 64 + "modifierMask": 64, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 128 + "modifierMask": 128, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 16 + "modifierMask": 16, + "type": "basic" }, { "keyActionType": "switchLayer", @@ -568,7 +656,8 @@ null, { "keyActionType": "keystroke", - "modifierMask": 2 + "modifierMask": 2, + "type": "basic" }, null, null, @@ -577,15 +666,18 @@ null, { "keyActionType": "keystroke", - "modifierMask": 1 + "modifierMask": 1, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 8 + "modifierMask": 8, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 4 + "modifierMask": 4, + "type": "basic" }, { "keyActionType": "switchLayer", @@ -662,15 +754,18 @@ }, { "keyActionType": "keystroke", - "modifierMask": 64 + "modifierMask": 64, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 128 + "modifierMask": 128, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 16 + "modifierMask": 16, + "type": "basic" }, { "keyActionType": "switchLayer", @@ -723,15 +818,18 @@ null, { "keyActionType": "keystroke", - "modifierMask": 1 + "modifierMask": 1, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 8 + "modifierMask": 8, + "type": "basic" }, { "keyActionType": "keystroke", - "modifierMask": 4 + "modifierMask": 4, + "type": "basic" }, { "keyActionType": "switchLayer", @@ -853,7 +951,8 @@ "keyActions": [ { "keyActionType": "keystroke", - "scancode": 111 + "scancode": 111, + "type": "basic" } ] } @@ -907,7 +1006,8 @@ "keyActions": [ { "keyActionType": "keystroke", - "scancode": 111 + "scancode": 111, + "type": "basic" }, null, null, @@ -991,7 +1091,8 @@ "keyActions": [ { "keyActionType": "keystroke", - "scancode": 111 + "scancode": 111, + "type": "basic" }, null, null, @@ -1075,7 +1176,8 @@ "keyActions": [ { "keyActionType": "keystroke", - "scancode": 111 + "scancode": 111, + "type": "basic" }, null, null, diff --git a/shared/src/services/mapper.service.ts b/shared/src/services/mapper.service.ts index a26390eb..59dc7651 100644 --- a/shared/src/services/mapper.service.ts +++ b/shared/src/services/mapper.service.ts @@ -3,11 +3,13 @@ const __svg__ = { path: '../../../images/icons/**/*.svg', name: 'assets/compiled /* tslint:enable:variable-name */ import { Injectable } from '@angular/core'; +import { KeystrokeType } from '../config-serializer/config-items/key-action/keystroke-type'; @Injectable() export class MapperService { - private scanCodeTextMap: Map; + private basicScanCodeTextMap: Map; + private mediaScanCodeTextMap: Map; private scanCodeFileName: Map; private nameToFileName: Map; @@ -18,8 +20,18 @@ export class MapperService { this.initNameToFileNames(); } - public scanCodeToText(scanCode: number): string[] { - return this.scanCodeTextMap.get(scanCode); + public scanCodeToText(scanCode: number, type: KeystrokeType = KeystrokeType.basic): string[] { + let map: Map; + switch (type) { + case KeystrokeType.shortMedia: + case KeystrokeType.longMedia: + map = this.mediaScanCodeTextMap; + break; + default: + map = this.basicScanCodeTextMap; + break; + } + return map.get(scanCode); } public hasScancodeIcon(scancode: number): boolean { @@ -48,130 +60,132 @@ export class MapperService { // TODO: read the mapping from JSON private initScanCodeTextMap(): void { - this.scanCodeTextMap = new Map(); - this.scanCodeTextMap.set(4, ['A']); - this.scanCodeTextMap.set(5, ['B']); - this.scanCodeTextMap.set(6, ['C']); - this.scanCodeTextMap.set(7, ['D']); - this.scanCodeTextMap.set(8, ['E']); - this.scanCodeTextMap.set(9, ['F']); - this.scanCodeTextMap.set(10, ['G']); - this.scanCodeTextMap.set(11, ['H']); - this.scanCodeTextMap.set(12, ['I']); - this.scanCodeTextMap.set(13, ['J']); - this.scanCodeTextMap.set(14, ['K']); - this.scanCodeTextMap.set(15, ['L']); - this.scanCodeTextMap.set(16, ['M']); - this.scanCodeTextMap.set(17, ['N']); - this.scanCodeTextMap.set(18, ['O']); - this.scanCodeTextMap.set(19, ['P']); - this.scanCodeTextMap.set(20, ['Q']); - this.scanCodeTextMap.set(21, ['R']); - this.scanCodeTextMap.set(22, ['S']); - this.scanCodeTextMap.set(23, ['T']); - this.scanCodeTextMap.set(24, ['U']); - this.scanCodeTextMap.set(25, ['V']); - this.scanCodeTextMap.set(26, ['W']); - this.scanCodeTextMap.set(27, ['X']); - this.scanCodeTextMap.set(28, ['Y']); - this.scanCodeTextMap.set(29, ['Z']); - this.scanCodeTextMap.set(30, ['1', '!']); - this.scanCodeTextMap.set(31, ['2', '@']); - this.scanCodeTextMap.set(32, ['3', '#']); - this.scanCodeTextMap.set(33, ['4', '$']); - this.scanCodeTextMap.set(34, ['5', '%']); - this.scanCodeTextMap.set(35, ['6', '^']); - this.scanCodeTextMap.set(36, ['7', '&']); - this.scanCodeTextMap.set(37, ['8', '*']); - this.scanCodeTextMap.set(38, ['9', '(']); - this.scanCodeTextMap.set(39, ['0', ')']); - this.scanCodeTextMap.set(40, ['Enter']); - this.scanCodeTextMap.set(41, ['Esc']); - this.scanCodeTextMap.set(42, ['Backspace']); - this.scanCodeTextMap.set(43, ['Tab']); - this.scanCodeTextMap.set(44, ['Space']); - this.scanCodeTextMap.set(45, ['-', '_']); - this.scanCodeTextMap.set(46, ['=', '+']); - this.scanCodeTextMap.set(47, ['[', '{']); - this.scanCodeTextMap.set(48, [']', '}']); - this.scanCodeTextMap.set(49, ['\\', '|']); - this.scanCodeTextMap.set(50, ['NON_US_HASHMARK_AND_TILDE']); - this.scanCodeTextMap.set(51, [';', ':']); - this.scanCodeTextMap.set(52, ['\'', '"']); - this.scanCodeTextMap.set(53, ['`', '~']); - this.scanCodeTextMap.set(54, [',', '<']); - this.scanCodeTextMap.set(55, ['.', '>']); - this.scanCodeTextMap.set(56, ['/', '?']); - this.scanCodeTextMap.set(57, ['Caps Lock']); - this.scanCodeTextMap.set(58, ['F1']); - this.scanCodeTextMap.set(59, ['F2']); - this.scanCodeTextMap.set(60, ['F3']); - this.scanCodeTextMap.set(61, ['F4']); - this.scanCodeTextMap.set(62, ['F5']); - this.scanCodeTextMap.set(63, ['F6']); - this.scanCodeTextMap.set(64, ['F7']); - this.scanCodeTextMap.set(65, ['F8']); - this.scanCodeTextMap.set(66, ['F9']); - this.scanCodeTextMap.set(67, ['F10']); - this.scanCodeTextMap.set(68, ['F11']); - this.scanCodeTextMap.set(69, ['F12']); - this.scanCodeTextMap.set(70, ['PrtScn']); - this.scanCodeTextMap.set(71, ['Scroll Lock']); - this.scanCodeTextMap.set(72, ['Pause']); - this.scanCodeTextMap.set(73, ['Insert']); - this.scanCodeTextMap.set(74, ['Home']); - this.scanCodeTextMap.set(75, ['PgUp']); - this.scanCodeTextMap.set(76, ['Del']); - this.scanCodeTextMap.set(77, ['End']); - this.scanCodeTextMap.set(78, ['PgDn']); - this.scanCodeTextMap.set(79, ['Right Arrow']); - this.scanCodeTextMap.set(80, ['Left Arrow']); - this.scanCodeTextMap.set(81, ['Down Arrow']); - this.scanCodeTextMap.set(82, ['Up Arrow']); - this.scanCodeTextMap.set(83, ['Num Lock']); - this.scanCodeTextMap.set(84, ['/']); - this.scanCodeTextMap.set(85, ['*']); - this.scanCodeTextMap.set(86, ['-']); - this.scanCodeTextMap.set(87, ['+']); - this.scanCodeTextMap.set(88, ['Enter']); - this.scanCodeTextMap.set(89, ['end', '1']); - this.scanCodeTextMap.set(90, ['2']); - this.scanCodeTextMap.set(91, ['pgdn', '3']); - this.scanCodeTextMap.set(92, ['4']); - this.scanCodeTextMap.set(93, ['5']); - this.scanCodeTextMap.set(94, ['6']); - this.scanCodeTextMap.set(95, ['home', '7']); - this.scanCodeTextMap.set(96, ['8']); - this.scanCodeTextMap.set(97, ['pgup', '9']); - this.scanCodeTextMap.set(98, ['Insert', '0']); - this.scanCodeTextMap.set(99, ['Del', '.']); - this.scanCodeTextMap.set(104, ['F13']); - this.scanCodeTextMap.set(105, ['F14']); - this.scanCodeTextMap.set(106, ['F15']); - this.scanCodeTextMap.set(107, ['F16']); - this.scanCodeTextMap.set(108, ['F17']); - this.scanCodeTextMap.set(109, ['F18']); - this.scanCodeTextMap.set(110, ['F19']); - this.scanCodeTextMap.set(111, ['F20']); - this.scanCodeTextMap.set(112, ['F21']); - this.scanCodeTextMap.set(113, ['F22']); - this.scanCodeTextMap.set(114, ['F23']); - this.scanCodeTextMap.set(115, ['F24']); - this.scanCodeTextMap.set(118, ['Menu']); - this.scanCodeTextMap.set(176, ['00']); - this.scanCodeTextMap.set(177, ['000']); - this.scanCodeTextMap.set(232, ['Play']); - this.scanCodeTextMap.set(233, ['Stop']); - this.scanCodeTextMap.set(234, ['Prev']); - this.scanCodeTextMap.set(235, ['Next']); - this.scanCodeTextMap.set(236, ['Eject']); - this.scanCodeTextMap.set(237, ['Vol +']); - this.scanCodeTextMap.set(238, ['Vol -']); - this.scanCodeTextMap.set(239, ['Mute']); - this.scanCodeTextMap.set(240, ['WWW']); - this.scanCodeTextMap.set(241, ['Bckwrd']); - this.scanCodeTextMap.set(242, ['Frwrd']); - this.scanCodeTextMap.set(243, ['Cancel']); + this.basicScanCodeTextMap = new Map(); + this.basicScanCodeTextMap.set(4, ['A']); + this.basicScanCodeTextMap.set(5, ['B']); + this.basicScanCodeTextMap.set(6, ['C']); + this.basicScanCodeTextMap.set(7, ['D']); + this.basicScanCodeTextMap.set(8, ['E']); + this.basicScanCodeTextMap.set(9, ['F']); + this.basicScanCodeTextMap.set(10, ['G']); + this.basicScanCodeTextMap.set(11, ['H']); + this.basicScanCodeTextMap.set(12, ['I']); + this.basicScanCodeTextMap.set(13, ['J']); + this.basicScanCodeTextMap.set(14, ['K']); + this.basicScanCodeTextMap.set(15, ['L']); + this.basicScanCodeTextMap.set(16, ['M']); + this.basicScanCodeTextMap.set(17, ['N']); + this.basicScanCodeTextMap.set(18, ['O']); + this.basicScanCodeTextMap.set(19, ['P']); + this.basicScanCodeTextMap.set(20, ['Q']); + this.basicScanCodeTextMap.set(21, ['R']); + this.basicScanCodeTextMap.set(22, ['S']); + this.basicScanCodeTextMap.set(23, ['T']); + this.basicScanCodeTextMap.set(24, ['U']); + this.basicScanCodeTextMap.set(25, ['V']); + this.basicScanCodeTextMap.set(26, ['W']); + this.basicScanCodeTextMap.set(27, ['X']); + this.basicScanCodeTextMap.set(28, ['Y']); + this.basicScanCodeTextMap.set(29, ['Z']); + this.basicScanCodeTextMap.set(30, ['1', '!']); + this.basicScanCodeTextMap.set(31, ['2', '@']); + this.basicScanCodeTextMap.set(32, ['3', '#']); + this.basicScanCodeTextMap.set(33, ['4', '$']); + this.basicScanCodeTextMap.set(34, ['5', '%']); + this.basicScanCodeTextMap.set(35, ['6', '^']); + this.basicScanCodeTextMap.set(36, ['7', '&']); + this.basicScanCodeTextMap.set(37, ['8', '*']); + this.basicScanCodeTextMap.set(38, ['9', '(']); + this.basicScanCodeTextMap.set(39, ['0', ')']); + this.basicScanCodeTextMap.set(40, ['Enter']); + this.basicScanCodeTextMap.set(41, ['Esc']); + this.basicScanCodeTextMap.set(42, ['Backspace']); + this.basicScanCodeTextMap.set(43, ['Tab']); + this.basicScanCodeTextMap.set(44, ['Space']); + this.basicScanCodeTextMap.set(45, ['-', '_']); + this.basicScanCodeTextMap.set(46, ['=', '+']); + this.basicScanCodeTextMap.set(47, ['[', '{']); + this.basicScanCodeTextMap.set(48, [']', '}']); + this.basicScanCodeTextMap.set(49, ['\\', '|']); + this.basicScanCodeTextMap.set(50, ['NON_US_HASHMARK_AND_TILDE']); + this.basicScanCodeTextMap.set(51, [';', ':']); + this.basicScanCodeTextMap.set(52, ['\'', '"']); + this.basicScanCodeTextMap.set(53, ['`', '~']); + this.basicScanCodeTextMap.set(54, [',', '<']); + this.basicScanCodeTextMap.set(55, ['.', '>']); + this.basicScanCodeTextMap.set(56, ['/', '?']); + this.basicScanCodeTextMap.set(57, ['Caps Lock']); + this.basicScanCodeTextMap.set(58, ['F1']); + this.basicScanCodeTextMap.set(59, ['F2']); + this.basicScanCodeTextMap.set(60, ['F3']); + this.basicScanCodeTextMap.set(61, ['F4']); + this.basicScanCodeTextMap.set(62, ['F5']); + this.basicScanCodeTextMap.set(63, ['F6']); + this.basicScanCodeTextMap.set(64, ['F7']); + this.basicScanCodeTextMap.set(65, ['F8']); + this.basicScanCodeTextMap.set(66, ['F9']); + this.basicScanCodeTextMap.set(67, ['F10']); + this.basicScanCodeTextMap.set(68, ['F11']); + this.basicScanCodeTextMap.set(69, ['F12']); + this.basicScanCodeTextMap.set(70, ['PrtScn']); + this.basicScanCodeTextMap.set(71, ['Scroll Lock']); + this.basicScanCodeTextMap.set(72, ['Pause']); + this.basicScanCodeTextMap.set(73, ['Insert']); + this.basicScanCodeTextMap.set(74, ['Home']); + this.basicScanCodeTextMap.set(75, ['PgUp']); + this.basicScanCodeTextMap.set(76, ['Del']); + this.basicScanCodeTextMap.set(77, ['End']); + this.basicScanCodeTextMap.set(78, ['PgDn']); + this.basicScanCodeTextMap.set(79, ['Right Arrow']); + this.basicScanCodeTextMap.set(80, ['Left Arrow']); + this.basicScanCodeTextMap.set(81, ['Down Arrow']); + this.basicScanCodeTextMap.set(82, ['Up Arrow']); + this.basicScanCodeTextMap.set(83, ['Num Lock']); + this.basicScanCodeTextMap.set(84, ['/']); + this.basicScanCodeTextMap.set(85, ['*']); + this.basicScanCodeTextMap.set(86, ['-']); + this.basicScanCodeTextMap.set(87, ['+']); + this.basicScanCodeTextMap.set(88, ['Enter']); + this.basicScanCodeTextMap.set(89, ['end', '1']); + this.basicScanCodeTextMap.set(90, ['2']); + this.basicScanCodeTextMap.set(91, ['pgdn', '3']); + this.basicScanCodeTextMap.set(92, ['4']); + this.basicScanCodeTextMap.set(93, ['5']); + this.basicScanCodeTextMap.set(94, ['6']); + this.basicScanCodeTextMap.set(95, ['home', '7']); + this.basicScanCodeTextMap.set(96, ['8']); + this.basicScanCodeTextMap.set(97, ['pgup', '9']); + this.basicScanCodeTextMap.set(98, ['Insert', '0']); + this.basicScanCodeTextMap.set(99, ['Del', '.']); + this.basicScanCodeTextMap.set(104, ['F13']); + this.basicScanCodeTextMap.set(105, ['F14']); + this.basicScanCodeTextMap.set(106, ['F15']); + this.basicScanCodeTextMap.set(107, ['F16']); + this.basicScanCodeTextMap.set(108, ['F17']); + this.basicScanCodeTextMap.set(109, ['F18']); + this.basicScanCodeTextMap.set(110, ['F19']); + this.basicScanCodeTextMap.set(111, ['F20']); + this.basicScanCodeTextMap.set(112, ['F21']); + this.basicScanCodeTextMap.set(113, ['F22']); + this.basicScanCodeTextMap.set(114, ['F23']); + this.basicScanCodeTextMap.set(115, ['F24']); + this.basicScanCodeTextMap.set(118, ['Menu']); + this.basicScanCodeTextMap.set(176, ['00']); + this.basicScanCodeTextMap.set(177, ['000']); + + this.mediaScanCodeTextMap = new Map(); + this.mediaScanCodeTextMap.set(226, ['Mute']); + this.mediaScanCodeTextMap.set(232, ['Play']); + this.mediaScanCodeTextMap.set(233, ['Stop']); + this.mediaScanCodeTextMap.set(234, ['Prev']); + this.mediaScanCodeTextMap.set(235, ['Next']); + this.mediaScanCodeTextMap.set(236, ['Eject']); + this.mediaScanCodeTextMap.set(237, ['Vol +']); + this.mediaScanCodeTextMap.set(238, ['Vol -']); + this.mediaScanCodeTextMap.set(240, ['WWW']); + this.mediaScanCodeTextMap.set(241, ['Bckwrd']); + this.mediaScanCodeTextMap.set(242, ['Frwrd']); + this.mediaScanCodeTextMap.set(243, ['Cancel']); } private initScanCodeFileName(): void {