diff --git a/apps/desktop/src/lib/__tests__/editor/shortcutDisplay.spec.ts b/apps/desktop/src/lib/__tests__/editor/shortcutDisplay.spec.ts index 66dcd0b37..233ccc86a 100644 --- a/apps/desktop/src/lib/__tests__/editor/shortcutDisplay.spec.ts +++ b/apps/desktop/src/lib/__tests__/editor/shortcutDisplay.spec.ts @@ -24,6 +24,11 @@ describe("shortcut display", () => { expect(formatShortcutDisplay("Shift+Alt+W", "Win32")).toBe("Shift + Alt + W"); }); + it("formats the close tab shortcut by platform", () => { + expect(formatShortcutDisplay("Mod+W", "MacIntel")).toBe("⌘ W"); + expect(formatShortcutDisplay("Mod+W", "Win32")).toBe("Ctrl + W"); + }); + it("formats shortcut pills with platform separators", () => { expect(formatShortcutDisplay("Shift+Alt+ArrowUp", "Win32")).toBe("Shift + Alt + ↑"); expect(formatShortcutDisplay("Shift+Alt+ArrowUp", "MacIntel")).toBe("⇧ ⌥ ↑"); diff --git a/apps/desktop/src/lib/__tests__/editor/shortcutRegistry.spec.ts b/apps/desktop/src/lib/__tests__/editor/shortcutRegistry.spec.ts index 5ed294260..09f57cc2a 100644 --- a/apps/desktop/src/lib/__tests__/editor/shortcutRegistry.spec.ts +++ b/apps/desktop/src/lib/__tests__/editor/shortcutRegistry.spec.ts @@ -44,6 +44,15 @@ describe("shortcutRegistry editor actions", () => { expect(normalizeShortcutSettings({ closeOtherTabs: "Shift+Mod+O" }).closeOtherTabs).toBe("Shift+Mod+O"); }); + it("uses the platform modifier for closing tabs and migrates the legacy Meta default", () => { + expect(DEFAULT_SHORTCUT_SETTINGS.closeTab).toBe("Mod+W"); + expect(formatShortcut(DEFAULT_SHORTCUT_SETTINGS.closeTab, "Win32")).toBe("Ctrl+W"); + expect(formatShortcut(DEFAULT_SHORTCUT_SETTINGS.closeTab, "MacIntel")).toBe("Cmd+W"); + expect(normalizeShortcutSettings({ closeTab: "Meta+W" }).closeTab).toBe("Mod+W"); + expect(normalizeShortcutSettings({ closeTab: "Shift+Mod+W" }).closeTab).toBe("Shift+Mod+W"); + expect(normalizeShortcutSettings({ closeTab: "" }).closeTab).toBe(""); + }); + it("normalizes custom, cleared, and invalid modifier-only shortcuts", () => { expect(normalizeShortcutSettings({ openDataInNewTab: "Shift" }).openDataInNewTab).toBe("Shift"); expect(normalizeShortcutSettings({ openDataInNewTab: "" }).openDataInNewTab).toBe(""); diff --git a/apps/desktop/src/lib/editor/shortcutRegistry.ts b/apps/desktop/src/lib/editor/shortcutRegistry.ts index fbf8787fe..8bf002288 100644 --- a/apps/desktop/src/lib/editor/shortcutRegistry.ts +++ b/apps/desktop/src/lib/editor/shortcutRegistry.ts @@ -68,8 +68,8 @@ export type ShortcutSettings = Record; // closeOtherTabs 的平台相关默认键。Windows/Linux 不用 Alt+Mod(= Ctrl+Alt, // 与国际键盘 AltGr 字符输入冲突),也不用 Ctrl+Shift+W(浏览器保留的关窗键, -// Web 形态不可拦截,closeTab 默认 Meta+W 同理);Shift+Alt+W 无浏览器保留 -// 冲突(Firefox accesskey 同为 Alt+Shift+字母,属正常应用快捷键区)。 +// Web 形态不可拦截);Shift+Alt+W 无浏览器保留冲突(Firefox accesskey +// 同为 Alt+Shift+字母,属正常应用快捷键区)。 // 已知取舍:Windows 的 Alt+Shift 布局切换只在单独按下并释放时触发, // Alt+Shift+字母会正常送达应用,多语言用户如遇干扰可自定义改键。 // macOS 的 ⌥⌘W 无上述问题 @@ -78,6 +78,7 @@ export function closeOtherTabsDefaultShortcut(platform = globalThis.navigator?.p } const CLOSE_OTHER_TABS_PLATFORM_DEFAULTS = new Set(["Alt+Mod+W", "Shift+Alt+W"]); +const LEGACY_CLOSE_TAB_DEFAULT = "Meta+W"; export const SHORTCUT_DEFINITIONS: ShortcutDefinition[] = [ { @@ -222,7 +223,7 @@ export const SHORTCUT_DEFINITIONS: ShortcutDefinition[] = [ id: "closeTab", labelKey: "settings.shortcutCloseTab", scope: "global", - defaultShortcut: "Meta+W", + defaultShortcut: "Mod+W", }, { id: "closeOtherTabs", @@ -416,6 +417,11 @@ export function normalizeShortcutSettings(settings?: Partial): if (definition.id === "closeOtherTabs" && CLOSE_OTHER_TABS_PLATFORM_DEFAULTS.has(configured)) { configured = definition.defaultShortcut; } + // Meta+W was the old macOS-only default. Treat that exact value as a + // legacy default so existing Windows/Linux settings adopt Ctrl+W. + if (definition.id === "closeTab" && configured === LEGACY_CLOSE_TAB_DEFAULT) { + configured = definition.defaultShortcut; + } const normalized = definition.inputKind === "modifier-only" ? normalizeModifierOnlyShortcut(configured, definition.defaultShortcut) : configured; return [definition.id, normalized]; }), diff --git a/packages/app-tests/keyboardShortcuts.test.ts b/packages/app-tests/keyboardShortcuts.test.ts index b08a486e9..9e1b2d0b4 100644 --- a/packages/app-tests/keyboardShortcuts.test.ts +++ b/packages/app-tests/keyboardShortcuts.test.ts @@ -129,12 +129,10 @@ test("ignores composing input events", () => { assert.equal(isExecuteSqlShortcut({ key: "Enter", metaKey: true, isComposing: true }), false); }); -test("matches Cmd+W for closing query tabs", () => { +test("matches the platform modifier for closing query tabs", () => { assert.equal(isCloseTabShortcut({ key: "w", metaKey: true }), true); -}); - -test("ignores Ctrl+W for closing query tabs", () => { - assert.equal(isCloseTabShortcut({ key: "w", ctrlKey: true }), false); + assert.equal(isCloseTabShortcut({ key: "w", ctrlKey: true }), true); + assert.equal(isCloseTabShortcut({ key: "w", ctrlKey: true }, { closeTab: "Meta+W" } as any), true); }); test("matches platform shortcuts for closing other tabs", () => {