# xkeyboard-config — X11 keyboard layouts, compiled to Zig

This module turns a physical key (a **USB HID usage**, as the [input module](../../docs/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.
