Each library domain (kernel, device, client, protocol, csv, xkeyboard-config) now owns a build.zig + build.zig.zon that wires and exports its modules, with a standalone `zig build test` per domain. The kernel package also exports abi (source stays in system/abi.zig) so every consumer names one module instance. The root build swaps its createModule calls for b.dependency(...).module(...) — no binary moves; the root is the pilot consumer (docs/build-packages-plan.md). Path dependencies deduplicate by resolved location, so the diamond (root -> device -> kernel, root -> kernel) yields a single instance of each module. Boot-image file list unchanged. |
||
|---|---|---|
| .. | ||
| generated | ||
| vendor | ||
| README.md | ||
| build.zig | ||
| build.zig.zon | ||
| xkeyboard-config.zig | ||
README.md
xkeyboard-config — X11 keyboard layouts, compiled to Zig
This module turns a physical key (a USB HID usage, as the input module
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
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
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
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
fetchdownloads the pinned xkeyboard-config release (version + sha256 in the script), resolves theincludegraph for the configured layouts, and vendors only the symbols files actually reached (pluskeysymdef.h,COPYING, andPROVENANCE.md) intovendor/. Run it when bumping the version or adding a layout.generateis deterministic and offline — same vendored input produces byte-identical output. To add a layout, extendTARGETS(andHID_TO_NAMEif a new physical key is involved), then re-runfetch(to vendor any new includes) andgenerate.
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
TARGETSas 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.