fix(desktop): stop Linux context menus from activating an item on open#3868
fix(desktop): stop Linux context menus from activating an item on open#3868xxashxx-svg wants to merge 2 commits into
Conversation
On Linux, Chromium fires contextmenu on right-button PRESS (Windows fires it on release), so the native menu pops up while the button is still physically held. The menu takes the pointer grab, and the tail end of the opening right-click — the button release — lands on whatever item sits under the cursor and activates it. The menu flashes and a random item runs, which also explains the known workaround (hold the right button and drag away before releasing). The earlier fix (pingdotgg#3025) hardened contextMenuFallback.ts, but the desktop app never uses that path — window.desktopBridge routes context menus to the native Electron menu, so the regression survived. Gate the desktopBridge.showContextMenu IPC on pointer release (Linux only): track button state in the preload and defer opening the menu until the press that triggered it is released, matching Windows semantics. Menus opened with no button held (keyboard, click-triggered) are unaffected, as are Windows and macOS. Fixes pingdotgg#3698 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 94840df. Configure here.
ApprovabilityVerdict: Needs human review 1 blocking correctness issue found. There is an unresolved review comment identifying a potential hang issue where context menus could be permanently blocked if the mouse button is released outside the window. This substantive concern warrants human review before merging. You can customize Macroscope's approvability policy. Learn more. |
… context menu gate Two review findings from Bugbot on the pointer-release gate: - Waiting for event.buttons === 0 meant a second held button (e.g. left held while right-clicking) kept the menu waiting until every button was released. Track the buttons held at request time and settle once those are up, ignoring buttons pressed mid-gesture. - blur/pointercancel previously settled the wait and opened the menu, which could pop it mid-hold (re-triggering the original bug) or at stale coordinates after focus loss. Treat those as gesture cancellation: resolve null without opening the menu, matching the bridge's existing 'no selection' contract. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Medium
t3code/apps/desktop/src/preload.ts
Line 51 in d82d568
showContextMenu can hang indefinitely when a right-click drag releases the mouse button outside the window. Without implicit pointer capture, the window may never receive pointerup, pointercancel, or blur for that gesture, so pointerButtonsHeld stays nonzero and waitForPointerRelease never resolves. Every subsequent context-menu call is then permanently gated until an unrelated blur or pointercancel resets the state. Consider adding a timeout fallback in waitForPointerRelease so the menu can still open if the release is not observed within a reasonable window.
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/desktop/src/preload.ts around line 51:
`showContextMenu` can hang indefinitely when a right-click drag releases the mouse button outside the window. Without implicit pointer capture, the window may never receive `pointerup`, `pointercancel`, or `blur` for that gesture, so `pointerButtonsHeld` stays nonzero and `waitForPointerRelease` never resolves. Every subsequent context-menu call is then permanently gated until an unrelated `blur` or `pointercancel` resets the state. Consider adding a timeout fallback in `waitForPointerRelease` so the menu can still open if the release is not observed within a reasonable window.

Fixes #3698
What
On Linux, right-clicking a project/thread in the sidebar makes the context menu flash open and instantly close, with a random menu item activated as if clicked (regression of #285 — still present in v0.0.28 despite the #3025 fix).
Why it happens
Two facts combine:
localApi.tsroutes context menus throughwindow.desktopBridge.showContextMenu→ IPC → the native Electron menu (ElectronMenu.ts) whenever the bridge exists — which on desktop is always. ThecanDismissFromPointerguard added by Polish web context menu fallback and sidebar icon actions #3025 lives incontextMenuFallback.ts, the browser-only fallback, so it could never fix the desktop bug.contextmenuon right-button press (Windows fires it on release). So the native menu pops up — positioned directly under the cursor — while the button is still physically held. The menu takes the pointer grab, and the tail of the same right-click gesture (the button release) lands on whatever item happens to sit under the cursor and activates it. This also explains the reported workaround: holding the right button and dragging away before releasing means the release lands outside the menu.Change
In the desktop preload,
desktopBridge.showContextMenunow waits (Linux only) for the pointer buttons to be released before invoking the context-menu IPC — i.e. the menu opens on release, exactly matching the Windows event semantics that don't exhibit the bug. Button state is tracked with capture-phase pointer listeners;pointercanceland windowblursettle the wait so it can't hang. Menus opened with no button held (keyboard, normal-click "…" buttons — whereclickfires after release) are unaffected, as are Windows and macOS entirely.The
process.platformcheck uses the repo's establishedoxlint-disablepattern for standalone non-Effect scripts (same asapps/desktop/scripts/*).Verification
vp checkandvp run typecheckpass.🤖 Generated with Claude Code
Note
Low Risk
Scoped to Linux preload pointer gating around context-menu IPC; other platforms and no-button menu paths are unchanged.
Overview
Fixes #3698: on Linux, native context menus opened while the right button was still down, so the release could activate a random item under the cursor.
desktopBridge.showContextMenuin the desktop preload is now async and, on Linux only, waits for pointer buttons to clear before calling the context-menu IPC. Global capture-phase listeners trackpointerButtonsHeld;waitForPointerReleaseproceeds immediately when no buttons are held (keyboard / “…” menus), waits for release of the buttons that were down at request time, or returnsnullonpointercancel/ windowblurso the menu does not open mid-gesture or at stale coordinates. Windows and macOS are unchanged.Reviewed by Cursor Bugbot for commit d82d568. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Fix Linux context menus activating an item on open by waiting for pointer release
On Linux, right-clicking to open a context menu could immediately trigger an item because the menu appeared while the pointer button was still held. This fix delays the
desktopBridge.showContextMenuIPC call until all held pointer buttons are released. If the gesture is cancelled or the window loses focus before release, the menu is not opened and the method returnsnull. Other platforms are unaffected.Macroscope summarized d82d568.