wlroots compositor in Zig
  • Zig 99.4%
  • Shell 0.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-08 23:07:21 -04:00
contrib doc: man pages suisei(1) and suictl(1), and git-style suictl help from the same page — tools/doc.zig turns the scdoc sources into roff and help tables, the build fails if a command has no entry, and COMMANDS.md goes; suictl suggests commands for typos, prints usage on bad arguments and says why it cannot reach suisei; a shorter README, and contrib/init maps the keys 2026-09-26 13:39:17 -04:00
doc suictl: help lists the common commands, as git help does — the whole list moved to help -a and always went through the pager; the common ones are checked against the commands at compile time, and a test keeps the list within an 80x24 terminal 2026-09-26 19:52:07 -04:00
protocol status stream: suisei-status-unstable-v1 delivers state changes as 2026-07-11 17:55:08 -04:00
src keyboard: a surface given focus isn't told a binding's key is held — the enter event listed every held key, the one a binding ate among them, and Xwayland repeats keys held at enter until they're let go, which the eaten release never told it: Alt+8 to a tag left an X window typing 8 forever; the key is now eaten before the binding runs, as it may move the focus 2026-10-08 23:07:21 -04:00
suictl suictl: help lists the common commands, as git help does — the whole list moved to help -a and always went through the pager; the common ones are checked against the commands at compile time, and a test keeps the list within an 80x24 terminal 2026-09-26 19:52:07 -04:00
tools doc: man pages suisei(1) and suictl(1), and git-style suictl help from the same page — tools/doc.zig turns the scdoc sources into roff and help tables, the build fails if a command has no entry, and COMMANDS.md goes; suictl suggests commands for typos, prints usage on bad arguments and says why it cannot reach suisei; a shorter README, and contrib/init maps the keys 2026-09-26 13:39:17 -04:00
.gitignore build on current zig master: pin wayland/pixman to the forge forks (path deps were stale machine-local clones), replace @cImport with a translate-c module, migrate removed std APIs (posix.fork/getuid/clock_gettime -> os.linux, dupeZ -> dupeSentinel, ArrayListUnmanaged{} -> .empty), fix a returned error set that should be an error, and raise minimum_zig_version accordingly 2026-07-10 03:02:44 -04:00
build.zig output: tear for a fullscreen window that asks to, wp-tearing-control-v1 — suisei showed every frame at the next vblank, so a game presenting uncapped while its buffers were scanned out got one back per refresh and ran at the refresh rate; now a fullscreen surface hinting async is flipped at once, falling back to the vblank when the output can't, and not while locked or in the overview. 2026-10-03 12:43:12 -04:00
build.zig.zon startup: run the init script and -c as everything else suisei spawns, with its whole environment, and reap them — since 5ffb8fa they got seven variables (no LANG, XDG_SESSION_ID, XDG_DATA_DIRS...), SIGPIPE ignored and suisei's 4096 fd limit, all passed on to dbus, pipewire and whatever else the init starts, and the init stayed a zombie all session; zig-wayland's addFd, which the reaping needs, fixed and pinned 2026-09-26 11:33:20 -04:00
LICENSE Initial commit 2026-07-10 02:34:02 -04:00
README.md README: the Vulkan headers can be a package of their own, and what -Dvulkan-renderer=true and =false each do — on Arch the loader's vulkan.pc comes without them, which is what the detection now looks for 2026-09-26 20:36:12 -04:00

suisei

suisei is a dynamic tiling Wayland compositor written in Zig, in the tradition of dwm and river.

Features

Windows tile into a main column and a stack. They are organized with tags rather than workspaces: a window may have several tags, and an output may show several at once. Window rules place and style windows by app id and title.

An overview shows every window at once, scaled down as in mango or in a grid as in hycov, and doubles as alt-tab. Windows animate as they move, open, close and switch tags, and scenefx draws rounded corners, shadows and blur.

suisei is configured at runtime with suictl. On startup it runs an init script, which usually calls suictl to map keys and set things up.

Building

Dependencies:

  • zig master, see minimum_zig_version in build.zig.zon
  • pkg-config
  • wayland, wayland-protocols, hwdata, libdrm, EGL, GLES2, gbm, lcms2, libseat, libudev, libdisplay-info, libinput, libevdev, xkbcommon, pixman, libxcb, xcb-util-renderutil and xcb-util-wm, for wlroots and scenefx, which are built from source and linked statically
  • fcft
  • Xwayland, for X11 clients
  • the Vulkan loader and headers and glslang, optionally, for wlroots' Vulkan renderer, which a second GPU falls back to when its GLES2 fails. Some distributions package the headers apart from the loader, such as Arch's vulkan-headers; without them the renderer is left out

Then run, for example:

zig build -Doptimize=ReleaseFast --prefix ~/.local install

This installs suisei, suictl and their man pages. -Dxwayland=false leaves out X11 support, -Dvulkan-renderer=false leaves out the Vulkan renderer even when its dependencies are found, -Dvulkan-renderer=true builds it or fails when they are missing, and -Dsystem-wlroots=true links the system's wlroots 0.20 instead of the bundled fork. zig build -h lists all options.

suisei renders with GLES2, so it needs a Mesa or NVIDIA driver.

Usage

Run suisei from a TTY. To start it from a display manager, add a wayland-sessions desktop entry that runs it.

Configuration

suisei runs ~/.config/suisei/init on startup if it is executable. It is a shell script, usually a list of suictl commands:

#!/bin/sh
suictl map Super Return spawn foot
suictl map Super q close
suictl rule-add -app-id pavucontrol float
suictl set-corner-radius 8

suictl help lists the commands, and suictl help <command> describes one. The man pages suisei(1) and suictl(1) cover everything. contrib/init is a complete example that also starts session services and maps a dwm-like set of keys; there are no default bindings.

Dark mode

Portal-aware applications (GTK, Qt, Firefox, Electron) follow the color scheme set with:

gsettings set org.gnome.desktop.interface color-scheme prefer-dark

This needs xdg-desktop-portal with its gtk and wlr backends, a session bus, as in contrib/init, and contrib/suisei-portals.conf copied to ~/.config/xdg-desktop-portal/.

License

GPL-3.0, see LICENSE.