fix(libei): only restart the capture session on device change under GNOME - #480
Merged
feschber merged 1 commit intoAug 31, 2026
Merged
Conversation
mrcha033
force-pushed
the
fix/gate-eis-session-restart-to-gnome
branch
from
August 6, 2026 23:55
10a9620 to
8c59706
Compare
…NOME `EiEvent::DeviceRemoved` currently tears down and recreates the whole input-capture session. That is a workaround for mutter, which stops delivering events after a device change, but it is applied on every compositor. Elsewhere the restart is pure overhead: every device change costs a CreateSession + ConnectToEIS round trip. On compositors that keep per-session state around it is worse than overhead - Hyprland keeps a keymap fd per EIS session and never reaps sessions whose client went away, so the churn drives it out of file descriptors and eventually crashes it. On this machine the churn ran at ~35 ConnectToEIS per 38 minutes; gating it to GNOME brought that to 0 with no change in capture behaviour. `SeatRemoved` still releases unconditionally - a seat going away really does invalidate the session. The default is derived from XDG_CURRENT_DESKTOP and can be overridden with LM_RESTART_SESSION_ON_DEVICE_CHANGE=1/0 for compositors that need the mutter behaviour but do not advertise themselves as GNOME.
feschber
force-pushed
the
fix/gate-eis-session-restart-to-gnome
branch
from
August 31, 2026 11:26
8c59706 to
78df7a0
Compare
Owner
|
Is there an open issue on Mutter about this? I'm also considering dropping support for older versions of GNOME that necessitate the recreation of the capture session for every barrier update. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
handle_ei_eventtreatsEiEvent::DeviceRemovedas a reason to release and recreate the entire input-capture session:That is a workaround for mutter, which stops delivering events after a device change — the same class of bug the comment above already documents for barrier updates. But it runs on every compositor.
On everything else the restart is pure overhead: each one costs a
CreateSession+ConnectToEISround trip, and devices come and go often enough that the session is rebuilt continuously during normal use.On compositors that keep per-session state around it is actively harmful. Hyprland allocates a keymap fd per EIS session and only reaps a session when the portal client destroys the resource, which does not happen when we drop a session this way. Sessions accumulate, and
CInputCaptureProtocol::updateKeymap()walks all of them on every focus change, so the leak grows quadratically. On my machine Hyprland reached 45k open fds and crashed (xkb_keymap_new_from_names()returns NULL under EMFILE and is dereferenced unchecked). That is a Hyprland bug and I am reporting it there separately, but lan-mouse is what drives the churn: ~35ConnectToEISper 38 minutes of ordinary use.Change
Gate the device-change restart on GNOME.
SeatRemovedstill releases unconditionally — a seat disappearing genuinely invalidates the session.The default comes from
XDG_CURRENT_DESKTOP;LM_RESTART_SESSION_ON_DEVICE_CHANGE=1/0overrides it, for compositors that need the mutter behaviour without advertising themselves as GNOME.Testing
ConnectToEISchurn went from ~35 per 38 min to 0, capture/release across the barrier unchanged over a multi-hour session.cargo clippy --all-targetsandcargo fmt --checkclean.Note: splitting the match arm makes rustfmt format that block for the first time (it previously bailed on the inline comment inside the multi-pattern arm), so the commit also carries two one-line reformats it demanded in adjacent arms. Happy to drop them into a separate commit if you'd rather keep the diff to the behaviour change.
I do not have a GNOME setup to verify the mutter path still behaves — it should be unchanged, since
XDG_CURRENT_DESKTOPcontains GNOME there, but a second pair of eyes on that would be good.