Skip to content

fix(desktop): stop Linux context menus from activating an item on open#3868

Open
xxashxx-svg wants to merge 1 commit into
pingdotgg:mainfrom
xxashxx-svg:fix/linux-context-menu-press-release
Open

fix(desktop): stop Linux context menus from activating an item on open#3868
xxashxx-svg wants to merge 1 commit into
pingdotgg:mainfrom
xxashxx-svg:fix/linux-context-menu-press-release

Conversation

@xxashxx-svg

@xxashxx-svg xxashxx-svg commented Jul 10, 2026

Copy link
Copy Markdown

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:

  1. The desktop app never runs the code Polish web context menu fallback and sidebar icon actions #3025 fixed. localApi.ts routes context menus through window.desktopBridge.showContextMenu → IPC → the native Electron menu (ElectronMenu.ts) whenever the bridge exists — which on desktop is always. The canDismissFromPointer guard added by Polish web context menu fallback and sidebar icon actions #3025 lives in contextMenuFallback.ts, the browser-only fallback, so it could never fix the desktop bug.
  2. On Linux, Chromium fires contextmenu on 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.showContextMenu now 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; pointercancel and window blur settle the wait so it can't hang. Menus opened with no button held (keyboard, normal-click "…" buttons — where click fires after release) are unaffected, as are Windows and macOS entirely.

The process.platform check uses the repo's established oxlint-disable pattern for standalone non-Effect scripts (same as apps/desktop/scripts/*).

Verification

  • vp check and vp run typecheck pass.
  • I don't have a Linux desktop environment to hand, so this is verified by analysis rather than by reproducing on Ubuntu — the event-order reasoning above matches the reporter's symptoms and workaround exactly, but a maintainer with a Linux box may want to sanity-check before merging. Happy to adjust if testing surfaces anything.

🤖 Generated with Claude Code


Note

Low Risk
Linux-only behavior in the desktop preload around context menu timing; no auth, data, or shared API contract changes.

Overview
Fixes #3698: on Linux, sidebar right-click context menus could open and immediately dismiss while a random item activated.

The desktop preload now gates context menu IPC on Linux only. It tracks pointer button state with capture-phase pointerdown/pointerup listeners (plus pointercancel and window blur so waits can't hang), and showContextMenu awaits pointer release before invoking the native menu—matching Windows-style open-on-release and avoiding the menu grabbing the pointer while the button is still down.

Keyboard and click-opened menus (no button held) and Windows/macOS are unchanged.

Reviewed by Cursor Bugbot for commit 94840df. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix Linux context menus from activating an item on open

On Linux, right-clicking to open a context menu could immediately activate the item under the cursor because the mousedown event fired before the menu appeared. This fix defers the IPC call that opens the context menu until all pointer buttons are released.

  • Adds a pointerButtonsHeld counter in preload.ts updated by global pointerdown, pointerup, pointercancel, and blur listeners.
  • Adds a waitForPointerRelease utility that resolves immediately when no buttons are held, or waits for the next pointerup/pointercancel/blur with zero buttons pressed.
  • desktopBridge.showContextMenu now awaits waitForPointerRelease on Linux before invoking the CONTEXT_MENU_CHANNEL IPC; behavior on macOS and Windows is unchanged.
📊 Macroscope summarized 94840df. 1 file reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

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>
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 578f31cf-c40d-45e6-80d9-a0546353b0e6

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Jul 10, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

❌ 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.

return new Promise((resolve) => {
if (pointerButtonsHeld === 0) {
resolve();
return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blur clears held button state

Medium Severity

On Linux, the context menu delay mechanism can fail. window.blur and pointercancel events prematurely signal button release, even when a pointer button is still physically held. This causes the context menu to appear too early, leading to accidental menu item activation.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 94840df. Configure here.

const onPointerUp = (event: PointerEvent) => {
if (event.buttons === 0) {
settle();
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait requires all buttons released

Medium Severity

On Linux, waitForPointerRelease only finishes when event.buttons is zero. After a right-click context menu, releasing the secondary button while another pointer button stays down leaves the bitmask non-zero, so the wait never completes on pointerup and the native menu may not open until focus is lost or every button is released.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 94840df. Configure here.

@macroscopeapp

macroscopeapp Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This Linux-specific context menu fix has two unresolved review comments identifying potential logic issues: premature resolution on blur/pointercancel events, and multi-button scenarios blocking menu display. These edge case concerns warrant human review before merging.

You can customize Macroscope's approvability policy. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Sidebar context menu auto-selects a random item on right-click (regression of #285)

1 participant