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
This commit is contained in:
committed by
László Monda
parent
8e823b57b4
commit
efe7e95b3e
+197
-103
File diff suppressed because it is too large
Load Diff
@@ -95,7 +95,8 @@
|
|||||||
"keyActions": [
|
"keyActions": [
|
||||||
{
|
{
|
||||||
"keyActionType": "keystroke",
|
"keyActionType": "keystroke",
|
||||||
"scancode": 111
|
"scancode": 111,
|
||||||
|
"type": "basic"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<b class="setting-label">Scancode:</b>
|
<b class="setting-label">Scancode:</b>
|
||||||
<select2
|
<select2
|
||||||
[data]="scanCodeGroups"
|
[data]="scanCodeGroups"
|
||||||
[value]="scanCode.toString()"
|
[value]="selectedScancodeOption.id"
|
||||||
(valueChanged)="onScancodeChange($event)"
|
(valueChanged)="onScancodeChange($event)"
|
||||||
[width]="200"
|
[width]="200"
|
||||||
[options]="options"
|
[options]="options"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { KeyAction, KeystrokeAction } from '../../../../config-serializer/config
|
|||||||
|
|
||||||
import { Tab } from '../tab';
|
import { Tab } from '../tab';
|
||||||
import { MapperService } from '../../../../services/mapper.service';
|
import { MapperService } from '../../../../services/mapper.service';
|
||||||
|
import { KeystrokeType } from '../../../../config-serializer/config-items/key-action/keystroke-type';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'keypress-tab',
|
selector: 'keypress-tab',
|
||||||
@@ -16,18 +17,18 @@ export class KeypressTabComponent extends Tab implements OnChanges {
|
|||||||
@Input() defaultKeyAction: KeyAction;
|
@Input() defaultKeyAction: KeyAction;
|
||||||
@Input() longPressEnabled: boolean;
|
@Input() longPressEnabled: boolean;
|
||||||
|
|
||||||
private leftModifiers: string[];
|
leftModifiers: string[];
|
||||||
private rightModifiers: string[];
|
rightModifiers: string[];
|
||||||
|
|
||||||
private leftModifierSelects: boolean[];
|
leftModifierSelects: boolean[];
|
||||||
private rightModifierSelects: boolean[];
|
rightModifierSelects: boolean[];
|
||||||
|
|
||||||
private scanCodeGroups: Array<Select2OptionData>;
|
scanCodeGroups: Array<Select2OptionData>;
|
||||||
private longPressGroups: Array<Select2OptionData>;
|
longPressGroups: Array<Select2OptionData>;
|
||||||
private options: Select2Options;
|
options: Select2Options;
|
||||||
|
|
||||||
private scanCode: number;
|
selectedScancodeOption: Select2OptionData;
|
||||||
private selectedLongPressIndex: number;
|
selectedLongPressIndex: number;
|
||||||
|
|
||||||
constructor(private mapper: MapperService) {
|
constructor(private mapper: MapperService) {
|
||||||
super();
|
super();
|
||||||
@@ -41,7 +42,7 @@ export class KeypressTabComponent extends Tab implements OnChanges {
|
|||||||
this.longPressGroups = require('json-loader!./longPress.json');
|
this.longPressGroups = require('json-loader!./longPress.json');
|
||||||
this.leftModifierSelects = Array(this.leftModifiers.length).fill(false);
|
this.leftModifierSelects = Array(this.leftModifiers.length).fill(false);
|
||||||
this.rightModifierSelects = Array(this.rightModifiers.length).fill(false);
|
this.rightModifierSelects = Array(this.rightModifiers.length).fill(false);
|
||||||
this.scanCode = 0;
|
this.selectedScancodeOption = this.scanCodeGroups[0];
|
||||||
this.selectedLongPressIndex = -1;
|
this.selectedLongPressIndex = -1;
|
||||||
this.options = {
|
this.options = {
|
||||||
templateResult: this.scanCodeTemplateResult,
|
templateResult: this.scanCodeTemplateResult,
|
||||||
@@ -70,11 +71,11 @@ export class KeypressTabComponent extends Tab implements OnChanges {
|
|||||||
return (keystrokeAction) ? (keystrokeAction.scancode > 0 || keystrokeAction.modifierMask > 0) : false;
|
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) {
|
if (event.code) {
|
||||||
this.scanCode = event.code;
|
this.selectedScancodeOption = this.findScancodeOptionByScancode(event.code, KeystrokeType.basic);
|
||||||
} else {
|
} else {
|
||||||
this.scanCode = 0;
|
this.selectedScancodeOption = this.scanCodeGroups[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.leftModifierSelects = event.left;
|
this.leftModifierSelects = event.left;
|
||||||
@@ -87,8 +88,8 @@ export class KeypressTabComponent extends Tab implements OnChanges {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const keystrokeAction: KeystrokeAction = <KeystrokeAction>keyAction;
|
const keystrokeAction: KeystrokeAction = <KeystrokeAction>keyAction;
|
||||||
// Restore scancode
|
// Restore selectedScancodeOption
|
||||||
this.scanCode = keystrokeAction.scancode || 0;
|
this.selectedScancodeOption = this.findScancodeOptionByScancode(keystrokeAction.scancode || 0, keystrokeAction.type);
|
||||||
|
|
||||||
const leftModifiersLength: number = this.leftModifiers.length;
|
const leftModifiersLength: number = this.leftModifiers.length;
|
||||||
|
|
||||||
@@ -112,8 +113,13 @@ export class KeypressTabComponent extends Tab implements OnChanges {
|
|||||||
|
|
||||||
toKeyAction(): KeystrokeAction {
|
toKeyAction(): KeystrokeAction {
|
||||||
const keystrokeAction: KeystrokeAction = new 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;
|
keystrokeAction.modifierMask = 0;
|
||||||
const modifiers = this.leftModifierSelects.concat(this.rightModifierSelects).map(x => x ? 1 : 0);
|
const modifiers = this.leftModifierSelects.concat(this.rightModifierSelects).map(x => x ? 1 : 0);
|
||||||
for (let i = 0; i < modifiers.length; ++i) {
|
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) {
|
if (state.additional && state.additional.explanation) {
|
||||||
return jQuery(
|
return jQuery(
|
||||||
'<span class="select2-item">'
|
'<span class="select2-item">'
|
||||||
+ '<span>' + state.text + '</span>'
|
+ '<span>' + state.text + '</span>'
|
||||||
+ '<span class="scancode--searchterm"> '
|
+ '<span class="scancode--searchterm"> '
|
||||||
+ state.additional.explanation
|
+ state.additional.explanation
|
||||||
+ '</span>' +
|
+ '</span>' +
|
||||||
'</span>'
|
'</span>'
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@@ -155,12 +161,65 @@ export class KeypressTabComponent extends Tab implements OnChanges {
|
|||||||
this.validAction.emit(this.keyActionValid());
|
this.validAction.emit(this.keyActionValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
onLongpressChange(event: {value: string}) {
|
onLongpressChange(event: { value: string }) {
|
||||||
this.selectedLongPressIndex = +event.value;
|
this.selectedLongPressIndex = +event.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
onScancodeChange(event: {value: string}) {
|
onScancodeChange(event: { value: string }) {
|
||||||
this.scanCode = +event.value;
|
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());
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -559,7 +559,11 @@
|
|||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"id": "127",
|
"id": "127",
|
||||||
"text": "Mute"
|
"text": "Mute",
|
||||||
|
"additional": {
|
||||||
|
"type": "media",
|
||||||
|
"scancode": 226
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "128",
|
"id": "128",
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ export class SvgKeyboardKeyComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
|
|
||||||
if (!keyAction.hasActiveModifier() && keyAction.hasScancode()) {
|
if (!keyAction.hasActiveModifier() && keyAction.hasScancode()) {
|
||||||
const scancode: number = keyAction.scancode;
|
const scancode: number = keyAction.scancode;
|
||||||
newLabelSource = this.mapper.scanCodeToText(scancode);
|
newLabelSource = this.mapper.scanCodeToText(scancode, keyAction.type);
|
||||||
if (this.mapper.hasScancodeIcon(scancode)) {
|
if (this.mapper.hasScancodeIcon(scancode)) {
|
||||||
this.labelSource = this.mapper.scanCodeToSvgImagePath(scancode);
|
this.labelSource = this.mapper.scanCodeToSvgImagePath(scancode);
|
||||||
this.labelType = LabelTypes.SingleIcon;
|
this.labelType = LabelTypes.SingleIcon;
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ export class SvgKeystrokeKeyComponent implements OnInit, OnChanges {
|
|||||||
let newLabelSource: string[];
|
let newLabelSource: string[];
|
||||||
if (this.keystrokeAction.hasScancode()) {
|
if (this.keystrokeAction.hasScancode()) {
|
||||||
const scancode: number = this.keystrokeAction.scancode;
|
const scancode: number = this.keystrokeAction.scancode;
|
||||||
newLabelSource = this.mapper.scanCodeToText(scancode);
|
newLabelSource = this.mapper.scanCodeToText(scancode, this.keystrokeAction.type);
|
||||||
if (newLabelSource) {
|
if (newLabelSource) {
|
||||||
if (newLabelSource.length === 1) {
|
if (newLabelSource.length === 1) {
|
||||||
this.labelSource = newLabelSource[0];
|
this.labelSource = newLabelSource[0];
|
||||||
|
|||||||
@@ -245,7 +245,8 @@ export class SvgKeyboardWrapComponent implements OnInit, OnChanges {
|
|||||||
|
|
||||||
if (keystrokeAction.hasScancode()) {
|
if (keystrokeAction.hasScancode()) {
|
||||||
let value: string = keystrokeAction.scancode.toString();
|
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) {
|
if (scanCodeTexts.length > 0) {
|
||||||
value += ' (' + scanCodeTexts + ')';
|
value += ' (' + scanCodeTexts + ')';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,17 +7,18 @@ export enum KeyActionId {
|
|||||||
NoneAction = 0,
|
NoneAction = 0,
|
||||||
KeystrokeAction = 1,
|
KeystrokeAction = 1,
|
||||||
/*
|
/*
|
||||||
1 - 7 are reserved for KeystrokeAction
|
1 - 31 are reserved for KeystrokeAction
|
||||||
3 bits:
|
5 bits:
|
||||||
1: Do we have scancode?
|
1: Do we have scancode?
|
||||||
2: Do we have modifiers?
|
2: Do we have modifiers?
|
||||||
3: Do we have longpress?
|
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
|
LastKeystrokeAction = 31, // TODO: remove this after refactoring the keyActionId check
|
||||||
SwitchLayerAction = 8,
|
SwitchLayerAction = 32,
|
||||||
SwitchKeymapAction = 9,
|
SwitchKeymapAction = 33,
|
||||||
MouseAction = 10,
|
MouseAction = 34,
|
||||||
PlayMacroAction = 11
|
PlayMacroAction = 35
|
||||||
}
|
}
|
||||||
|
|
||||||
export let keyActionType = {
|
export let keyActionType = {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { UhkBuffer } from '../../UhkBuffer';
|
|||||||
import { KeyModifiers } from '../KeyModifiers';
|
import { KeyModifiers } from '../KeyModifiers';
|
||||||
import { LongPressAction } from '../LongPressAction';
|
import { LongPressAction } from '../LongPressAction';
|
||||||
import { KeyAction, KeyActionId, keyActionType } from './KeyAction';
|
import { KeyAction, KeyActionId, keyActionType } from './KeyAction';
|
||||||
|
import { KeystrokeType } from './keystroke-type';
|
||||||
|
|
||||||
export enum KeystrokeActionFlag {
|
export enum KeystrokeActionFlag {
|
||||||
scancode = 1 << 0,
|
scancode = 1 << 0,
|
||||||
@@ -10,19 +11,31 @@ export enum KeystrokeActionFlag {
|
|||||||
longPressAction = 1 << 2
|
longPressAction = 1 << 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const KEYSTROKE_ACTION_FLAG_LENGTH = 3;
|
||||||
|
|
||||||
interface JsonObjectKeystrokeAction {
|
interface JsonObjectKeystrokeAction {
|
||||||
keyActionType: string;
|
keyActionType: string;
|
||||||
scancode?: number;
|
scancode?: number;
|
||||||
modifierMask?: number;
|
modifierMask?: number;
|
||||||
longPressAction?: string;
|
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 {
|
export class KeystrokeAction extends KeyAction {
|
||||||
|
|
||||||
@assertUInt8
|
set scancode(scancode: number) {
|
||||||
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
|
@assertUInt8
|
||||||
modifierMask: number;
|
modifierMask: number;
|
||||||
@@ -30,19 +43,41 @@ export class KeystrokeAction extends KeyAction {
|
|||||||
@assertEnum(LongPressAction)
|
@assertEnum(LongPressAction)
|
||||||
longPressAction: 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) {
|
constructor(other?: KeystrokeAction) {
|
||||||
super();
|
super();
|
||||||
if (!other) {
|
if (!other) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.scancode = other.scancode;
|
this.type = other.type;
|
||||||
|
this._scancode = other._scancode;
|
||||||
this.modifierMask = other.modifierMask;
|
this.modifierMask = other.modifierMask;
|
||||||
this.longPressAction = other.longPressAction;
|
this.longPressAction = other.longPressAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
fromJsonObject(jsonObject: JsonObjectKeystrokeAction): KeystrokeAction {
|
fromJsonObject(jsonObject: JsonObjectKeystrokeAction): KeystrokeAction {
|
||||||
this.assertKeyActionType(jsonObject);
|
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.modifierMask = jsonObject.modifierMask;
|
||||||
this.longPressAction = LongPressAction[jsonObject.longPressAction];
|
this.longPressAction = LongPressAction[jsonObject.longPressAction];
|
||||||
return this;
|
return this;
|
||||||
@@ -51,8 +86,9 @@ export class KeystrokeAction extends KeyAction {
|
|||||||
fromBinary(buffer: UhkBuffer): KeystrokeAction {
|
fromBinary(buffer: UhkBuffer): KeystrokeAction {
|
||||||
const keyActionId: KeyActionId = this.readAndAssertKeyActionId(buffer);
|
const keyActionId: KeyActionId = this.readAndAssertKeyActionId(buffer);
|
||||||
const flags: number = keyActionId - KeyActionId.KeystrokeAction;
|
const flags: number = keyActionId - KeyActionId.KeystrokeAction;
|
||||||
|
this.type = (flags >> 3) & 0b11;
|
||||||
if (flags & KeystrokeActionFlag.scancode) {
|
if (flags & KeystrokeActionFlag.scancode) {
|
||||||
this.scancode = buffer.readUInt8();
|
this._scancode = this.type === KeystrokeType.longMedia ? buffer.readUInt16() : buffer.readUInt8();
|
||||||
}
|
}
|
||||||
if (flags & KeystrokeActionFlag.modifierMask) {
|
if (flags & KeystrokeActionFlag.modifierMask) {
|
||||||
this.modifierMask = buffer.readUInt8();
|
this.modifierMask = buffer.readUInt8();
|
||||||
@@ -68,8 +104,14 @@ export class KeystrokeAction extends KeyAction {
|
|||||||
keyActionType: keyActionType.KeystrokeAction
|
keyActionType: keyActionType.KeystrokeAction
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (this.type === KeystrokeType.shortMedia || this.type === KeystrokeType.longMedia) {
|
||||||
|
jsonObject.type = 'media';
|
||||||
|
} else {
|
||||||
|
jsonObject.type = KeystrokeType[this.type];
|
||||||
|
}
|
||||||
|
|
||||||
if (this.hasScancode()) {
|
if (this.hasScancode()) {
|
||||||
jsonObject.scancode = this.scancode;
|
jsonObject.scancode = this._scancode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.hasActiveModifier()) {
|
if (this.hasActiveModifier()) {
|
||||||
@@ -85,33 +127,45 @@ export class KeystrokeAction extends KeyAction {
|
|||||||
|
|
||||||
toBinary(buffer: UhkBuffer) {
|
toBinary(buffer: UhkBuffer) {
|
||||||
let flags = 0;
|
let flags = 0;
|
||||||
const bufferData: number[] = [];
|
const toWrite: {
|
||||||
|
data: number,
|
||||||
|
long: boolean
|
||||||
|
}[] = [];
|
||||||
|
|
||||||
if (this.hasScancode()) {
|
if (this.hasScancode()) {
|
||||||
flags |= KeystrokeActionFlag.scancode;
|
flags |= KeystrokeActionFlag.scancode;
|
||||||
bufferData.push(this.scancode);
|
toWrite.push({ data: this._scancode, long: this.type === KeystrokeType.longMedia });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.hasActiveModifier()) {
|
if (this.hasActiveModifier()) {
|
||||||
flags |= KeystrokeActionFlag.modifierMask;
|
flags |= KeystrokeActionFlag.modifierMask;
|
||||||
bufferData.push(this.modifierMask);
|
toWrite.push({ data: this.modifierMask, long: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.hasLongPressAction()) {
|
if (this.hasLongPressAction()) {
|
||||||
flags |= KeystrokeActionFlag.longPressAction;
|
flags |= KeystrokeActionFlag.longPressAction;
|
||||||
bufferData.push(this.longPressAction);
|
toWrite.push({ data: this.longPressAction, long: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.writeUInt8(KeyActionId.KeystrokeAction + flags);
|
const TYPE_OFFSET = flags + (this.type << KEYSTROKE_ACTION_FLAG_LENGTH);
|
||||||
for (let i = 0; i < bufferData.length; ++i) {
|
|
||||||
buffer.writeUInt8(bufferData[i]);
|
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 {
|
toString(): string {
|
||||||
const properties: string[] = [];
|
const properties: string[] = [];
|
||||||
|
properties.push(`type="${KeystrokeType[this.type]}"`);
|
||||||
|
|
||||||
if (this.hasScancode()) {
|
if (this.hasScancode()) {
|
||||||
properties.push(`scancode="${this.scancode}"`);
|
properties.push(`scancode="${this._scancode}"`);
|
||||||
}
|
}
|
||||||
if (this.hasActiveModifier()) {
|
if (this.hasActiveModifier()) {
|
||||||
properties.push(`modifierMask="${this.modifierMask}"`);
|
properties.push(`modifierMask="${this.modifierMask}"`);
|
||||||
@@ -136,7 +190,7 @@ export class KeystrokeAction extends KeyAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hasScancode(): boolean {
|
hasScancode(): boolean {
|
||||||
return !!this.scancode;
|
return !!this._scancode;
|
||||||
}
|
}
|
||||||
|
|
||||||
hasOnlyOneActiveModifier(): boolean {
|
hasOnlyOneActiveModifier(): boolean {
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
export enum KeystrokeType {
|
||||||
|
basic,
|
||||||
|
shortMedia,
|
||||||
|
longMedia,
|
||||||
|
system
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -3,11 +3,13 @@ const __svg__ = { path: '../../../images/icons/**/*.svg', name: 'assets/compiled
|
|||||||
/* tslint:enable:variable-name */
|
/* tslint:enable:variable-name */
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
import { KeystrokeType } from '../config-serializer/config-items/key-action/keystroke-type';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MapperService {
|
export class MapperService {
|
||||||
|
|
||||||
private scanCodeTextMap: Map<number, string[]>;
|
private basicScanCodeTextMap: Map<number, string[]>;
|
||||||
|
private mediaScanCodeTextMap: Map<number, string[]>;
|
||||||
|
|
||||||
private scanCodeFileName: Map<number, string>;
|
private scanCodeFileName: Map<number, string>;
|
||||||
private nameToFileName: Map<string, string>;
|
private nameToFileName: Map<string, string>;
|
||||||
@@ -18,8 +20,18 @@ export class MapperService {
|
|||||||
this.initNameToFileNames();
|
this.initNameToFileNames();
|
||||||
}
|
}
|
||||||
|
|
||||||
public scanCodeToText(scanCode: number): string[] {
|
public scanCodeToText(scanCode: number, type: KeystrokeType = KeystrokeType.basic): string[] {
|
||||||
return this.scanCodeTextMap.get(scanCode);
|
let map: Map<number, string[]>;
|
||||||
|
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 {
|
public hasScancodeIcon(scancode: number): boolean {
|
||||||
@@ -48,130 +60,132 @@ export class MapperService {
|
|||||||
|
|
||||||
// TODO: read the mapping from JSON
|
// TODO: read the mapping from JSON
|
||||||
private initScanCodeTextMap(): void {
|
private initScanCodeTextMap(): void {
|
||||||
this.scanCodeTextMap = new Map<number, string[]>();
|
this.basicScanCodeTextMap = new Map<number, string[]>();
|
||||||
this.scanCodeTextMap.set(4, ['A']);
|
this.basicScanCodeTextMap.set(4, ['A']);
|
||||||
this.scanCodeTextMap.set(5, ['B']);
|
this.basicScanCodeTextMap.set(5, ['B']);
|
||||||
this.scanCodeTextMap.set(6, ['C']);
|
this.basicScanCodeTextMap.set(6, ['C']);
|
||||||
this.scanCodeTextMap.set(7, ['D']);
|
this.basicScanCodeTextMap.set(7, ['D']);
|
||||||
this.scanCodeTextMap.set(8, ['E']);
|
this.basicScanCodeTextMap.set(8, ['E']);
|
||||||
this.scanCodeTextMap.set(9, ['F']);
|
this.basicScanCodeTextMap.set(9, ['F']);
|
||||||
this.scanCodeTextMap.set(10, ['G']);
|
this.basicScanCodeTextMap.set(10, ['G']);
|
||||||
this.scanCodeTextMap.set(11, ['H']);
|
this.basicScanCodeTextMap.set(11, ['H']);
|
||||||
this.scanCodeTextMap.set(12, ['I']);
|
this.basicScanCodeTextMap.set(12, ['I']);
|
||||||
this.scanCodeTextMap.set(13, ['J']);
|
this.basicScanCodeTextMap.set(13, ['J']);
|
||||||
this.scanCodeTextMap.set(14, ['K']);
|
this.basicScanCodeTextMap.set(14, ['K']);
|
||||||
this.scanCodeTextMap.set(15, ['L']);
|
this.basicScanCodeTextMap.set(15, ['L']);
|
||||||
this.scanCodeTextMap.set(16, ['M']);
|
this.basicScanCodeTextMap.set(16, ['M']);
|
||||||
this.scanCodeTextMap.set(17, ['N']);
|
this.basicScanCodeTextMap.set(17, ['N']);
|
||||||
this.scanCodeTextMap.set(18, ['O']);
|
this.basicScanCodeTextMap.set(18, ['O']);
|
||||||
this.scanCodeTextMap.set(19, ['P']);
|
this.basicScanCodeTextMap.set(19, ['P']);
|
||||||
this.scanCodeTextMap.set(20, ['Q']);
|
this.basicScanCodeTextMap.set(20, ['Q']);
|
||||||
this.scanCodeTextMap.set(21, ['R']);
|
this.basicScanCodeTextMap.set(21, ['R']);
|
||||||
this.scanCodeTextMap.set(22, ['S']);
|
this.basicScanCodeTextMap.set(22, ['S']);
|
||||||
this.scanCodeTextMap.set(23, ['T']);
|
this.basicScanCodeTextMap.set(23, ['T']);
|
||||||
this.scanCodeTextMap.set(24, ['U']);
|
this.basicScanCodeTextMap.set(24, ['U']);
|
||||||
this.scanCodeTextMap.set(25, ['V']);
|
this.basicScanCodeTextMap.set(25, ['V']);
|
||||||
this.scanCodeTextMap.set(26, ['W']);
|
this.basicScanCodeTextMap.set(26, ['W']);
|
||||||
this.scanCodeTextMap.set(27, ['X']);
|
this.basicScanCodeTextMap.set(27, ['X']);
|
||||||
this.scanCodeTextMap.set(28, ['Y']);
|
this.basicScanCodeTextMap.set(28, ['Y']);
|
||||||
this.scanCodeTextMap.set(29, ['Z']);
|
this.basicScanCodeTextMap.set(29, ['Z']);
|
||||||
this.scanCodeTextMap.set(30, ['1', '!']);
|
this.basicScanCodeTextMap.set(30, ['1', '!']);
|
||||||
this.scanCodeTextMap.set(31, ['2', '@']);
|
this.basicScanCodeTextMap.set(31, ['2', '@']);
|
||||||
this.scanCodeTextMap.set(32, ['3', '#']);
|
this.basicScanCodeTextMap.set(32, ['3', '#']);
|
||||||
this.scanCodeTextMap.set(33, ['4', '$']);
|
this.basicScanCodeTextMap.set(33, ['4', '$']);
|
||||||
this.scanCodeTextMap.set(34, ['5', '%']);
|
this.basicScanCodeTextMap.set(34, ['5', '%']);
|
||||||
this.scanCodeTextMap.set(35, ['6', '^']);
|
this.basicScanCodeTextMap.set(35, ['6', '^']);
|
||||||
this.scanCodeTextMap.set(36, ['7', '&']);
|
this.basicScanCodeTextMap.set(36, ['7', '&']);
|
||||||
this.scanCodeTextMap.set(37, ['8', '*']);
|
this.basicScanCodeTextMap.set(37, ['8', '*']);
|
||||||
this.scanCodeTextMap.set(38, ['9', '(']);
|
this.basicScanCodeTextMap.set(38, ['9', '(']);
|
||||||
this.scanCodeTextMap.set(39, ['0', ')']);
|
this.basicScanCodeTextMap.set(39, ['0', ')']);
|
||||||
this.scanCodeTextMap.set(40, ['Enter']);
|
this.basicScanCodeTextMap.set(40, ['Enter']);
|
||||||
this.scanCodeTextMap.set(41, ['Esc']);
|
this.basicScanCodeTextMap.set(41, ['Esc']);
|
||||||
this.scanCodeTextMap.set(42, ['Backspace']);
|
this.basicScanCodeTextMap.set(42, ['Backspace']);
|
||||||
this.scanCodeTextMap.set(43, ['Tab']);
|
this.basicScanCodeTextMap.set(43, ['Tab']);
|
||||||
this.scanCodeTextMap.set(44, ['Space']);
|
this.basicScanCodeTextMap.set(44, ['Space']);
|
||||||
this.scanCodeTextMap.set(45, ['-', '_']);
|
this.basicScanCodeTextMap.set(45, ['-', '_']);
|
||||||
this.scanCodeTextMap.set(46, ['=', '+']);
|
this.basicScanCodeTextMap.set(46, ['=', '+']);
|
||||||
this.scanCodeTextMap.set(47, ['[', '{']);
|
this.basicScanCodeTextMap.set(47, ['[', '{']);
|
||||||
this.scanCodeTextMap.set(48, [']', '}']);
|
this.basicScanCodeTextMap.set(48, [']', '}']);
|
||||||
this.scanCodeTextMap.set(49, ['\\', '|']);
|
this.basicScanCodeTextMap.set(49, ['\\', '|']);
|
||||||
this.scanCodeTextMap.set(50, ['NON_US_HASHMARK_AND_TILDE']);
|
this.basicScanCodeTextMap.set(50, ['NON_US_HASHMARK_AND_TILDE']);
|
||||||
this.scanCodeTextMap.set(51, [';', ':']);
|
this.basicScanCodeTextMap.set(51, [';', ':']);
|
||||||
this.scanCodeTextMap.set(52, ['\'', '"']);
|
this.basicScanCodeTextMap.set(52, ['\'', '"']);
|
||||||
this.scanCodeTextMap.set(53, ['`', '~']);
|
this.basicScanCodeTextMap.set(53, ['`', '~']);
|
||||||
this.scanCodeTextMap.set(54, [',', '<']);
|
this.basicScanCodeTextMap.set(54, [',', '<']);
|
||||||
this.scanCodeTextMap.set(55, ['.', '>']);
|
this.basicScanCodeTextMap.set(55, ['.', '>']);
|
||||||
this.scanCodeTextMap.set(56, ['/', '?']);
|
this.basicScanCodeTextMap.set(56, ['/', '?']);
|
||||||
this.scanCodeTextMap.set(57, ['Caps Lock']);
|
this.basicScanCodeTextMap.set(57, ['Caps Lock']);
|
||||||
this.scanCodeTextMap.set(58, ['F1']);
|
this.basicScanCodeTextMap.set(58, ['F1']);
|
||||||
this.scanCodeTextMap.set(59, ['F2']);
|
this.basicScanCodeTextMap.set(59, ['F2']);
|
||||||
this.scanCodeTextMap.set(60, ['F3']);
|
this.basicScanCodeTextMap.set(60, ['F3']);
|
||||||
this.scanCodeTextMap.set(61, ['F4']);
|
this.basicScanCodeTextMap.set(61, ['F4']);
|
||||||
this.scanCodeTextMap.set(62, ['F5']);
|
this.basicScanCodeTextMap.set(62, ['F5']);
|
||||||
this.scanCodeTextMap.set(63, ['F6']);
|
this.basicScanCodeTextMap.set(63, ['F6']);
|
||||||
this.scanCodeTextMap.set(64, ['F7']);
|
this.basicScanCodeTextMap.set(64, ['F7']);
|
||||||
this.scanCodeTextMap.set(65, ['F8']);
|
this.basicScanCodeTextMap.set(65, ['F8']);
|
||||||
this.scanCodeTextMap.set(66, ['F9']);
|
this.basicScanCodeTextMap.set(66, ['F9']);
|
||||||
this.scanCodeTextMap.set(67, ['F10']);
|
this.basicScanCodeTextMap.set(67, ['F10']);
|
||||||
this.scanCodeTextMap.set(68, ['F11']);
|
this.basicScanCodeTextMap.set(68, ['F11']);
|
||||||
this.scanCodeTextMap.set(69, ['F12']);
|
this.basicScanCodeTextMap.set(69, ['F12']);
|
||||||
this.scanCodeTextMap.set(70, ['PrtScn']);
|
this.basicScanCodeTextMap.set(70, ['PrtScn']);
|
||||||
this.scanCodeTextMap.set(71, ['Scroll Lock']);
|
this.basicScanCodeTextMap.set(71, ['Scroll Lock']);
|
||||||
this.scanCodeTextMap.set(72, ['Pause']);
|
this.basicScanCodeTextMap.set(72, ['Pause']);
|
||||||
this.scanCodeTextMap.set(73, ['Insert']);
|
this.basicScanCodeTextMap.set(73, ['Insert']);
|
||||||
this.scanCodeTextMap.set(74, ['Home']);
|
this.basicScanCodeTextMap.set(74, ['Home']);
|
||||||
this.scanCodeTextMap.set(75, ['PgUp']);
|
this.basicScanCodeTextMap.set(75, ['PgUp']);
|
||||||
this.scanCodeTextMap.set(76, ['Del']);
|
this.basicScanCodeTextMap.set(76, ['Del']);
|
||||||
this.scanCodeTextMap.set(77, ['End']);
|
this.basicScanCodeTextMap.set(77, ['End']);
|
||||||
this.scanCodeTextMap.set(78, ['PgDn']);
|
this.basicScanCodeTextMap.set(78, ['PgDn']);
|
||||||
this.scanCodeTextMap.set(79, ['Right Arrow']);
|
this.basicScanCodeTextMap.set(79, ['Right Arrow']);
|
||||||
this.scanCodeTextMap.set(80, ['Left Arrow']);
|
this.basicScanCodeTextMap.set(80, ['Left Arrow']);
|
||||||
this.scanCodeTextMap.set(81, ['Down Arrow']);
|
this.basicScanCodeTextMap.set(81, ['Down Arrow']);
|
||||||
this.scanCodeTextMap.set(82, ['Up Arrow']);
|
this.basicScanCodeTextMap.set(82, ['Up Arrow']);
|
||||||
this.scanCodeTextMap.set(83, ['Num Lock']);
|
this.basicScanCodeTextMap.set(83, ['Num Lock']);
|
||||||
this.scanCodeTextMap.set(84, ['/']);
|
this.basicScanCodeTextMap.set(84, ['/']);
|
||||||
this.scanCodeTextMap.set(85, ['*']);
|
this.basicScanCodeTextMap.set(85, ['*']);
|
||||||
this.scanCodeTextMap.set(86, ['-']);
|
this.basicScanCodeTextMap.set(86, ['-']);
|
||||||
this.scanCodeTextMap.set(87, ['+']);
|
this.basicScanCodeTextMap.set(87, ['+']);
|
||||||
this.scanCodeTextMap.set(88, ['Enter']);
|
this.basicScanCodeTextMap.set(88, ['Enter']);
|
||||||
this.scanCodeTextMap.set(89, ['end', '1']);
|
this.basicScanCodeTextMap.set(89, ['end', '1']);
|
||||||
this.scanCodeTextMap.set(90, ['2']);
|
this.basicScanCodeTextMap.set(90, ['2']);
|
||||||
this.scanCodeTextMap.set(91, ['pgdn', '3']);
|
this.basicScanCodeTextMap.set(91, ['pgdn', '3']);
|
||||||
this.scanCodeTextMap.set(92, ['4']);
|
this.basicScanCodeTextMap.set(92, ['4']);
|
||||||
this.scanCodeTextMap.set(93, ['5']);
|
this.basicScanCodeTextMap.set(93, ['5']);
|
||||||
this.scanCodeTextMap.set(94, ['6']);
|
this.basicScanCodeTextMap.set(94, ['6']);
|
||||||
this.scanCodeTextMap.set(95, ['home', '7']);
|
this.basicScanCodeTextMap.set(95, ['home', '7']);
|
||||||
this.scanCodeTextMap.set(96, ['8']);
|
this.basicScanCodeTextMap.set(96, ['8']);
|
||||||
this.scanCodeTextMap.set(97, ['pgup', '9']);
|
this.basicScanCodeTextMap.set(97, ['pgup', '9']);
|
||||||
this.scanCodeTextMap.set(98, ['Insert', '0']);
|
this.basicScanCodeTextMap.set(98, ['Insert', '0']);
|
||||||
this.scanCodeTextMap.set(99, ['Del', '.']);
|
this.basicScanCodeTextMap.set(99, ['Del', '.']);
|
||||||
this.scanCodeTextMap.set(104, ['F13']);
|
this.basicScanCodeTextMap.set(104, ['F13']);
|
||||||
this.scanCodeTextMap.set(105, ['F14']);
|
this.basicScanCodeTextMap.set(105, ['F14']);
|
||||||
this.scanCodeTextMap.set(106, ['F15']);
|
this.basicScanCodeTextMap.set(106, ['F15']);
|
||||||
this.scanCodeTextMap.set(107, ['F16']);
|
this.basicScanCodeTextMap.set(107, ['F16']);
|
||||||
this.scanCodeTextMap.set(108, ['F17']);
|
this.basicScanCodeTextMap.set(108, ['F17']);
|
||||||
this.scanCodeTextMap.set(109, ['F18']);
|
this.basicScanCodeTextMap.set(109, ['F18']);
|
||||||
this.scanCodeTextMap.set(110, ['F19']);
|
this.basicScanCodeTextMap.set(110, ['F19']);
|
||||||
this.scanCodeTextMap.set(111, ['F20']);
|
this.basicScanCodeTextMap.set(111, ['F20']);
|
||||||
this.scanCodeTextMap.set(112, ['F21']);
|
this.basicScanCodeTextMap.set(112, ['F21']);
|
||||||
this.scanCodeTextMap.set(113, ['F22']);
|
this.basicScanCodeTextMap.set(113, ['F22']);
|
||||||
this.scanCodeTextMap.set(114, ['F23']);
|
this.basicScanCodeTextMap.set(114, ['F23']);
|
||||||
this.scanCodeTextMap.set(115, ['F24']);
|
this.basicScanCodeTextMap.set(115, ['F24']);
|
||||||
this.scanCodeTextMap.set(118, ['Menu']);
|
this.basicScanCodeTextMap.set(118, ['Menu']);
|
||||||
this.scanCodeTextMap.set(176, ['00']);
|
this.basicScanCodeTextMap.set(176, ['00']);
|
||||||
this.scanCodeTextMap.set(177, ['000']);
|
this.basicScanCodeTextMap.set(177, ['000']);
|
||||||
this.scanCodeTextMap.set(232, ['Play']);
|
|
||||||
this.scanCodeTextMap.set(233, ['Stop']);
|
this.mediaScanCodeTextMap = new Map<number, string[]>();
|
||||||
this.scanCodeTextMap.set(234, ['Prev']);
|
this.mediaScanCodeTextMap.set(226, ['Mute']);
|
||||||
this.scanCodeTextMap.set(235, ['Next']);
|
this.mediaScanCodeTextMap.set(232, ['Play']);
|
||||||
this.scanCodeTextMap.set(236, ['Eject']);
|
this.mediaScanCodeTextMap.set(233, ['Stop']);
|
||||||
this.scanCodeTextMap.set(237, ['Vol +']);
|
this.mediaScanCodeTextMap.set(234, ['Prev']);
|
||||||
this.scanCodeTextMap.set(238, ['Vol -']);
|
this.mediaScanCodeTextMap.set(235, ['Next']);
|
||||||
this.scanCodeTextMap.set(239, ['Mute']);
|
this.mediaScanCodeTextMap.set(236, ['Eject']);
|
||||||
this.scanCodeTextMap.set(240, ['WWW']);
|
this.mediaScanCodeTextMap.set(237, ['Vol +']);
|
||||||
this.scanCodeTextMap.set(241, ['Bckwrd']);
|
this.mediaScanCodeTextMap.set(238, ['Vol -']);
|
||||||
this.scanCodeTextMap.set(242, ['Frwrd']);
|
this.mediaScanCodeTextMap.set(240, ['WWW']);
|
||||||
this.scanCodeTextMap.set(243, ['Cancel']);
|
this.mediaScanCodeTextMap.set(241, ['Bckwrd']);
|
||||||
|
this.mediaScanCodeTextMap.set(242, ['Frwrd']);
|
||||||
|
this.mediaScanCodeTextMap.set(243, ['Cancel']);
|
||||||
}
|
}
|
||||||
|
|
||||||
private initScanCodeFileName(): void {
|
private initScanCodeFileName(): void {
|
||||||
|
|||||||
Reference in New Issue
Block a user