fix(wlroots): share one virtual keyboard across clients - #491
Open
0xFlo wants to merge 2 commits into
Open
Conversation
Owner
|
Yeah this is probably a good idea. The current design predates the connection based model, where now every connection has its own virtual keyboard instead of every remote device, as was previously the case. |
add_client sent a keymap fd per emulation client, and it is the same fd every time, so under client churn the queue grew past MAX_FDS_OUT and sendmsg failed with ETOOMANYREFS. One lazily created keyboard sends it once. The pointer stays per client because it carries no descriptor.
Creates N emulation clients while sampling open descriptors, with a control mode that holds the client count at one to distinguish client creation from the event path. Motion is always zero valued so it never moves the cursor.
feschber
force-pushed
the
fix/shared-virtual-keyboard
branch
from
August 31, 2026 11:14
fba0341 to
b420da1
Compare
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.
Fixes the file descriptor exhaustion behind #478.
Cause
State::add_clientcreates a virtual keyboard per emulation client and hands the compositor a keymap descriptor:It is the same descriptor on every call. Wayland caps descriptors per
sendmsg(MAX_FDS_OUT), so under client-creation churn they queue faster than the compositor drains them, and the kernel eventually refuses the send.too_many_unix_fds()compares the user's total in-flightSCM_RIGHTScount against the sender'sRLIMIT_NOFILE, which is why this shows up on an otherwise idle desktop: a distro with the traditional 1024 soft limit is already close to the ceiling before lan-mouse adds anything.Reproduction
Added as an example so it can be re-run:
cargo run --release -p input-emulation --example keymap_fd_churn. It creates N emulation clients and samples/proc/self/fd.--controlholds the client count at one and sends the same number of events instead.On Arch, Hyprland 0.56.2, at
ulimit -n 2048:That is
ETOOMANYREFS, the error in #478. Control mode stays flat at 12 descriptors and completes clean, which is what identifies client creation rather than the event path as the source.Note the threshold is environment dependent. The ambient in-flight count on this machine sits around 1024 to 1152, so a limit below that fails at iteration 0 regardless of this bug, and a limit far above it never trips. 1536 and 2048 both discriminate here.
After
Interleaved A/B at
ulimit -n 2048, alternating binaries so ambient pressure is not mistaken for the effect:WAYLAND_DEBUG=1over a 2000 client run confirms it at the protocol level:create_virtual_keyboard1,zwp_virtual_keyboard_v1.keymap1,create_virtual_pointer2000.Why sharing the keyboard is safe
wl_seat, so wlroots merged their key and modifier streams into one focused surface. N objects never gave clients independent keyboard state, only independent handles onto the same seat.XModsstays inVirtualInput, one per client.keyboard.destroy().InputEmulation::destroycallsrelease_keysfirst, which emits explicit releases and zeroed modifiers before the backend'sdestroyruns.new(), so the keyboard appears on the seat at the same moment as before, and never appears if no client is created.Testing
Verified end to end between two Arch machines running Hyprland over a LAN, layer-shell capture and wlroots emulation on both: cursor crossing, text entry, and Shift and Ctrl held while typing, with no stuck or dropped modifiers on either side.
Adjacent, not addressed here
Dispatch<WlSeat>callsseat.get_keyboard(...)on everyCapabilitiesevent and never releases thewl_keyboard, so repeated capability announcements would leak keyboard objects and keymap descriptors. It looks unreachable today because nothing dispatches the queue afternew(), so I have left it alone rather than change it without a reproduction.