Summary
The Mutter Direct pipeline's EIS input path sends an invalid capability bitmask when binding to a seat, causing Mutter/libeis to immediately close the EIS connection. Keyboard and mouse input are non-functional on GNOME sessions using the Mutter Direct API.
Root Cause
In handle_eis_event(), the Seat::Done handler calls seat.bind(u64::MAX) which sends all 64 capability bits. The EIS protocol only defines bits 0-5 (pointer, pointer_absolute, keyboard, touch, scroll, button -- mask 0x3F). Mutter's libeis validates the bind mask and closes the connection when undefined bits are present.
Additionally, Seat::Capability events from the server are logged but never stored, so the advertised capabilities are discarded rather than accumulated for the bind call.
Expected Behavior
The client should accumulate capability masks from Seat::Capability events and pass only the server-advertised capabilities to seat.bind(), matching the behavior of the working libei/Portal code path.
Observed Behavior
Server journal shows the EIS connection closes via EOF approximately 8 microseconds after the bind+flush sequence, consistently across all GNOME test sessions. No EIS devices are ever created, so keyboard and mouse input are completely non-functional.
Reproduced On
- lamco-rdp-server v1.4.2 (build from tagged release)
- Fedora 41 GNOME (Mutter 47.x), VM fedora-gnome at 192.168.1.145
- FreeRDP xfreerdp3 client
Affected Versions
v1.4.2 and earlier (Mutter Direct path only; the libei/Portal path is unaffected).
Summary
The Mutter Direct pipeline's EIS input path sends an invalid capability bitmask when binding to a seat, causing Mutter/libeis to immediately close the EIS connection. Keyboard and mouse input are non-functional on GNOME sessions using the Mutter Direct API.
Root Cause
In
handle_eis_event(), theSeat::Donehandler callsseat.bind(u64::MAX)which sends all 64 capability bits. The EIS protocol only defines bits 0-5 (pointer, pointer_absolute, keyboard, touch, scroll, button -- mask0x3F). Mutter's libeis validates the bind mask and closes the connection when undefined bits are present.Additionally,
Seat::Capabilityevents from the server are logged but never stored, so the advertised capabilities are discarded rather than accumulated for the bind call.Expected Behavior
The client should accumulate capability masks from
Seat::Capabilityevents and pass only the server-advertised capabilities toseat.bind(), matching the behavior of the working libei/Portal code path.Observed Behavior
Server journal shows the EIS connection closes via EOF approximately 8 microseconds after the bind+flush sequence, consistently across all GNOME test sessions. No EIS devices are ever created, so keyboard and mouse input are completely non-functional.
Reproduced On
Affected Versions
v1.4.2 and earlier (Mutter Direct path only; the libei/Portal path is unaffected).