authorgravatar for 153842990+yashranaway@users.noreply.github.comAditya Garud <153842990+yashranaway@users.noreply.github.com> 2026-08-15 18:03:52+05:30
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-08-15 12:33:52+00:00
log664499c92e838f36a0ff8187bc2cd95d7b8ef9d5
treebbc5764f1f50dcf4eb346093a7bf7069e98a70b8
parent931e91527c285c49d8482328877c93c8c684591a
signature Signed by PGP key B5690EEEBB952194

Limit physical key fallback to non-Latin layout output (#4469)


2 files changed, 37 insertions(+), 2 deletions(-)

apps/web/src/keybindings.test.ts+29
......@@ -728,6 +728,35 @@ describe("resolveShortcutCommand", () => {
728728 "rightPanel.toggle",
729729 );
730730 });
731
732 it("matches non-Latin layout letters using the physical key code", () => {
733 const keybindings = compile([{ shortcut: modShortcut("d"), command: "diff.toggle" }]);
734
735 assert.strictEqual(
736 resolveShortcutCommand(event({ key: "в", code: "KeyD", metaKey: true }), keybindings, {
737 platform: "MacIntel",
738 }),
739 "diff.toggle",
740 );
741 });
742
743 it("ignores the physical key code when the layout types a different Latin letter", () => {
744 const keybindings = compile([{ shortcut: modShortcut("d"), command: "diff.toggle" }]);
745
746 // On a remapped layout the physical D key types "a"; only the physical
747 // key whose layout output is "d" may trigger the shortcut.
748 assert.isNull(
749 resolveShortcutCommand(event({ key: "a", code: "KeyD", metaKey: true }), keybindings, {
750 platform: "MacIntel",
751 }),
752 );
753 assert.strictEqual(
754 resolveShortcutCommand(event({ key: "d", code: "KeyL", metaKey: true }), keybindings, {
755 platform: "MacIntel",
756 }),
757 "diff.toggle",
758 );
759 });
731760});
732761
733762describe("formatShortcutLabel", () => {
apps/web/src/keybindings.ts+8-2
......@@ -71,9 +71,15 @@ function normalizeEventKey(key: string): string {
7171}
7272
7373function resolveEventKeys(event: ShortcutEventLike): Set<string> {
74 const keys = new Set([normalizeEventKey(event.key)]);
74 const layoutKey = normalizeEventKey(event.key);
75 const keys = new Set([layoutKey]);
76 // The physical-position fallback exists for layouts that type non-Latin
77 // letters (Cyrillic, Greek) and for Option-modified symbols on macOS.
78 // When the layout already produces a Latin letter, match on it alone;
79 // otherwise a remapped physical key triggers shortcuts for two different
80 // letters at once and shadows system shortcuts on non-QWERTY layouts.
7581 const letterCode = event.code?.match(/^Key([A-Z])$/)?.[1];
76 if (letterCode) {
82 if (letterCode && !/^[a-z]$/.test(layoutKey)) {
7783 keys.add(letterCode.toLowerCase());
7884 }
7985 const aliases = event.code ? EVENT_CODE_KEY_ALIASES[event.code] : undefined;