https://bugs.kde.org/show_bug.cgi?id=525896

Dmitry <[email protected]> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |DUPLICATE
             Status|REPORTED                    |RESOLVED

--- Comment #1 from Dmitry <[email protected]> ---
Duplicate of [bug 506325](https://bugs.kde.org/show_bug.cgi?id=506325) -- "Text
selection
and primary clipboard malfunction on non-Qt applications" (plasmashell /
Clipboard widget
& pop-up), already RESOLVED FIXED. Closing this one; posting the trace since it
confirms
the same root cause from a different angle.

## Same root cause

Klipper publishes `PRIMARY` through `wlr-data-control` with the marker MIME
type
`application/x-kde-onlyReplaceEmpty`, meaning "restore this only if nobody owns
the
selection". KWin decides whether to honour it. In 6.7.5 that decision is too
weak --
`src/wayland/seat.cpp`:

```cpp
const bool isKlipperEmptyReplacement = dataDevice->primarySelection() &&
dataDevice->primarySelection()->mimeTypes().contains(QLatin1StringView("application/x-kde-onlyReplaceEmpty"));
if (isKlipperEmptyReplacement && currentPrimarySelection) {
    dataDevice->primarySelection()->cancel();
    return;
}
```

Only `currentPrimarySelection` is checked, so "the owner disconnected" and "a
live owner
deliberately cleared it" are indistinguishable.

GTK3 clears `PRIMARY` in the middle of every mouse selection gesture
(`gtk/gtktextbuffer.c`, `update_selection_clipboards()` calls
`gtk_clipboard_clear()` as
soon as the buffer has no selection). So on a press that starts a new
selection:

1. `GtkTextView` collapses the old selection to place the cursor.
2. GTK releases `PRIMARY`.
3. `currentPrimarySelection` is null, the guard does not fire, KWin accepts
Klipper's
   stale replacement.
4. The rest of the drag keeps extending the selection, but the application no
longer owns
   `PRIMARY`, so `clipboard_clear_selection_cb()` (`gtktextbuffer.c:3187`)
moves
   `selection_bound` back onto `insert` on every update. The drag produces
nothing.

Dragging when nothing is selected works, because the application does not own
`PRIMARY`
at press time, nothing is released mid-gesture, and the drag acquires ownership
cleanly.

## Evidence

The reproducer prints who holds `PRIMARY` right after a failed drag:

```
press#1 btn=1 at (207,32) event_window=text window (ok) had_selection=yes
  selection_bound moved: NO SELECTION
  [PRIMARY owner-change] we own it: NO (taken away), NO SELECTION
  [PRIMARY now offered by someone else] types:
application/x-kde-onlyReplaceEmpty, text/plain;charset=utf-8, text/plain
  [PRIMARY content] "gtk-primary-selection-bug.c"
  selection_bound moved: NO SELECTION
  selection_bound moved: NO SELECTION
  after release: NO SELECTION
```

The marker MIME type is there and the content is stale -- a string selected
long before
the test. The same GTK build behaves correctly under X11, sway and Mutter.

This also explains why the Klipper options exposed in System Settings
(`IgnoreSelection`, `SyncClipboards`) change nothing: the decision is taken on
the KWin
side, and the relevant Klipper knob (`NoEmptyClipboard`) is not in the KCM.

## Fix and version boundary

Commit `d9de57d2bda68e6964a904ca7454946515de5435`, "wayland: Only allow
replacing a
destroyed primary or clipboard selection" (Tomáš Hnyk, pushed by Vlad
Zahorodnii
2026-09-09), `BUG: 506325`:

```diff
-        if (isKlipperEmptyReplacement && currentPrimarySelection) {
+        if (isKlipperEmptyReplacement && (currentPrimarySelection ||
lastPrimarySelectionOwner)) {
```

with `lastPrimarySelectionOwner` recorded in
`SeatInterface::setPrimarySelection()` as a
`QPointer<ClientConnection>`, so it goes null only when the owning client
actually
disconnects -- exactly the "owner is gone" condition the workaround needed.

Verified against the KWin git tags:

- `git merge-base --is-ancestor d9de57d2 v6.7.5` -> not an ancestor, the fix is
**not** in 6.7.5
- `git tag --contains d9de57d2` -> `v6.7.90`, so it first ships in 6.8

Per the commit message the fix is Wayland-only: under Xwayland
`selection->client()` is
null, so the gating does not apply and the old, weaker check remains.

## Workaround until 6.8

`~/.config/klipperrc`:

```ini
[General]
NoEmptyClipboard=false
```

then restart Klipper -- currently a logout, until
[plasma-workspace!6983](https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/6983)
lands. Trade-off: clipboard content is no longer preserved when the application
that put
it there closes (it stays in the Klipper history, just not directly pastable).

## Upstream GTK side

The GTK behaviour that this interacts with is tracked at
https://gitlab.gnome.org/GNOME/gtk/-/work_items/317

*** This bug has been marked as a duplicate of bug 506325 ***

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to