Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package kf6-kguiaddons for openSUSE:Factory 
checked in at 2026-01-12 10:11:36
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kf6-kguiaddons (Old)
 and      /work/SRC/openSUSE:Factory/.kf6-kguiaddons.new.1928 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kf6-kguiaddons"

Mon Jan 12 10:11:36 2026 rev:23 rq:1326426 version:6.22.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/kf6-kguiaddons/kf6-kguiaddons.changes    
2025-12-16 15:56:06.574492305 +0100
+++ /work/SRC/openSUSE:Factory/.kf6-kguiaddons.new.1928/kf6-kguiaddons.changes  
2026-01-12 10:15:40.283555489 +0100
@@ -1,0 +2,16 @@
+Sun Jan  4 14:47:11 UTC 2026 - Christophe Marin <[email protected]>
+
+- Update to 6.22.0
+  * New feature release
+  * For more details please see:
+  * https://kde.org/announcements/frameworks/6/6.22.0
+- Changes since 6.21.0:
+  * Update dependency version to 6.22.0
+  * ksystemclipboard: Use WaylandClipboard also on wayland-egl
+  * ksystemclipboard: Dispatch read events in another thread (kde#480448)
+  * Remove focus hacks as preparation for clipoard thread
+  * Add manual test for ksystemclipboard
+  * Deprecate KColorSchemeWatcher
+  * Update version to 6.22.0
+
+-------------------------------------------------------------------

Old:
----
  kguiaddons-6.21.0.tar.xz
  kguiaddons-6.21.0.tar.xz.sig

New:
----
  kguiaddons-6.22.0.tar.xz
  kguiaddons-6.22.0.tar.xz.sig

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ kf6-kguiaddons.spec ++++++
--- /var/tmp/diff_new_pack.e3tDTN/_old  2026-01-12 10:15:42.043627765 +0100
+++ /var/tmp/diff_new_pack.e3tDTN/_new  2026-01-12 10:15:42.047627929 +0100
@@ -32,11 +32,11 @@
 %define mypython_sitearch %{expand:%%%{mypython}_sitearch}
 %endif
 
-# Full KF6 version (e.g. 6.21.0)
+# Full KF6 version (e.g. 6.22.0)
 %{!?_kf6_version: %global _kf6_version %{version}}
 %bcond_without released
 Name:           kf6-kguiaddons
-Version:        6.21.0
+Version:        6.22.0
 Release:        0
 Summary:        Utilities for graphical user interfaces
 License:        LGPL-2.1-or-later


++++++ kguiaddons-6.21.0.tar.xz -> kguiaddons-6.22.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kguiaddons-6.21.0/CMakeLists.txt 
new/kguiaddons-6.22.0/CMakeLists.txt
--- old/kguiaddons-6.21.0/CMakeLists.txt        2025-12-05 14:21:33.000000000 
+0100
+++ new/kguiaddons-6.22.0/CMakeLists.txt        2026-01-02 18:41:55.000000000 
+0100
@@ -1,10 +1,10 @@
 cmake_minimum_required(VERSION 3.16)
 
-set(KF_VERSION "6.21.0") # handled by release scripts
+set(KF_VERSION "6.22.0") # handled by release scripts
 project(KGuiAddons VERSION ${KF_VERSION})
 
 include(FeatureSummary)
-find_package(ECM 6.21.0  NO_MODULE)
+find_package(ECM 6.22.0  NO_MODULE)
 set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake 
Modules." URL "https://commits.kde.org/extra-cmake-modules";)
 feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND 
FATAL_ON_MISSING_REQUIRED_PACKAGES)
 
@@ -103,7 +103,7 @@
                         SOVERSION 6)
 
 ecm_set_disabled_deprecation_versions(
-    QT 6.10
+    QT 6.11
 )
 
 add_subdirectory(src)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kguiaddons-6.21.0/src/CMakeLists.txt 
new/kguiaddons-6.22.0/src/CMakeLists.txt
--- old/kguiaddons-6.21.0/src/CMakeLists.txt    2025-12-05 14:21:33.000000000 
+0100
+++ new/kguiaddons-6.22.0/src/CMakeLists.txt    2026-01-02 18:41:55.000000000 
+0100
@@ -121,7 +121,7 @@
     VERSION ${KF_VERSION}
     USE_VERSION_HEADER
     DEPRECATED_BASE_VERSION 0
