Skip to content

fix: make compositor keyboard layout policy follow layout switches - #24

Open
maryny4 wants to merge 1 commit into
MuNeNiCK:mainfrom
maryny4:fix/compositor-layout-policy
Open

fix: make compositor keyboard layout policy follow layout switches#24
maryny4 wants to merge 1 commit into
MuNeNiCK:mainfrom
maryny4:fix/compositor-layout-policy

Conversation

@maryny4

@maryny4 maryny4 commented Aug 6, 2026

Copy link
Copy Markdown

Problem

With keyboard_layout_policy = "compositor", layout switching never works over RDP: hyprctl switchxkblayout all next has no effect on RDP input, and Alt+Shift forwarded by the RDP client snaps back on the next modifier press. This is the behavior #14 describes; the sync added in a6b0e43 cannot receive the data it needs:

  1. wl_state.keyboard_group is only updated from wl_keyboard::Event::Modifiers, but Wayland delivers modifiers only after wl_keyboard.enter, i.e. to the client whose surface holds keyboard focus. hypr-rdp has no surfaces, so the event never arrives and the group stays 0 forever. Verified with a minimal surfaceless client (bind wl_seatget_keyboard, switch layouts): it receives keymap=1, enter=0, modifiers=0, repeat_info=1. The existing unit tests pass because they set keyboard_group on the struct directly.
  2. Every modifier state change (and every KeyboardEvent::Synchronize mstsc sends on window focus) then emits zwp_virtual_keyboard_v1.modifiers(..., group=0), resetting whatever layout was switched — including group toggles Hyprland itself performs on the virtual keyboard when the client forwards Alt+Shift.
  3. Hyprland silently ignores switchxkblayout for virtual keyboards (returns ok, index unchanged) and emits no activelayout events for them, so the virtual keyboard's group can only be set by its owner through the virtual-keyboard protocol.

Fix

Replace the unreachable wl_keyboard sync with two mechanisms (both under the compositor policy):

  • Subscribe to Hyprland socket2 activelayout events via the existing hyprland::EventStream, resolve the event's layout name against the compiled keymap's layout names, and mirror external switches (hyprctl switchxkblayout, physical keyboards) onto the virtual keyboard with an immediate modifiers() send.
  • Replicate per-key XKB state processing in KeyboardStateTracker (xkb_state_update_key + serialize_layout), so group toggle options like grp:alt_shift_toggle forwarded by the RDP client switch the tracked group in lockstep with the compositor's own processing of the same key stream.

client policy behavior is unchanged. No new dependencies. xkb::State is wrapped with an explicit unsafe impl Send — access is serialized by the InputState mutex, and libxkbcommon objects have no thread affinity.

Verification

  • cargo fmt --check, cargo clippy -- -D warnings, cargo test and cargo test --no-default-features all pass; new tests cover the Alt+Shift toggle, composition of external switches with toggles, layout-name resolution, and activelayout parsing.
  • Live side-by-side on Hyprland 0.56.1: the stock instance's virtual keyboard stays on group 0 through switchxkblayout all next, the patched instance follows the switch and back (hyprctl devices + log).
  • Real session (Windows RDP client): Alt+Shift switches reliably, including typing capitals right after switching, which previously snapped the layout back.

Fixes the remaining part of #14.

Two mechanisms replace the wl_keyboard.modifiers sync, which is
unreachable for hypr-rdp: modifiers events are delivered only after
wl_keyboard.enter, i.e. to the client whose surface holds keyboard
focus, and hypr-rdp has no surfaces. The group therefore stayed 0
forever and every modifier change reset the virtual keyboard's layout
(Hyprland also silently ignores switchxkblayout for virtual keyboards,
so only the virtual keyboard owner can switch its group).

- Subscribe to Hyprland socket2 activelayout events and mirror external
  layout switches (hyprctl switchxkblayout, physical keyboards) onto the
  virtual keyboard.
- Replicate per-key XKB state processing so group toggle options
  (e.g. grp:alt_shift_toggle) forwarded by the RDP client switch the
  tracked group in lockstep with the compositor's own processing.

(cherry picked from commit 4d4a193)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant