Skip to content

Fix the desktop app's Linux gaps: window geometry, HUD click-through, and window-read diagnostics - #82201

Merged
OutThisLife merged 3 commits into
mainfrom
bb/xplat
Aug 9, 2026
Merged

Fix the desktop app's Linux gaps: window geometry, HUD click-through, and window-read diagnostics#82201
OutThisLife merged 3 commits into
mainfrom
bb/xplat

Conversation

@OutThisLife

Copy link
Copy Markdown
Collaborator

Three places where the desktop app quietly depended on a platform-gated Electron API and did nothing at all on Linux. Each is a fix for the whole class rather than the one call site, and each ships with tests over an extracted helper so the platform reasoning is checkable without booting Electron.

Window geometry was never saved on Linux

main.ts persisted window state from moved and resized, and Electron tags both @platform darwin,win32 — they never fire on Linux, so neither the main window nor the HUD ever heard that it had been dragged or resized. The main window had a close flush to fall back on; the HUD had nothing, so its position was lost outright every launch.

Both windows now bind through one bindGeometryPersistence helper using move/resize, which carry no platform tag. Those fire continuously mid-drag, which is what the existing trailing debounce is already for — so the settled-only events were buying nothing the debounce didn't give us.

The HUD was permanently click-through on Linux

Click-through decides whether to swallow the mouse by hit-testing the document under the cursor, and it learns where the cursor is from mousemove. Those keep arriving while the window is ignoring the mouse only because of setIgnoreMouseEvents(true, { forward: true }), and forward is @platform darwin,win32. On Linux the moves stop the instant the HUD turns click-through, so it never sees the pointer come back to the bar: the bar is visible, and clicking it hits whatever is behind.

Main can still see the cursor, so on Linux it polls and pushes the position to the renderer, which runs its usual hit test on it. The decision and its rules stay in one place — only the courier for that one input changes. The conversion is the fiddly part and is extracted to hud-cursor.ts: screen space to window space, then DIP to CSS pixels, since getCursorScreenPoint() and elementFromPoint agree only at zoom 1. Off-window returns null, which is already how the renderer hands the mouse back.

read_window_below failed without saying why

Any enumeration failure produced "could not determine the window underneath (the desktop app did not answer, or window enumeration is unavailable on this system)" — true, and a dead end. On Linux the two ways it fails have opposite fixes and neither is guessable from that message: a Wayland session withholds window identity from applications outright, while an X11 session needs xprop and xwininfo present because that is what the enumerator shells out to.

It now answers with the reason. A session with both WAYLAND_DISPLAY and DISPLAY is XWayland, where xprop can still answer, so it gets the tooling advice rather than being told to change session type. The tool schema tells the model to relay the reason rather than retry.

Not included

Windows 11 frost via backgroundMaterial was investigated and dropped. The material paints the entire window rectangle, and the HUD window is mostly empty space with a bar and a band floating in it — acrylic there frosts a large slab over whatever the user is working in, and it also removes the rounded corners (electron#43075, electron#47510). The CSS fill remains the right fallback on Windows.

Test plan

  • npx vitest run electron/ — 930 passed, 2 skipped
  • npx tsc --noEmit clean, eslint clean on all changed files
  • scripts/run_tests.sh tests/tools/test_read_window_tool.py
  • Manual pass on a Linux box: drag/resize the HUD and the main window, reopen, confirm both come back where they were
  • Manual pass on Linux: move the cursor off the HUD and back onto the bar, confirm it takes clicks again
  • Confirm macOS and Windows are unchanged — the cursor feed is Linux-only and never starts elsewhere

`moved` and `resized` are macOS/Windows only — Electron tags them
`@platform darwin,win32` — so on Linux neither the main window nor the HUD
ever heard that it had been dragged or resized, and both reopened at their
default placement every launch. The main window had a `close` flush to fall
back on; the HUD had nothing, so its position was lost outright.

Bind `move`/`resize` instead. Those carry no platform tag and fire everywhere,
and the trailing debounce already collapses the mid-drag stream a settled event
would have saved us from.
Click-through decides whether to swallow the mouse by hit-testing the document
under the cursor, and it learns where the cursor is from mousemove. Those keep
arriving while the window ignores the mouse only because of
`setIgnoreMouseEvents(true, { forward: true })`, and `forward` is
`@platform darwin,win32`. On Linux the moves stop the instant the HUD turns
click-through, so it never sees the pointer return to the bar: the bar is
visible, and clicking it hits whatever is behind.

Main can still see the cursor, so on Linux it polls and pushes the position to
the renderer, which runs its usual hit test on it. The decision and its rules
stay in one place — only the courier for that one input changes — and off-window
is sent as null, which is already how the renderer hands the mouse back.
When enumeration was impossible the tool answered "could not determine the
window underneath (the desktop app did not answer, or window enumeration is
unavailable on this system)" — true, and a dead end. On Linux the two ways it
fails have opposite fixes and neither is guessable from that: a Wayland session
withholds window identity from applications outright, while an X11 session
needs xprop and xwininfo installed, because that is what the enumerator shells
out to.

Answer with the reason instead of nothing. A session with both WAYLAND_DISPLAY
and DISPLAY is XWayland, where xprop can still answer, so it gets the tooling
advice rather than being told to change session type.
@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

૮ >ﻌ< ა ci review

ran on 04afc8d

⚠️ Warnings

OSV vulnerability scan · View job

21 known vulnerabilities found in pinned dependencies.

How to fix:

Review the findings in the Security tab. Update the affected dependencies if a patched version is available.


debug info

CI timings

CI timings · View report · View job

Wall time 6m29s vs 6m23s (+1.6%). 16 job(s) slower, 16 faster, 2 unchanged.

  • Python tests / Run tests slice 3/12: -39.0s
  • JS & TS checks / ui-tui / check: +29.0s
  • Python tests / Run tests slice 11/12: -28.0s
  • Python tests / Run tests slice 9/12: +23.0s
  • Python tests / Run tests slice 5/12: +15.0s

@OutThisLife
OutThisLife enabled auto-merge August 9, 2026 03:23
@OutThisLife
OutThisLife merged commit 4b60193 into main Aug 9, 2026
53 checks passed
@OutThisLife
OutThisLife deleted the bb/xplat branch August 9, 2026 03:25
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/desktop Electron desktop app (apps/desktop/*) comp/tools Tool registry, model_tools, toolsets labels Aug 9, 2026
@rdxhemadri

Copy link
Copy Markdown

@OutThisLife can you pls look into it #75038

randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
Fix the desktop app's Linux gaps: window geometry, HUD click-through, and window-read diagnostics
33hodl pushed a commit to 33hodl/hermes-agent that referenced this pull request Aug 12, 2026
Fix the desktop app's Linux gaps: window geometry, HUD click-through, and window-read diagnostics
prmartinow pushed a commit to prmartinow/hermes-agent that referenced this pull request Aug 26, 2026
Fix the desktop app's Linux gaps: window geometry, HUD click-through, and window-read diagnostics
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/desktop Electron desktop app (apps/desktop/*) comp/tools Tool registry, model_tools, toolsets P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants