mirror of
https://github.com/aaddrick/claude-desktop-debian.git
synced 2026-05-17 08:36:35 +03:00
fix(lifecycle): hide main window to tray on close, Linux (#451)
* fix(lifecycle): hide main window to tray on close, Linux (#448) Electron's default window-all-closed handler quits the app on Linux. The existing tray icon and Ctrl+Q patches keep the app reachable while a window is alive, but as soon as the last window is closed (stray click on X, or a sign-out flow that closes mainWindow) the app exits and the tray goes with it — taking any in-app schedulers / MCP servers / cron tasks (/schedule skill) down silently until the user re-launches. Intercept BrowserWindow.close on main windows (not popups; Quick Entry and About already dismiss via hide(), never emit close) and preventDefault + hide unless app is in a real quit path. The quit path is detected via before-quit: Ctrl+Q, tray Quit, cmd+Q, SIGTERM and app.quit() from anywhere all emit before-quit, which arms app._quittingIntentionally so the close handler lets the window actually close. Gated by CLOSE_TO_TRAY, default on. Set CLAUDE_QUIT_ON_CLOSE=1 to restore the Electron-default behaviour. Fixes #448 Co-Authored-By: Claude <claude@anthropic.com> * fix(frame-fix-wrapper): drop superseded globalShortcut Ctrl+Q Removes the globalShortcut.register('CommandOrControl+Q') block that #484 superseded with the per-window webContents.on('before-input-event') listener. Auto-merging main into this branch left both registrations in place, which would re-introduce the AZERTY physical-keycode grab and system-wide shortcut steal that #484 fixed. The focus-scoped listener already covers the original #321 hidden-menu-bar use case. Also updates the close-to-tray comment to reference the new listener path instead of the removed global shortcut. Co-Authored-By: Claude <claude@anthropic.com> * docs(readme): credit lizthegrey for close-to-tray contribution Co-Authored-By: Claude <claude@anthropic.com> --------- Co-authored-by: Claude <claude@anthropic.com> Co-authored-by: aaddrick <aaddrick@gmail.com>
This commit is contained in:
@@ -181,7 +181,9 @@ Special thanks to:
|
||||
- Quick window submit fix
|
||||
- **[janfrederik](https://github.com/janfrederik)** for the `--exe` flag to use a local installer
|
||||
- **[MrEdwards007](https://github.com/MrEdwards007)** for discovering the OAuth token cache fix
|
||||
- **[lizthegrey](https://github.com/lizthegrey)** for version update contributions
|
||||
- **[lizthegrey](https://github.com/lizthegrey)**
|
||||
- Version update contributions
|
||||
- Close-to-tray on Linux to keep in-app schedulers, MCP servers, and the tray icon alive across window close
|
||||
- **[mathys-lopinto](https://github.com/mathys-lopinto)**
|
||||
- AUR package
|
||||
- Automated deployment
|
||||
|
||||
@@ -38,6 +38,18 @@ if (resolvedMode !== rawMenuBarMode) {
|
||||
}
|
||||
console.log(`[Frame Fix] Menu bar mode: ${MENU_BAR_MODE}`);
|
||||
|
||||
// Keep the app alive when the main window is closed (hide to tray),
|
||||
// so in-app schedulers / MCP servers / the tray icon survive a
|
||||
// stray click on X. Explicit quit paths (Ctrl+Q via the focused
|
||||
// webContents listener above, tray menu Quit, File > Quit, cmd+Q,
|
||||
// SIGTERM) still go through app.quit() → before-quit, which arms
|
||||
// the flag so the close handler lets the windows actually close.
|
||||
// Set CLAUDE_QUIT_ON_CLOSE=1 to restore the Electron-default
|
||||
// "closing the last window quits the app" behaviour.
|
||||
const CLOSE_TO_TRAY = process.platform === 'linux'
|
||||
&& process.env.CLAUDE_QUIT_ON_CLOSE !== '1';
|
||||
console.log(`[Frame Fix] Close-to-tray: ${CLOSE_TO_TRAY ? 'on' : 'off'}`);
|
||||
|
||||
// Detect if a window intends to be frameless (popup/Quick Entry/About)
|
||||
// Quick Entry: titleBarStyle:"", skipTaskbar:true, transparent:true, resizable:false
|
||||
// About: titleBarStyle:"", skipTaskbar:true, resizable:false
|
||||
@@ -156,6 +168,22 @@ Module.prototype.require = function(id) {
|
||||
}
|
||||
|
||||
if (!popup) {
|
||||
// Close-to-tray: intercept close on main windows and hide
|
||||
// instead. app.on('before-quit') below sets the flag when
|
||||
// the user picks an explicit quit path, so real quits still
|
||||
// let the window actually close. Popups (Quick Entry,
|
||||
// About) already dismiss via hide() in the upstream code;
|
||||
// they never see close events, so they're unaffected.
|
||||
// Fixes: #448
|
||||
if (CLOSE_TO_TRAY) {
|
||||
this.on('close', (e) => {
|
||||
if (!result.app._quittingIntentionally && !this.isDestroyed()) {
|
||||
e.preventDefault();
|
||||
this.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Directly set child view bounds to match content size.
|
||||
// This bypasses Chromium's stale LayoutManagerBase cache
|
||||
// (only invalidated via _NET_WM_STATE atom changes, which
|
||||
@@ -334,6 +362,17 @@ Module.prototype.require = function(id) {
|
||||
}
|
||||
};
|
||||
|
||||
// Arm the close-to-tray flag on every real quit path
|
||||
// (app.quit() from Ctrl+Q, tray Quit, cmd+Q, SIGTERM). The
|
||||
// BrowserWindow close handler above checks this flag to
|
||||
// decide whether to hide or actually close. Harmless when
|
||||
// CLOSE_TO_TRAY is off (the close handler is never attached).
|
||||
if (CLOSE_TO_TRAY) {
|
||||
result.app.on('before-quit', () => {
|
||||
result.app._quittingIntentionally = true;
|
||||
});
|
||||
}
|
||||
|
||||
console.log('[Frame Fix] Patches built successfully');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user