-    DEPRECATION_VERSIONS 6.3 6.12
+    DEPRECATION_VERSIONS 6.3 6.12 6.22
 )
 
 set(kguiaddons_INCLUDES
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kguiaddons-6.21.0/src/colors/kcolorschemewatcher.cpp 
new/kguiaddons-6.22.0/src/colors/kcolorschemewatcher.cpp
--- old/kguiaddons-6.21.0/src/colors/kcolorschemewatcher.cpp    2025-12-05 
14:21:33.000000000 +0100
+++ new/kguiaddons-6.22.0/src/colors/kcolorschemewatcher.cpp    2026-01-02 
18:41:55.000000000 +0100
@@ -6,6 +6,8 @@
 
 #include "kcolorschemewatcher.h"
 
+#if KGUIADDONS_BUILD_DEPRECATED_SINCE(6, 22)
+
 #include "kcolorschemewatcher_qt.h"
 #include "kcolorschemewatcherbackend.h"
 
@@ -63,3 +65,5 @@
 }
 
 #include "moc_kcolorschemewatcher.cpp"
+
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kguiaddons-6.21.0/src/colors/kcolorschemewatcher.h 
new/kguiaddons-6.22.0/src/colors/kcolorschemewatcher.h
--- old/kguiaddons-6.21.0/src/colors/kcolorschemewatcher.h      2025-12-05 
14:21:33.000000000 +0100
+++ new/kguiaddons-6.22.0/src/colors/kcolorschemewatcher.h      2026-01-02 
18:41:55.000000000 +0100
@@ -15,11 +15,15 @@
 
 class KColorSchemeWatcherPrivate;
 
+#if KGUIADDONS_ENABLE_DEPRECATED_SINCE(6, 22)
+
 /*!
  * \class KColorSchemeWatcher
  * \inmodule KGuiAddons
  * \brief Information about system-wide color preferences.
  * \since 5.100
+ * \deprecated[6.22]
+ * Use QStyleHints and QAccessibilityHints instead
  */
 class KGUIADDONS_EXPORT KColorSchemeWatcher : public QObject
 {
@@ -49,6 +53,7 @@
     /*!
      *
      */
+    KGUIADDONS_DEPRECATED_VERSION(6, 22, "Use Qt API instead")
     KColorSchemeWatcher(QObject *parent = nullptr);
     ~KColorSchemeWatcher() override;
 
@@ -68,3 +73,5 @@
 };
 
 #endif
+
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kguiaddons-6.21.0/src/systemclipboard/ksystemclipboard.cpp 
new/kguiaddons-6.22.0/src/systemclipboard/ksystemclipboard.cpp
--- old/kguiaddons-6.21.0/src/systemclipboard/ksystemclipboard.cpp      
2025-12-05 14:21:33.000000000 +0100
+++ new/kguiaddons-6.22.0/src/systemclipboard/ksystemclipboard.cpp      
2026-01-02 18:41:55.000000000 +0100
@@ -24,7 +24,7 @@
 
 #ifdef WITH_WAYLAND
     static bool s_waylandChecked = false;
