diff --git a/src/vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts b/src/vs/workbench/services/keybinding/common/macLinuxKeyboardMapper.ts index aca99296aeb0114006a068423f51700eca3ac44a..5953ce2b8c32fe77b07351333d18dec329f0daad 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 { UILabelProvider, AriaLabelProvider, UserSettingsLabelProvider, ElectronAcceleratorLabelProvider, NO_MODIFIERS } from 'vs/platform/keybinding/common/keybindingLabels'; import { IKeyboardMapper } from 'vs/workbench/services/keybinding/common/keyboardMapper'; @@ -1055,6 +1055,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 bc4545febce198dfef9806a1319f626b8422b73d..a264847b1275b794065010cf05e74e7d2d044359 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 728dec806f0c90640548333b0648889de6c5f2f4..76706a750f28fb1235d5281f45f4486e9f7a3a00 100644 --- a/src/vs/workbench/services/keybinding/test/macLinuxKeyboardMapper.test.ts +++ b/src/vs/workbench/services/keybinding/test/macLinuxKeyboardMapper.test.ts @@ -1599,6 +1599,51 @@ suite('keyboardMapper', () => { ); }); + test('issue #24064: NumLock/NumPad keys stopped working in 1.11 on Linux', () => { + let mapper = new MacLinuxKeyboardMapper(false, {}, 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, + labelWithoutModifiers: label, + ariaLabelWithoutModifiers: 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', () => {