diff --git a/packages/core/src/browser/keybinding.spec.ts b/packages/core/src/browser/keybinding.spec.ts index a7f0e2614859f..e467e7098772a 100644 --- a/packages/core/src/browser/keybinding.spec.ts +++ b/packages/core/src/browser/keybinding.spec.ts @@ -497,18 +497,23 @@ describe('keys api', () => { }); it('it should be a modifier only', () => { - const keyCode = KeyCode.createKeyCode({ modifiers: [KeyModifier.CtrlCmd] }); expect(keyCode).to.be.deep.equal(KeyCode.createKeyCode({ modifiers: [KeyModifier.CtrlCmd] })); expect(keyCode.isModifierOnly()).to.be.true; }); it('it should be multiple modifiers only', () => { - const keyCode = KeyCode.createKeyCode({ modifiers: [KeyModifier.CtrlCmd, KeyModifier.Alt] }); expect(keyCode).to.be.deep.equal(KeyCode.createKeyCode({ modifiers: [KeyModifier.CtrlCmd, KeyModifier.Alt] })); expect(keyCode.isModifierOnly()).to.be.true; }); + + it('it should translate non US layout chords properly', () => { + // mimic a german layout, i.e. the '/' is on the 'Shift+7'. + const keyCode = new KeyCode(KeyCode.parse('ctrlcmd+shift+7').keystroke, '/'); + const normalized = keyCode.normalizeToUsLayout(); + expect(normalized).to.be.deep.equal(KeyCode.parse('ctrlcmd+/')); + }); }); const TEST_COMMAND: Command = { diff --git a/packages/core/src/browser/keybinding.ts b/packages/core/src/browser/keybinding.ts index 4f950c53041d0..e18c354482271 100644 --- a/packages/core/src/browser/keybinding.ts +++ b/packages/core/src/browser/keybinding.ts @@ -290,27 +290,39 @@ export class KeybindingRegistry { protected getKeySequenceCollisions(bindings: Keybinding[], keySequence: KeyCode[]): KeybindingRegistry.KeybindingsResult { const result = new KeybindingRegistry.KeybindingsResult(); - for (const registeredBinding of bindings) { - try { - const bindingKeySequence = KeySequence.parse(registeredBinding.keybinding); - const compareResult = KeySequence.compare(keySequence, bindingKeySequence); - switch (compareResult) { - case KeySequence.CompareResult.FULL: { - result.full.push(registeredBinding); - break; - } - case KeySequence.CompareResult.PARTIAL: { - result.partial.push(registeredBinding); - break; - } - case KeySequence.CompareResult.SHADOW: { - result.shadow.push(registeredBinding); - break; - } - default: { - break; + /** + * compare the given KeySequence with a particular binding + */ + function compareBinding(candidate: KeyCode[], binding: Keybinding) { + const bindingKeySequence = KeySequence.parse(binding.keybinding); + const compareResult = KeySequence.compare(candidate, bindingKeySequence); + switch (compareResult) { + case KeySequence.CompareResult.FULL: { + result.full.push(binding); + break; + } + case KeySequence.CompareResult.PARTIAL: { + result.partial.push(binding); + break; + } + case KeySequence.CompareResult.SHADOW: { + result.shadow.push(binding); + break; + } + default: { + // no match. Let's try with a US keborad normalized version if there is one. + const normalizedUs = candidate.map(k => k.normalizeToUsLayout()); + if (normalizedUs.indexOf(undefined) === -1) { + compareBinding(normalizedUs as KeyCode[], binding); } + break; } + } + } + + for (const registeredBinding of bindings) { + try { + compareBinding(keySequence, registeredBinding); } catch (error) { this.logger.warn(error); } diff --git a/packages/core/src/browser/keys.ts b/packages/core/src/browser/keys.ts index 72d2945f898c3..f1da38996ff5d 100644 --- a/packages/core/src/browser/keys.ts +++ b/packages/core/src/browser/keys.ts @@ -194,6 +194,30 @@ export class KeyCode { } } + public normalizeToUsLayout(): KeyCode | undefined { + if (this.shift && this.character && EASY_TO_KEY[this.character]) { + const modifiers: KeyModifier[] = []; + if (isOSX) { + if (this.meta) { + modifiers.push(KeyModifier.CtrlCmd); + } + if (this.ctrl) { + modifiers.push(KeyModifier.MacCtrl); + } + } else { + if (this.ctrl) { + modifiers.push(KeyModifier.CtrlCmd); + } + } + if (this.alt) { + modifiers.push(KeyModifier.Alt); + } + + return KeyCode.createKeyCode({ first: EASY_TO_KEY[this.character], modifiers }); + } + return undefined; + } + /* Return true of string is a modifier M1 to M4 */ public static isModifierString(key: string) { if (key === KeyModifier.CtrlCmd