Cancel native middle-click paste on tab mouseup#2518
Merged
nwparker merged 1 commit intoMay 22, 2026
Merged
Conversation
4 tasks
On Linux with primary-selection paste enabled, middle-clicking a tab to close it triggered an unwanted primary-selection paste into whichever terminal became active after the close. The existing onMouseDown preventDefault on each tab blocks Chromium's middle-button auto-scroll but does not block the native paste pipeline, which is gated on mouseup. After the tab unmounts via onAuxClick → onClose, focus moves to xterm's hidden textarea on the newly active terminal, and the primary selection lands there. Add a small named helper preventMiddleButtonDefault and wire it as onMouseUp on SortableTab, BrowserTab, and EditorFileTab. Mirrors the preventDefault that usePrimarySelectionPaste's enabled=false branch already performs for non-tab surfaces. No platform branching: the mouseup cancel is a no-op on macOS and Windows because there is no native primary-selection paste pipeline to cancel. Fixes stablyai#2346
f0e0831 to
8984f96
Compare
nwparker
approved these changes
May 22, 2026
Contributor
nwparker
left a comment
There was a problem hiding this comment.
Reviewed and took ownership of the final validation. Rebased onto current main, tightened the helper comment to match the repo comment rules, and re-ran verification locally: targeted Vitest for the new guard + primary-selection coverage, full pnpm typecheck, pnpm lint, git diff --check, and full pnpm test (9360 passed, 10 skipped). The fix is intentionally tab-local and matches the Linux mouseup cancellation path described in #2346.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #2346.
On Linux with primary-selection paste enabled (the default), middle-clicking a tab to close it produced an unwanted primary-selection paste into whichever terminal became active after the close. Repro is in the linked issue.
The existing `onMouseDown` `preventDefault` on each tab blocks Chromium's middle-button auto-scroll but is not sufficient to block the native paste pipeline — that one is gated on `mouseup`. After the tab unmounts via `onAuxClick` → `onClose`, focus moves to xterm's hidden `<textarea>` on the newly active terminal, and the native paste lands there.
This applies on both X11 and Wayland sessions (the issue author confirmed Hyprland with `wp_primary_selection_unstable_v1`).
Fix
Adopt the same option-(a) approach from the issue's analysis:
The change is tab-local and surgical: only the three components that already close on `auxclick` get the new `onMouseUp`. No global event listeners are added or modified.
No platform branching
`event.preventDefault()` on a `mouseup` event is harmless on macOS and Windows — there is no native primary-selection paste pipeline to cancel there. Avoiding a platform check keeps the surfaces consistent and follows the project's cross-platform guidance (no `navigator.userAgent` sniffing for a behavior that's a no-op off Linux).
Tests
`src/renderer/src/components/tab-bar/middle-button-default-guard.test.ts` pins the contract:
(Project convention is to extract logic into named functions and unit-test those — no React rendering in tests. See `QuickLaunchButton.test.ts` for the same pattern.)
No visual change
This is pure event-handler behavior; the rendered tab markup is unchanged.
Manual verification
Manual repro requires a Linux session with primary-selection paste enabled, which I do not have available locally. The fix follows the issue author's analysis precisely and matches the working pattern in the existing `enabled=false` branch of `usePrimarySelectionPaste`. Linux verification by a reviewer / the issue author would be appreciated before merge.
Cross-platform / security review
CI checks run locally