Skip to content

fix: paste with Ctrl+V on Windows instead of the Win key - #555

Draft
leftos wants to merge 8 commits into
penso:mainfrom
leftos:fix/windows-ctrl-v-paste
Draft

leftos wants to merge 8 commits into
penso:mainfrom
leftos:fix/windows-ctrl-v-paste

Conversation

@leftos

@leftos leftos commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

🤖 Posted by Claude Code on behalf of @leftos.

Stacked on #637: merge #637 first. This branch carries #637's commit (f81762f) under its own two, so until #637 merges the diff here shows both. Merged on its own, it would not build: its Ctrl+V calls #637's held-paste path.

Summary

On Windows, plain Ctrl+V in a pane went to the terminal as ^V, and the Edit menu labelled paste with Ctrl+Shift+V, which other apps often take system-wide.

  • In a pane on Windows, plain Ctrl+V is the app's paste while the clipboard holds text. It goes through the same path as Ctrl+Shift+V (paste() → fix: hold a paste or file drop until the window's frame returns #637's paste_or_hold), so a Ctrl+V pressed while the window waits for its frame is held like any other paste and pastes the clipboard as it is when the frame returns.
  • With no text on the clipboard, Ctrl+V keeps its terminal meaning: on an SSH or WSL endpoint a clipboard image goes through the image bridge, and on a local endpoint ^V reaches the pane so an agent can read the clipboard itself.
  • The Edit menu labels paste on Windows as plain Ctrl+V (actions::EDIT_KEYS). Cut, copy and select all stay Ctrl+Shift+X/C/A.
  • README: the Images section and the Edit keys paragraph say what Ctrl+V does on Windows.

macOS and Linux behaviour is unchanged.

Validation

On #637 at f81762f, main at 7c64479; run at e200326 (the same change as fb4d19fa, re-stacked onto #637's final commit without conflicts).

  • check-commits (upstream/main..HEAD): passed
  • Windows 11 x86_64 at fb4d19fa: format-check, check-file-size, check-sorted, lint passed; cargo test --workspace default and all features passed apart from 4 Credential Manager tests that need an interactive logon (they pass in one) and 4 timing tests that passed on re-run.
  • Windows at e200326: window::pending_input and window::input: 23 passed, 0 failed.
  • WSL Ubuntu at fb4d19fa: clippy all features and no default features passed; cargo test --workspace failed only orchestrator::tests::service::the_worker_shows_runs_another_application_writes, a load-timing test in code this PR does not touch, which passes alone.
  • New tests failed before the change: actions/tests/edit_keys.rs, window/input/tests/ctrl_v_paste.rs, and window/pending_input/tests/ctrl_v.rs (a Ctrl+V held for the frame pastes the clipboard once it returns).
  • test-mockup-wait: the known Windows-only failure in test_wait.py; this PR touches nothing it covers.

Screenshots

None captured. The only visible difference is the Edit menu's paste label on Windows (Ctrl+V).

Manual QA (native Windows, not yet done)

  • Ctrl+V with text on the clipboard in a local shell pane pastes it (bracketed paste in an editor).
  • Ctrl+V with an image on the clipboard in a local pane running Claude Code still reaches the agent as ^V.
  • Ctrl+V with an image (no text) on an SSH or WSL endpoint sends it through the image bridge.
  • Ctrl+V in the find field and in a dialog field.
  • Edit menu shows Ctrl+Shift+X, Ctrl+Shift+C, Ctrl+V and Ctrl+Shift+A, and each item works.
  • macOS: Cmd-V, Cmd-C and Cmd-A unchanged. Linux: Ctrl+Shift+V unchanged, and plain Ctrl+V still reaches the pane.

@greptile-apps

greptile-apps Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; the previous finding is fixed and no new blocking issue remains.

Summary

The PR replaces Windows Win-key edit shortcuts with Ctrl shortcuts and makes plain Ctrl+V paste clipboard text.

  • Windows uses Ctrl-based shortcuts for the app’s Edit actions.
  • Windows Ctrl+V pastes clipboard text and leaves other contents to the pane.

Reviews (2) · Last reviewed commit: "fix: send Ctrl+V to SSH panes on Windows..." · Reviewed by Greptile

Comment thread crates/herdr-gpui/README.md Outdated
@penso

penso commented Oct 14, 2026

Copy link
Copy Markdown
Owner

@greptileai review

@penso penso added the windows Improves Herdr UI on Windows label Oct 17, 2026
@leftos
leftos force-pushed the fix/windows-ctrl-v-paste branch from 851f776 to b5c3ddb Compare October 17, 2026 13:14
@leftos

leftos commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor Author

🤖 Posted by Claude Code on behalf of @leftos.

