Add native KWin support (libei pointer + ScreenShot2 target detection)#97
Add native KWin support (libei pointer + ScreenShot2 target detection)#97mcdax wants to merge 15 commits into
Conversation
… poll
Two defects found via live testing on KWin (Plasma 6, Wayland):
- KWin ties the EIS session to the D-Bus connection that called
connectToEIS. eis_dbus_connect() unref'd the bus immediately, so KWin
tore the session down ("Disconnected by EIS") before any input could
be sent. eis_dbus now returns an eis_connection {bus, fd} the caller
keeps open until after ei_unref(), via eis_dbus_disconnect().
- The handshake pump poll()ed before the first ei_dispatch(), so the
initial libei connection handshake (and queued capability binding) was
never driven and the device never resumed (2s timeout). Dispatch now
runs at the top of both pump loops, before poll().
Verified: cursor moves to exact global coordinates incl. a second
monitor (e.g. 3000,500), no disconnect, click path flushes via ei_ping.
|
Thank your for your PR, this is an interesting addition. I don't use KDE thus why I didn't actively worked on supporting it, however it's still something I'm interested in supporting. I like the fact that this is all optional since it inevitably brings new dependencies. In fact, that's the reason why the detection feature is optional. I've tested it on my machine and I have a few observations:
I haven't looked into the code in detail yet. I also haven't tested a multiple monitor setup either. I will do that a bit later. |
|
Thank you very much for your input! I'll analyse the issues over the next few days. Interestingly, I don't experience any delay or click issues at all (KDE Plasma 6.6.4 on Kubuntu 26.04). I'm going to test on a few more machines. ▎ The way I've ran it is by creating a secondary file with the options I needed. That can't be the only way, is it? That's exactly how I tested it too, since I can't think of another way that wouldn't make things even more complex. I'll give it more thought. There's also the issue that you can start the binary multiple times, which leads to strange effects. Multi-monitor is still a limitation: it currently only works on the active output. |
query_screenshot() can return NULL on the KWin backend when the compositor denies the org.kde.KWin.ScreenShot2 request (the wlroots backend never returned NULL). Detection dereferenced the buffer unconditionally, segfaulting. Bail out with an empty area list instead.
The feature targets the KWin compositor specifically, so name it after the compositor everywhere in the code and build (option, KWIN_ENABLED macro, file/symbol names, --version marker). 'KDE' is kept only in user-facing prose in the README and in the actual D-Bus interface names (org.kde.KWin.*, X-KDE-DBUS-Restricted-Interfaces).
Open the EIS/libei session once and reuse it for every pointer move instead of reconnecting -- plus running pointer_kwin_available()'s extra connect/close probe -- on every keystroke. Per-keystroke session churn made KWin repeatedly build and tear down a virtual pointer device, and left the final click racing against the teardown of the preview move's session: a likely cause of the unreliable clicks reported in moverest#97. Also inject motion, press and release as separate frames with a flush_until_pong() round-trip between each, mirroring the working wlr_virtual_pointer path. Without it KWin received the whole burst at once with near-identical ei_now() timestamps, producing a zero-duration click. Reusing the session also requires a monotonically increasing start_emulating() sequence number. Adds temporary diagnostic logging (device capabilities, regions, click timestamps) to compare behaviour across machines; to be removed before merge. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
Hi @moverest, I can't reproduce it on my other machine either, unfortunately. (Arch with recent plasma-desktop) I did a small refactor around the roundtrips and the EIS connection handling. It now opens one connection and reuses it instead of reconnecting on every keystroke and I also added some extra debug logging. Could you pull the latest commit, build with Btw, I don't think the overlay is stealing the click: its input region is empty, so clicks pass straight through to the window underneath. That probably also explains why the 1s delay didn't help. Thanks! PS: Most of the code is AI generated, I still have to revise esp. the comments. |
Open the EIS/libei session once and reuse it for every pointer move instead of reconnecting -- plus running pointer_kwin_available()'s extra connect/close probe -- on every keystroke. Per-keystroke session churn made KWin repeatedly build and tear down a virtual pointer device, and left the final click racing against the teardown of the preview move's session: a likely cause of the unreliable clicks reported in moverest#97. Also inject motion, press and release as separate frames with a flush_until_pong() round-trip between each, mirroring the working wlr_virtual_pointer path. Without it KWin received the whole burst at once with near-identical ei_now() timestamps, producing a zero-duration click. Reusing the session also requires a monotonically increasing start_emulating() sequence number. Adds temporary diagnostic logging (device capabilities, regions, click timestamps) to compare behaviour across machines; to be removed before merge.
a9d3bd3 to
cbbb0a9
Compare
|
btw. Most of the code can also be used for GNOME support. (In the long run) |
Implements #44 — native KWin support, gated behind a new optional
kdeMeson feature so the wlroots path and minimal builds are unchanged.Pointer movement & clicks
KWin doesn't implement
wlr-virtual-pointer, so the pointer is driven through libei over an EIS socket obtained from KWin'sorg.kde.KWin.EIS.RemoteDesktop.connectToEISD-Bus method — the approach described by @Gliese852 in #44 (thanks!).move_pointer()is now a small dispatcher that picks the wlroots backend whenwl_virtual_pointeris present, otherwise the KDE backend.A couple of things that were needed to make it reliable on KWin:
connectToEISmust stay alive for the lifetime of the EIS session (KWin tears the session down otherwise);ei_dispatch()has to run beforepoll()so the initial libei handshake is driven, and anei_ping()round-trip flushes the final click before teardown.Target auto-detection (
floating+detect)Since KWin also lacks
wlr-screencopy, the screen is captured via KWin'sorg.kde.KWin.ScreenShot2D-Bus interface (CaptureArea) and fed into the existing OpenCV pipeline unchanged. This path is built only when bothopencvandkdeare enabled. BecauseScreenShot2is a restricted interface, the installed desktop file now carriesX-KDE-DBUS-Restricted-Interfaces=org.kde.KWin.ScreenShot2and uses an absoluteExec(generated viaconfigure_file); capture only works for an installed binary, not from the build tree.Build
New dependencies (only with
-Dkde):libeiand an sd-bus implementation (libsystemd, orbasuon non-systemd systems).wl-kbptr --versionprints(kde).Testing
Tested on KWin Plasma 6 (Wayland):
ScreenShot2and the OpenCV pipeline returns sensible targets;-Dkdeand a wlroots compositor behave exactly as before;Known limitations
ScreenShot2auto-detection requires the program to be installed (allow-list entry), so it can't be exercised from the build tree.Happy to adjust naming, the feature split, or anything else to fit the project's conventions.