fix: wl-copy --paste-once for fast clipboard on Wayland/GNOME
Some checks are pending
Build & Release / Build & test (push) Waiting to run
Build & Release / Build .deb (push) Blocked by required conditions

This commit is contained in:
Khoa Vo 2026-07-01 12:41:56 +07:00
parent 800d33e6a7
commit cc05e02559

View file

@ -495,28 +495,44 @@ impl UinputInjector {
fn copy_to_clipboard(s: &str) -> bool {
let is_wayland = std::env::var("WAYLAND_DISPLAY").is_ok();
let (prog, args): (&str, &[&str]) = if is_wayland {
("wl-copy", &[])
// On Wayland/GNOME, wl-copy exits before the compositor reads
// the clipboard data. --paste-once keeps it alive until pasted,
// eliminating the 300900ms compositor lookup delay. We spawn
// it detached (no .wait()) — the child lives until Ctrl+V lands.
("wl-copy", &["--paste-once"])
} else {
("xclip", &["-selection", "clipboard", "-i"])
};
let mut cmd = Self::user_cmd(prog);
cmd.args(args);
let result = cmd
.stdin(std::process::Stdio::piped())
.spawn()
.and_then(|mut child| {
cmd.stdin(std::process::Stdio::piped());
cmd.stdout(std::process::Stdio::null());
cmd.stderr(std::process::Stdio::null());
match cmd.spawn() {
Ok(mut child) => {
use std::io::Write;
child.stdin.take().unwrap().write_all(s.as_bytes())?;
child.wait()
if let Some(mut stdin) = child.stdin.take() {
let _ = stdin.write_all(s.as_bytes());
}
if is_wayland {
// --paste-once: don't wait — child stays alive until the
// compositor reads the data (Ctrl+V arrives later).
// Detach the wait so we don't block.
std::thread::spawn(move || {
let _ = child.wait();
});
if let Ok(status) = result {
if status.success() {
return true;
}
// X11: wait for xclip to finish writing
child.wait().map(|s| s.success()).unwrap_or(false)
}
eprintln!("[vietc] copy_to_clipboard: {} failed", prog);
Err(e) => {
eprintln!("[vietc] copy_to_clipboard: {} spawn failed: {}", prog, e);
false
}
}
}
/// Send Ctrl+V through our uinput device.
fn send_ctrl_v(&self) {