Skip to content

fix(linux): paste via xclip on X11 regardless of clipboard ownership - #171

Open
trouni wants to merge 1 commit into
Sathvik-Rao:mainfrom
trouni:fix/x11-paste-falls-back-to-wl-copy
Open

fix(linux): paste via xclip on X11 regardless of clipboard ownership#171
trouni wants to merge 1 commit into
Sathvik-Rao:mainfrom
trouni:fix/x11-paste-falls-back-to-wl-copy

Conversation

@trouni

@trouni trouni commented Sep 3, 2026

Copy link
Copy Markdown

Fixes #156. Same bug as #99 (reported March 2025, closed only because the reporter stopped using the app).

Cause

ClipboardManager.paste() picks its clipboard tool with XMODE and self.is_x_clipboard_owner (clipboard_manager.py:221 and :261), which ANDs two unrelated signals:

  • XMODE already answers the 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". That says nothing about which tool can write to it, and xclip -selection clipboard does not require a prior owner — it becomes one.

The probe also runs only once, in __init__ (:41), and is cached for the process lifetime. When ClipCascade starts before anything has been copied — the normal case for an autostart entry or a systemd unit ordered after graphical-session.targetxclip -t TARGETS -o exits non-zero, the cached value is False, and every subsequent paste takes the wl-copy branch for the rest of the session.

On an X11-only host wl-copy is not installed, so every inbound clip fails:

INFO  - XMODE: True
INFO  - Starting GTK clipboard monitoring for X11 display server.
ERROR - Failed to execute command: [Errno 2] No such file or directory: 'wl-copy'
ERROR - Failed to copy data to clipboard: [Errno 2] No such file or directory: 'wl-copy'
ERROR - Failed to convert base64 data to clipboard: [Errno 2] No such file or directory: 'wl-copy'

Sync itself stays healthy throughout — only the local write fails — so the symptom is silent one-way sync, and launching the app manually after copying something masks it entirely. That matches the autostart-only behaviour reported in both #156 and #99.

Change

Select the tool by display server alone, in both the text and image paths, and drop the now-unused probe from __init__.

Relationship to #157

Complementary, not competing — #157 changes the probe command in clipboard_monitor_linux.py; this changes the paste decision in clipboard_manager.py, which #157 does not touch. They do not conflict. I have left _start_clipboard_polling()'s use of the same probe (clipboard_monitor_linux.py:380) alone: it only runs when the GTK X11 path is unavailable, so I could not exercise it.

Testing

On X11, forced is_x_clipboard_owner() to return False (the bug condition), called paste(), and confirmed it selects xclip and the text lands in the clipboard. Byte-compiles clean, no imports orphaned, and the change is whitespace-neutral so formatting is unaffected.

One thing worth a second opinion: on XWayland XMODE is also True, so the fallback there changes from wl-copy to xclip. That appears to be the intent given detect_linux_display_server() deliberately maps XWayland to XMODE = True, but I only have an X11 machine and cannot verify it.

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 <noreply@anthropic.com>
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.

ClipCascade try to use wayland on xserver

1 participant