# Architecture Keyboard Layout Switcher is a Quickshell plugin over Hyprland's existing XKB configuration. ```text KeyboardLayoutSwitcher.qml ─┬─ bar status / quick switch ─┐ └─ loads Panel.qml ├─ bin/keyboard-layout-switcher │ → keyboard_layout_switcher/core.py Service.qml ─── focus and reload events ───┘ │ ├─ hyprctl -j devices ├─ hyprctl switchxkblayout ├─ hyprctl getoption/eval └─ ~/.config/omarchy-keyboard-switcher/policy.json ~/.config/hypr/input.lua ── configures device XKB groups ── Hyprland ~/.config/xkb/symbols/* ─── defines custom mappings ──────── XKB ``` ## Source-of-truth boundary - Hyprland reports connected keyboards, their configured XKB group lists, and their active group index. - Keyboard Layout Switcher never replaces a device's configured group list. - The layouts shown for a keyboard are exactly the layouts configured for that device, including global input settings and per-device overrides. - User-owned XKB files and `input.lua` are opened in the configured editor. They are not generated or rewritten by Keyboard Layout Switcher. - `policy.json` stores only the selected keyboard, last successful group per keyboard, shortcut preference, application rules, and focus restoration state. ## Shell data boundary All data entering the long-lived shell through the backend is bounded: - Each child command has a two-second deadline and a 256 KiB combined output ceiling. Output is read incrementally, and the child is terminated on either limit. - Device, layout, client, application, rule, field, path, policy-file, and final-response sizes have explicit limits. Exceeding a limit returns a small error instead of a partial snapshot. - The three QML processes that collect JSON have five-second watchdogs. Other background actions use quiet mode and do not allocate an output collector. - Plugin-owned text uses `Text.PlainText`. Values passed into shared Omarchy controls cross a plain-display boundary that removes control and markup delimiters first. ## Switching transaction 1. Refresh `hyprctl -j devices`. 2. Confirm the selected typing keyboard is connected. 3. Confirm the requested layout is in that keyboard's configured XKB groups. 4. Run `hyprctl switchxkblayout ` as an argument vector. 5. Read the device state back and verify its active index. 6. Persist the remembered group only after verification succeeds. ## Application rules Rules match the focused window class. A rule names a configured layout and one keyboard or the explicit `all` target. On focus entry, Keyboard Layout Switcher records each target's current group and switches compatible connected targets. On focus leave, it restores those recorded groups. Disconnected or incompatible targets are reported without changing another keyboard. Rules can also override `input.resolve_binds_by_sym` through Hyprland's Lua runtime API. Symbol-following uses the active typing layout. Disabling it keeps shortcuts in the first globally configured layout's positions. Keyboard Layout Switcher restores the previous setting when focus leaves. ## Keyboard discovery Hyprland reports power buttons, virtual input-method devices, and other non-typing inputs in its keyboard list. Keyboard Layout Switcher filters known auxiliary and virtual devices. Remaining devices appear in the keyboard picker and keep independent active and remembered groups.