Skip to content

fix(web): terminal paste no longer opens Firefox's Paste prompt - #27451

Open
tastelessjolt wants to merge 2 commits into
pingdotgg:mainfrom
tastelessjolt:fix/terminal-firefox-paste-prompt
Open

tastelessjolt wants to merge 2 commits into
pingdotgg:mainfrom
tastelessjolt:fix/terminal-firefox-paste-prompt

Conversation

@tastelessjolt

@tastelessjolt tastelessjolt commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Problem

In Firefox, pressing Ctrl+Shift+V in the integrated terminal pastes the text, but Firefox also opens a one-item native Paste menu at the mouse pointer. The menu takes focus from the terminal (#27439).

Text pasted, with Firefox's Paste prompt open at the pointer

The terminal's keydown handler called navigator.clipboard.readText() right away, as a fallback for browsers that fire no native paste. It also left the browser's own paste in place. When the native paste event arrives, onPaste advances pasteShortcutToken, so the read's result is thrown away anyway. But Firefox (and Safari) answer a page's clipboard read with that confirmation menu. Chromium asks for a site permission instead, which is why the earlier double-paste fix (#19366) didn't hit this.

Change

Delay the fallback readText() by one task, and skip it if native paste has claimed the token. Native paste can also arrive after that timer, so the fallback requires support for the clipboard-read permission. Firefox and Safari use native paste without opening a clipboard-read prompt. Chromium keeps the fallback when permission allows it. If native paste arrives late, the existing duplicate check from #19366 still handles it.

Scope and approval

This fixes #27439 (filed alongside this PR). It's a small, focused bug fix in one handler: no new behavior, settings, or surfaces. Desktop (Electron/Chromium) and mobile don't show this prompt and keep the same paste paths.

Verification

  • Extended the existing pastes once when %s arrives first case to assert that readText is never called when the native paste arrives first. That assertion fails on main (expected "vi.fn()" to be called +0 times, but got 1 times) and passes with the fix. The clipboard-first case still reads exactly once and pastes once. All 33 cases in surface.test.ts pass.
  • vp run check:changed: format, lint, knip, typecheck, tests and React compiler all pass.
  • Real Firefox 158 on Linux (X11: Xvfb + twm), with a dev server on isolated state and the clipboard owned by another X client (xclip). On a bare X server Firefox closes the Paste prompt the moment it opens, which rejects the read before it can be seen. So this test profile sets ui.popup.disable_autohide, which only stops popups from auto-closing. The page code is unchanged; the two clips differ only in this commit.
    • Before (main): the text pastes, then Firefox's Paste prompt opens at the pointer and takes keyboard focus. The terminal cursor goes hollow, and ; echo still here, typed afterwards, never reaches the shell.
    • After: the text pastes, no prompt opens, the cursor stays solid, and ; echo still here lands in the terminal.

Before:

Before: Paste prompt opens and typed text is lost

After:

After: no prompt, typed text reaches the terminal

Not verified: Safari, and the timing of macOS Chromium's late native paste. That path runs into the existing duplicate check, which this change doesn't touch.

Reviewed with sol-loop: 1 round with gpt-6.1-sol on high. Sol verdict: approved

Implemented, tested and recorded with Claude Opus 5.5 in Claude Code, through T3 Code.

🤖 Generated with Claude Code

takeover verification at ab16435f50

real firefox 159 still reproduced the prompt on the original timer-only head. the takeover adds a clipboard-read permission capability check, preserving chromium fallback while firefox/safari use native paste. the real app now retains typing after paste; five repeats and shift+insert passed. real codex gpt-6.1-sol turns and chrome native paste passed. blacksmith passed all 34 terminal tests and check:changed against the pr base. native clients, safari, macos/windows and remote connection modes remain unverified.

before: firefox paste prompt on main

after: fixed firefox paste retains typing

firefox paste before and after

Ctrl+Shift+V read the clipboard on keydown even when the browser's own
paste event delivered the text. Firefox and Safari answer that read with
a native Paste prompt that steals focus from the terminal. Defer the
fallback read one task so a native paste claims the shortcut first.

Fixes pingdotgg#27439

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XS 0-9 changed lines (additions + deletions). labels Oct 30, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 30, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at ab56917

Macroscope's review found this PR approvable — The terminal now lets native paste run before attempting a fallback clipboard read, avoiding Firefox's focus-stealing prompt. Existing paste encoding and duplicate protection remain unchanged, keeping the change narrowly scoped.

You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between ab56917 and ab16435.

Files selected for processing: 2
  • apps/web/src/terminal/ghostty/surface.test.ts
  • apps/web/src/terminal/ghostty/surface.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.

Walkthrough

The terminal paste shortcut now defers its clipboard fallback, checks clipboard-read permission, and skips the read if permission is denied or the query fails. Tests cover native-paste-first and clipboard-read-first ordering.

Changes: Terminal paste handling

Layer / File(s) Summary
Deferred clipboard fallback
apps/web/src/terminal/ghostty/surface.ts, apps/web/src/terminal/ghostty/surface.test.ts
The shortcut checks clipboard-read permission before reading and retains its disposal, token, and gesture checks. Tests cover permission-query failure, native and clipboard paste ordering, and a later menu paste.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Low

Suggested reviewers: t3dotgg, maria-rcks

Merge Risk: Minimal · up to ab164

The change stops Firefox's Paste prompt from taking focus on the terminal paste shortcut while native paste keeps working. No concrete merge-blocking risk remains.

Pre-merge checks: Passed 3 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Linked Issues check Warning Issue [#27439] requires the delayed clipboard-read fallback to remain available when no native paste event arrives. The handler returns from the timeout when `navigator.permissions.query({ name: "cl… Keep the one-task delay and token check, but preserve the fallback for browsers that do not provide or reject the permission query. Add a test for the rejected or unsupported permission query with no native paste event, and verify one clipb…
Passed Passed checks: 3 passed
Check name Status Explanation
Title check Passed The title names the main change: terminal paste in Firefox no longer opens the native Paste prompt. It matches the changeset, which delays the fallback clipboard read and skips it when a native paste …
Out of Scope Changes check Passed The changes are limited to the integrated terminal paste handler and its focused tests. The permission check, timing change, and test updates address the Firefox paste prompt and paste deduplication i…
Description check Passed The description is complete and follows the required template. It explains the Firefox paste prompt problem, the delayed permission-aware fallback change, the focused scope, detailed automated and man…
Full details: Title check

Explanation

The title names the main change: terminal paste in Firefox no longer opens the native Paste prompt. It matches the changeset, which delays the fallback clipboard read and skips it when a native paste has already claimed the shortcut token. It follows the conventional commit form the template asks for.

Full details: Out of Scope Changes check

Explanation

The changes are limited to the integrated terminal paste handler and its focused tests. The permission check, timing change, and test updates address the Firefox paste prompt and paste deduplication in [#27439]. No unrelated surface or behavior changes are shown.

Full details: Description check

Explanation

The description is complete and follows the required template. It explains the Firefox paste prompt problem, the delayed permission-aware fallback change, the focused scope, detailed automated and manual verification, known unverified cases, screenshots, and agent attribution. It also identifies issue #27439 and explains why this focused bug fix does not require separate approval.

Full details: Linked Issues check

Explanation

Issue [#27439] requires the delayed clipboard-read fallback to remain available when no native paste event arrives. The handler returns from the timeout when navigator.permissions.query({ name: "clipboard-read" }) rejects or is unavailable. Therefore, browsers without this permission query cannot use the fallback. The test covers the rejected-query case only when a native paste arrives first, so it does not verify the required fallback path.

Resolution

Keep the one-task delay and token check, but preserve the fallback for browsers that do not provide or reject the permission query. Add a test for the rejected or unsupported permission query with no native paste event, and verify one clipboard read and one paste.

Finishing Touches
Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

@github-actions github-actions Bot added size:S 10-29 changed lines (additions + deletions). and removed size:XS 0-9 changed lines (additions + deletions). labels Oct 31, 2026

maria-rcks commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

Note

Written by gpt-6.1-sol on behalf of Maria

Verified in a real dev environment

reproduced on github/main (5fe18d79ac) in a separate worktree. firefox 159 on linux pasted the clipboard text, opened its native "paste" prompt, and dropped characters typed afterward. the original pr head ab56917 also reproduced this intermittently: native paste can arrive after the zero-delay fallback.

pushed ab16435f50 to the existing contributor branch. the fallback now checks clipboard-read permission support; firefox and safari use native paste instead of a permissionless read that opens a prompt. chromium keeps its fallback and duplicate protection.

ran one background dev server at a time after vp i, with isolated state. created the real git project and threads through the app. real codex gpt-6.1-sol shell turns returned provider-path-ok on main, the original pr, and after the fix/restart. chrome was driven with the repo's playwright and /usr/bin/google-chrome; firefox used native X11 keyboard input and an external xclip clipboard. firefox's ui.popup.disable_autohide preference kept the native prompt visible for capture; GTK_IM_MODULE=xim avoided the VM's ibus event backlog.

after the fix, firefox ctrl+shift+v pasted once without a prompt and subsequent typing executed. five consecutive pastes and shift+insert also retained typing without duplicates. chrome native paste delivered once with zero fallback reads. uploaded video playback and seeking were checked.

terminal: printf paste-ok; printf " typed-ok\n"
output:   paste-ok typed-ok
repeat-1 through repeat-5: each printed once
shift+insert: paste-okshift-insert-ok
chrome: native paste once, fallback readText calls = 0
blacksmith: 34 terminal tests passed
blacksmith: check:changed against 5ef56853ef18 passed
  format, lint, knip, affected typechecks, terminal tests, react compiler

the new unsupported-permission row failed before the fix and passed afterward. two independent read-only reviews found no blockers in the final head.

before: firefox paste prompt on main

after: fixed firefox paste retains typing

firefox paste before and after

review note: the unsupported-permission test dispatches native paste after the timer, not before it. the clipboard-first row covers a missing native event and preserves the chromium fallback. restoring a read after an unsupported permission query would reopen the firefox prompt reproduced above, so browsers without that permission intentionally use native paste. the issue's one-task timing assumption did not hold in firefox 159.

all 29 ci checks passed on ab16435f50506e75d0229d0d8a227b69daba6e31.

Not verified

native electron, ios/android, safari, macos/windows, and remote/relay/tunnel connections were not exercised on this linux VM. macos chromium's late-native-paste timing was not exercised; its existing duplicate tests pass. other providers were outside this clipboard-only change.

This branch has not been deployed

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

Labels

size:S 10-29 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]: Ctrl+Shift+V in the terminal opens Firefox's Paste prompt and steals focus

2 participants