提交 f8faa583 编写于 作者: A Alex Dima

Extract ScanCodeKeyCodeMapper out of MacLinuxKeyboardMapper

上级 969cbdfe
...@@ -157,6 +157,137 @@ interface IScanCodeMapping { ...@@ -157,6 +157,137 @@ interface IScanCodeMapping {
withShiftAltGr: number; withShiftAltGr: number;
} }
class ScanCodeCombo {
public readonly ctrlKey: boolean;
public readonly shiftKey: boolean;
public readonly altKey: boolean;
public readonly scanCode: ScanCode;
constructor(ctrlKey: boolean, shiftKey: boolean, altKey: boolean, scanCode: ScanCode) {
this.ctrlKey = ctrlKey;
this.shiftKey = shiftKey;
this.altKey = altKey;
this.scanCode = scanCode;
}
}
class KeyCodeCombo {
public readonly ctrlKey: boolean;
public readonly shiftKey: boolean;
public readonly altKey: boolean;
public readonly keyCode: KeyCode;
constructor(ctrlKey: boolean, shiftKey: boolean, altKey: boolean, keyCode: KeyCode) {
this.ctrlKey = ctrlKey;
this.shiftKey = shiftKey;
this.altKey = altKey;
this.keyCode = keyCode;
}
}
class ScanCodeKeyCodeMapper {
/**
* ScanCode combination => KeyCode combination.
* Only covers relevant modifiers ctrl, shift, alt (since meta does not influence the mappings).
*/
private readonly _scanCodeToKeyCode: number[] = [];
/**
* inverse of `_scanCodeToKeyCode`.
* KeyCode combination => ScanCode combination.
* Only covers relevant modifiers ctrl, shift, alt (since meta does not influence the mappings).
*/
private readonly _keyCodeToScanCode: number[][] = [];
constructor() {
this._scanCodeToKeyCode = [];
this._keyCodeToScanCode = [];
}
public checkComplete(): void {
for (let i = 0; i < ScanCode.MAX_VALUE; i++) {
let base = (i << 3);
for (let j = 0; j < 8; j++) {
let actual = base + j;
let entry = this._scanCodeToKeyCode[actual];
if (typeof entry === 'undefined') {
log(`${ScanCodeUtils.toString(i)} - ${j.toString(2)} --- is missing`);
}
}
}
}
public registerIfUnknown(scanCodeCombo: ScanCodeCombo, keyCodeCombo: KeyCodeCombo): void {
const scanCodeComboEncoded = this._encodeScanCodeCombo(scanCodeCombo);
const keyCodeComboEncoded = this._encodeKeyCodeCombo(keyCodeCombo);
let existing = this._scanCodeToKeyCode[scanCodeComboEncoded] | 0;
let existingKeyCode: KeyCode = (existing >>> 3);
if (existingKeyCode !== KeyCode.Unknown) {
return;
}
this._scanCodeToKeyCode[scanCodeComboEncoded] = keyCodeComboEncoded;
if (keyCodeCombo.keyCode !== KeyCode.Unknown) {
// Do not save an inverse lookup for Unknown
this._keyCodeToScanCode[keyCodeComboEncoded] = this._keyCodeToScanCode[keyCodeComboEncoded] || [];
this._keyCodeToScanCode[keyCodeComboEncoded].unshift(scanCodeComboEncoded);
}
}
public lookupKeyCodeCombo(keyCodeCombo: KeyCodeCombo): ScanCodeCombo[] {
const keyCodeComboEncoded = this._encodeKeyCodeCombo(keyCodeCombo);
const scanCodeCombosEncoded = this._keyCodeToScanCode[keyCodeComboEncoded];
if (!scanCodeCombosEncoded || scanCodeCombosEncoded.length === 0) {
return [];
}
let result: ScanCodeCombo[] = [];
for (let i = 0, len = scanCodeCombosEncoded.length; i < len; i++) {
const scanCodeComboEncoded = scanCodeCombosEncoded[i];
const ctrlKey = (scanCodeComboEncoded & 0b001) ? true : false;
const shiftKey = (scanCodeComboEncoded & 0b010) ? true : false;
const altKey = (scanCodeComboEncoded & 0b100) ? true : false;
const scanCode: ScanCode = (scanCodeComboEncoded >>> 3);
result[i] = new ScanCodeCombo(ctrlKey, shiftKey, altKey, scanCode);
}
return result;
}
public lookupScanCodeCombo(scanCodeCombo: ScanCodeCombo): KeyCodeCombo {
const scanCodeComboEncoded = this._encodeScanCodeCombo(scanCodeCombo);
const keyCodeComboEncoded = this._scanCodeToKeyCode[scanCodeComboEncoded] | 0;
const ctrlKey = (keyCodeComboEncoded & 0b001) ? true : false;
const shiftKey = (keyCodeComboEncoded & 0b010) ? true : false;
const altKey = (keyCodeComboEncoded & 0b100) ? true : false;
const keyCode: KeyCode = (keyCodeComboEncoded >>> 3);
return new KeyCodeCombo(ctrlKey, shiftKey, altKey, keyCode);
}
private _encodeScanCodeCombo(scanCodeCombo: ScanCodeCombo): number {
return this._encode(scanCodeCombo.ctrlKey, scanCodeCombo.shiftKey, scanCodeCombo.altKey, scanCodeCombo.scanCode);
}
private _encodeKeyCodeCombo(keyCodeCombo: KeyCodeCombo): number {
return this._encode(keyCodeCombo.ctrlKey, keyCodeCombo.shiftKey, keyCodeCombo.altKey, keyCodeCombo.keyCode);
}
private _encode(ctrlKey: boolean, shiftKey: boolean, altKey: boolean, principal: number): number {
return (
((ctrlKey ? 1 : 0) << 0)
| ((shiftKey ? 1 : 0) << 1)
| ((altKey ? 1 : 0) << 2)
| principal << 3
) >>> 0;
}
}
export class MacLinuxKeyboardMapper implements IKeyboardMapper { export class MacLinuxKeyboardMapper implements IKeyboardMapper {
/** /**
...@@ -172,16 +303,9 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper { ...@@ -172,16 +303,9 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
*/ */
private readonly _codeInfo: IScanCodeMapping[]; private readonly _codeInfo: IScanCodeMapping[];
/** /**
* ScanCode combination => KeyCode combination. * Maps ScanCode combos <-> KeyCode combos.
* Only covers relevant modifiers ctrl, shift, alt (since meta does not influence the mappings).
*/ */
private readonly _scanCodeToKeyCode: number[] = []; private readonly _scanCodeKeyCodeMapper: ScanCodeKeyCodeMapper;
/**
* inverse of `_scanCodeToKeyCode`.
* KeyCode combination => ScanCode combination.
* Only covers relevant modifiers ctrl, shift, alt (since meta does not influence the mappings).
*/
private readonly _keyCodeToScanCode: number[][] = [];
/** /**
* UI label for a ScanCode. * UI label for a ScanCode.
*/ */
...@@ -194,9 +318,8 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper { ...@@ -194,9 +318,8 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
constructor(rawMappings: IMacLinuxKeyboardMapping, OS: OperatingSystem) { constructor(rawMappings: IMacLinuxKeyboardMapping, OS: OperatingSystem) {
this._rawMappings = rawMappings; this._rawMappings = rawMappings;
this._OS = OS; this._OS = OS;
this._codeInfo = [];
this._scanCodeToKeyCode = []; this._scanCodeKeyCodeMapper = new ScanCodeKeyCodeMapper();
this._keyCodeToScanCode = [];
this._scanCodeToLabel = []; this._scanCodeToLabel = [];
this._scanCodeToDispatch = []; this._scanCodeToDispatch = [];
...@@ -214,7 +337,6 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper { ...@@ -214,7 +337,6 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
} }
} }
this._codeInfo = [];
let mappings: IScanCodeMapping[] = [], mappingsLen = 0; let mappings: IScanCodeMapping[] = [], mappingsLen = 0;
for (let strScanCode in rawMappings) { for (let strScanCode in rawMappings) {
if (rawMappings.hasOwnProperty(strScanCode)) { if (rawMappings.hasOwnProperty(strScanCode)) {
...@@ -290,7 +412,7 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper { ...@@ -290,7 +412,7 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
const mapping = mappings[i]; const mapping = mappings[i];
this._registerCharCode(mapping.scanCode, false, false, false, mapping.value); this._registerCharCode(mapping.scanCode, false, false, false, mapping.value);
} }
// // Handle all left-over available digits // Handle all left-over available digits
this._registerAllCombos1(false, false, false, ScanCode.Digit1, KeyCode.KEY_1); this._registerAllCombos1(false, false, false, ScanCode.Digit1, KeyCode.KEY_1);
this._registerAllCombos1(false, false, false, ScanCode.Digit2, KeyCode.KEY_2); this._registerAllCombos1(false, false, false, ScanCode.Digit2, KeyCode.KEY_2);
this._registerAllCombos1(false, false, false, ScanCode.Digit3, KeyCode.KEY_3); this._registerAllCombos1(false, false, false, ScanCode.Digit3, KeyCode.KEY_3);
...@@ -302,16 +424,7 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper { ...@@ -302,16 +424,7 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
this._registerAllCombos1(false, false, false, ScanCode.Digit9, KeyCode.KEY_9); this._registerAllCombos1(false, false, false, ScanCode.Digit9, KeyCode.KEY_9);
this._registerAllCombos1(false, false, false, ScanCode.Digit0, KeyCode.KEY_0); this._registerAllCombos1(false, false, false, ScanCode.Digit0, KeyCode.KEY_0);
for (let i = 0; i < ScanCode.MAX_VALUE; i++) { this._scanCodeKeyCodeMapper.checkComplete();
let base = (i << 3);
for (let j = 0; j < 8; j++) {
let actual = base + j;
let entry = this._scanCodeToKeyCode[actual];
if (typeof entry === 'undefined') {
log(`${ScanCodeUtils.toString(i)} - ${j.toString(2)} --- is missing`);
}
}
}
} }
public dumpRawDebugInfo(): string { public dumpRawDebugInfo(): string {
...@@ -339,9 +452,9 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper { ...@@ -339,9 +452,9 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
const uiLabel = this._scanCodeToLabel[scanCode]; const uiLabel = this._scanCodeToLabel[scanCode];
for (let mod = 0; mod < 8; mod++) { for (let mod = 0; mod < 8; mod++) {
const hwCtrlKey = (mod & 0b0001) ? true : false; const hwCtrlKey = (mod & 0b001) ? true : false;
const hwShiftKey = (mod & 0b0010) ? true : false; const hwShiftKey = (mod & 0b010) ? true : false;
const hwAltKey = (mod & 0b0100) ? true : false; const hwAltKey = (mod & 0b100) ? true : false;
const strHw = `${hwCtrlKey ? 'Ctrl+' : ''}${hwShiftKey ? 'Shift+' : ''}${hwAltKey ? 'Alt+' : ''}${strCode}`; const strHw = `${hwCtrlKey ? 'Ctrl+' : ''}${hwShiftKey ? 'Shift+' : ''}${hwAltKey ? 'Alt+' : ''}${strCode}`;
const uiHwLabel = `${hwCtrlKey ? 'Ctrl+' : ''}${hwShiftKey ? 'Shift+' : ''}${hwAltKey ? 'Alt+' : ''}${uiLabel}`; const uiHwLabel = `${hwCtrlKey ? 'Ctrl+' : ''}${hwShiftKey ? 'Shift+' : ''}${hwAltKey ? 'Alt+' : ''}${uiLabel}`;
...@@ -367,13 +480,10 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper { ...@@ -367,13 +480,10 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
} }
} }
const hwEncoded = this._encode(hwCtrlKey, hwShiftKey, hwAltKey, scanCode); const hwCombo = new ScanCodeCombo(hwCtrlKey, hwShiftKey, hwAltKey, scanCode);
const kbEncoded = this._scanCodeToKeyCode[hwEncoded]; const kbCombo = this._scanCodeKeyCodeMapper.lookupScanCodeCombo(hwCombo);
const kbCtrlKey = (kbEncoded & 0b0001) ? true : false;
const kbShiftKey = (kbEncoded & 0b0010) ? true : false; const strKb = `${kbCombo.ctrlKey ? 'Ctrl+' : ''}${kbCombo.shiftKey ? 'Shift+' : ''}${kbCombo.altKey ? 'Alt+' : ''}${KeyCodeUtils.toString(kbCombo.keyCode)}`;
const kbAltKey = (kbEncoded & 0b0100) ? true : false;
const keyCode = (kbEncoded >>> 3);
const strKb = `${kbCtrlKey ? 'Ctrl+' : ''}${kbShiftKey ? 'Shift+' : ''}${kbAltKey ? 'Alt+' : ''}${KeyCodeUtils.toString(keyCode)}`;
const hwKeyPress = new ScanCodePress(hwCtrlKey, hwShiftKey, hwAltKey, false, scanCode); const hwKeyPress = new ScanCodePress(hwCtrlKey, hwShiftKey, hwAltKey, false, scanCode);
const dispatchStr = this.getDispatchStrForScanCodePress(hwKeyPress); const dispatchStr = this.getDispatchStrForScanCodePress(hwKeyPress);
...@@ -401,23 +511,10 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper { ...@@ -401,23 +511,10 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
hwCtrlKey: boolean, hwShiftKey: boolean, hwAltKey: boolean, scanCode: ScanCode, hwCtrlKey: boolean, hwShiftKey: boolean, hwAltKey: boolean, scanCode: ScanCode,
kbCtrlKey: boolean, kbShiftKey: boolean, kbAltKey: boolean, keyCode: KeyCode, kbCtrlKey: boolean, kbShiftKey: boolean, kbAltKey: boolean, keyCode: KeyCode,
): void { ): void {
let hwEncoded = this._encode(hwCtrlKey, hwShiftKey, hwAltKey, scanCode); this._scanCodeKeyCodeMapper.registerIfUnknown(
let kbEncoded = this._encode(kbCtrlKey, kbShiftKey, kbAltKey, keyCode); new ScanCodeCombo(hwCtrlKey, hwShiftKey, hwAltKey, scanCode),
new KeyCodeCombo(kbCtrlKey, kbShiftKey, kbAltKey, keyCode)
let existing = this._scanCodeToKeyCode[hwEncoded] | 0; );
let existingKeyCode = existing >>> 3;
if (existingKeyCode !== 0) {
return;
}
this._scanCodeToKeyCode[hwEncoded] = kbEncoded;
if (keyCode !== KeyCode.Unknown) {
// Do not save an inverse lookup for Unknown
this._keyCodeToScanCode[kbEncoded] = this._keyCodeToScanCode[kbEncoded] || [];
this._keyCodeToScanCode[kbEncoded].unshift(hwEncoded);
}
} }
private _registerAllCombos1( private _registerAllCombos1(
...@@ -499,14 +596,14 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper { ...@@ -499,14 +596,14 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
} }
public simpleKeybindingToScanCodePress(keybinding: SimpleKeybinding): ScanCodePress[] { public simpleKeybindingToScanCodePress(keybinding: SimpleKeybinding): ScanCodePress[] {
const kbEncoded = this._encode(keybinding.ctrlKey, keybinding.shiftKey, keybinding.altKey, keybinding.keyCode); const scanCodeCombos = this._scanCodeKeyCodeMapper.lookupKeyCodeCombo(
const hwEncoded = this._keyCodeToScanCode[kbEncoded]; new KeyCodeCombo(keybinding.ctrlKey, keybinding.shiftKey, keybinding.altKey, keybinding.keyCode)
);
let result: ScanCodePress[] = []; let result: ScanCodePress[] = [];
if (hwEncoded) { for (let i = 0, len = scanCodeCombos.length; i < len; i++) {
for (let i = 0, len = hwEncoded.length; i < len; i++) { const scanCodeCombo = scanCodeCombos[i];
result[i] = this._decodeHw(hwEncoded[i], keybinding.metaKey); result[i] = new ScanCodePress(scanCodeCombo.ctrlKey, scanCodeCombo.shiftKey, scanCodeCombo.altKey, keybinding.metaKey, scanCodeCombo.scanCode);
}
} }
return result; return result;
} }
...@@ -626,18 +723,21 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper { ...@@ -626,18 +723,21 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
// Check if this scanCode always maps to the same keyCode and back // Check if this scanCode always maps to the same keyCode and back
let constantKeyCode: KeyCode = -1; let constantKeyCode: KeyCode = -1;
for (let mod = 0; mod < 8; mod++) { for (let mod = 0; mod < 8; mod++) {
const hwEncoded = ((scanCode << 3) + mod) >>> 0; const hwCtrlKey = (mod & 0b001) ? true : false;
const kbEncoded = this._scanCodeToKeyCode[hwEncoded]; const hwShiftKey = (mod & 0b010) ? true : false;
const keyCode = (kbEncoded >>> 3); const hwAltKey = (mod & 0b100) ? true : false;
const hwCombo = new ScanCodeCombo(hwCtrlKey, hwShiftKey, hwAltKey, scanCode);
const kbCombo = this._scanCodeKeyCodeMapper.lookupScanCodeCombo(hwCombo);
if (keyCode === KeyCode.Unknown) { if (kbCombo.keyCode === KeyCode.Unknown) {
// maps to unknown keyCode // maps to unknown keyCode
return -1; return -1;
} }
if (constantKeyCode === -1) { if (constantKeyCode === -1) {
constantKeyCode = keyCode; constantKeyCode = kbCombo.keyCode;
} else if (constantKeyCode !== keyCode) { } else if (constantKeyCode !== kbCombo.keyCode) {
// maps to different keyCode // maps to different keyCode
return -1; return -1;
} }
...@@ -712,24 +812,6 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper { ...@@ -712,24 +812,6 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper {
} }
return charCode; return charCode;
} }
private _encode(ctrlKey: boolean, shiftKey: boolean, altKey: boolean, principal: number): number {
return (
((ctrlKey ? 1 : 0) << 0)
| ((shiftKey ? 1 : 0) << 1)
| ((altKey ? 1 : 0) << 2)
| principal << 3
) >>> 0;
}
private _decodeHw(hwEncoded: number, metaKey: boolean): ScanCodePress {
const ctrlKey = (hwEncoded & 0b0001) ? true : false;
const shiftKey = (hwEncoded & 0b0010) ? true : false;
const altKey = (hwEncoded & 0b0100) ? true : false;
const scanCode = (hwEncoded >>> 3);
return new ScanCodePress(ctrlKey, shiftKey, altKey, metaKey, scanCode);
}
} }
(function () { (function () {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册