Per-keyboard-device xkb and repeat configuration (carries upstream niri#4459) - #44
Merged
Merged
Conversation
Adds an optional device name argument to the keyboard block, e.g.
`keyboard "My External Keyboard" { ... }`, collected into
Input::keyboards. Named blocks inherit unset settings from the unnamed
keyboard block in the same input section, then fall back to the
regular defaults.
Input::fallback_keyboard() and Input::keyboard_named() resolve the
config for a given device name, used by the following commit to
actually apply per-device settings.
The Wayland protocol only allows one active keymap per seat, so per-device configuration is implemented by resolving and re-applying the keyboard config for whichever physical device sent the most recent key event, caching the resolved config by device so idle devices are free. This reuses the same set_xkb_config()/ change_repeat_info() calls already used for the layout-switch bind and config hot-reload. The resolved-config cache is cleared and the tracked active keyboard reset to the fallback whenever the keyboard configs change on reload, so edits take effect on the next keystroke instead of sticking to stale per-device settings. Also switches bind key repeat and the accessibility repeat-delay heuristic to use the currently tracked keyboard instead of always the fallback one.
…eyboards The per-device switch path applied the new keymap directly through the Smithay keyboard handle instead of State::set_xkb_config(), so every switch between keyboards reset num lock. It also ignored the locale1 settings that a config reload uses when xkb is left unset, and never told IPC listeners that the layout list had changed. Split the switch out of the device resolution into switch_keyboard_config() so it can be driven from the headless fixture, and make it follow the same chain as reload_config(): xkb file first, then the rules-based config with locale1 filling in the defaults, via the num-lock-preserving wrapper, followed by the keyboard-layouts IPC event.
niri msg keyboard-layouts lists layout names, not devices.
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.
Part of #43.
Carries upstream niri-wm#4459 (three commits, cherry-picked as-is) onto
main, plus two fork commits on top.What it does
keyboard "device name" { … }blocks insideinput {}configure one physical keyboard. A named block inherits any setting it leaves unset (repeat-rate,repeat-delay,numlock,track-layout) from the unnamed block;xkb {}is one setting and replaces as a whole. Device names match case-insensitively against the libinput device name. A Wayland seat has a single keymap, so the resolved config is applied when a key event arrives from a different device than the last one. Resolved configs are cached per device and the cache is dropped whenever the keyboard blocks change on reload.Fork changes on top of the upstream PR
reload_config()uses when xkb is left unset, and never sentKeyboardLayoutsChangedover IPC. The switch now goes throughState::set_xkb_config()with the same chain as a reload and notifies IPC. The switch logic lives inswitch_keyboard_config()so the headless fixture can drive it.niri msg keyboard-layoutsto find device names; that command lists layouts, not devices. The wiki page and the default config now point atlibinput list-devicesand/proc/bus/input/devices.Tests
xkbreplacing wholesale, case-insensitive matching, unknown device falling back, named-only config using the defaults, an includedinputsection replacing all keyboard blocks). Written before the cherry-pick; they failed to compile until the config commit landed.src/tests/keyboard_config.rs(named layout applied, num lock kept, locale1 used when switching back to an unset xkb). The last two failed against the upstream code and pass with the fix.cargo test -p niri -p niri-config -p niri-ipc: 316 and 81 pass.cargo fmt --checkclean.cargo clippyon those crates adds no warnings on changed lines. Workspace-wide clippy fails inniri-visual-testson a missing gdk-pixbuf, unrelated to this branch.Hardware test on sixseven (pending)
keyboard "Logitech USB Receiver" { xkb { … } }next to the unnamed block, typing on each keyboard produces its own layout from the first keystrokeniri msg event-streamreportsKeyboardLayoutsChangedwhen the active device changesKnown limitations carried from upstream:
track-layout "window"with several named keyboards keeps one layout per surface, not per (keyboard, surface); XWayland clients see a single X11 keymap.