Linux/WSL desktop window controls missing or broken
NousResearch/hermes-agent · cluster 53514 · apps/desktop
Data as of
Nothing open on GitHub. Fix merged in #53989. Check it covers your case.
The short answer
- Known?
- Yes. 11 related items grouped here, 4 issues already closed.
- Fix event
- A fix was merged to main in PR #53989. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
partially resolved, deciding PR #113247. That is separate from the fix event. - Still open
- Nothing open on GitHub.
Multiple bug reports and fix attempts addressing missing or broken native window controls (minimize, maximize, close) on Linux desktop environments including Wayland, WSLg, X11/XWayland, and with titleBarStyle hidden or overlay configurations. The work spans Electron 40+ compatibility, renderer-drawn fallbacks, and related titlebar layout concerns.
Open issues0
Open PRs0
Fixes on record
-
#53989 fix(desktop): restore window controls on plain Linux (min/max/close)
files:
apps/desktop/electron/main.cjs,apps/desktop/electron/titlebar-overlay-width.cjs,apps/desktop/electron/titlebar-overlay-width.test.cjs,scripts/release.pyShow the diff
-
apps/desktop/electron/main.cjs@@ -534,9 +534,10 @@ function getTitleBarOverlayOptions() { return { height: TITLEBAR_HEIGHT } } - // Windows + WSLg paint WCO natively; plain Linux disables it (frameless hidden - // titlebar still applies). - if (!IS_WINDOWS && !IS_WSL) { + // WSLg paints WCO via the RDP host's own min/max/close, so requesting + // an Electron overlay there just leaves a dead gap. Plain Linux (KDE, + // GNOME) can use the native overlay — let it through. + if (!IS_WINDOWS && IS_WSL) { return false } @@ -3788,7 +3789,7 @@ function getWindowButtonPosition() { } function getNativeOverlayWidth() { - return computeNativeOverlayWidth({ isWindows: IS_WINDOWS, isWsl: IS_WSL }) + return computeNativeOverlayWidth({ isWindows: IS_WINDOWS, isWsl: IS_WSL, isMac: IS_MAC }) } function getWindowState() { -
apps/desktop/electron/titlebar-overlay-width.cjs@@ -1,11 +1,24 @@ -// Pre-layout fallback for WCO right-edge reservation (--titlebar-tools-right). -// Live width comes from navigator.windowControlsOverlay in the renderer. +'use strict' const OVERLAY_FALLBACK_WIDTH = 144 -/** @param {{ isWindows?: boolean, isWsl?: boolean }} opts */ -function nativeOverlayWidth({ isWindows = false, isWsl = false } = {}) { - return isWindows || isWsl ? OVERLAY_FALLBACK_WIDTH : 0 +/** + * Static pre-layout reservation (px) for the right-side native window-controls + * overlay (min/max/close). Only a FALLBACK — once laid out the renderer reads + * the exact width from navigator.windowControlsOverlay + * (use-window-controls-overlay-width.ts) and uses this value only when the WCO + * API is unavailable. + * + * macOS uses traffic lights positioned via trafficLightPosition, not a WCO + * overlay, so it reserves nothing here. Every other desktop platform now paints + * the Electron overlay (Windows, WSLg, and plain Linux KDE/GNOME), so they all + * reserve the fallback width. + * + * @param {{ isWindows?: boolean, isWsl?: boolean, isMac?: boolean }} opts + */ +function nativeOverlayWidth({ isWindows = false, isWsl = false, isMac = false } = {}) { + if (isMac) return 0 + return OVERLAY_FALLBACK_WIDTH } module.exports = { OVERLAY_FALLBACK_WIDTH, nativeOverlayWidth } -
apps/desktop/electron/titlebar-overlay-width.test.cjs@@ -18,10 +18,17 @@ test('WSLg paints the same WCO, so it reserves the same fallback width', () => { assert.equal(nativeOverlayWidth({ isWsl: true }), OVERLAY_FALLBACK_WIDTH) }) -test('plain Linux and macOS reserve nothing', () => { - assert.equal(nativeOverlayWidth({ isWindows: false, isWsl: false }), 0) - assert.equal(nativeOverlayWidth(), 0) - assert.equal(nativeOverlayWidth({}), 0) +test('plain Linux paints the WCO too, so it reserves the fallback width', () => { + // Regression #53185: re-enabling the overlay on plain Linux (KDE/GNOME) + // without reserving its width left the native min/max/close buttons painting + // on top of the app's right-edge titlebar tools. + assert.equal(nativeOverlayWidth({ isWindows: false, isWsl: false }), OVERLAY_FALLBACK_WIDTH) + assert.equal(nativeOverlayWidth(), OVERLAY_FALLBACK_WIDTH) + assert.equal(nativeOverlayWidth({}), OVERLAY_FALLBACK_WIDTH) +}) + +test('macOS uses traffic lights, not a WCO overlay, so it reserves nothing', () => { + assert.equal(nativeOverlayWidth({ isMac: true }), 0) }) test('the fallback width is a sane positive pixel value', () => { -
scripts/release.py@@ -70,6 +70,7 @@ "[redacted:email]": "uperLu", # PR #50958 salvage (rename plugins/cron → plugins/cron_providers; #50872) "[redacted:email]": "yusekiotacode", # PR #48706 salvage (anthropic OAuth login token endpoint → platform.claude.com; #45250/#49821) "[redacted:email]": "s010mn", # PR #29221 salvage (ollama-cloud reasoning_effort xhigh→max) + "[redacted:email]": "chriswesley4", # PR #53185 salvage (re-enable titleBarOverlay on plain Linux; missing min/max/close regression) "[redacted:email]": "jeeves-assistant", # PR #50771 (computer-use CuaDriver vision capture routing) "[redacted:email]": "ScotterMonk", # PR #50145 salvage (cron output truncation: adapter-aware chunking, #50126) "[redacted:email]": "TutkuEroglu", # PR #50481 salvage (AGENTS.md stale token-lock adapter path)
-
-
#113247 fix(desktop): working WSLg window controls and native Wayland launch
files:
apps/desktop/electron/entry.ts,apps/desktop/electron/main.ts,apps/desktop/electron/preload.ts,apps/desktop/electron/titlebar-overlay-width.test.ts,apps/desktop/electron/titlebar-overlay-width.ts,apps/desktop/electron/window-chrome-events.test.ts,apps/desktop/electron/window-chrome-events.ts,apps/desktop/electron/window-controls.test.ts,apps/desktop/electron/window-controls.ts,apps/desktop/electron/wslg-launch-process.test.ts,apps/desktop/electron/wslg-launch-process.ts,apps/desktop/electron/wslg-launch.test.ts,apps/desktop/electron/wslg-launch.ts,apps/desktop/scripts/bundle-electron-main.mjs,apps/desktop/src/app/contrib/wiring.tsx,apps/desktop/src/app/shell/wslg-window-controls.test.tsx,apps/desktop/src/app/shell/wslg-window-controls.tsx,apps/desktop/src/global.d.ts,website/docs/user-guide/desktop.md
5 PRs closed without merging
From the close comments: superseded by another PR 4 · done elsewhere 1
-
#53326 fix(desktop): enable titleBarOverlay on Linux for Electron 40+ · superseded by another PR →
#53989 -
#53528 fix(desktop): add Linux close fallback when no titlebar overlay · done elsewhere →
97640fd,#53514,#53326 -
#64505 fix(desktop): renderer-drawn WSLg window controls, zoom-restore coordinator, work-area snap · superseded by another PR →
#70803 -
#70803 fix(desktop): WSLg window controls + GPU crash-loop fallback · superseded by another PR →
#113247 -
#71754 fix(desktop): request window controls overlay on WSLg (#57614) · superseded by another PR →
#113247
Closed issues · 4
- Closed#53514[Bug]: Linux desktop: no close button when titleBarStyle is hidden
- Closed#53690Linux (X11/XWayland): Electron 40+ window frame missing with titleBarStyle: "hidden"
- Closed#54294[Bug]: Desktop (Linux/Wayland): Native window controls (minimize/maximize/close) are missing
- Closed#57614[Bug] Desktop (WSL/WSLg): no minimize/maximize/close buttons (companion to #53514)
How this cluster was grouped
-
Link evidence (
partly structural links): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text. - Members outside that structural core may belong to a different underlying problem.
-
Pairwise link density
0.18: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the Lab