A German keyboard typed US characters — nothing carried the box's layout into the session #257
Merged
enricobuehler
merged 1 commits from 2026-08-15 21:58:29 +00:00
worktree-ipad-keyboard-layout into main
1
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
94be547da0 |
fix(input): a German keyboard typed US characters — nothing carried the box's layout into the session
ci / bun-nix (pull_request) Successful in 21s
ci / web (pull_request) Successful in 1m5s
ci / docs-site (pull_request) Successful in 9m7s
ci / rust-arm64 (pull_request) Successful in 9m47s
android / android (pull_request) Successful in 15m41s
ci / rust (pull_request) Successful in 16m49s
Reported from an iPad on a Bazzite host in Game Mode: `#` arrived as `\`, `-` as `/`, `ä` as `'`. That set is not random — they are the US ANSI keys that sit where the German ISO ones do, which says the client was right and the host session was resolving positions with a US keymap. The key wire is US-POSITIONAL by design: a client sends the physical key, `vk_to_evdev` turns it into an evdev code, and the session's keymap picks the character. So the contract is "host layout == the layout on the client's keyboard", and nothing was upholding it: - Nothing exports `XKB_DEFAULT_*`. `localectl set-x11-keymap de` writes /etc/X11/xorg.conf.d/00-keyboard.conf — a file only Xorg reads — and libxkbcommon's fallback chain stops at the env vars, which no session manager sets. Compiling from empty names on a properly-configured German box therefore yielded evdev/pc105/us, silently. - gamescope reads those env vars and then publishes the keymap to nobody. It builds the keymap onto `keyboard_group`, but the seat carries `virtual_keyboard_device` — a stub whose own comment says it exists "only to set the keymap" and which never gets one. `wlserver_keyboardfocus()` rebinds that stub on every focus change, and the real group only reaches the seat from a libinput key event, which a `--backend headless` session never has. Verified on the box: both Xwayland servers map evdev 53/40/43 to slash/apostrophe/backslash on a de/nodeadkeys machine. `pf_host_config::layout` resolves what the box actually recorded (`XKB_DEFAULT_*`, then xorg.conf.d, then vconsole's XKBLAYOUT — never vconsole's KEYMAP, whose names are console names and do not map onto xkb's). From there: - the wlroots injector compiles its uploaded keymap from it instead of from empty names, which fixes Sway/Hyprland hosts outright; - all four gamescope launch paths hand the session `XKB_DEFAULT_*`, gated behind a `+pfhdr8` probe that warns when the binary predates the fix rather than leaving it unexplained; - `sync_session_keyboard_layout()` covers the case none of that reaches — the autologin session punktfunk ATTACHES to, where no launch-time decision applies — by pointing each gamescope Xwayland at the box's layout on adoption. Everything in Game Mode is an X11 client of those servers, so this is the leg that fixes the report. `PUNKTFUNK_SESSION_LAYOUT=0` turns it off. gamescope patch 0010 sets the keymap on the stub as well, which is what makes the env legs mean anything for Wayland-native clients. It is NOT build-verified (no gamescope build environment here); the series does apply `git am`-clean at the pinned 5fb8dce4. Verified: 10 new unit tests over the resolver; pf-inject + pf-host-config clippy `-D warnings` and those tests on real linux-gnu in the CI image; pf-vdisplay checks and clippies clean on linux-gnu via scripts/xcheck.sh, confirmed non-vacuous with a planted error. The character mapping itself was confirmed on the box with `xmodmap -pke` before and after applying the layout. |