diff --git a/apps/desktop/src/main/tray-manager.test.ts b/apps/desktop/src/main/tray-manager.test.ts index 2203be1119..8a9990ac80 100644 --- a/apps/desktop/src/main/tray-manager.test.ts +++ b/apps/desktop/src/main/tray-manager.test.ts @@ -252,6 +252,32 @@ describe("setupTray", () => { } }); + it("tray click on darwin always shows + focuses a visible window, never hides it", () => { + const orig = Object.getOwnPropertyDescriptor(process, "platform"); + Object.defineProperty(process, "platform", { value: "darwin" }); + try { + const showOrCreateWindow = vi.fn(); + const visibleWindow = { + isDestroyed: () => false, + isVisible: () => true, + isMinimized: () => false, + hide: vi.fn(), + show: vi.fn(), + focus: vi.fn(), + restore: vi.fn(), + } as unknown as Electron.BrowserWindow; + setupTray({ getWindow: () => visibleWindow, showOrCreateWindow }); + const click = h.trayInstances[0]!.clickListeners[0]!; + click(); + click(); + click(); + expect(showOrCreateWindow).toHaveBeenCalledTimes(3); + expect(visibleWindow.hide).not.toHaveBeenCalled(); + } finally { + if (orig) Object.defineProperty(process, "platform", orig); + } + }); + it("replays current status on subscribe and renders an initial menu", () => { h.lastEmit.value = { state: "running", pid: 99, agents: ["a"] }; setupTray({ getWindow: () => null, showOrCreateWindow: vi.fn() }); diff --git a/apps/desktop/src/main/tray-manager.ts b/apps/desktop/src/main/tray-manager.ts index 82d72c87b1..f80eb1ded4 100644 --- a/apps/desktop/src/main/tray-manager.ts +++ b/apps/desktop/src/main/tray-manager.ts @@ -154,20 +154,12 @@ export function setupTray(opts: TrayOptions): void { // Left-click handler is a macOS/Windows nice-to-have only. Linux's // AppIndicator surface doesn't fire `click`, so all actions must remain // reachable via the context menu — which they are (see buildMenuTemplate). + // Click always shows + focuses the main window; hiding is reserved for + // the closeToTray pref (PR2). showOrCreateWindow restores from minimized, + // shows if hidden, and focuses an already-visible window. if (process.platform !== "linux") { tray.on("click", () => { - const win = opts.getWindow(); - // The window may have been closed (mainWindow === null after the - // owner's `closed` handler) or destroyed; in either case recreate. - if (!win || win.isDestroyed()) { - opts.showOrCreateWindow(); - return; - } - if (win.isVisible() && !win.isMinimized()) { - win.hide(); - } else { - opts.showOrCreateWindow(); - } + opts.showOrCreateWindow(); }); }