# AGENTS.md

Workspace of three independent Meson projects for Wayland keyboard layout tooling.

## Projects

| Directory | Language | What it is |
|---|---|---|
| `libsni-exporter/` | C (GLib/GIO) | Shared library exporting StatusNotifierItem + dbusmenu over D-Bus |
| `labwc-kbd/` | Vala + GTK3 | `wl-kbd-config` keyboard layout config GUI for labwc/sway/hyprland/wayfire/river |
| `wl-kbd-assets/` | — (data only) | SVG flag icons + xkeyboardconfig catalog; no source files |
| `wl-kbd/` | C (GLib/Cairo/Wayland) | Keyboard layout tray indicator; SNI icon, FLAG/LETTERS modes |

Each project is fully independent — no shared build root.

## Build Commands (per project)

```bash
# Development build
meson setup build --prefix=/usr
meson compile -C build

# Install (e.g. for integration testing or PKGBUILD)
DESTDIR=/tmp/pkg meson install -C build

# Release / package build (matches PKGBUILD)
meson setup build-pkg --prefix=/usr --buildtype=release --wrap-mode=nodownload
meson compile -C build-pkg
```

Run all commands from within the project directory (e.g. `labwc-kbd/`).

## Tests

### `libsni-exporter` — C / GTestDBus

Tests are always compiled (hardcoded `subdir('tests')` in root `meson.build`).  
Each test spins up its own private D-Bus via `GTestDBus` — no system/session bus needed.

```bash
# From libsni-exporter/
meson setup build --prefix=/usr
meson compile -C build
meson test -C build          # or: ./build/tests/test_menu
```

### `labwc-kbd` (`wl-kbd-config`) — Vala / GLib test

Tests are **off by default**. Enable with `-Dtests=true`. Workdir during test run is `tests/` (fixtures live there). Test-only code is gated behind `--define=UNIT_TEST` Vala flag (already wired in `tests/meson.build`).

```bash
# From labwc-kbd/
meson setup build --prefix=/usr -Dtests=true
meson compile -C build
meson test -C build
```

### `wl-kbd-assets`

No tests — data-only project.

## Key Quirks

### wl-kbd-config locale path is hardcoded
`main.vala` hardcodes `/usr/share/locale`. Translations only appear when the app is properly installed. During dev builds without install, UI strings show English regardless of locale.

### wl-kbd-assets must be installed for wl-kbd-config to show flag icons
`wl-kbd-config` depends on `wl-kbd-assets` at runtime (listed in PKGBUILD). Install `wl-kbd-assets` first when setting up a test environment. Flag icons are installed under **both** `wl-kbd-layout-XX.svg` and `labwc-kbd-layout-XX.svg` name prefixes for compatibility.

### libsni-exporter VAPI
`vapi/sni-exporter.vapi` provides Vala bindings. Installed to `$(datadir)/vala/vapi`. Required when using the library from Vala (e.g. `wl-kbd-config` if it switches to libsni-exporter).

### libsni-exporter: ItemIsMenu defaults to true
Call `sni_exporter_set_item_is_menu(tray, FALSE)` **before** `sni_exporter_start()` to enable `Activate` on left-click in Waybar/swaybar. sfwbar always opens the menu regardless.

### sfwbar ignores ItemsPropertiesUpdated
Live menu label updates via `sni_exporter_menu_update_label()` do not propagate in sfwbar. Use `menu_begin()` / `menu_end()` for a full rebuild instead.

### SNI watcher conflict
Only one `org.kde.StatusNotifierWatcher` can run at a time. If `kded6` (KDE daemon) starts first, it steals the watcher and tray icons vanish. Fix: `pkill kded6`.

### ARGB pixmap byte order
Cairo `CAIRO_FORMAT_ARGB32` is BGRA on little-endian x86. SNI expects ARGB big-endian. Manual per-pixel swap required — see `examples/minimal-tray.c` for the canonical conversion.

### wl-kbd-config: supported WMs
`WMConfigModifier` handles labwc, sway, wayfire, river, hyprland. Each uses a different config file location and format — config paths are hardcoded per WM in `src/wm_config_modifier.vala`. Labwc writes a managed block (`# BEGIN wl-kbd-config` / `# END wl-kbd-config`) in `~/.config/labwc/autostart`.

## wl-kbd

Runtime indicator (no window). Sources: `src/{main,config,icon,layout_code,wl_keyboard,indicator}.c`.

- **Config**: `~/.config/wl-kbd/indicator.ini` — `tray_style` (FLAG/LETTERS), `letter_theme` (light/dark).
- **Icon modes**: FLAG → `sni_exporter_set_icon_name("wl-kbd-layout-XX")`; LETTERS → Cairo 24×24 ARGB pixmap via `sni_exporter_set_icon_argb()`. **Never** call `sni_exporter_set_icon_theme_path()` for letter icons.
- **Keyboard tracking**: `wl_seat` → `wl_keyboard`; layout codes from `$XKB_DEFAULT_LAYOUT`; group from `wl_keyboard.modifiers` (requires a focused surface — only fires when compositor sends it).
- **Layout mapping**: `layout_code.c` ports `flag_utils.vala` logic; `layout_to_icon_code("russian")` → `"ru"`, etc.
- **Build deps**: `sni-exporter` (this repo), `wl-kbd-assets` (runtime flag icons), `cairo`, `pango`, `wayland-client`, `xkbcommon`.
- **No compiler in this container** — code review only; build requires installing gcc/clang first.

## i18n (wl-kbd-config)

```bash
# Update pot template
cd labwc-kbd
xgettext --from-code=UTF-8 -k_ -kN_ src/*.vala -o po/wl-kbd-config.pot

# Compile translations (done automatically by meson install)
msgfmt po/ru.po -o po/ru.mo
```

Active languages listed in `po/LINGUAS` (currently: `ru`).
