diff --git a/apps/client/src/services/shortcuts.spec.ts b/apps/client/src/services/shortcuts.spec.ts index ec9a0a581..d22a1e081 100644 --- a/apps/client/src/services/shortcuts.spec.ts +++ b/apps/client/src/services/shortcuts.spec.ts @@ -119,11 +119,6 @@ describe("shortcuts", () => { metaKey: options.metaKey || false } as KeyboardEvent); - it("should match simple key shortcuts", () => { - const event = createKeyboardEvent({ key: "a", code: "KeyA" }); - expect(matchesShortcut(event, "a")).toBe(true); - }); - it("should match shortcuts with modifiers", () => { const event = createKeyboardEvent({ key: "a", code: "KeyA", ctrlKey: true }); expect(matchesShortcut(event, "ctrl+a")).toBe(true); @@ -148,6 +143,11 @@ describe("shortcuts", () => { expect(matchesShortcut(event, "a")).toBe(false); }); + it("should not match when no modifiers are used", () => { + const event = createKeyboardEvent({ key: "a", code: "KeyA" }); + expect(matchesShortcut(event, "a")).toBe(false); + }); + it("should handle alternative modifier names", () => { const ctrlEvent = createKeyboardEvent({ key: "a", code: "KeyA", ctrlKey: true }); expect(matchesShortcut(ctrlEvent, "control+a")).toBe(true); diff --git a/apps/client/src/services/shortcuts.ts b/apps/client/src/services/shortcuts.ts index a2aca5d80..1ba7919b3 100644 --- a/apps/client/src/services/shortcuts.ts +++ b/apps/client/src/services/shortcuts.ts @@ -51,7 +51,7 @@ export function isIMEComposing(e: KeyboardEvent): boolean { if (!e) { return false; } - + // Standard check for composition state // e.isComposing is true when IME is actively composing // e.keyCode === 229 is a fallback for older browsers where 229 indicates IME processing @@ -86,13 +86,13 @@ function bindElShortcut($el: JQuery, keyboardShortcut: st } const e = evt as KeyboardEvent; - + // Skip processing if IME is composing to prevent shortcuts from // interfering with text input in CJK languages if (isIMEComposing(e)) { return; } - + if (matchesShortcut(e, keyboardShortcut)) { e.preventDefault(); e.stopPropagation(); @@ -162,6 +162,11 @@ export function matchesShortcut(e: KeyboardEvent, shortcut: string): boolean { const expectedShift = modifiers.includes('shift'); const expectedMeta = modifiers.includes('meta') || modifiers.includes('cmd') || modifiers.includes('command'); + // Refuse key combinations that don't include modifiers because they interfere with the normal usage of the application. + if (!(expectedCtrl || expectedAlt || expectedShift || expectedMeta)) { + return false; + } + return e.ctrlKey === expectedCtrl && e.altKey === expectedAlt && e.shiftKey === expectedShift &&