Local just ci at cbb9fd1, which merges #637's updated branch (602a976, carrying main at 0ca50aa and #637's fix for the held_paste tests on Linux and macOS), on Windows 11 x86_64:

  • check-commits (upstream/main..HEAD): passed
  • format-check, check-file-size, check-sorted: passed
  • lint, all features and no default features: passed
  • test, default features: passed, 0 failed (herdr-gpui 4229)
  • test, all features: passed, 0 failed (herdr-gpui 4273), on a run with the machine to itself. Runs beside other work on the machine timed out in tests this PR does not touch (herdr-client clipboard_tests::session::uploads, browser::view_tests::code, git probes, a sidebar menu test); each passed when rerun alone.
  • test-mockup-wait: not rerun; it fails on every Windows machine until test: run the mockup wait tests on Windows #643 merges, and this PR touches nothing it covers.

WSL (Linux x86_64) at cbb9fd1: endpoint::lifecycle_tests, 125 passed, including every held_paste test that failed on the Linux and macOS CI jobs before #637's fix.

The Windows native GUI jobs fail on main too (0ca50aa and later): the native_sidebar paint probe measures the child label at 179px or 127px against an expected 161px. This PR does not touch the sidebar.

@penso

penso commented Oct 17, 2026

Copy link
Copy Markdown
Owner

@leftos Remove the draft status once the PR is ready to be looked at. Thanks!

@leftos

leftos commented Oct 17, 2026

Copy link
Copy Markdown
Contributor Author

@penso will do, still working on it!

leftos added a commit to leftos/herdr-gpui that referenced this pull request Oct 17, 2026
The plain Ctrl+V branch from PR penso#555 called paste_terminal_clipboard,
which PR penso#637's review round made test-only. Call paste_item, the
function it wrapped; the branch ignored its result either way.
The previous commit let a paste or a file drop take a tab back from
another window, but what was pasted or dropped was still thrown away: a
window whose frame does not match its size refuses input, and only typed
keys were held for later. The first paste or drop in an idle window was
lost, and the user had to repeat it.

Keys, pastes, and drops now share one hold queue, so they are delivered
in the order the user made them once the frame matches. A held paste
keeps only the action and reads the clipboard when it is delivered, so
no image is kept in memory and nothing is read on the UI thread. A file
drop is held for the pane under the pointer, or for the drop point when
no frame is shown, which is hit-tested once one arrives. Ctrl-V on a
remote pane is held the same way.

Held pastes and drops follow the rules of held keys: they are dropped
with an error if focus moves first, cleared on reconnect, and capped at
four per gap, past which they are refused with an error. A held send
that fails now says how many held inputs it discarded.

A held paste or drop that is refused, or one that starts a remote file
copy whose paths arrive only once it completes, ends the batch: the
input held after it is discarded with the count, so a held Enter never
runs a command without what was pasted before it. A fifth paste or
drop refused at the cap ends the batch the same way. A held paste
delivered while a menu is open or a focus click is pending is refused
with a reason, and on macOS a held paste always reads the clipboard in
the background. A live paste or drop sends held input before itself.
Off Linux the Edit keys were cmd-x/c/v/a. GPUI parses cmd as the
platform modifier, which on Windows is the Win key, and Windows keeps
Win+V (clipboard history), Win+X, Win+C and Win+A for itself, so the
app's paste could not be reached. Plain Ctrl+V went to the pane as ^V,
and Ctrl+Shift+V is often taken system-wide by other apps.

Windows now follows Linux's Ctrl scheme: the Edit keys are
Ctrl+Shift+X/C/A, fields accept plain Ctrl, and Edit menu clicks replay
Ctrl+Shift. In a pane, plain Ctrl+V is the app's paste while the
clipboard holds text. With no text on the clipboard it keeps its
terminal meaning: an SSH endpoint's image bridge takes a clipboard image,
and a local pane still receives ^V so an agent can read the clipboard
itself. Windows has no clipboard image reader of its own.

The Ctrl+V decision is a pure function with the platform passed in, so
its tests run on every OS; the key_down wiring needs a native check.
On Windows plain Ctrl+V is the app's paste only while the clipboard
holds text. Without text it keeps its terminal meaning: an SSH or WSL
endpoint's image bridge takes a clipboard image, now that the Windows
client reads clipboard images and uploads them, and a local pane
receives ^V so an agent can read the clipboard itself.
@leftos
leftos force-pushed the fix/windows-ctrl-v-paste branch from b5c3ddb to e200326 Compare October 17, 2026 19:12
leftos added a commit to leftos/herdr-gpui that referenced this pull request Oct 17, 2026
@penso penso added bug Something isn't working P1 High priority: crashes, blocked core workflows, or significant input regressions labels Oct 19, 2026
…l-frame

# Conflicts:
#	crates/herdr-gpui/src/window/file_drop.rs
#	crates/herdr-gpui/src/window/pending_input.rs
The merge of upstream main brought tests that still read paste_files as
a bool; it now returns Delivery, so they compare against Refused.
Since the metadata-update change on main, a newer snapshot that keeps
the same focus and changes only metadata keeps input flowing, so the
held-paste tests that opened their gap that way never saw input pause
and timed out on every Unix CI job. The gap's snapshot now also
republishes the host's key bindings, which still holds input until the
matching surface arrives.

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

bug Something isn't working P1 High priority: crashes, blocked core workflows, or significant input regressions windows Improves Herdr UI on Windows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants