Skip to content

fix(tui): read Wayland clipboard via wl-paste#2540

Draft
cyq1017 wants to merge 1 commit into
Hmbown:mainfrom
cyq1017:codex/1920-wlpaste-read
Draft

fix(tui): read Wayland clipboard via wl-paste#2540
cyq1017 wants to merge 1 commit into
Hmbown:mainfrom
cyq1017:codex/1920-wlpaste-read

Conversation

@cyq1017
Copy link
Copy Markdown
Contributor

@cyq1017 cyq1017 commented Jun 1, 2026

Summary:

  • try wl-paste before arboard on Linux clipboard reads
  • keep the existing arboard text/image path as the fallback
  • cover the new helper with a focused stdout-based test

Issue:
Refs #1920

Validation:

  • cargo test -p codewhale-tui wl_paste_helper_reads_text_from_stdout --locked
  • cargo test -p codewhale-tui clipboard --locked
  • cargo fmt --all -- --check
  • git diff --check

Greptile Summary

This PR adds a wl-paste read path for the Wayland clipboard on Linux, invoked before the existing arboard fallback in ClipboardHandler::read. A focused unit test covers the new helper by stubbing the binary with a temporary shell script.

  • New read_text_with_wlpaste_using_argv helper runs wl-paste --type text/plain and returns its stdout as a UTF-8 string; cfg attributes are correct and the fallback order (wl-paste → arboard text → arboard image) is appropriate.
  • --no-newline is missing from the wl-paste invocationwl-paste appends a trailing \ by default for text MIME types; the test mock uses printf without a newline so it doesn't catch this, meaning Wayland pastes always carry an extra newline that arboard (and macOS/Windows paths) do not produce.

Confidence Score: 3/5

The Wayland read path is functional but will silently corrupt pasted text by appending a trailing newline on every paste, producing output that differs from the arboard path on the same machine.

The missing --no-newline flag means that on any Wayland session, copied text is returned with a trailing that arboard (X11, macOS, Windows) never adds. This is a consistent, reproducible behavioral difference that would affect every paste on the new code path. The test mock uses printf without a newline so it doesn't exercise or catch this divergence.

crates/tui/src/tui/clipboard.rs — the wl-paste invocation and its accompanying test

Important Files Changed

Filename Overview
crates/tui/src/tui/clipboard.rs Adds wl-paste read path for Wayland on Linux (before arboard fallback); missing --no-newline flag causes every Wayland paste to include an extra trailing newline not present via arboard/macOS/Windows paths. Test mock doesn't simulate this behavior.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["ClipboardHandler::read()"] --> B{Linux non-test?}
    B -- Yes --> C["read_text_with_wlpaste()\nwl-paste --type text/plain"]
    C -- Ok(text) --> D["return ClipboardContent::Text(text)"]
    C -- Err --> E["ensure_clipboard() / arboard"]
    B -- No --> E
    E --> F{arboard available?}
    F -- Yes --> G["clipboard.get_text()"]
    G -- Ok --> D
    G -- Err --> H["clipboard.get_image()"]
    H -- Ok --> I["save_image_as_png()"]
    I --> J["return ClipboardContent::Image(pasted)"]
    H -- Err --> K["return None"]
    F -- No --> K
Loading

Fix All in Codex Fix All in Claude Code Fix All in Cursor

Reviews (1): Last reviewed commit: "fix(tui): read Wayland clipboard via wl-..." | Re-trigger Greptile

Greptile also left 2 inline comments on this PR.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

Comment on lines +230 to +235
let output = Command::new(program)
.arg("--type")
.arg("text/plain")
.stdout(Stdio::piped())
.stderr(Stdio::null())
.output()
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.

P1 wl-paste appends a trailing newline to text output by default (from the man page: "Do not append a newline character after the pasted clipboard content" is what --no-newline / -n suppresses). Without this flag, every paste on a Wayland session will include an extra that arboard — used on X11, macOS, and Windows — does not add. The test doesn't catch this because its mock script uses printf which emits no newline of its own.

Suggested change
let output = Command::new(program)
.arg("--type")
.arg("text/plain")
.stdout(Stdio::piped())
.stderr(Stdio::null())
.output()
let output = Command::new(program)
.arg("--no-newline")
.arg("--type")
.arg("text/plain")
.stdout(Stdio::piped())
.stderr(Stdio::null())
.output()

Fix in Codex Fix in Claude Code Fix in Cursor

fn wl_paste_helper_reads_text_from_stdout() {
let dir = tempfile::tempdir().unwrap();
let script = dir.path().join("wl-paste");
std::fs::write(&script, "#!/bin/sh\nprintf 'from-wayland'\n").unwrap();
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.

P2 The mock script uses printf 'from-wayland' which never appends a newline, so the test doesn't exercise the trailing-newline path that real wl-paste always emits. Once --no-newline is added to the command, consider updating the mock to emit a trailing newline to verify the flag is actually in effect.

Suggested change
std::fs::write(&script, "#!/bin/sh\nprintf 'from-wayland'\n").unwrap();
// Real wl-paste appends a newline unless --no-newline is passed; the
// mock simulates that so the test verifies the flag is actually wired up.
std::fs::write(&script, "#!/bin/sh\nprintf 'from-wayland\\n'\n").unwrap();

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Codex Fix in Claude Code Fix in Cursor

Hmbown added a commit that referenced this pull request Jun 1, 2026
@Hmbown
Copy link
Copy Markdown
Owner

Hmbown commented Jun 1, 2026

Harvested the narrow read-side Wayland clipboard fix into #2504 for v0.8.50 as e2201b87d, preserving @cyq1017's authored commit.

I also added a maintainer follow-up in 9f33c4d59 for Greptile's wl-paste newline concern: the helper now passes --no-newline, and the mock wl-paste test fails unless both --no-newline and --type text/plain are present.

Local validation on #2504 after the harvest:

  • cargo test -p codewhale-tui --all-features --locked wl_paste_helper_reads_text_from_stdout -- --nocapture
  • cargo test -p codewhale-tui --all-features --locked clipboard -- --nocapture
  • cargo fmt --all -- --check
  • git diff --check origin/codex/v0.8.50-triage..HEAD
  • ./scripts/release/check-versions.sh
  • cargo clippy -p codewhale-tui --all-targets --all-features --locked -- -D warnings

Thanks for the focused fix. Once #2504 lands, this draft PR should be treated as superseded by the release harvest.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants