Omarchy on Kandelo — the desktop shell: layer-shell bar, launcher, themes - #1241
Draft
mho22 wants to merge 6 commits into
Draft
Omarchy on Kandelo — the desktop shell: layer-shell bar, launcher, themes#1241mho22 wants to merge 6 commits into
mho22 wants to merge 6 commits into
Conversation
…me engine The Tier 1 / O1 desktop shell from the Hyprland-class compositor plan (docs/plans/2026-07-14-build-hyprland-class-compositor-plan.md §3). Compositor: zwlr_layer_shell_v1 (anchors, margins, exclusive zones, keyboard-interactivity). layers_arrange() computes the window work area from the anchored strips, background→overlay, then retiles. A surface joins the layer list at role creation, not at map, so a client dying mid-handshake cannot strand a strip. Compositing and hit-testing put background/bottom under windows and top/overlay over them on the GPU and CPU paths; layer surfaces show on every workspace. Theme engine: theme_scan/theme_load/theme_apply/theme_switch over /usr/share/kandelo/themes/<name>/theme.conf. `theme =` config key, `kwlctl theme` query, `dispatch theme <name|next|prev>`, a `theme` keybind dispatcher, and a `theme>>name` broadcast. Gaps and the focus border color are theme variables; the wallpaper repaints and re-uploads through a retained staging bo on switch. Fixes: SIGPIPE from a control client that exits without reading its reply no longer kills the compositor; a failed exec reports KWLCTL_EXEC_FAILED on stdout. libkwl: kwl_layer_create() + struct kwl_layer_opts; the connect path is factored into kwl_open()/kwl_open_buffers() shared with kwl_window_create(). New clients: kbar (top bar, exclusive zone, workspace pills + focused window + clock off the kwlctl socket) and klauncher (overlay launcher, keyboard-exclusive, filters /usr/share/kandelo/apps, Enter dispatches exec). Tests: layer-shell and theme Node smokes; the resize smoke now waits for both windows' resize markers instead of racing the second one. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The O1 integration gate: the tiling compositor boots with kbar on a layer-shell strip, klauncher on SUPER/CTRL+Space, and three themes (Tokyo Night, Catppuccin Mocha, Gruvbox) cycling on CTRL+SHIFT+Space. omarchy-desktop.ts carries the data half: the compositor config, the launcher app registry, and the theme palettes. Staging and spawn reuse the hyprland block in live-setup.ts; only the extra files and the two extra binaries differ. Every SUPER bind is mirrored on CTRL because the browser reserves SUPER for the OS. Both hosts: the compositor, bar, launcher, and theme engine are gated by Node smokes (previous commit); the browser path is gated by the new kandelo-omarchy.spec.ts Playwright suite (config + theme loaded, bar anchored, windows tile under the bar, canvas composited, launcher takes the keyboard + filters + launches, theme cycles, bar tracks the workspace). Docs: architecture.md gains the desktop-shell subsection; browser-support.md gains the demo-table row and the Omarchy demo section. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A theme's theme.conf gains `wallpaper = <file>`: KWLP raw pixels
("KWLP", u32le width/height, XRGB) that the compositor bilinear-scales
into g.wallpaper, falling back to the gradient when the key is absent
or the file fails to load. Raw pixels because nothing in the
compositor decodes PNG/JPEG — whoever stages the theme renders the
image.
The demo now ships six themes — Tokyo Night, Catppuccin Mocha,
Gruvbox, Nord, Everforest, Rosé Pine — each with an aurora wallpaper
the page renders at staging time (renderWallpaperKwlp: radial glows in
the palette colours on an OffscreenCanvas, 960x540, ~2 MB staged per
theme).
Fix exposed by per-theme gaps: wlterm only redrew + committed on a
KWL_RESIZE that changed its cell grid, but kwl_apply_resize has
already destroyed the buffer the compositor held — a tile shift
smaller than one cell (a theme's gap change) left the window invisible
until the shell printed again. wlterm now always recommits and gates
only the PTY winsize/SIGWINCH on a grid change. The other libkwl
clients already redrew unconditionally.
Both hosts: theme smoke gains the wallpaper triple (image, gradient
fallback, broken file) and the small-gap recommit regression (three
1px gap steps guarantee a grid-preserving resize); the Playwright gate
asserts WALLPAPER image and the widened theme-cycle set; hyprland +
omarchy browser gates green, all 10 wlcompositor/wlterm Node suites
green serially.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The launcher registry now offers the shell image's real software next to the demo clients: Vim, NetHack and Nano run unmodified inside a wlterm (`exec = /usr/local/bin/wlterm /usr/bin/vim`), plus a Bash terminal. The binaries lazy-fetch from the image's archives on first launch — the normal runtime path, no demo staging. wlterm now sets TERM=vt100 in its forkpty child: the inherited TERM describes the launcher's terminal, and curses apps must see the type this terminal implements. `klauncher --menu` opens the Omarchy menu: a root level (Apps, Theme) that descends into the app list or the installed-theme list (read from `kwlctl theme`, switched with `dispatch theme`). ESC in a submenu goes back to the root; ESC at the root dismisses. Bound to SUPER/CTRL+ALT+Space in the demo config. Compositor: the keybind engine gains the ALT (Mod1) modifier, and the self-contained xkb keymap gains Alt_L and the four arrow keys — the keymap had no arrows, so Up/Down never reached the launcher (or vim) in the browser. Both hosts: keybind smoke gains a CTRL ALT exact-mods case; theme smoke gains the menu flow (root → themes → dispatch, ESC back to root); the Playwright gate gains the vim launch through the launcher (lazy fetch + fifth tile + an ABI-mismatch guard) and the menu flow. All 10 wlcompositor/wlterm Node suites and the omarchy/hyprland/ wayland browser gates pass. The vim launch initially died on exec: the cached vim archive was built against ABI 15 (stale June link output reused by an incremental build). Rebuilt locally against the current sysroot; the published archive needs a re-publish for abi-v17. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
Phase B-1 matrix build status —
|
| Package | Arch | Status | Sha |
|---|---|---|---|
| alsa-lib | wasm32 | failed | — |
| libcurl | wasm32 | failed | — |
| libcxx | wasm32 | failed | — |
| libcxx | wasm64 | failed | — |
| libdrm | wasm32 | failed | — |
| libevdev | wasm32 | failed | — |
| libffi | wasm32 | failed | — |
| libinput-lite | wasm32 | failed | — |
| libinput | wasm32 | failed | — |
| libpng | wasm32 | failed | — |
| libudev | wasm32 | failed | — |
| libwayland | wasm32 | failed | — |
| libxkbcommon | wasm32 | failed | — |
| libxml2 | wasm32 | failed | — |
| libxml2 | wasm64 | failed | — |
| mtdev | wasm32 | failed | — |
| openssl | wasm32 | failed | — |
| openssl | wasm64 | failed | — |
| sdl2 | wasm32 | failed | — |
| sqlite | wasm32 | failed | — |
| sqlite | wasm64 | failed | — |
| zlib | wasm32 | failed | — |
| zlib | wasm64 | failed | — |
| bc | wasm32 | failed | — |
| bzip2 | wasm32 | failed | — |
| coreutils | wasm32 | failed | — |
| curl | wasm32 | failed | — |
| dash | wasm32 | failed | — |
| diffutils | wasm32 | failed | — |
| dinit | wasm32 | failed | — |
| fbdoom | wasm32 | failed | — |
| file | wasm32 | failed | — |
| findutils | wasm32 | failed | — |
| gawk | wasm32 | failed | — |
| git | wasm32 | failed | — |
| grep | wasm32 | failed | — |
| gzip | wasm32 | failed | — |
| kandelo-sdk | wasm32 | failed | — |
| kernel | wasm32 | failed | — |
| less | wasm32 | failed | — |
| lsof | wasm32 | failed | — |
| m4 | wasm32 | failed | — |
| make | wasm32 | failed | — |
| mariadb | wasm32 | failed | — |
| mariadb | wasm64 | failed | — |
| msmtpd | wasm32 | failed | — |
| nano | wasm32 | failed | — |
| ncurses | wasm32 | failed | — |
| netcat | wasm32 | failed | — |
| nginx | wasm32 | failed | — |
| php | wasm32 | failed | — |
| posix-utils-lite | wasm32 | failed | — |
| sed | wasm32 | failed | — |
| spidermonkey | wasm32 | failed | — |
| tar | wasm32 | failed | — |
| tcl | wasm32 | failed | — |
| unzip | wasm32 | failed | — |
| userspace | wasm32 | failed | — |
| vim | wasm32 | failed | — |
| wget | wasm32 | failed | — |
| xz | wasm32 | failed | — |
| zip | wasm32 | failed | — |
| zstd | wasm32 | failed | — |
| bash | wasm32 | failed | — |
| mariadb-test | wasm32 | failed | — |
| mariadb-vfs | wasm32 | failed | — |
| mariadb-vfs | wasm64 | failed | — |
| nethack | wasm32 | failed | — |
| node | wasm32 | failed | — |
| spidermonkey-node | wasm32 | failed | — |
| vim-browser-bundle | wasm32 | failed | — |
| nethack-browser-bundle | wasm32 | failed | — |
| rootfs | wasm32 | failed | — |
| shell | wasm32 | failed | — |
| lamp | wasm32 | failed | — |
| node-vfs | wasm32 | failed | — |
| wordpress | wasm32 | failed | — |
Auto-generated; replaced on each push. Raw data in the publish-status workflow artifact.
knotify — the notify-send slot: one toast per process. A corner- anchored overlay layer surface (top-right, under the bar's strip) shows `knotify <title> <body…>` for a moment and exits; the surface teardown is the dismissal, so there is no daemon and no unmap protocol. It adopts the compositor's live theme over kwlctl. The compositor gains a `notify = <path>` config key: a theme switch spawns the configured notifier with the new name — the hook Omarchy fills with notify-send in its scripts. Absent key, no spawn. libkwl: kwl_layer_opts gains margins (zwlr_layer_surface_v1.set_margin), which corner toasts need. kbar: the right side gains the kernel's monotonic uptime next to the clock, in the theme's muted colour. The kernel exposes no /proc/meminfo, so there is no memory module — real stats or none. Both hosts: theme smoke asserts the notify hook fires on a switch (Node); the Playwright gate asserts the toast maps and dismisses after the theme cycle. All 10 wlcompositor/wlterm Node suites and the omarchy/hyprland/wayland browser gates pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The browser input bridge translated keys purely by physical position (KeyboardEvent.code), and the kernel-side xkb keymap is a fixed US layout — so a non-US physical layout delivered the letter printed at the US position of the pressed key. On AZERTY the key labeled W sits at the QWERTY-Z position: Ctrl+W arrived at the compositor as Ctrl+Z and the killactive bind never fired, and every typed letter in wlterm or the launcher came out QWERTY-scrambled. charToKey maps a single typed ASCII letter to its US-layout keycode and wins over the positional path; everything else (digits, punctuation, dead keys, modifier-altered characters) keeps KeyboardEvent.code, because their key value depends on Shift and the layout's unshifted symbols. The Framebuffer pane's own translation stays positional on purpose — game movement keys are positional. Browser-only layer: Node has no keyboard capture (tests inject evdev codes directly), so there is no Node-side counterpart to change. Unit tests cover the AZERTY Ctrl+W pair and the non-letter fallback; verified live against /?demo=omarchy with synthesized code=KeyZ/key=w events (window closes), and the omarchy/hyprland/wayland/sdl2 browser gates pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #976 (the tiling WM). This starts at the O1 milestone of
docs/plans/2026-07-14-build-hyprland-class-compositor-plan.md§3 (PR15–PR18) and continues past it: the desktop shell that turns the tiling compositor into an Omarchy-shaped desktop, then the identity work that makes it look and feel like Omarchy rather than a compositor test.Commits
zwlr_layer_shell_v1(anchors, margins, exclusive zones, keyboard-interactivity) with the arrangement engine that reserves strips and retiles beneath them; the file-based theme system (/usr/share/kandelo/themes/<name>/theme.conf,kwlctl dispatch theme,theme>>broadcast);kbarandklauncher;kwl_layer_create()in libkwl; a SIGPIPE fix (a control client exiting without reading its reply killed the desktop)./?demo=omarchy— the O1 integration gate: bar + launcher + themes, every SUPER bind mirrored on CTRL (browsers reserve SUPER).wallpaper = <file>(KWLP raw pixels, bilinear-scaled by the compositor; raw because nothing in C decodes PNG/JPEG — the page renders per-theme aurora wallpapers at staging time). Tokyo Night, Catppuccin Mocha, Gruvbox, Nord, Everforest, Rosé Pine. Fixes a wlterm bug this exposed: a resize smaller than one terminal cell left the window buffer-less and invisible.klauncher --menuis the Omarchy menu (Apps/Theme, ESC back to root) on SUPER/CTRL+ALT+Space; the compositor gains the ALT modifier and the keymap gains Alt_L + arrow keys (arrows never reached clients before); wlterm advertises TERM=vt100 to its child.notify = <path>spawns a themed overlay toast on every theme switch; kbar shows the kernel's monotonic uptime (no /proc/meminfo → no memory module; real stats or none).Both hosts
wlcompositor-{layer-shell,theme,keybind,resize,…}smokes — all 10 wlcompositor/wlterm suites pass serially, including new coverage for the wallpaper triple (image / gradient fallback / broken file), the grid-preserving-resize recommit regression, CTRL-ALT exact-mods binds, the menu flow, and the notify hook.kandelo-omarchy.spec.tsgrew from 7 to 10 gates (vim launch through the launcher incl. an ABI-mismatch guard, the menu flow, the toast lifecycle); omarchy + hyprland + wayland gates pass.Verification: cargo
-p kandelo --lib0 fail;run-libc-tests.sh/run-posix-tests.sh0 FAIL;check-abi-version.shin sync — everything here is additive userspace, noABI_VERSIONbump.Known issues carried in the tree (not this PR's regressions): the published vim archive is still abi-v15 and needs a matrix re-publish (a locally rebuilt vim.zip is what the demo uses meanwhile); the exclusive-zone release path (bar exits → tiling area grows back) remains untested — a prototype
dispatch closelayerexposed a host-layer deadlock when a layer client exits in reaction to a compositor event, which needs its own investigation.Docs: architecture.md (desktop shell, themes, menu, knotify), browser-support.md (Omarchy demo section), presets.