Skip to content

feat: layout-independent keybinds#3801

Draft
ronharel02 wants to merge 7 commits intoniri-wm:mainfrom
ronharel02:layout-independent-binds
Draft

feat: layout-independent keybinds#3801
ronharel02 wants to merge 7 commits intoniri-wm:mainfrom
ronharel02:layout-independent-binds

Conversation

@ronharel02
Copy link
Copy Markdown

@ronharel02 ronharel02 commented Apr 9, 2026

This PR adds explicit layout-independent keybinds that resolve symbolic binds against a reference binds.xkb keymap and then match them by physical key at runtime. The feature keeps normal keysym binds unchanged, while allowing punctuation and non-latin layout cases like Mod+/ to continue working across layout switches.

Layout-independent resolution is configured locally within each binds {} block. A block can declare a default with layout-independent true/false, a reference keymap with xkb { ... }, and individual binds in that same block can opt in or out explicitly using layout-independent=true/false. The symbolic key must resolve to at least one physical key in the reference keymap; missing or colliding resolutions are treated as configuration errors.

Several existing issues point to the same underlying problem: keybind behavior changes unexpectedly across keyboard layouts, especially for non-latin layouts, punctuation, and keys whose logical meaning depends on the active XKB layout - e.g. #2818, #1519, #1913, #283, #1225, and #2390.

I did not find an issue that proposes this exact solution/ configuration model directly, but this seemed like a good direction for addressing that broader class of problems while maintaining the default bind behavior.

This also ended up being a larger PR then I intended for it to be, sorry.

Add config fields for layout-independent binds at both the `binds {}` and individual bind levels, plus a separate `binds.xkb` reference keymap section.
Validate the merged binds configuration after includes are applied so that layout-independent binds require a reference XKB config, and that config describes a single reference layout unless an explicit keymap file is used.
Introduce runtime-specific bind types so input handling no longer depends directly on config-layer bind structures.
This keeps bind presentation on the original config data, while letting the runtime and MRU-generated bindings work with owned compiled triggers that can later represent more than plain keysyms.
Compile layout-independent binds against the configured reference keymap and match them by physical key at runtime.
This wires bind compilation into startup, validation, and config reload, and rejects binds that cannot be resolved uniquely or that collide after physical key resolution.
When both a physical-key bind and a keysym bind match the same event, the compiled physical-key bind takes precedence.
Document the new layout-independent bind mode, including how `binds.xkb` defines the reference keymap used for physical-key matching.
Also add commented guidance to the default config so users can discover the feature and see the minimal setup it requires.
Treat `layout-independent` and `binds.xkb` as applying only to binds in the same `binds { }` block.
Move `Xkb` into individual `Bind` entries and validate per-block during decoding.
Update `compile_binds` to use each bind's xkb, cache multiple keymaps, and report per-bind errors on resolution failures.
Also consolidate modifier display and XKB-name parsing through a shared modifier-name table.
`Bind` no longer stores a separate `layout_independent` flag.
Instead, layout-independent matching is represented entirely by `Bind.xkb`: if it is present, the bind is resolved against that reference keymap, and if it is absent, the bind remains a normal keysym bind.

The `layout-independent` setting is now treated purely as `binds {}` block parsing state.
During decoding, each bind computes its effective override from the bind-local property or the block default, validates that the trigger is a keysym when enabled, and copies the block `xkb` onto the bind when needed.

This makes the resolved bind representation simpler and more semantic.
Runtime code no longer has to interpret a tri-state `Option<bool>` alongside `xkb`, and bind compilation can infer layout-independent behavior directly from whether an `xkb` is attached.
Let layout-independent binds compile to multiple physical keys when the reference keymap maps the requested keysym to more than one key.
Keep duplicate detection after expansion, so ambiguous binds are allowed only when their expanded key set does not collide with another bind.
@ronharel02 ronharel02 force-pushed the layout-independent-binds branch from d956e8a to 5288c78 Compare April 9, 2026 18:56
@Sempyos Sempyos added area:input Keyboard, mouse, touchpad, tablet, gestures, pointer pr kind:feature New features and functionality area:config Config parsing, default config, new settings labels Apr 10, 2026
@calops
Copy link
Copy Markdown
Contributor

calops commented Apr 10, 2026

Wouldn't this be covered by #3366?

@ronharel02
Copy link
Copy Markdown
Author

ronharel02 commented Apr 10, 2026

Wouldn't this be covered by #3366?

I wasn’t aware of #3366 when I opened this, thanks for pointing it out.

The main thing this PR adds beyond it is symbolic layout-independent binds for keys that are not simple first-level symbols in the default layout. With #3366, those cases still seem to require either changing bind resolution globally or writing raw binds, while this PR keeps normal keysym binds unchanged and lets specific binds opt into an explicit reference xkb map, including symbols that require modifiers like Shift or AltGr.

With that being said, #3366 is much simpler, so I see why it would be favorable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:config Config parsing, default config, new settings area:input Keyboard, mouse, touchpad, tablet, gestures, pointer pr kind:feature New features and functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants