From 4fdd4f4a96757652e07a5d89558f343b23b644df Mon Sep 17 00:00:00 2001 From: Trouni Tiet Date: Thu, 3 Sep 2026 15:06:43 +0900 Subject: [PATCH] fix(linux): paste via xclip on X11 regardless of clipboard ownership On Linux the paste path chose its clipboard tool with `XMODE and self.is_x_clipboard_owner`, ANDing two unrelated signals. XMODE already answers the relevant question: it is derived from XDG_SESSION_TYPE via detect_linux_display_server(), so it is True on X11 and XWayland. is_x_clipboard_owner() answers "does something currently hold the CLIPBOARD selection", which says nothing about which tool can write to it -- and `xclip -selection clipboard` does not need a prior owner, it becomes one. The probe runs once in __init__ and is cached for the process lifetime. When ClipCascade starts before anything has been copied -- the normal case for a session-scoped systemd unit ordered after graphical-session.target -- `xclip -t TARGETS -o` exits non-zero, the cached value is False, and every subsequent paste falls through to the wl-copy branch. On an X11-only host wl-copy is not installed, so every incoming clip fails for the whole session: ERROR - Failed to execute command: [Errno 2] No such file or directory: 'wl-copy' ERROR - Failed to copy data to clipboard: [Errno 2] ... ERROR - Failed to convert base64 data to clipboard: [Errno 2] ... Sync itself is healthy throughout; only the local write fails, so the symptom is silent one-way sync until the process is restarted at a moment when the clipboard happens to be owned. Select the tool by display server alone, and drop the now-unused probe from __init__. Co-Authored-By: Claude Opus 5 --- ClipCascade_Desktop/src/clipboard/clipboard_manager.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/ClipCascade_Desktop/src/clipboard/clipboard_manager.py b/ClipCascade_Desktop/src/clipboard/clipboard_manager.py index 6a83f64b1..9088f2498 100644 --- a/ClipCascade_Desktop/src/clipboard/clipboard_manager.py +++ b/ClipCascade_Desktop/src/clipboard/clipboard_manager.py @@ -37,9 +37,6 @@ def __init__(self, config: Config): self.sys_tray: TaskbarPanel = None self.is_files_download_enabled = False - if PLATFORM.startswith(LINUX) and XMODE: - self.is_x_clipboard_owner = clipboard_monitor.is_x_clipboard_owner() - def set_tray_ref(self, sys_tray: TaskbarPanel): """ Sets the system tray reference. @@ -218,7 +215,7 @@ def paste(self, payload: any, payload_type: str = "text"): if PLATFORM == WINDOWS or PLATFORM == MACOS: pyperclip.copy(payload) elif PLATFORM.startswith(LINUX): - if XMODE and self.is_x_clipboard_owner: + if XMODE: ClipboardManager.execute_command( "xclip", "-selection", @@ -258,7 +255,7 @@ def paste(self, payload: any, payload_type: str = "text"): png_data = output.getvalue() clipboard_monitor.enable_block_image_once() # Block image copy to prevent deadlock - if XMODE and self.is_x_clipboard_owner: + if XMODE: ClipboardManager.execute_command( "xclip", "-selection",