-    if (!systemClipboard && qGuiApp->platformName() == 
QLatin1String("wayland") && !s_waylandChecked) {
+    if (!systemClipboard && 
qGuiApp->platformName().startsWith(QLatin1String("wayland")) && 
!s_waylandChecked) {
         s_waylandChecked = true;
 
         if (auto waylandClipboard = WaylandClipboard::create(qApp)) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kguiaddons-6.21.0/src/systemclipboard/waylandclipboard.cpp 
new/kguiaddons-6.22.0/src/systemclipboard/waylandclipboard.cpp
--- old/kguiaddons-6.21.0/src/systemclipboard/waylandclipboard.cpp      
2025-12-05 14:21:33.000000000 +0100
+++ new/kguiaddons-6.22.0/src/systemclipboard/waylandclipboard.cpp      
2026-01-02 18:41:55.000000000 +0100
@@ -1,7 +1,6 @@
 /*
     SPDX-FileCopyrightText: 2020 David Edmundson <[email protected]>
     SPDX-FileCopyrightText: 2021 Méven Car <[email protected]>
-
     SPDX-License-Identifier: LGPL-2.0-or-later
 */
 
@@ -13,7 +12,10 @@
 #include <QImageReader>
 #include <QImageWriter>
 #include <QMimeData>
+#include <QMutex>
 #include <QPointer>
+#include <QThread>
+#include <QTimer>
 #include <QWaylandClientExtension>
 #include <QWindow>
 #include <QtWaylandClientVersion>
@@ -28,6 +30,14 @@
 #include "qwayland-wayland.h"
 #include "qwayland-ext-data-control-v1.h"
 
+/**
+ * Wayland clipboard wraps ext_data_control an additional is used as we need 
to avoid
+ * deadlocks if an application tries to read the normal clipboard whilst it 
owns the data control.
+ *
+ * To solve this all ext_data_control classes live on another thread which 
dispatches events on a separate
+ * queue. A recursive mutex allows the main thread to read mimedata and no 
wayland events which change the mimedata process until this is complete.
+ */
+
 static inline QString applicationQtXImageLiteral()
 {
     return QStringLiteral("application/x-qt-image");
@@ -298,10 +308,6 @@
     {
         return m_mimeData.get();
     }
-    std::unique_ptr<QMimeData> releaseMimeData()
-    {
-        return std::move(m_mimeData);
-    }
 
 Q_SIGNALS:
     void cancelled();
@@ -445,6 +451,7 @@
 
     void ext_data_control_device_v1_selection(struct 
::ext_data_control_offer_v1 *id) override
     {
+        QMutexLocker locker(&m_selectionLock);
         if (!id) {
             m_receivedSelection.reset();
         } else {
@@ -457,6 +464,7 @@
 
     void ext_data_control_device_v1_primary_selection(struct 
::ext_data_control_offer_v1 *id) override
     {
+        QMutexLocker locker(&m_primarySelectionLock);
         if (!id) {
             m_receivedPrimarySelection.reset();
         } else {
@@ -468,9 +476,11 @@
     }
 
 private:
+    QRecursiveMutex m_selectionLock;
     std::unique_ptr<DataControlSource> m_selection; // selection set locally
     std::unique_ptr<DataControlOffer> m_receivedSelection; // latest selection 
set from externally to here
 
+    QRecursiveMutex m_primarySelectionLock;
     std::unique_ptr<DataControlSource> m_primarySelection; // selection set 
locally
     std::unique_ptr<DataControlOffer> m_receivedPrimarySelection; // latest 
selection set from externally to here
     friend WaylandClipboard;
@@ -478,106 +488,92 @@
 
 void DataControlDevice::setSelection(std::unique_ptr<DataControlSource> 
selection)
 {
-    set_selection(selection->object());
+    {
+        QMutexLocker locker(&m_selectionLock);
+        set_selection(selection->object());
 
-    // Note the previous selection is destroyed after the set_selection 
request.
-    m_selection = std::move(selection);
-    connect(m_selection.get(), &DataControlSource::cancelled, this, [this]() {
-        m_selection.reset();
-    });
+        // Note the previous selection is destroyed after the set_selection 
request.
+        m_selection = std::move(selection);
+        connect(m_selection.get(), &DataControlSource::cancelled, this, 
[this]() {
+            m_selection.reset();
+        });
+    }
 
     Q_EMIT selectionChanged();
 }
 
 void DataControlDevice::setPrimarySelection(std::unique_ptr<DataControlSource> 
selection)
 {
-    set_primary_selection(selection->object());
+    {
+        QMutexLocker locker(&m_primarySelectionLock);
+        set_primary_selection(selection->object());
 
-    // Note the previous selection is destroyed after the 
set_primary_selection request.
-    m_primarySelection = std::move(selection);
-    connect(m_primarySelection.get(), &DataControlSource::cancelled, this, 
[this]() {
-        m_primarySelection.reset();
-    });
+        // Note the previous selection is destroyed after the 
set_primary_selection request.
+        m_primarySelection = std::move(selection);
+        connect(m_primarySelection.get(), &DataControlSource::cancelled, this, 
[this]() {
+            m_primarySelection.reset();
+        });
+    }
 
     Q_EMIT primarySelectionChanged();
 }
-class Keyboard;
-// We are binding to Seat/Keyboard manually because we want to react to 
gaining focus but inside Qt the events are Qt and arrive to late
-class KeyboardFocusWatcher : public 
QWaylandClientExtensionTemplate<KeyboardFocusWatcher>, public QtWayland::wl_seat
+
+class ClipboardThread : public QThread
 {
-    Q_OBJECT
 public:
-    KeyboardFocusWatcher()
-        : QWaylandClientExtensionTemplate(5)
-    {
-        initialize();
-        auto waylandApp = 
qGuiApp->nativeInterface<QNativeInterface::QWaylandApplication>();
-        auto display = waylandApp->display();
-        // so we get capabilities
-        wl_display_roundtrip(display);
-    }
-    ~KeyboardFocusWatcher() override
+    ClipboardThread(wl_display *display)
+        : m_display(display)
     {
-        if (isActive()) {
-            release();
-        }
+        m_queue = wl_display_create_queue_with_name(m_display, 
"ksystemclipboard queue");
     }
-    void seat_capabilities(uint32_t capabilities) override
+
+    ~ClipboardThread()
     {
-        const bool hasKeyboard = capabilities & capability_keyboard;
-        if (hasKeyboard && !m_keyboard) {
-            m_keyboard = std::make_unique<Keyboard>(get_keyboard(), *this);
-        } else if (!hasKeyboard && m_keyboard) {
-            m_keyboard.reset();
+        if (m_callback) {
+            wl_callback_destroy(m_callback);
         }
+        wl_event_queue_destroy(m_queue);
     }
-    bool hasFocus() const
-    {
-        return m_focus;
-    }
-Q_SIGNALS:
-    void keyboardEntered();
-
-private:
-    friend Keyboard;
-    bool m_focus = false;
-    std::unique_ptr<Keyboard> m_keyboard;
-};
 
-class Keyboard : public QtWayland::wl_keyboard
-{
-public:
-    Keyboard(::wl_keyboard *keyboard, KeyboardFocusWatcher &seat)
-        : wl_keyboard(keyboard)
-        , m_seat(seat)
+    void syncQueue()
     {
-    }
-    ~Keyboard()
-    {
-        release();
+        // wl_display_dispatch_queue will block until it gets an event, as 
KSystemClipboard
+        // has the lifespan of the QApplication and the QPA is still alive
+        // we need something to explicitly wake up the event queue up before 
the main thread
+        // blocks waiting for this thread.
+        auto wrapped_display = wl_proxy_create_wrapper(m_display);
+        wl_proxy_set_queue(static_cast<wl_proxy *>(wrapped_display), m_queue);
+        m_callback = wl_display_sync(static_cast<struct wl_display 
*>(wrapped_display));
+        wl_display_flush(m_display);
+        wl_proxy_wrapper_destroy(wrapped_display);
     }
 
-private:
-    void keyboard_enter([[maybe_unused]] uint32_t serial, [[maybe_unused]] 
wl_surface *surface, [[maybe_unused]] wl_array *keys) override
+    void run() override
     {
-        m_seat.m_focus = true;
-        Q_EMIT m_seat.keyboardEntered();
-    }
-    void keyboard_leave([[maybe_unused]] uint32_t serial, [[maybe_unused]] 
wl_surface *surface) override
-    {
-        m_seat.m_focus = false;
+        int ret = 0;
+        while (ret >= 0 && !qGuiApp->closingDown()) {
+            ret = wl_display_dispatch_queue(m_display, m_queue);
+        }
     }
-    KeyboardFocusWatcher &m_seat;
+    wl_callback *m_callback = nullptr;
+    wl_event_queue *m_queue = nullptr;
+    wl_display *m_display = nullptr;
 };
 
 WaylandClipboard::WaylandClipboard(QObject *parent)
     : KSystemClipboard(parent)
-    , m_keyboardFocusWatcher(new KeyboardFocusWatcher)
     , m_manager(new DataControlDeviceManager)
 {
+    auto waylandApp = 
qGuiApp->nativeInterface<QNativeInterface::QWaylandApplication>();
+    if (!waylandApp) {
+        return;
+    }
+
     connect(m_manager.get(), &DataControlDeviceManager::activeChanged, this, 
[this]() {
         if (m_manager->isActive()) {
             auto waylandApp = 
qGuiApp->nativeInterface<QNativeInterface::QWaylandApplication>();
+            m_thread = 
std::make_unique<ClipboardThread>(waylandApp->display());
+
             if (!waylandApp) {
                 return;
             }
@@ -586,7 +582,9 @@
             if (!seat) {
                 return;
             }
+            wl_proxy_set_queue(reinterpret_cast<wl_proxy 
*>(m_manager->object()), m_thread->m_queue);
             m_device.reset(new 
DataControlDevice(m_manager->get_data_device(seat)));
+            m_device->moveToThread(m_thread.get());
 
             connect(m_device.get(), 
&DataControlDevice::receivedSelectionChanged, this, [this]() {
                 // When our source is still valid, so the offer is for setting 
it or we emit changed when it is cancelled
@@ -607,16 +605,25 @@
             connect(m_device.get(), 
&DataControlDevice::primarySelectionChanged, this, [this]() {
                 Q_EMIT changed(QClipboard::Selection);
             });
+            m_thread->start();
 
         } else {
             m_device.reset();
+            m_thread->wait();
+            m_thread.reset();
         }
     });
 
     m_manager->instantiate();
 }
 
-WaylandClipboard::~WaylandClipboard() = default;
+WaylandClipboard::~WaylandClipboard()
+{
+    if (m_thread->isRunning()) {
+        m_thread->syncQueue();
+        m_thread->wait();
+    }
+}
 
 WaylandClipboard *WaylandClipboard::create(QObject *parent)
 {
@@ -639,23 +646,8 @@
         return;
     }
 
-    // roundtrip to have accurate focus state when losing focus but setting 
mime data before processing wayland events.
-    auto waylandApp = 
qGuiApp->nativeInterface<QNativeInterface::QWaylandApplication>();
-    auto display = waylandApp->display();
-    wl_display_roundtrip(display);
-
-    // If the application is focused, use the normal mechanism so a future 
paste will not deadlock itselfs
-    if (m_keyboardFocusWatcher->hasFocus()) {
-        QGuiApplication::clipboard()->setMimeData(mime, mode);
-        // if we short-circuit the ext_data_device, when we receive the data
-        // we cannot identify ourselves as the owner
-        // because of that we act like it's a synchronous action to not 
confuse klipper.
-        wl_display_roundtrip(display);
-        return;
-    }
-    // If not, set the clipboard once the app receives focus to avoid the 
deadlock
-    connect(m_keyboardFocusWatcher.get(), 
&KeyboardFocusWatcher::keyboardEntered, this, &WaylandClipboard::gainedFocus, 
Qt::UniqueConnection);
     auto source = 
std::make_unique<DataControlSource>(m_manager->create_data_source(), mime);
+    source->moveToThread(m_thread.get());
     if (mode == QClipboard::Clipboard) {
         m_device->setSelection(std::move(source));
     } else if (mode == QClipboard::Selection) {
@@ -663,31 +655,18 @@
     }
 }
 
-void WaylandClipboard::gainedFocus()
-{
-    disconnect(m_keyboardFocusWatcher.get(), 
&KeyboardFocusWatcher::keyboardEntered, this, nullptr);
-    // QClipboard takes ownership of the QMimeData so we need to transfer and 
unset our selections
-    if (auto &selection = m_device->m_selection) {
-        std::unique_ptr<QMimeData> data = selection->releaseMimeData();
-        selection.reset();
-        QGuiApplication::clipboard()->setMimeData(data.release(), 
QClipboard::Clipboard);
-    }
-    if (auto &primarySelection = m_device->m_primarySelection) {
-        std::unique_ptr<QMimeData> data = primarySelection->releaseMimeData();
-        primarySelection.reset();
-        QGuiApplication::clipboard()->setMimeData(data.release(), 
QClipboard::Selection);
-    }
-}
-
 void WaylandClipboard::clear(QClipboard::Mode mode)
 {
     if (!m_device) {
         return;
     }
+
     if (mode == QClipboard::Clipboard) {
+        QMutexLocker locker(&m_device->m_selectionLock);
         m_device->set_selection(nullptr);
         m_device->m_selection.reset();
     } else if (mode == QClipboard::Selection) {
+        QMutexLocker locker(&m_device->m_primarySelectionLock);
         m_device->set_primary_selection(nullptr);
         m_device->m_primarySelection.reset();
     }
@@ -699,24 +678,42 @@
         return nullptr;
     }
 
+    // WaylandClipboard owns the mimedata, but the caller can read it until 
the next event loop runs.
+    auto lockWithUnlockLater = [this](QRecursiveMutex &mutex) {
+        mutex.lock();
+        QTimer::singleShot(0, this, [&mutex, guard = 
QPointer<DataControlDevice>(m_device.get())] {
+            if (!guard) {
+                return;
+            }
+            mutex.unlock();
+        });
+    };
+
     // return our locally set selection if it's not cancelled to avoid copying 
data to ourselves
     if (mode == QClipboard::Clipboard) {
+        QMutexLocker lock(&m_device->m_selectionLock);
         if (m_device->selection()) {
             return m_device->selection();
         }
+
         // This application owns the clipboard via the regular data_device, 
use it so we don't block ourselves
         if (QGuiApplication::clipboard()->ownsClipboard()) {
             return QGuiApplication::clipboard()->mimeData(mode);
         }
+        lockWithUnlockLater(m_device->m_selectionLock);
         return m_device->receivedSelection();
     } else if (mode == QClipboard::Selection) {
+        QMutexLocker lock(&m_device->m_primarySelectionLock);
         if (m_device->primarySelection()) {
             return m_device->primarySelection();
         }
+
         // This application owns the primary selection via the regular 
primary_selection_device, use it so we don't block ourselves
         if (QGuiApplication::clipboard()->ownsSelection()) {
             return QGuiApplication::clipboard()->mimeData(mode);
         }
+
+        lockWithUnlockLater(m_device->m_primarySelectionLock);
         return m_device->receivedPrimarySelection();
     }
     return nullptr;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/kguiaddons-6.21.0/src/systemclipboard/waylandclipboard_p.h 
new/kguiaddons-6.22.0/src/systemclipboard/waylandclipboard_p.h
--- old/kguiaddons-6.21.0/src/systemclipboard/waylandclipboard_p.h      
2025-12-05 14:21:33.000000000 +0100
+++ new/kguiaddons-6.22.0/src/systemclipboard/waylandclipboard_p.h      
2026-01-02 18:41:55.000000000 +0100
@@ -13,10 +13,11 @@
 
 class DataControlDevice;
 class DataControlDeviceManager;
-class KeyboardFocusWatcher;
+class ClipboardThread;
 
 class WaylandClipboard : public KSystemClipboard
 {
+    Q_OBJECT
 public:
     ~WaylandClipboard();
     static WaylandClipboard *create(QObject *parent);
@@ -28,8 +29,7 @@
 
 private:
     WaylandClipboard(QObject *parent);
-    void gainedFocus();
-    std::unique_ptr<KeyboardFocusWatcher> m_keyboardFocusWatcher;
+    std::unique_ptr<ClipboardThread> m_thread;
     std::unique_ptr<DataControlDeviceManager> m_manager;
     std::unique_ptr<DataControlDevice> m_device;
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kguiaddons-6.21.0/tests/CMakeLists.txt 
new/kguiaddons-6.22.0/tests/CMakeLists.txt
--- old/kguiaddons-6.21.0/tests/CMakeLists.txt  2025-12-05 14:21:33.000000000 
+0100
+++ new/kguiaddons-6.22.0/tests/CMakeLists.txt  2026-01-02 18:41:55.000000000 
+0100
@@ -20,4 +20,5 @@
   kcursorsavergui_test
   kcolorschemewatchertest
   kcountryflagemojiiconenginedemo
+  clipboardtest
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kguiaddons-6.21.0/tests/clipboardtest.cpp 
new/kguiaddons-6.22.0/tests/clipboardtest.cpp
--- old/kguiaddons-6.21.0/tests/clipboardtest.cpp       1970-01-01 
01:00:00.000000000 +0100
+++ new/kguiaddons-6.22.0/tests/clipboardtest.cpp       2026-01-02 
18:41:55.000000000 +0100
@@ -0,0 +1,116 @@
+/*
+    SPDX-FileCopyrightText: 2025 David Edmundson <[email protected]>
+    SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include <KSystemClipboard>
+#include <QApplication>
+#include <QClipboard>
+#include <QFormLayout>
+#include <QGroupBox>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QLineEdit>
+#include <QMimeData>
+#include <QPushButton>
+#include <QTableView>
+#include <QTextEdit>
+#include <QVBoxLayout>
+#include <QWidget>
+
+// This tests KSystemClipboard
+// it also shows the Qt Clipboard so that we can confirm nothing deadlocks
+// copying between the two
+
+int main(int argc, char **argv)
+{
+    QApplication app(argc, argv);
+
+    QWidget window;
+    window.setWindowTitle(QStringLiteral("Clipboard Test"));
+
+    auto *rootLayout = new QHBoxLayout(&window);
+
+    // regular clipboard
+    {
+        auto clipboard = QApplication::clipboard();
+        auto *group = new QGroupBox(QStringLiteral("Normal Clipboard"), 
&window);
+        rootLayout->addWidget(group);
+
+        auto *groupLayout = new QVBoxLayout(group);
+
+        auto *clipboardView = new QTextEdit(&window);
+        clipboardView->setEnabled(false);
+
+        clipboardView->setMinimumHeight(200);
+        QObject::connect(clipboard, &QClipboard::changed, clipboardView, 
[clipboardView, clipboard](QClipboard::Mode mode) {
+            if (mode != QClipboard::Clipboard) {
+                return;
+            }
+            clipboardView->setText(clipboard->text());
+        });
+        clipboardView->setText(clipboard->text());
+
+        groupLayout->addWidget(clipboardView);
+
+        auto *textEdit = new QTextEdit(group);
+        textEdit->setPlaceholderText(QStringLiteral("Enter clipboard content 
here…"));
+        textEdit->setMinimumHeight(120);
+        groupLayout->addWidget(textEdit);
+
+        auto *btnRow = new QHBoxLayout();
+        btnRow->addStretch();
+        auto *submitBtn = new QPushButton(QStringLiteral("Submit"), group);
+        btnRow->addWidget(submitBtn);
+        groupLayout->addLayout(btnRow);
+
+        QObject::connect(submitBtn, &QPushButton::clicked, &window, [textEdit, 
clipboard]() {
+            auto mimeData = new QMimeData;
+            mimeData->setText(textEdit->toPlainText());
+            clipboard->setMimeData(mimeData, QClipboard::Clipboard);
+        });
+    }
+    // system clipboard
+    {
+        auto clipboard = KSystemClipboard::instance();
+        auto *group = new QGroupBox(QStringLiteral("System Clipboard"), 
&window);
+        rootLayout->addWidget(group);
+
+        auto *groupLayout = new QVBoxLayout(group);
+
+        auto *clipboardView = new QTextEdit(&window);
+        clipboardView->setEnabled(false);
+
+        clipboardView->setMinimumHeight(200);
+        QObject::connect(clipboard, &KSystemClipboard::changed, clipboardView, 
[clipboardView, clipboard](QClipboard::Mode mode) {
+            if (mode != QClipboard::Clipboard) {
+                return;
+            }
+            clipboardView->setText(clipboard->text(mode));
+        });
+        clipboardView->setText(clipboard->text(QClipboard::Clipboard));
+
+        groupLayout->addWidget(clipboardView);
+
+        auto *textEdit = new QTextEdit(group);
+        textEdit->setPlaceholderText(QStringLiteral("Enter clipboard content 
here…"));
+        textEdit->setMinimumHeight(120);
+        groupLayout->addWidget(textEdit);
+
+        auto *btnRow = new QHBoxLayout();
+        btnRow->addStretch();
+        auto *submitBtn = new QPushButton(QStringLiteral("Submit"), group);
+        btnRow->addWidget(submitBtn);
+        groupLayout->addLayout(btnRow);
+
+        QObject::connect(submitBtn, &QPushButton::clicked, &window, [textEdit, 
clipboard]() {
+            auto mimeData = new QMimeData;
+            mimeData->setText(textEdit->toPlainText());
+            clipboard->setMimeData(mimeData, QClipboard::Clipboard);
+        });
+    }
+
+    window.resize(600, 500);
+    window.show();
+    return app.exec();
+}

Reply via email to