# xkeyboard-config — X11 keyboard layouts, compiled to Zig This module turns a physical key (a **USB HID usage**, as the [input module](../../docs/device-driver-development/input.md) delivers in `KeyEvent.keycode`) plus a modifier state into a **keysym** and, when the key produces one, a **character** (a Unicode scalar). It is what lets a `keycode` become a `character` — a keymap — without danos shipping an X11 runtime. The layout data comes from the X11 [xkeyboard-config](https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config) database, but it is **compiled to native Zig at build time** rather than parsed at runtime. `tools/make-xkeyboard-config.py` reads the vendored xkb data and emits pure-data tables into `generated/layouts.zig`; `xkeyboard-config.zig` is the hand-written API over them. This is the same build-time-codegen pattern as `tools/make-initial-ramdisk.py`. ## Using it ```zig const xkb = @import("xkeyboard-config"); const m = xkb.map(xkb.us, key_event.keycode, .{ .shift = shift_held, .caps_lock = caps }); if (m.character) |ch| { /* a printable Unicode scalar */ } // m.keysym is always set (e.g. an X11 keysym for Return / F1 / a dead key). const layout = xkb.byName("gb") orelse xkb.us; // choose a layout by name for (xkb.all) |l| { /* enumerate available layouts */ } ``` `Modifiers` carries `shift`, `caps_lock`, `level3` (AltGr), and `control`. `map` selects the level from the key's XKB *type* (the generated data) and those modifiers (the policy, in `xkeyboard-config.zig`), so data and semantics stay separable. Layouts: **us, gb, de, fr, es, dvorak**. ## Regenerating ```sh python3 tools/make-xkeyboard-config.py fetch # network: download + vendor the data subset python3 tools/make-xkeyboard-config.py generate # offline: emit generated/layouts.zig # or, from the build: zig build gen-xkeyboard-config ``` - **`fetch`** downloads the pinned xkeyboard-config release (version + sha256 in the script), resolves the `include` graph for the configured layouts, and vendors *only* the symbols files actually reached (plus `keysymdef.h`, `COPYING`, and `PROVENANCE.md`) into `vendor/`. Run it when bumping the version or adding a layout. - **`generate`** is deterministic and offline — same vendored input produces byte-identical output. To add a layout, extend `TARGETS` (and `HID_TO_NAME` if a new physical key is involved), then re-run `fetch` (to vendor any new includes) and `generate`. ## Scope A pragmatic subset, enough for real Latin-script typing: - **Group 1 only** — no multi-layout group switching. - **No dead-key / compose composition** — a dead key returns its keysym with no `character` (composing `´` + `e` → `é` is a higher layer's job). - **Curated key types** — the common XKB types (one/two-level, alphabetic, four-level, …); unmapped keys and unknown types fall back to level-by-shift. - **6 layouts** — extend via `TARGETS` as above. ## Licensing xkeyboard-config and `keysymdef.h` (xorgproto) are MIT/X11 licensed. The vendored data subset carries the upstream `vendor/COPYING`, and `vendor/PROVENANCE.md` records the exact version, source URL, and sha256. The generated tables are a derived work under the same terms.