From 9f34837ca58ebc9900d0cb8cd4b43b681ff8f3b1 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Mon, 10 Apr 2017 16:54:02 +0200 Subject: [PATCH] Fixes #24064: NumLock/NumPad keys stopped working in 1.11 on Linux --- .../common/macLinuxKeyboardMapper.ts | 25 +++++++++- .../services/keybinding/common/scanCode.ts | 25 +++++++++- .../test/macLinuxKeyboardMapper.test.ts | 48 +++++++++++++++++++ 3 files changed, 96 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts b/src/vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts index 632abe886260e..4c32ee2ed6066 100644 --- a/src/vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts +++ b/src/vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts @@ -7,7 +7,7 @@ import { OperatingSystem } from 'vs/base/common/platform'; import { KeyCode, ResolvedKeybinding, KeyCodeUtils, SimpleKeybinding, Keybinding, KeybindingType, USER_SETTINGS } from 'vs/base/common/keyCodes'; -import { ScanCode, ScanCodeUtils, IMMUTABLE_CODE_TO_KEY_CODE, ScanCodeBinding } from 'vs/workbench/services/keybinding/common/scanCode'; +import { ScanCode, ScanCodeUtils, IMMUTABLE_CODE_TO_KEY_CODE, IMMUTABLE_KEY_CODE_TO_CODE, ScanCodeBinding } from 'vs/workbench/services/keybinding/common/scanCode'; import { CharCode } from 'vs/base/common/charCode'; import { IHTMLContentElement } from 'vs/base/common/htmlContent'; import { UILabelProvider, AriaLabelProvider, UserSettingsLabelProvider, ElectronAcceleratorLabelProvider } from 'vs/platform/keybinding/common/keybindingLabels'; @@ -1046,6 +1046,29 @@ export class MacLinuxKeyboardMapper implements IKeyboardMapper { if (code === ScanCode.NumpadEnter) { code = ScanCode.Enter; } + + if ( + (code === ScanCode.Numpad1) + || (code === ScanCode.Numpad2) + || (code === ScanCode.Numpad3) + || (code === ScanCode.Numpad4) + || (code === ScanCode.Numpad5) + || (code === ScanCode.Numpad6) + || (code === ScanCode.Numpad7) + || (code === ScanCode.Numpad8) + || (code === ScanCode.Numpad9) + || (code === ScanCode.Numpad0) + || (code === ScanCode.NumpadDecimal) + ) { + // "Dispatch" on keyCode for all numpad keys in order for NumLock to work correctly + if (keyboardEvent.keyCode >= 0) { + const immutableScanCode = IMMUTABLE_KEY_CODE_TO_CODE[keyboardEvent.keyCode]; + if (immutableScanCode !== -1) { + code = immutableScanCode; + } + } + } + const keypress = new ScanCodeBinding(keyboardEvent.ctrlKey, keyboardEvent.shiftKey, keyboardEvent.altKey, keyboardEvent.metaKey, code); return new NativeResolvedKeybinding(this, this._OS, keypress, null); } diff --git a/src/vs/workbench/services/keybinding/common/scanCode.ts b/src/vs/workbench/services/keybinding/common/scanCode.ts index bc4545febce19..a264847b1275b 100644 --- a/src/vs/workbench/services/keybinding/common/scanCode.ts +++ b/src/vs/workbench/services/keybinding/common/scanCode.ts @@ -220,10 +220,15 @@ export const ScanCodeUtils = { }; /** - * -1 if a HwCode => KeyCode mapping depends on kb layout. + * -1 if a ScanCode => KeyCode mapping depends on kb layout. */ export const IMMUTABLE_CODE_TO_KEY_CODE: KeyCode[] = []; +/** + * -1 if a KeyCode => ScanCode mapping depends on kb layout. + */ +export const IMMUTABLE_KEY_CODE_TO_CODE: ScanCode[] = []; + export class ScanCodeBinding { public readonly ctrlKey: boolean; public readonly shiftKey: boolean; @@ -468,10 +473,28 @@ export class ScanCodeBinding { IMMUTABLE_CODE_TO_KEY_CODE[i] = -1; } + for (let i = 0; i <= KeyCode.MAX_VALUE; i++) { + IMMUTABLE_KEY_CODE_TO_CODE[i] = -1; + } + function define(code: ScanCode, keyCode: KeyCode): void { IMMUTABLE_CODE_TO_KEY_CODE[code] = keyCode; + + if ( + (keyCode !== KeyCode.Unknown) + && (keyCode !== KeyCode.Enter) + && (keyCode !== KeyCode.Ctrl) + && (keyCode !== KeyCode.Shift) + && (keyCode !== KeyCode.Alt) + && (keyCode !== KeyCode.Meta) + ) { + IMMUTABLE_KEY_CODE_TO_CODE[keyCode] = code; + } } + // Manually added due to the exclusion above (due to duplication with NumpadEnter) + IMMUTABLE_KEY_CODE_TO_CODE[KeyCode.Enter] = ScanCode.Enter; + define(ScanCode.None, KeyCode.Unknown); define(ScanCode.Hyper, KeyCode.Unknown); define(ScanCode.Super, KeyCode.Unknown); diff --git a/src/vs/workbench/services/keybinding/test/macLinuxKeyboardMapper.test.ts b/src/vs/workbench/services/keybinding/test/macLinuxKeyboardMapper.test.ts index 5a9fe60aaeb6c..7f334513a925a 100644 --- a/src/vs/workbench/services/keybinding/test/macLinuxKeyboardMapper.test.ts +++ b/src/vs/workbench/services/keybinding/test/macLinuxKeyboardMapper.test.ts @@ -1575,6 +1575,54 @@ suite('keyboardMapper', () => { ); }); + test('issue #24064: NumLock/NumPad keys stopped working in 1.11 on Linux', () => { + let mapper = new MacLinuxKeyboardMapper(false, {}, OperatingSystem.Linux); + + function _simpleHTMLLabel(pieces: string[]): IHTMLContentElement { + return simpleHTMLLabel(pieces, OperatingSystem.Linux); + } + + function assertNumpadKeyboardEvent(keyCode: KeyCode, code: string, label: string, electronAccelerator: string, userSettingsLabel: string, dispatch: string): void { + assertResolveKeyboardEvent( + mapper, + { + ctrlKey: false, + shiftKey: false, + altKey: false, + metaKey: false, + keyCode: keyCode, + code: code + }, + { + label: label, + ariaLabel: label, + HTMLLabel: [_simpleHTMLLabel([label])], + electronAccelerator: electronAccelerator, + userSettingsLabel: userSettingsLabel, + isWYSIWYG: true, + isChord: false, + hasCtrlModifier: false, + hasShiftModifier: false, + hasAltModifier: false, + hasMetaModifier: false, + dispatchParts: [dispatch, null], + } + ); + } + + assertNumpadKeyboardEvent(KeyCode.End, 'Numpad1', 'End', 'End', 'end', '[End]'); + assertNumpadKeyboardEvent(KeyCode.DownArrow, 'Numpad2', 'DownArrow', 'Down', 'down', '[ArrowDown]'); + assertNumpadKeyboardEvent(KeyCode.PageDown, 'Numpad3', 'PageDown', 'PageDown', 'pagedown', '[PageDown]'); + assertNumpadKeyboardEvent(KeyCode.LeftArrow, 'Numpad4', 'LeftArrow', 'Left', 'left', '[ArrowLeft]'); + assertNumpadKeyboardEvent(KeyCode.Unknown, 'Numpad5', 'NumPad5', null, 'numpad5', '[Numpad5]'); + assertNumpadKeyboardEvent(KeyCode.RightArrow, 'Numpad6', 'RightArrow', 'Right', 'right', '[ArrowRight]'); + assertNumpadKeyboardEvent(KeyCode.Home, 'Numpad7', 'Home', 'Home', 'home', '[Home]'); + assertNumpadKeyboardEvent(KeyCode.UpArrow, 'Numpad8', 'UpArrow', 'Up', 'up', '[ArrowUp]'); + assertNumpadKeyboardEvent(KeyCode.PageUp, 'Numpad9', 'PageUp', 'PageUp', 'pageup', '[PageUp]'); + assertNumpadKeyboardEvent(KeyCode.Insert, 'Numpad0', 'Insert', 'Insert', 'insert', '[Insert]'); + assertNumpadKeyboardEvent(KeyCode.Delete, 'NumpadDecimal', 'Delete', 'Delete', 'delete', '[Delete]'); + }); + }); suite('keyboardMapper - LINUX ru', () => {