Skip to content

Clipboard copy silently fails on non-wlroots Wayland compositors (e.g. niri) / 在非 wlroots 的 Wayland 合成器上剪贴板复制静默失败 (e.g. niri) #1920

@NLD37BYs

Description

@NLD37BYs

EN

Environment

  • deepseek-tui version: 0.8.40
  • OS: CachyOS (Arch Linux)
  • Compositor: niri (Wayland, non-wlroots)
  • Clipboard tool: wl-copy / wl-paste

Description

Selecting text inside deepseek-tui and copying (via the mouse selection menu) writes
nothing to the system clipboard. The copy action appears to succeed (no error shown), but
pasting in other applications yields nothing.

Root cause

deepseek-tui uses the arboard crate for clipboard access. On Wayland, arboard uses the
wlr-data-control-unstable-v1 protocol — a wlroots-specific extension. Compositors that are
not based on wlroots (niri, River, cosmic-comp, etc.) do not implement this protocol, so
arboard::Clipboard::set_text() silently fails.

The fallback to OSC 52 (write_text_with_osc52) is never reached because arboard returns
Ok(()) even when the data was never actually written to the system clipboard.

Suggested fix

Before falling through to arboard on Linux, try writing to the clipboard via the standard
wl-copy tool (which uses the wl_data_device_manager protocol supported by all Wayland
compositors). Only fall back to arboard (and then to OSC 52) if wl-copy fails.

Patch

--- a/src/tui/clipboard.rs
+++ b/src/tui/clipboard.rs
@@ -132,6 +132,14 @@
         #[cfg(not(test))]
         {
             self.ensure_clipboard();
+
+            // Linux: try wl-copy first because arboard's Wayland backend
+            // requires wlr-data-control which niri does not implement.
+            #[cfg(target_os = "linux")]
+            if write_text_with_wlcopy(text).is_ok() {
+                return Ok(());
+            }
+
             if let Some(clipboard) = self.clipboard.as_mut()
                 && clipboard.set_text(text.to_string()).is_ok()
             {
@@ -200,6 +208,30 @@
     Err(anyhow::anyhow!("Set-Clipboard failed"))
 }
 
+/// Write text to the Wayland clipboard via `wl-copy`.
+#[cfg(target_os = "linux")]
+fn write_text_with_wlcopy(text: &str) -> Result<()> {
+    let mut child = std::process::Command::new("wl-copy")
+        .stdin(std::process::Stdio::piped())
+        .spawn()
+        .map_err(|e| anyhow::anyhow!("Failed to run wl-copy: {e}"))?;
+    if let Some(mut stdin) = child.stdin.take() {
+        use std::io::Write;
+        stdin
+            .write_all(text.as_bytes())
+            .map_err(|e| anyhow::anyhow!("Failed to write to wl-copy: {e}"))?;
+    }
+    let status = child
+        .wait()
+        .map_err(|e| anyhow::anyhow!("Failed to wait for wl-copy: {e}"))?;
+    if status.success() {
+        return Ok(());
+    }
+    Err(anyhow::anyhow!("wl-copy failed"))
+}
+
 #[cfg(not(test))]
 fn write_text_with_osc52(text: &str) -> Result<()> {
     let mut stdout = io::stdout();

────────────────────────────────────────────────────────────

ZH / 中文说明

环境

  • deepseek-tui 版本:0.8.40
  • 操作系统:CachyOS (Arch Linux)
  • 合成器:niri(Wayland,非 wlroots)
  • 剪贴板工具:wl-copy / wl-paste

问题描述

在 deepseek-tui
中选中文本并复制(通过鼠标选择菜单),系统剪贴板中没有写入任何内容。复制操作看似成功(无错
误提示),但在其他应用中粘贴无效。

根因

deepseek-tui 使用 arboard 库访问剪贴板。在 Wayland 上,arboard 依赖
wlr-data-control-unstable-v1 协议——这是 wlroots 系的私有扩展。非 wlroots 的合成器
(niri、River、cosmic-comp 等)不支持该协议,导致 arboard::Clipboard::set_text()
静默失败。

OSC 52 回退路径永远走不到,因为 arboard 返回 Ok(()) 时实际并未写入数据。

修复方案

在 Linux 上,优先使用标准工具 wl-copy(走 wl_data_device_manager 协议,所有 Wayland
合成器均支持),写入成功则直接返回。只有 wl-copy 失败时才回退到 arboard 和 OSC 52。

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    Status
    Backlog

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions