From 7c2f9160a3a31dd56190996a0a0986c344d53789 Mon Sep 17 00:00:00 2001 From: Zhora Zmeykin Date: Mon, 3 Aug 2026 15:33:44 +0300 Subject: [PATCH] Backport Wayland clipboard fix --- fix-qtbase-wayland-clipboard-focus.patch | 59 ++++++++++++++++++++++++ qtbase.spec | 2 + 2 files changed, 61 insertions(+) create mode 100644 fix-qtbase-wayland-clipboard-focus.patch diff --git a/fix-qtbase-wayland-clipboard-focus.patch b/fix-qtbase-wayland-clipboard-focus.patch new file mode 100644 index 00000000000..bf9dcd071d0 --- /dev/null +++ b/fix-qtbase-wayland-clipboard-focus.patch @@ -0,0 +1,59 @@ +From: David Edmundson +Date: Tue, 19 May 2026 19:47:10 +0100 +Subject: [PATCH] wayland: avoid resetting clipboard on focus out + +The wayland specification as written is rather flawed. + +> The data_offer is valid until a new data_offer or NULL is received or +until the client loses keyboard focus. Switching surface with keyboard +focus within the same client doesn't mean a new selection will be sent. + +Switching keyboard surface within the same client is not atomic in +Wayland. + +Right now we try and sync things with a roundtrip but this does not +suffice. If we close two popups in quick succession, such as a +popup-tree, the compositor may try and focus the other the now-closed +window. By the time the compositor has handled that second window +closure our callback is complete. + +The data offer not being valid doesn't mean we explicitly have to reset +our concept of it. We can treat it as being inert by just not doing +anything. It's not an error to use a defuct data_offer. It will be reset +before the next keyboard_enter event. + +This matches GTK. + +Upstream-Commit: 78a7fc3e253c48f01d86c18209aff12c0dc75d5f +Upstream-Review: https://codereview.qt-project.org/c/qt/qtbase/+/746667 +Origin-Commit: 12c844c85a66b96c73998e88fd9ace244db06e6e +Change-Id: Iaa09b642c2aa64c52ad34fb2169c3c3b6f9fa958 +Backport-Note: Keep only the runtime change needed by Qt 6.10.3; omit +the upstream test-suite changes to minimize the backport surface. +--- + src/plugins/platforms/wayland/qwaylanddisplay.cpp | 13 ------------- + 1 file changed, 13 deletions(-) + +diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp +--- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp ++++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp +@@ -1005,19 +1005,6 @@ void QWaylandDisplay::handleWaylandSync() + QWindow *activeWindow = mActiveWindows.empty() ? nullptr : mActiveWindows.last()->window(); + if (activeWindow != QGuiApplication::focusWindow()) + QWindowSystemInterface::handleFocusWindowChanged(activeWindow); +- +- if (!activeWindow) { +- if (lastInputDevice()) { +-#if QT_CONFIG(clipboard) +- if (auto *dataDevice = lastInputDevice()->dataDevice()) +- dataDevice->invalidateSelectionOffer(); +-#endif +-#if QT_CONFIG(wayland_client_primary_selection) +- if (auto *device = lastInputDevice()->primarySelectionDevice()) +- device->invalidateSelectionOffer(); +-#endif +- } +- } + } + + const wl_callback_listener QWaylandDisplay::syncCallbackListener = { diff --git a/qtbase.spec b/qtbase.spec index dcbd4acef10..1cc1f28106d 100644 --- a/qtbase.spec +++ b/qtbase.spec @@ -69,6 +69,7 @@ Patch202: qtbase-wayland-optimize-scroll-operations.patch Patch203: qtbase-wayland-enable-event-compression-and-fix-scroll-end-event.patch Patch204: qtbase-wayland-fix-crash-in-qwaylandshmbackingstore-scroll.patch Patch205: QTBUG-145310.patch +Patch206: fix-qtbase-wayland-clipboard-focus.patch # ALT Patch1000: alt-timezone.patch Patch1001: alt-zonetab.patch @@ -416,6 +417,7 @@ Requires: %name-common %patch203 -p1 %patch204 -p1 %patch205 -p1 +%patch206 -p1 # %patch1000 -p1 %patch1001 -p1 -- 2.50.1