diff --git a/roles/kde/patches/kwin/patches.txt b/roles/kde/patches/kwin/patches.txt index f860b5d..7ac9343 100644 --- a/roles/kde/patches/kwin/patches.txt +++ b/roles/kde/patches/kwin/patches.txt @@ -3,3 +3,4 @@ Pr 3612 https://invent.kde.org/plasma/kwin/-/merge_requests/3612 Pr 7823 https://invent.kde.org/plasma/kwin/-/merge_requests/7823 Pr 8005 https://invent.kde.org/plasma/kwin/-/merge_requests/8005 Depends on Pr 7927 https://invent.kde.org/plasma/kwin/-/merge_requests/7927 +Pr 8155 https://invent.kde.org/plasma/kwin/-/merge_requests/8155 diff --git a/roles/kde/patches/kwin/pr8155.patch b/roles/kde/patches/kwin/pr8155.patch new file mode 100644 index 0000000..ff8eb4b --- /dev/null +++ b/roles/kde/patches/kwin/pr8155.patch @@ -0,0 +1,60 @@ +From bab7c4a4c5e2fb7be83ba94fdd0da7fd196654fa Mon Sep 17 00:00:00 2001 +From: David Redondo +Date: Thu, 25 Sep 2025 12:00:51 +0200 +Subject: [PATCH] Make sure XdgToplevelWindow always has an icon + +If the client never called set_app_id and did not set a custom +icon the window would end up without an icon at all. This ensures +that all windows always have at least the default icon. +--- + autotests/integration/xdgshellwindow_test.cpp | 13 +++++++++++-- + src/xdgshellwindow.cpp | 1 + + 2 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/autotests/integration/xdgshellwindow_test.cpp b/autotests/integration/xdgshellwindow_test.cpp +index 0903043808d..a3658ee62e7 100644 +--- a/autotests/integration/xdgshellwindow_test.cpp ++++ b/autotests/integration/xdgshellwindow_test.cpp +@@ -683,16 +683,25 @@ void TestXdgShellWindow::testDesktopFileName() + std::unique_ptr surface(Test::createSurface()); + // only xdg-shell as ShellSurface misses the setter + std::unique_ptr shellSurface(Test::createXdgToplevelSurface(surface.get())); +- shellSurface->set_app_id(QStringLiteral("org.kde.foo")); + auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); + QVERIFY(window); ++ ++ // A client that never call set_app_id still gets the default icon ++ QCOMPARE(window->desktopFileName(), QString()); ++ QVERIFY(window->resourceClass().startsWith("testXdgShellWindow")); ++ QVERIFY(window->resourceName().startsWith("testXdgShellWindow")); ++ QCOMPARE(window->icon().name(), QStringLiteral("wayland")); ++ ++ QSignalSpy desktopFileNameChangedSpy(window, &Window::desktopFileNameChanged); ++ ++ shellSurface->set_app_id(QStringLiteral("org.kde.foo")); ++ QVERIFY(desktopFileNameChangedSpy.wait()); + QCOMPARE(window->desktopFileName(), QStringLiteral("org.kde.foo")); + QCOMPARE(window->resourceClass(), QStringLiteral("org.kde.foo")); + QVERIFY(window->resourceName().startsWith("testXdgShellWindow")); + // the desktop file does not exist, so icon should be generic Wayland + QCOMPARE(window->icon().name(), QStringLiteral("wayland")); + +- QSignalSpy desktopFileNameChangedSpy(window, &Window::desktopFileNameChanged); + QSignalSpy iconChangedSpy(window, &Window::iconChanged); + shellSurface->set_app_id(QStringLiteral("org.kde.bar")); + QVERIFY(desktopFileNameChangedSpy.wait()); +diff --git a/src/xdgshellwindow.cpp b/src/xdgshellwindow.cpp +index f585d3aef95..092c284b8c2 100644 +--- a/src/xdgshellwindow.cpp ++++ b/src/xdgshellwindow.cpp +@@ -1426,6 +1426,7 @@ void XdgToplevelWindow::initialize() + scheduleConfigure(); + updateColorScheme(); + updateCapabilities(); ++ updateIcon(); + setupWindowManagementInterface(); + + m_isInitialized = true; +-- +GitLab + diff --git a/roles/kde/patches/kwindowsystem/1-pr187.patch b/roles/kde/patches/kwindowsystem/1-pr187.patch new file mode 100644 index 0000000..9021735 --- /dev/null +++ b/roles/kde/patches/kwindowsystem/1-pr187.patch @@ -0,0 +1,78 @@ +From b05d0431d741510c12294c85dc5ce001a8aceca2 Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Wed, 17 Sep 2025 11:41:15 +0300 +Subject: [PATCH 1/2] wayland: Fix leaking xdg activation objects + +Nobody destroys WaylandXdgActivationV1 objects, we also must call destroy() +manually. +--- + src/platforms/wayland/waylandxdgactivationv1_p.h | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/src/platforms/wayland/waylandxdgactivationv1_p.h b/src/platforms/wayland/waylandxdgactivationv1_p.h +index e74c550b..e3b14c27 100644 +--- a/src/platforms/wayland/waylandxdgactivationv1_p.h ++++ b/src/platforms/wayland/waylandxdgactivationv1_p.h +@@ -16,10 +16,18 @@ class QWaylandSurface; + class WaylandXdgActivationTokenV1 : public QObject, public QtWayland::xdg_activation_token_v1 + { + Q_OBJECT ++ + public: ++ ~WaylandXdgActivationTokenV1() override ++ { ++ destroy(); ++ } ++ ++protected: + void xdg_activation_token_v1_done(const QString &token) override + { + Q_EMIT done(token); ++ deleteLater(); + } + + Q_SIGNALS: +-- +GitLab + + +From ac28bf993ba7295faf39607d4b4402f6dce1c36b Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Wed, 17 Sep 2025 11:43:16 +0300 +Subject: [PATCH 2/2] wayland: Drop WaylandXdgActivationTokenV1::failed signal + +It's not emitted by anyone. +--- + src/platforms/wayland/waylandxdgactivationv1_p.h | 1 - + src/platforms/wayland/windowsystem.cpp | 3 --- + 2 files changed, 4 deletions(-) + +diff --git a/src/platforms/wayland/waylandxdgactivationv1_p.h b/src/platforms/wayland/waylandxdgactivationv1_p.h +index e3b14c27..077ccd93 100644 +--- a/src/platforms/wayland/waylandxdgactivationv1_p.h ++++ b/src/platforms/wayland/waylandxdgactivationv1_p.h +@@ -31,7 +31,6 @@ protected: + } + + Q_SIGNALS: +- void failed(); + void done(const QString &token); + }; + +diff --git a/src/platforms/wayland/windowsystem.cpp b/src/platforms/wayland/windowsystem.cpp +index 034ffd37..f2d8b4f2 100644 +--- a/src/platforms/wayland/windowsystem.cpp ++++ b/src/platforms/wayland/windowsystem.cpp +@@ -95,9 +95,6 @@ void WindowSystem::requestToken(QWindow *window, uint32_t serial, const QString + auto waylandApp = qGuiApp->nativeInterface(); + auto seat = waylandApp ? waylandApp->lastInputSeat() : nullptr; + auto tokenReq = activation->requestXdgActivationToken(seat, wlSurface, serial, app_id); +- connect(tokenReq, &WaylandXdgActivationTokenV1::failed, KWindowSystem::self(), [serial, app_id]() { +- Q_EMIT KWaylandExtras::self()->xdgActivationTokenArrived(serial, {}); +- }); + connect(tokenReq, &WaylandXdgActivationTokenV1::done, KWindowSystem::self(), [serial](const QString &token) { + Q_EMIT KWaylandExtras::self()->xdgActivationTokenArrived(serial, token); + }); +-- +GitLab + diff --git a/roles/kde/patches/kwindowsystem/patches.txt b/roles/kde/patches/kwindowsystem/patches.txt new file mode 100644 index 0000000..f7b32a9 --- /dev/null +++ b/roles/kde/patches/kwindowsystem/patches.txt @@ -0,0 +1,4 @@ +Plasma 6.6.0: + +Pr 186 https://invent.kde.org/frameworks/kwindowsystem/-/merge_requests/186 +Pr 187 https://invent.kde.org/frameworks/kwindowsystem/-/merge_requests/187 diff --git a/roles/kde/patches/kwindowsystem/pr186.patch b/roles/kde/patches/kwindowsystem/pr186.patch new file mode 100644 index 0000000..c77e64f --- /dev/null +++ b/roles/kde/patches/kwindowsystem/pr186.patch @@ -0,0 +1,415 @@ +From 9d0ffb13d290d76df03d199b50c3b3364d4b93bc Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Wed, 17 Sep 2025 10:14:15 +0300 +Subject: [PATCH 1/2] Add QFuture-based xdg-activation token helpers + +QFuture can be used to make the code that needs activation tokens cleaner. +--- + src/kwaylandextras.cpp | 14 +++++++++++ + src/kwaylandextras.h | 21 ++++++++++++++++ + src/kwindowsystem_p.h | 8 ++++++ + .../wayland/waylandxdgactivationv1_p.h | 19 ++++++++++++++ + src/platforms/wayland/windowsystem.cpp | 25 ++++++++++++++++--- + src/platforms/wayland/windowsystem.h | 3 ++- + tests/activationtest.cpp | 13 +++++----- + tests/kwaylandextrastest.cpp | 12 +++------ + 8 files changed, 95 insertions(+), 20 deletions(-) + +diff --git a/src/kwaylandextras.cpp b/src/kwaylandextras.cpp +index 036d57d3..a5f8af8f 100644 +--- a/src/kwaylandextras.cpp ++++ b/src/kwaylandextras.cpp +@@ -63,4 +63,18 @@ void KWaylandExtras::unexportWindow(QWindow *window) + } + } + ++QFuture KWaylandExtras::xdgActivationToken(QWindow *window, uint32_t serial, const QString &appId) ++{ ++ if (auto dv3 = dynamic_cast(KWindowSystem::d_func())) { ++ return dv3->xdgActivationToken(window, serial, appId); ++ } else { ++ return QFuture(); ++ } ++} ++ ++QFuture KWaylandExtras::xdgActivationToken(QWindow *window, const QString &appId) ++{ ++ return xdgActivationToken(window, lastInputSerial(window), appId); ++} ++ + #include "moc_kwaylandextras.cpp" +diff --git a/src/kwaylandextras.h b/src/kwaylandextras.h +index f43135d0..2f763dd5 100644 +--- a/src/kwaylandextras.h ++++ b/src/kwaylandextras.h +@@ -9,6 +9,7 @@ + #ifndef KWAYLANDEXTRAS_H + #define KWAYLANDEXTRAS_H + ++#include + #include + #include + +@@ -61,6 +62,26 @@ public: + */ + Q_INVOKABLE static void unexportWindow(QWindow *window); + ++ /*! ++ * Requests an xdg_activation_v1 token for a specific window \a window with the given \a appId. ++ * The \a serial indicates an event that triggered the request. ++ * ++ * \note No xdgActivationTokenArrived() signal will be emitted for this token. ++ * ++ * \since 6.19 ++ */ ++ static QFuture xdgActivationToken(QWindow *window, uint32_t serial, const QString &appId); ++ ++ /*! ++ * Requests an xdg_activation_v1 token for a specific window \a window with the given \a appId. ++ * The last received input serial will be used to request the token. ++ * ++ * \note No xdgActivationTokenArrived() signal will be emitted for this token. ++ * ++ * \since 6.19 ++ */ ++ static QFuture xdgActivationToken(QWindow *window, const QString &appId); ++ + Q_SIGNALS: + /*! + * Activation \a token to pass to the client. +diff --git a/src/kwindowsystem_p.h b/src/kwindowsystem_p.h +index eb9348ba..e4b51e3e 100644 +--- a/src/kwindowsystem_p.h ++++ b/src/kwindowsystem_p.h +@@ -7,6 +7,8 @@ + #define KWINDOWSYSTEM_P_H + + #include "netwm_def.h" ++ ++#include + #include + #include //For WId + #include +@@ -33,4 +35,10 @@ public: + virtual void unexportWindow(QWindow *window) = 0; + }; + ++class KWINDOWSYSTEM_EXPORT KWindowSystemPrivateV3 : public KWindowSystemPrivateV2 ++{ ++public: ++ virtual QFuture xdgActivationToken(QWindow *window, uint32_t serial, const QString &appId) = 0; ++}; ++ + #endif +diff --git a/src/platforms/wayland/waylandxdgactivationv1_p.h b/src/platforms/wayland/waylandxdgactivationv1_p.h +index 077ccd93..629d45ef 100644 +--- a/src/platforms/wayland/waylandxdgactivationv1_p.h ++++ b/src/platforms/wayland/waylandxdgactivationv1_p.h +@@ -8,7 +8,10 @@ + #define WAYLANDXDGACTIVATIONV1_P_H + + #include "qwayland-xdg-activation-v1.h" ++ ++#include + #include ++#include + #include + + class QWaylandSurface; +@@ -18,20 +21,36 @@ class WaylandXdgActivationTokenV1 : public QObject, public QtWayland::xdg_activa + Q_OBJECT + + public: ++ WaylandXdgActivationTokenV1() ++ { ++ m_promise.start(); ++ } ++ + ~WaylandXdgActivationTokenV1() override + { + destroy(); + } + ++ QFuture future() const ++ { ++ return m_promise.future(); ++ } ++ + protected: + void xdg_activation_token_v1_done(const QString &token) override + { ++ m_promise.addResult(token); ++ m_promise.finish(); ++ + Q_EMIT done(token); + deleteLater(); + } + + Q_SIGNALS: + void done(const QString &token); ++ ++private: ++ QPromise m_promise; + }; + + class WaylandXdgActivationV1 : public QWaylandClientExtensionTemplate, public QtWayland::xdg_activation_v1 +diff --git a/src/platforms/wayland/windowsystem.cpp b/src/platforms/wayland/windowsystem.cpp +index f2d8b4f2..ebb22d78 100644 +--- a/src/platforms/wayland/windowsystem.cpp ++++ b/src/platforms/wayland/windowsystem.cpp +@@ -50,9 +50,7 @@ public: + }; + + WindowSystem::WindowSystem() +- : QObject() +- , KWindowSystemPrivateV2() +- , m_lastToken(qEnvironmentVariable("XDG_ACTIVATION_TOKEN")) ++ : m_lastToken(qEnvironmentVariable("XDG_ACTIVATION_TOKEN")) + { + m_windowManagement = new WindowManagement; + } +@@ -303,4 +301,25 @@ void WindowSystem::doSetMainWindow(QWindow *window, const QString &handle) + } + } + ++QFuture WindowSystem::xdgActivationToken(QWindow *window, uint32_t serial, const QString &appId) ++{ ++ WaylandXdgActivationV1 *activation = WaylandXdgActivationV1::self(); ++ if (!activation->isActive()) { ++ return QFuture(); ++ } ++ ++ auto waylandApp = qGuiApp->nativeInterface(); ++ if (!waylandApp) { ++ return QFuture(); ++ } ++ ++ if (window) { ++ window->create(); ++ } ++ wl_surface *wlSurface = surfaceForWindow(window); ++ ++ auto token = activation->requestXdgActivationToken(waylandApp->lastInputSeat(), wlSurface, serial, appId); ++ return token->future(); ++} ++ + #include "moc_windowsystem.cpp" +diff --git a/src/platforms/wayland/windowsystem.h b/src/platforms/wayland/windowsystem.h +index 87bf23ed..4df82388 100644 +--- a/src/platforms/wayland/windowsystem.h ++++ b/src/platforms/wayland/windowsystem.h +@@ -12,7 +12,7 @@ + + class WindowManagement; + +-class WindowSystem : public QObject, public KWindowSystemPrivateV2 ++class WindowSystem : public QObject, public KWindowSystemPrivateV3 + { + Q_OBJECT + public: +@@ -27,6 +27,7 @@ public: + void exportWindow(QWindow *window) override; + void unexportWindow(QWindow *window) override; + void setMainWindow(QWindow *window, const QString &handle) override; ++ QFuture xdgActivationToken(QWindow *window, uint32_t serial, const QString &appId) override; + + protected: + bool eventFilter(QObject *watched, QEvent *event) override; +diff --git a/tests/activationtest.cpp b/tests/activationtest.cpp +index 306c6048..7aaae4ea 100644 +--- a/tests/activationtest.cpp ++++ b/tests/activationtest.cpp +@@ -28,13 +28,12 @@ public: + pushButton->setText("Raise other"); + layout()->addWidget(pushButton); + +- connect(pushButton, &QPushButton::clicked, this, [this] { +- KWaylandExtras::requestXdgActivationToken(windowHandle(), KWaylandExtras::lastInputSerial(windowHandle()), QString()); +- }); +- +- connect(KWaylandExtras::self(), &KWaylandExtras::xdgActivationTokenArrived, this, [otherWindow](int /*serial*/, const QString &token) { +- KWindowSystem::setCurrentXdgActivationToken(token); +- KWindowSystem::activateWindow(otherWindow->windowHandle()); ++ connect(pushButton, &QPushButton::clicked, this, [this, otherWindow] { ++ KWaylandExtras::xdgActivationToken(windowHandle(), KWaylandExtras::lastInputSerial(windowHandle()), QString()) ++ .then(otherWindow, [otherWindow](const QString &token) { ++ KWindowSystem::setCurrentXdgActivationToken(token); ++ KWindowSystem::activateWindow(otherWindow->windowHandle()); ++ }); + }); + } + }; +diff --git a/tests/kwaylandextrastest.cpp b/tests/kwaylandextrastest.cpp +index 3048cb37..2ee86a82 100644 +--- a/tests/kwaylandextrastest.cpp ++++ b/tests/kwaylandextrastest.cpp +@@ -79,16 +79,10 @@ void Window::updateSerial() + + void Window::requestToken() + { +- connect( +- KWaylandExtras::self(), +- &KWaylandExtras::xdgActivationTokenArrived, +- this, +- [this](int /*serial*/, const QString &token) { ++ KWaylandExtras::xdgActivationToken(windowHandle(), KWaylandExtras::self()->lastInputSerial(windowHandle()), QString()) ++ .then(this, [this](const QString &token) { + m_tokenLabel->setText("XDG actvation token: " + token); +- }, +- Qt::SingleShotConnection); +- +- KWaylandExtras::requestXdgActivationToken(windowHandle(), KWaylandExtras::self()->lastInputSerial(windowHandle()), QString()); ++ }); + } + + void Window::exportWindow() +-- +GitLab + + +From 1b16c417c697b5d30724ce37d0364af894f6680d Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Wed, 17 Sep 2025 12:01:53 +0300 +Subject: [PATCH 2/2] Deprecate KWaylandExtras::requestXdgActivationToken() + +KWaylandExtras::xdgActivationToken() provides a more convenient way to +retrieve an xdg activation token. + +Note that the QML side has no corresponding counterpart, however on the +other hand, there is no QML code that uses this function too. If the need +arises, the QML specific API could provide a Promise-like object. +--- + src/CMakeLists.txt | 2 +- + src/kwaylandextras.cpp | 2 ++ + src/kwaylandextras.h | 9 ++++++++- + src/kwindowsystem_p.h | 2 ++ + src/platforms/wayland/windowsystem.cpp | 2 ++ + src/platforms/wayland/windowsystem.h | 2 ++ + 6 files changed, 17 insertions(+), 2 deletions(-) + +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index fd72063b..ba748c2c 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -88,7 +88,7 @@ ecm_generate_export_header(KF6WindowSystem + VERSION ${KF_VERSION} + USE_VERSION_HEADER + DEPRECATED_BASE_VERSION 0 +- DEPRECATION_VERSIONS 6.0 ++ DEPRECATION_VERSIONS 6.0 6.19 + EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT} + ) + +diff --git a/src/kwaylandextras.cpp b/src/kwaylandextras.cpp +index a5f8af8f..241f80be 100644 +--- a/src/kwaylandextras.cpp ++++ b/src/kwaylandextras.cpp +@@ -26,6 +26,7 @@ KWaylandExtras *KWaylandExtras::self() + return &instance; + } + ++#if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(6, 19) + void KWaylandExtras::requestXdgActivationToken(QWindow *window, uint32_t serial, const QString &app_id) + { + auto dv2 = dynamic_cast(KWindowSystem::d_func()); +@@ -39,6 +40,7 @@ void KWaylandExtras::requestXdgActivationToken(QWindow *window, uint32_t serial, + } + dv2->requestToken(window, serial, app_id); + } ++#endif + + quint32 KWaylandExtras::lastInputSerial(QWindow *window) + { +diff --git a/src/kwaylandextras.h b/src/kwaylandextras.h +index 2f763dd5..56424b89 100644 +--- a/src/kwaylandextras.h ++++ b/src/kwaylandextras.h +@@ -31,14 +31,18 @@ public: + */ + static KWaylandExtras *self(); + ++#if KWINDOWSYSTEM_ENABLE_DEPRECATED_SINCE(6, 19) + /*! + * Requests an xdg_activation_v1 token for a specific window \a win with the given \a app_id. + * + * \a serial Serial of the event that triggered the request. + * + * \sa lastInputSerial ++ * \deprecated [6.19] Use xdgActivationToken() instead. + */ ++ KWINDOWSYSTEM_DEPRECATED_VERSION(6, 19, "Use xdgActivationToken()") + Q_INVOKABLE static void requestXdgActivationToken(QWindow *win, uint32_t serial, const QString &app_id); ++#endif + + /*! + * Offers the seat's current serial for the given \a window. +@@ -83,14 +87,17 @@ public: + static QFuture xdgActivationToken(QWindow *window, const QString &appId); + + Q_SIGNALS: ++#if KWINDOWSYSTEM_ENABLE_DEPRECATED_SINCE(6, 19) + /*! + * Activation \a token to pass to the client. + * + * \a serial Serial of the event that triggered the request + * + * \sa requestXdgActivationToken ++ * \deprecated [6.19] Use xdgActivationToken() instead. + */ +- void xdgActivationTokenArrived(int serial, const QString &token); ++ KWINDOWSYSTEM_DEPRECATED_VERSION(6, 19, "Use xdgActivationToken()") void xdgActivationTokenArrived(int serial, const QString &token); ++#endif + + /*! + * The \a handle of the given \a window to pass to the client. +diff --git a/src/kwindowsystem_p.h b/src/kwindowsystem_p.h +index e4b51e3e..92997120 100644 +--- a/src/kwindowsystem_p.h ++++ b/src/kwindowsystem_p.h +@@ -27,7 +27,9 @@ public: + class KWINDOWSYSTEM_EXPORT KWindowSystemPrivateV2 : public KWindowSystemPrivate + { + public: ++#if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(6, 19) + virtual void requestToken(QWindow *win, uint32_t serial, const QString &app_id) = 0; ++#endif + virtual void setCurrentToken(const QString &token) = 0; + virtual quint32 lastInputSerial(QWindow *window) = 0; + virtual void setMainWindow(QWindow *window, const QString &handle) = 0; +diff --git a/src/platforms/wayland/windowsystem.cpp b/src/platforms/wayland/windowsystem.cpp +index ebb22d78..bc803a4f 100644 +--- a/src/platforms/wayland/windowsystem.cpp ++++ b/src/platforms/wayland/windowsystem.cpp +@@ -74,6 +74,7 @@ void WindowSystem::activateWindow(QWindow *win, long int time) + activation->activate(m_lastToken, s); + } + ++#if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(6, 19) + void WindowSystem::requestToken(QWindow *window, uint32_t serial, const QString &app_id) + { + if (window) { +@@ -97,6 +98,7 @@ void WindowSystem::requestToken(QWindow *window, uint32_t serial, const QString + Q_EMIT KWaylandExtras::self()->xdgActivationTokenArrived(serial, token); + }); + } ++#endif + + void WindowSystem::setCurrentToken(const QString &token) + { +diff --git a/src/platforms/wayland/windowsystem.h b/src/platforms/wayland/windowsystem.h +index 4df82388..e9dca128 100644 +--- a/src/platforms/wayland/windowsystem.h ++++ b/src/platforms/wayland/windowsystem.h +@@ -19,7 +19,9 @@ public: + WindowSystem(); + ~WindowSystem() override; + void activateWindow(QWindow *win, long time) override; ++#if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(6, 19) + void requestToken(QWindow *win, uint32_t serial, const QString &app_id) override; ++#endif + quint32 lastInputSerial(QWindow *window) override; + void setCurrentToken(const QString &token) override; + bool showingDesktop() override; +-- +GitLab + diff --git a/roles/kde/patches/plasma-workspace/patches.txt b/roles/kde/patches/plasma-workspace/patches.txt index 26a8d42..49de017 100644 --- a/roles/kde/patches/plasma-workspace/patches.txt +++ b/roles/kde/patches/plasma-workspace/patches.txt @@ -14,3 +14,8 @@ Pr 5678 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5678 Depends on Pr 5673 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5673 Pr 5788 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5788 Allows compiling on gcc 14 after applying pr 5678 + +Plasma 6.6.0: + +Pr 5818 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5818 +Pr 5816 https://invent.kde.org/plasma/plasma-workspace/-/merge_requests/5816 diff --git a/roles/kde/patches/plasma-workspace/pr5816.patch b/roles/kde/patches/plasma-workspace/pr5816.patch new file mode 100644 index 0000000..7a1925a --- /dev/null +++ b/roles/kde/patches/plasma-workspace/pr5816.patch @@ -0,0 +1,349 @@ +From 77b3ec8cf4fb9414167bb15bcc3c69b1be6c2dbf Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Tue, 16 Sep 2025 15:52:29 +0300 +Subject: [PATCH 1/2] shell: Pass an xdg activation token from DesktopView to + KRunner + +This makes sure that krunner gets focused after starting to type while +a desktop view is focused when using medium or high focus stealing +prevention level. +--- + krunner/dbus/org.kde.krunner.App.xml | 4 ++ + krunner/view.cpp | 14 +++++++ + krunner/view.h | 1 + + shell/desktopview.cpp | 61 ++++++++++++++++++++++++++-- + shell/desktopview.h | 2 + + 5 files changed, 79 insertions(+), 3 deletions(-) + +diff --git a/krunner/dbus/org.kde.krunner.App.xml b/krunner/dbus/org.kde.krunner.App.xml +index 6553e9a1b56..e6926b1b63a 100644 +--- a/krunner/dbus/org.kde.krunner.App.xml ++++ b/krunner/dbus/org.kde.krunner.App.xml +@@ -17,5 +17,9 @@ + + + ++ ++ ++ ++ + + +diff --git a/krunner/view.cpp b/krunner/view.cpp +index afefe9ab486..bb7edd5d654 100644 +--- a/krunner/view.cpp ++++ b/krunner/view.cpp +@@ -263,6 +263,20 @@ void View::querySingleRunner(const QString &runnerName, const QString &term) + m_engine->rootObject()->setProperty("query", term); + } + ++void View::queryWithActivationToken(const QString &term, const QString &activationToken) ++{ ++ qputenv("XDG_ACTIVATION_TOKEN", activationToken.toUtf8()); ++ ++ if (!isVisible()) { ++ display(); ++ } else { ++ requestActivate(); ++ } ++ ++ m_engine->rootObject()->setProperty("singleRunner", QString()); ++ m_engine->rootObject()->setProperty("query", term); ++} ++ + bool View::pinned() const + { + return m_pinned; +diff --git a/krunner/view.h b/krunner/view.h +index 979c6d3b483..af1d477d6f3 100644 +--- a/krunner/view.h ++++ b/krunner/view.h +@@ -93,6 +93,7 @@ public Q_SLOTS: + void displayWithClipboardContents(); + void query(const QString &term); + void querySingleRunner(const QString &runnerName, const QString &term); ++ void queryWithActivationToken(const QString &term, const QString &activationToken); + + protected Q_SLOTS: + void loadConfig(); +diff --git a/shell/desktopview.cpp b/shell/desktopview.cpp +index 36e23149272..744176e6d3e 100644 +--- a/shell/desktopview.cpp ++++ b/shell/desktopview.cpp +@@ -23,6 +23,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -384,11 +385,54 @@ bool DesktopView::event(QEvent *e) + { + if (e->type() == QEvent::FocusOut) { + m_krunnerText.clear(); ++ ++ if (!m_krunnerFuture.isCanceled()) { ++ m_krunnerFuture.cancel(); ++ m_krunnerFuture = {}; ++ } + } + + return PlasmaQuick::ContainmentView::event(e); + } + ++class ActivationTokenRequest : public QObject ++{ ++ Q_OBJECT ++ ++public: ++ explicit ActivationTokenRequest(QWindow *window) ++ : m_serial(KWaylandExtras::lastInputSerial(window)) ++ { ++ m_promise.start(); ++ ++ connect(KWaylandExtras::self(), &KWaylandExtras::xdgActivationTokenArrived, this, [this](int serial, const QString &token) { ++ if (m_serial == serial) { ++ if (!m_promise.isCanceled()) { ++ m_promise.addResult(token); ++ } ++ m_promise.finish(); ++ delete this; ++ } ++ }); ++ KWaylandExtras::requestXdgActivationToken(window, m_serial, QString()); ++ } ++ ++ QFuture future() const ++ { ++ return m_promise.future(); ++ } ++ ++private: ++ QPromise m_promise; ++ int m_serial; ++}; ++ ++static QFuture fetchActivationToken(QWindow *window) ++{ ++ auto request = new ActivationTokenRequest(window); ++ return request->future(); ++} ++ + bool DesktopView::handleKRunnerTextInput(QKeyEvent *e) + { + // allow only Shift and GroupSwitch modifiers +@@ -408,12 +452,22 @@ bool DesktopView::handleKRunnerTextInput(QKeyEvent *e) + krunnerTextChanged = true; + } + if (krunnerTextChanged) { +- const QString interface(QStringLiteral("org.kde.krunner")); + if (!KAuthorized::authorize(QStringLiteral("run_command"))) { + return false; + } +- org::kde::krunner::App krunner(interface, QStringLiteral("/App"), QDBusConnection::sessionBus()); +- krunner.query(m_krunnerText); ++ if (KWindowSystem::isPlatformWayland()) { ++ if (!m_krunnerFuture.isCanceled()) { ++ m_krunnerFuture.cancel(); ++ } ++ m_krunnerFuture = fetchActivationToken(this); ++ m_krunnerFuture.then(this, [this](const QString &token) { ++ org::kde::krunner::App krunner(QStringLiteral("org.kde.krunner"), QStringLiteral("/App"), QDBusConnection::sessionBus()); ++ krunner.queryWithActivationToken(m_krunnerText, token); ++ }); ++ } else { ++ org::kde::krunner::App krunner(QStringLiteral("org.kde.krunner"), QStringLiteral("/App"), QDBusConnection::sessionBus()); ++ krunner.query(m_krunnerText); ++ } + return true; + } + return false; +@@ -596,4 +650,5 @@ void DesktopView::setAccentColorFromWallpaper(const QColor &accentColor) + QDBusConnection::sessionBus().send(applyAccentColor); + } + ++#include "desktopview.moc" + #include "moc_desktopview.cpp" +diff --git a/shell/desktopview.h b/shell/desktopview.h +index c2b642d9a15..9e152611a31 100644 +--- a/shell/desktopview.h ++++ b/shell/desktopview.h +@@ -10,6 +10,7 @@ + + #include + #include ++#include + #include + + #include +@@ -127,6 +128,7 @@ private: + QPointer m_screenToFollow; + LayerShellQt::Window *m_layerWindow = nullptr; + QString m_krunnerText; ++ QFuture m_krunnerFuture; + + // KRunner config + KConfigWatcher::Ptr m_configWatcher; +-- +GitLab + + +From b3d97405cb5b0ee9859576309bd826dea6b74274 Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Wed, 17 Sep 2025 09:59:07 +0300 +Subject: [PATCH 2/2] shell: Use org.freedesktop.Application.ActivateAction to + pass xdg activation token to krunner + +--- + krunner/dbus/org.kde.krunner.App.xml | 4 ---- + krunner/main.cpp | 4 +++- + krunner/view.cpp | 14 ------------ + krunner/view.h | 1 - + shell/CMakeLists.txt | 4 ---- + shell/desktopview.cpp | 32 +++++++++++++++++++++++----- + 6 files changed, 30 insertions(+), 29 deletions(-) + +diff --git a/krunner/dbus/org.kde.krunner.App.xml b/krunner/dbus/org.kde.krunner.App.xml +index e6926b1b63a..6553e9a1b56 100644 +--- a/krunner/dbus/org.kde.krunner.App.xml ++++ b/krunner/dbus/org.kde.krunner.App.xml +@@ -17,9 +17,5 @@ + + + +- +- +- +- + + +diff --git a/krunner/main.cpp b/krunner/main.cpp +index 514c34b032f..02174bb2cda 100644 +--- a/krunner/main.cpp ++++ b/krunner/main.cpp +@@ -136,9 +136,11 @@ int main(int argc, char **argv) + parser.parse(arguments); + updateVisibility(); + }); +- QObject::connect(&service, &KDBusService::activateActionRequested, &view, [&view](const QString &action) { ++ QObject::connect(&service, &KDBusService::activateActionRequested, &view, [&view](const QString &action, const QVariant ¶meter) { + if (action == QLatin1String("RunClipboard")) { + view.displayWithClipboardContents(); ++ } else if (action == QLatin1String("Query")) { ++ view.query(parameter.toString()); + } + }); + +diff --git a/krunner/view.cpp b/krunner/view.cpp +index bb7edd5d654..afefe9ab486 100644 +--- a/krunner/view.cpp ++++ b/krunner/view.cpp +@@ -263,20 +263,6 @@ void View::querySingleRunner(const QString &runnerName, const QString &term) + m_engine->rootObject()->setProperty("query", term); + } + +-void View::queryWithActivationToken(const QString &term, const QString &activationToken) +-{ +- qputenv("XDG_ACTIVATION_TOKEN", activationToken.toUtf8()); +- +- if (!isVisible()) { +- display(); +- } else { +- requestActivate(); +- } +- +- m_engine->rootObject()->setProperty("singleRunner", QString()); +- m_engine->rootObject()->setProperty("query", term); +-} +- + bool View::pinned() const + { + return m_pinned; +diff --git a/krunner/view.h b/krunner/view.h +index af1d477d6f3..979c6d3b483 100644 +--- a/krunner/view.h ++++ b/krunner/view.h +@@ -93,7 +93,6 @@ public Q_SLOTS: + void displayWithClipboardContents(); + void query(const QString &term); + void querySingleRunner(const QString &runnerName, const QString &term); +- void queryWithActivationToken(const QString &term, const QString &activationToken); + + protected Q_SLOTS: + void loadConfig(); +diff --git a/shell/CMakeLists.txt b/shell/CMakeLists.txt +index 96b91888f1b..814413ac827 100644 +--- a/shell/CMakeLists.txt ++++ b/shell/CMakeLists.txt +@@ -92,10 +92,6 @@ qt6_generate_wayland_protocol_client_sources(plasmashell + ${PLASMA_WAYLAND_PROTOCOLS_DIR}/plasma-shell.xml + ) + +-set(krunner_xml ${plasma-workspace_SOURCE_DIR}/krunner/dbus/org.kde.krunner.App.xml) +-qt_add_dbus_interface(plasma_shell_SRCS ${krunner_xml} krunner_interface) +- +- + target_sources(plasmashell PRIVATE ${plasma_shell_SRCS}) + + target_link_libraries(plasmashell PRIVATE +diff --git a/shell/desktopview.cpp b/shell/desktopview.cpp +index 744176e6d3e..9c3baa84b91 100644 +--- a/shell/desktopview.cpp ++++ b/shell/desktopview.cpp +@@ -6,12 +6,12 @@ + + #include "desktopview.h" + #include "containmentconfigview.h" +-#include "krunner_interface.h" + #include "screenpool.h" + #include "shellcorona.h" + + #include + #include ++#include + #include + #include + #include +@@ -461,12 +461,34 @@ bool DesktopView::handleKRunnerTextInput(QKeyEvent *e) + } + m_krunnerFuture = fetchActivationToken(this); + m_krunnerFuture.then(this, [this](const QString &token) { +- org::kde::krunner::App krunner(QStringLiteral("org.kde.krunner"), QStringLiteral("/App"), QDBusConnection::sessionBus()); +- krunner.queryWithActivationToken(m_krunnerText, token); ++ auto message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.krunner"), ++ QStringLiteral("/org/kde/krunner"), ++ QStringLiteral("org.freedesktop.Application"), ++ QStringLiteral("ActivateAction")); ++ message.setArguments({ ++ QStringLiteral("Query"), ++ QVariantList{ ++ m_krunnerText, ++ }, ++ QVariantMap{ ++ {QStringLiteral("activation-token"), token}, ++ }, ++ }); ++ QDBusConnection::sessionBus().asyncCall(message); + }); + } else { +- org::kde::krunner::App krunner(QStringLiteral("org.kde.krunner"), QStringLiteral("/App"), QDBusConnection::sessionBus()); +- krunner.query(m_krunnerText); ++ auto message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.krunner"), ++ QStringLiteral("/org/kde/krunner"), ++ QStringLiteral("org.freedesktop.Application"), ++ QStringLiteral("ActivateAction")); ++ message.setArguments({ ++ QStringLiteral("Query"), ++ QVariantList{ ++ m_krunnerText, ++ }, ++ QVariantMap{}, ++ }); ++ QDBusConnection::sessionBus().asyncCall(message); + } + return true; + } +-- +GitLab + diff --git a/roles/kde/patches/plasma-workspace/pr5818.patch b/roles/kde/patches/plasma-workspace/pr5818.patch new file mode 100644 index 0000000..12417f1 --- /dev/null +++ b/roles/kde/patches/plasma-workspace/pr5818.patch @@ -0,0 +1,76 @@ +From b29509a32a0aa93555f47bc3d3f04c665c511f30 Mon Sep 17 00:00:00 2001 +From: Vlad Zahorodnii +Date: Wed, 17 Sep 2025 10:27:07 +0300 +Subject: [PATCH] shell: Port to KWaylandExtras::xdgActivationToken() + +--- + shell/desktopview.cpp | 41 +---------------------------------------- + 1 file changed, 1 insertion(+), 40 deletions(-) + +diff --git a/shell/desktopview.cpp b/shell/desktopview.cpp +index 9c3baa84b91..ca48e44e887 100644 +--- a/shell/desktopview.cpp ++++ b/shell/desktopview.cpp +@@ -395,44 +395,6 @@ bool DesktopView::event(QEvent *e) + return PlasmaQuick::ContainmentView::event(e); + } + +-class ActivationTokenRequest : public QObject +-{ +- Q_OBJECT +- +-public: +- explicit ActivationTokenRequest(QWindow *window) +- : m_serial(KWaylandExtras::lastInputSerial(window)) +- { +- m_promise.start(); +- +- connect(KWaylandExtras::self(), &KWaylandExtras::xdgActivationTokenArrived, this, [this](int serial, const QString &token) { +- if (m_serial == serial) { +- if (!m_promise.isCanceled()) { +- m_promise.addResult(token); +- } +- m_promise.finish(); +- delete this; +- } +- }); +- KWaylandExtras::requestXdgActivationToken(window, m_serial, QString()); +- } +- +- QFuture future() const +- { +- return m_promise.future(); +- } +- +-private: +- QPromise m_promise; +- int m_serial; +-}; +- +-static QFuture fetchActivationToken(QWindow *window) +-{ +- auto request = new ActivationTokenRequest(window); +- return request->future(); +-} +- + bool DesktopView::handleKRunnerTextInput(QKeyEvent *e) + { + // allow only Shift and GroupSwitch modifiers +@@ -459,7 +421,7 @@ bool DesktopView::handleKRunnerTextInput(QKeyEvent *e) + if (!m_krunnerFuture.isCanceled()) { + m_krunnerFuture.cancel(); + } +- m_krunnerFuture = fetchActivationToken(this); ++ m_krunnerFuture = KWaylandExtras::xdgActivationToken(this, QString()); + m_krunnerFuture.then(this, [this](const QString &token) { + auto message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.krunner"), + QStringLiteral("/org/kde/krunner"), +@@ -672,5 +634,4 @@ void DesktopView::setAccentColorFromWallpaper(const QColor &accentColor) + QDBusConnection::sessionBus().send(applyAccentColor); + } + +-#include "desktopview.moc" + #include "moc_desktopview.cpp" +-- +GitLab +