A Wayland compositor for people who live in a terminal and die in games.
> [!WARNING] > **Early alpha.** NeferWL is developed and tested mostly on AMD CPUs and GPUs. NVIDIA support is incomplete and untested; expect bugs and breaking config changes. --- ## Why NeferWL NeferWL does a few things and does them fast. No animations, no themes, no built-in bar or wallpaper: those are choices, not missing features. Every frame budget goes to your apps. - **A terminal, then out of the way.** One workspace opens your terminal at startup. Bars, launchers and notifications are external clients (Waybar, fuzzel, mako…). - **Columns between tiling and scrolling.** Up to `max-columns` windows share the screen like a classic tiling WM (Sway); past that, columns scroll to the right like Niri, or split in a spiral with `overflow = fixed`. Each workspace picks its own rules. - **Workspaces you design.** Numbered workspaces are dynamic. Named workspaces can be hidden behind a bind, and **slots** declare their columns (width + command): NeferWL starts the apps in the background and puts each window in its place. - **Multi-monitor done right.** Each monitor owns its workspaces. Unplug one and its workspaces move to another monitor; plug it back and they return home, without stealing your focus. - **Built for games.** Fullscreen games skip composition entirely (details below), with tearing and VRR when the game asks. - **Light.** A running session uses about 40–80 MB of RAM with two 4K monitors, and near-zero CPU when nothing changes on screen. - **Live config.** One flat `key = value` file. Every key applies on save, keyboard layout included; windows stay open. A complete desktop in a few lines: ```text keyboard.layout = fr terminal = foot startup = waybar output.DP-1 = 3840x2160@144 output.DP-1.scale = 1.5 layout.max-columns = 3 # A hidden dev workspace: editor and terminal, started and placed for you. workspace.dev.hidden = on workspace.dev.column.1 = 67%, code --new-window workspace.dev.column.2 = 33%, foot bind.cmd+d = workspace dev ``` ### The performance path Every Wayland protocol NeferWL implements is there because it saves work or latency: - **Zero copy.** GPU clients (`zwp_linux_dmabuf_v1` v4) are sampled in place. Vulkan composes straight into exported scanout images, and the frame fence goes to KMS as `IN_FENCE_FD`: no CPU copy, no CPU wait before a flip. - **Direct scanout.** A fullscreen window's buffer goes straight to the display plane; dmabuf feedback sends the game a scanout-ready format first. A lone opaque window can use an overlay plane. - **Tearing and VRR.** `wp_tearing_control_v1` flips without waiting for vblank when the game requests it; variable refresh runs while a buffer is scanned out. - **Explicit sync.** `wp_linux_drm_syncobj_v1` passes GPU fences end to end (needed by NVIDIA). - **Frame pacing.** `wp_presentation` from kernel flip timestamps, `wp_fifo_v1`, `wp_commit_timing_v1` and `wp_content_type_v1`. - **Only what changed.** Damage-limited redraws, occlusion culling of hidden surfaces, idle outputs never redraw. Atomic KMS: frame, cursor, overlay and VRR in one commit. - **Input for games.** Relative pointer, pointer constraints, keyboard shortcuts inhibit, 1 kHz+ non-blocking input, hardware cursor plane. - **X11 games.** Steam and Wine run through xwayland-satellite, started on the first X11 connection. Requires Linux and Go 1.27. ## Hardware support NeferWL needs a GPU and kernel driver with atomic KMS and a Vulkan 1.3 device that can export images as dmabufs; without them it stops at startup with an error. Frames are composed on the GPU only: no CPU copy and no CPU wait for the GPU before a page flip. - **AMD GPUs:** developed and tested on AMD (radv). - **NVIDIA GPUs:** untested. Explicit sync (`linux-drm-syncobj`), which NVIDIA drivers need, is implemented. Testers with NVIDIA hardware are welcome to report issues or contribute. - **Intel GPUs:** untested. Build: `make build`. Run: `neferwl --backend=headless --timeout 5s` ## Install (Arch Linux) ```sh make pkg # builds dist/neferwl-*.pkg.tar.zst from HEAD sudo pacman -U dist/neferwl-*.pkg.tar.zst ``` The package installs `neferwl` and a **NeferWL** session for display managers (Ly, GDM, SDDM). The session runs `neferwl --session`, which shares `WAYLAND_DISPLAY` and `DISPLAY` with D-Bus and systemd user services, so portals and notification daemons reach it. ## Developing the bindings NeferWL depends on tagged releases of [purego-libwayland](https://github.com/bnema/purego-libwayland) and [purego-vulkan](https://github.com/bnema/purego-vulkan). To change them together with NeferWL, check them out next to it and use a Go workspace (not committed): ```sh go work init . ../purego-libwayland ../purego-vulkan ``` `make pkg` ignores the workspace and builds the versions in `go.mod`: tag a binding change and update `go.mod` before packaging it. ## Configuration Configuration lives at `$XDG_CONFIG_HOME/neferwl/config` (or `~/.config/neferwl/config`). Use `neferwl --config path` to select another file; `neferwl validate-config [path]` checks it without starting the compositor. One `key = value` per line; `#` starts a comment: ```text keyboard.layout = fr terminal = foot bind.cmd+return = spawn-terminal bind.ctrl+cmd+space = spawn fuzzel startup = wl-paste --watch cliphist store ``` Every key, value and default bind is listed in [docs/config.md](docs/config.md); `examples/config` is a commented copy of the defaults. A missing file means defaults. An invalid line logs a warning and keeps that key's default; the rest of the file still applies. Every key applies live when the file changes, including the keyboard layout; each reload logs the keys that changed. ## Running commands NeferWL starts a program, not a shell line: `spawn` runs a binary or a script. Anything more than one command with arguments, such as pipes or variables, goes in a script that you write. `spawn