[plasma/xdg-desktop-portal-kde/Plasma/6.7] src: session: release all sessions when the portal frontend disappears
David Redondo <[email protected]> Tue, 4 Aug 2026 13:48:31 +0000 (UTC)
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit b4d3f6cd01edd5302030f2b8292ed82315069f27 by David Redondo. Committed on 04/08/2026 at 13:41. Pushed by davidre into branch 'Plasma/6.7'. session: release all sessions when the portal frontend disappears Every session in this backend is created on behalf of the single portal frontend (org.freedesktop.portal.Desktop). If it drops off the bus without cleanly closing its sessions - for example if it crashes - nothing tears them down. For an InputCapture session that means KWin keeps diverting all pointer and keyboard input into the now ownerless EIS channel, so the desktop renders normally but accepts no input until KWin is killed. Watch the frontend centrally and close every session if it disappears, which drives the existing Session::closed teardown for each. This covers all session types rather than only input capture. BUG: 523515 (cherry picked from commit e0cf8bf311a7baad8933797ec2fca0b94eb7d3d5) Co-authored-by: Marcus Renheim <[email protected]> M +10 -0 src/desktopportal.cpp M +2 -0 src/desktopportal.h M +13 -0 src/session.cpp M +1 -0 src/session.h https://invent.kde.org/plasma/xdg-desktop-portal-kde/-/commit/b4d3f6cd01edd5302030f2b8292ed82315069f27 diff --git a/src/desktopportal.cpp b/src/desktopportal.cpp index a3d4b78e..3649ec42 100644 --- a/src/desktopportal.cpp +++ b/src/desktopportal.cpp @@ -8,6 +8,10 @@ #include "desktopportal.h" #include "desktopportal_debug.h" +#include "session.h" + +#include <QDBusConnection> +#include <QDBusServiceWatcher> #include "access.h" #include "account.h" @@ -42,6 +46,7 @@ DesktopPortal::DesktopPortal(QObject *parent) , m_print(new PrintPortal(this)) , m_settings(new SettingsPortal(this)) , m_dynamicLauncher(new DynamicLauncherPortal(this)) + , m_frontendWatcher(QStringLiteral("org.freedesktop.portal.Desktop"), QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForUnregistration) { const QByteArray xdgCurrentDesktop = qgetenv("XDG_CURRENT_DESKTOP"); if (xdgCurrentDesktop.compare("KDE", Qt::CaseInsensitive) == 0) { @@ -59,6 +64,11 @@ DesktopPortal::DesktopPortal(QObject *parent) WaylandIntegration::init(); } new UsbPortal(this); + + // Fail-safe: close all sessions if the portal frontend disappears without closing them. + connect(&m_frontendWatcher, &QDBusServiceWatcher::serviceUnregistered, this, [] { + Session::closeAll(); + }); } #include "moc_desktopportal.cpp" diff --git a/src/desktopportal.h b/src/desktopportal.h index 824837c8..08989eb7 100644 --- a/src/desktopportal.h +++ b/src/desktopportal.h @@ -10,6 +10,7 @@ #define XDG_DESKTOP_PORTAL_KDE_DESKTOP_PORTAL_H #include <QDBusContext> +#include <QDBusServiceWatcher> #include <QObject> class AccessPortal; @@ -46,6 +47,7 @@ private: ScreenCastPortal *m_screenCast = nullptr; RemoteDesktopPortal *m_remoteDesktop = nullptr; DynamicLauncherPortal *const m_dynamicLauncher; + QDBusServiceWatcher m_frontendWatcher; }; #endif // XDG_DESKTOP_PORTAL_KDE_DESKTOP_PORTAL_H diff --git a/src/session.cpp b/src/session.cpp index bb8e7015..50333a8e 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -74,6 +74,19 @@ Session *Session::getSession(const QString &sessionHandle) return sessionList.value(sessionHandle); } +void Session::closeAll() +{ + // Iterate over a copy: close() removes the session from sessionList. + const auto sessions = sessionList.values(); + if (sessions.isEmpty()) { + return; + } + qCInfo(XdgSessionKdeSession) << "Closing" << sessions.count() << "session(s) after the portal frontend disappeared"; + for (Session *session : sessions) { + session->close(); + } +} + void Session::Close() { close(); diff --git a/src/session.h b/src/session.h index 3446f387..5a19b136 100644 --- a/src/session.h +++ b/src/session.h @@ -39,6 +39,7 @@ public: virtual SessionType type() const = 0; static Session *getSession(const QString &sessionHandle); + static void closeAll(); template<typename T> static T *getSession(const QString &sessionHandle) {