If the xdg-desktop-portal *frontend* process dies while an InputCapture session is active (an app such as Deskflow / Input Leap holding a screen-edge barrier), the input-capture session is never torn down. KWin keeps diverting ALL pointer and keyboard input into the now-ownerless EIS channel: the desktop keeps rendering and the cursor still moves, but nothing accepts input -- no clicks, no keyboard, no Alt+Tab, no taskbar. Recovery requires an out-of-band action (SSH, or the built-in Meta+Shift+Escape disable shortcut if it still reaches KWin). This is a fail-safe problem, not merely a crash follow-on: when the owner of an InputCapture session goes away, the compositor must release capture rather than divert all input into a dead session. It is a denial-of-input hazard. STEPS TO REPRODUCE 1. Have an InputCapture consumer running with a screen-edge barrier (e.g. Deskflow linking this machine to another; the pointer crossing the shared edge engages capture). 2. Kill the portal frontend: systemctl --user kill -s ABRT xdg-desktop-portal.service (In the wild this happened via an unrelated portal crash during a PipeWire audio-stack restart.) 3. Move the pointer across the barrier to engage capture. OBSERVED All input is diverted; the desktop accepts no keyboard/pointer input while continuing to render. Journal shows "Invalid session type for signal" and a flood of "Error disabling capture on zone change". EXPECTED When the session's owner (the portal frontend / the app) is gone, the capture is released and local input is restored. ROOT CAUSE (source analysis of current master: xdg-desktop-portal-kde 449b1ae, kwin 9ec0d6f) The teardown chain that would release capture is only driven by an explicit session Close(), which a crashed frontend can never send: * xdg-desktop-portal-kde -- src/session.cpp: Session::close() (line 56) emits closed() and is only reached via the D-Bus method Session::Close() (line 77). The class registers NO QDBusServiceWatcher and does not react to its owning peer disconnecting. * The KWin-side teardown is wired to that signal -- src/inputcapture.cpp:90-94: connect(session, &Session::closed, ... removeInputCapture ...). Without closed(), removeInputCapture is never sent to KWin. * KWin -- src/plugins/eis/eisinputcapturemanager.cpp: it does have a fail-safe (QDBusServiceWatcher, lines 125-135) but it watches its immediate caller, the xdg-desktop-portal-kde backend (message().service(), line 193), which stays alive when the frontend dies. The input filter installed at barrierHit() (line 210) therefore stays installed. So a frontend crash leaves the backend Session alive (no caller watcher), KWin is never told to remove the capture, and input stays diverted. The same codebase already uses the missing pattern elsewhere: src/appchooser.cpp:124-125 creates a QDBusServiceWatcher(WatchForUnregistration) on its caller and cleans up on serviceUnregistered. SUGGESTED FIX DIRECTION (not a patch) * Primary (xdg-desktop-portal-kde): tie the Session -- at least InputCapture sessions -- to the lifetime of the D-Bus peer that owns it (the frontend, i.e. the sender of CreateSession/Start). Watch it with QDBusServiceWatcher and call close() on unregistration, mirroring appchooser.cpp. This drives the existing correct teardown: closed() -> removeInputCapture -> KWin deactivate(). * Secondary (KWin, defense-in-depth): independently release an active capture if the session it serves is gone, rather than relying on the backend to always call removeInputCapture. ENVIRONMENT * KDE Plasma 6.6.4 / kwin_wayland 6.6.4 (Wayland) * xdg-desktop-portal 1.21.1; xdg-desktop-portal-kde from Plasma 6.6.4 * Reproduced on the running system; root cause re-checked against current master (xdg-desktop-portal-kde 449b1ae, kwin 9ec0d6f). NOTES Related but distinct: the frontend crash that first triggered this on my machine is a separate use-after-free in xdg-desktop-portal (flatpak/xdg-desktop-portal PR #2074). This report is about the compositor / portal backend NOT releasing capture once the owner is gone -- an independent fail-safe defect that would strand input on any frontend death.
Withdrawn by the reporter. This was filed prematurely, before it had been reviewed, and I am retracting it. Please disregard. Apologies for the noise.
I have now reviewed the report again the bug and its description are confirmed.
Update: I have now reproduced this and verified a fix at runtime on Plasma/KWin 6.6.4 (Wayland), with an InputCapture consumer (Deskflow) using a screen-edge barrier. Reproduction (unpatched, stock 6.6.4): with an active InputCapture session, killing the xdg-desktop-portal frontend (systemctl --user kill -s ABRT xdg-desktop-portal.service) and then crossing the barrier freezes all input - the compositor keeps rendering (mouse-shake still triggers the shake-cursor effect) but no pointer or keyboard events get through, because KWin's capture filter is never removed. Recovery required restarting the backend/frontend out of band. Fix: tie the InputCapture session to the lifetime of the requesting client. In InputCapturePortal, when the capture is set up, install a QDBusServiceWatcher(WatchForUnregistration) on the caller (the frontend, i.e. the sender of Start), parented to the Session so its lifetime matches the capture, and call session->close() on serviceUnregistered. That drives the existing Session::closed -> removeInputCapture teardown, which already works - it just never fired on the frontend-death path. (This mirrors the intent of the watcher in appchooser.cpp, but with the watcher owned by the session so it actually outlives the call.) Result (patched): the same frontend kill now logs "Input capture requester .../portal... disappeared, releasing capture" and input remains fully responsive across the barrier - no freeze. This was verified with the machine's own out-of-band auto-recovery disabled, so the patched watcher was the only thing that could release the capture. I'll open a merge request against xdg-desktop-portal-kde with this change and link it here.
Thanks for the report, and the incoming patch!
A possibly relevant merge request was started @ https://invent.kde.org/plasma/xdg-desktop-portal-kde/-/merge_requests/607
Merge request opened: https://invent.kde.org/plasma/xdg-desktop-portal-kde/-/merge_requests/607 It implements the fix described above: a QDBusServiceWatcher(WatchForUnregistration) on the requesting frontend (the sender of Start), parented to the InputCapture session so it outlives the call, calling session->close() on serviceUnregistered. That drives the existing Session::closed -> removeInputCapture teardown, so KWin releases the capture instead of diverting all input into an ownerless EIS channel. Rebased on current master; single commit.
Git commit e0cf8bf311a7baad8933797ec2fca0b94eb7d3d5 by Marcus Renheim. Committed on 04/08/2026 at 10:08. Pushed by davidre into branch 'master'. 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. 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/e0cf8bf311a7baad8933797ec2fca0b94eb7d3d5
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. (cherry picked from commit e0cf8bf311a7baad8933797ec2fca0b94eb7d3d5) Co-authored-by: Marcus Renheim <marcus@renheim.com> 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
Git commit 867386a6e43d9b63fd23fca27d6f3f0b43a740b9 by David Redondo. Committed on 04/08/2026 at 14:22. Pushed by davidre into branch 'Plasma/6.6'. 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. (cherry picked from commit e0cf8bf311a7baad8933797ec2fca0b94eb7d3d5) Co-authored-by: Marcus Renheim <marcus@renheim.com> (cherry picked from commit b4d3f6cd01edd5302030f2b8292ed82315069f27) Co-authored-by: David Redondo <kde@david-redondo.de> 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/867386a6e43d9b63fd23fca27d6f3f0b43a740b9