A visually expressive Wayland compositor that keeps the fast path fast.
Aqueous combines a native tiling window manager, fluid compositor-side motion, and Aqueous-owned Vulkan effects in one Zig process. It is designed for desktops that want rounded windows, backdrop blur, focus-aware opacity, animated placement, and sliding workspaces—without turning routine window management into a chain of scripts, subprocesses, or IPC round trips.
Aqueous began as a fork of River. Its River-derived foundation and retained protocol work are documented as project provenance. Today, Aqueous owns its window-management policy, layouts, rules, input, workspaces, and output configuration in-process and configures them through its own TOML format.
Aqueous does not make you choose between a visually polished desktop and a focused window manager. Its defining features are designed as one coherent system:
- Switch freely between scrolling, classic tiling, recursive tiling, floating, monocle, grid, rows, game-focused, and composable multi-region layouts without replacing the window manager or installing layout extensions.
- Keep window, workspace, input, rule, and output policy in one typed Zig process, configured through validated TOML rather than a collection of runtime scripts.
- Add smooth movement, workspace transitions, rounded corners, blur, and focus-aware opacity at the compositor level while retaining explicit ways to disable their cost.
- Give games a purpose-built layout that can anchor the primary window and arrange launchers, chats, terminals, and other companion windows around it.
- Treat multi-monitor setup as native policy, including profiles, hotplug, scaling, transforms, adaptive sync, and sensible automatic placement.
The result is a desktop that can change workflow by workspace or output while remaining one small, predictable system. Visual effects enhance the layout model; they do not replace it.
- Effects with an off switch. The default Vulkan build provides rounded corners and damage-aware backdrop blur. Opacity can be global, focus-sensitive, or selected by application rules. Expensive effects can be disabled globally or avoided for games and fullscreen media.
- Motion owned by the compositor. Window placement animates at render time, scrolling layouts move as a viewport, and workspace changes can slide without making the layout engine or clients produce intermediate geometry.
- Workspace-local window overview. Press
Super+Wto inspect frozen thumbnails of every focusable window on the active workspace—including scrolling windows outside the current viewport—then navigate with arrows, H/J/K/L, or Tab and confirm without reconfiguring clients. - Ten in-process layouts. Choose from master/stack
tile,monocle,grid,rows, recursivedwindle, mirroredreverse-dwindle, column-basedscrolling,floating, andgame-mode, or compose up to four of the standard leaf layouts into fixed monitor regions. Layout selection can vary by output and workspace. - Game Mode that understands the rest of the desktop. Anchor a game at a requested size and position while arranging companion windows with any of the standard tiling engines.
- Rules that respect user intent. Match app IDs and titles to select workspaces, layouts, placement, fullscreen state, floating state, opacity, or blur. Rule-owned state can be manually overridden instead of being forced back on every manage cycle.
- First-class multi-monitor behavior. Aqueous applies modes, scale, transform, adaptive sync, position, profiles, and hotplug changes directly through wlroots. Unconfigured displays receive non-overlapping automatic positions.
- Basic screen mirroring. Mirror an SDR output to a projector or capture card on the same device, with independent refresh and automatic letterboxing. See configuration and limitations.
- Wayland-native, with practical X11 support. Layer shell, screencopy,
session lock, pointer constraints, color management, and other modern Wayland
protocols are supported. Optional XWayland is started and managed directly by
Aqueous—no
xwayland-satelliteprocess is required. - Choose your desktop. The GTK Welcome to Aqueous
installs and sets up Pearl (
pearl), DankMaterialShell, Noctalia, or a shell-free session. Shelly handles package installation and all optional dependencies; the shell stays separate from the compositor.
Visual polish is useful only when the desktop still feels immediate. Aqueous keeps policy and rendering close together: layouts return final placements, the compositor applies them in a batched manage cycle, and damage-driven frames advance only the visual state that is changing. Stable window handles and per-output/workspace layout state avoid rebuilding policy in external clients.
Effects are also explicit build-time and runtime choices. Animations can be
compiled out with -Danimations=false; the Aqueous Vulkan effects backend is
enabled by default; and -Dvulkan-effects=false produces a square/no-blur
diagnostic build using the same pinned wlroots. Blur and opacity default to
configurable policy, and per-application rules can keep latency-sensitive surfaces fully
opaque and unblurred. Aqueous does not claim that effects are free—it makes
their cost visible and optional.
Aqueous discovers five compatible files in ~/.config/aqueous/:
wm.toml— bindings, actions, workspaces, struts, and global policy.outputs.toml— preferred physical display policy and output profiles; unset values inherit fromwm.toml.layout.toml— layout defaults, slots, options, and workspace/output overrides.input.toml— XKB and libinput policy, plus optional gesture bindings.rules.toml— window and layer-shell matching, placement, state, and visual behavior.
Configuration changes are parsed into validated immutable snapshots and
hot-reloaded on the Wayland event loop. Invalid updates do not require a
compositor restart. Start with the repository's wm.toml and annotated
*.toml.example files.
# layout.toml
[layout]
default = "scrolling"
gaps_outer = 8
gaps_inner = 4
[layout.options.scrolling]
column_fraction = "0.5"
center_focused = "true"# rules.toml
[[window]]
app_id = "com.example.Game"
layout = "game-mode"
output = "DP-2"
workspace = 9
blur = false
opacity = 1.0
[[layer]]
namespace = "waybar"
blur = true
blur_popups = trueFractional-scale-aware clients use their exact output scale by default. For a client whose toolkit produces softer glyphs at fractional device coordinates, an opt-in rule can request an integer-ceil backing buffer while keeping the window's logical size and output scale unchanged:
[[window]]
app_id = "com.example.Editor"
buffer_scale_policy = "integer-ceil"This compatibility mode increases the client's pixel count and GPU/memory
cost. Aqueous ships no application-specific opt-ins; use aqueousctl inspect --rule to obtain the exact, case-sensitive app ID before adding one. On a
live session, scripts/aqueous-scalebench.py
A/B-measures the cost of the global policy: mpv render wall time, Qt Quick
GPU load via MangoHud, and battery power while discharging.
See the layout guide, rules reference, and compositor interaction guide for the full configuration and window-flow model.
The build installs aqueousctl, a Wayland client for discovering the exact
identities used by window rules, the modes advertised by each output, and the
active workspace layout:
aqueousctl windows
aqueousctl scene
aqueousctl windows --json
aqueousctl inspect --rule
aqueousctl outputs
aqueousctl outputs --json
aqueousctl overlay-planes
aqueousctl overlay-planes --json
aqueousctl layout --output DP-1 --json
aqueousctl layout --output DP-1 --set grid --jsonThe rule command emits ready-to-paste [[window]] entries. Native Wayland
windows use app_id; XWayland windows use their WM_CLASS as class.
Unmanaged XWayland popups also appear in windows --json (managed: false)
and in shell watch --json (kind: "unmanaged_window"). inspect --rule
emits scope = "override_redirect" for these surfaces. Scoped popup rules
support opacity, focus suppression and output-relative x/y placement; see
rules.toml.example. Ordinary rules still apply only to
managed windows.
The outputs command provides the full wlr-randr information set: identity,
physical size, enabled state, every advertised mode, logical position,
transform, scale, and adaptive-sync state. It also prints a quoted, stable
sha256: EDID identifier derived from the make, model, and serial when that
metadata is available. Its JSON form uses wlr-randr-compatible field names and
value types and exposes the identifier as edid_sha256. The current and
preferred modes are marked.
The layout command targets the explicitly named output and can apply an
immediate runtime override without editing configuration files.
wlrctl toplevel list remains supported through the legacy foreign-toplevel
management protocol for compatibility.
Aqueous exports AQUEOUS_SOCKET to session children and services. Shells can
connect directly for capability discovery, snapshots, acknowledged state deltas
and typed runtime commands, avoiding an aqueousctl process for each action.
The compositor hosts the nonblocking socket and shares its state and command
backend with the existing Wayland shell protocol.
See the IPC v1 contract and standalone DMS migration plan. DMS needs that consumer migration to use the socket; settings and keybind configuration helpers remain a separate follow-on. Existing aqueousctl commands remain supported.
Building requires Zig 0.16 or newer, Wayland, wayland-protocols 1.49 or newer, libxkbcommon,
libinput, libevdev, pixman, Vulkan headers and loader, pkg-config, Meson, Ninja,
glslang, and the dependencies listed by wlroots 0.20. -Dxwayland builds
additionally require the Xwayland server executable (xorg-xwayland on Arch
Linux).
scripts/build-compositor.shFor direct development:
cd compositor
scripts/build-wlroots-render-hook.sh
export PKG_CONFIG_PATH="$PWD/.deps/wlroots-render-hook/lib/pkgconfig"
zig build test
scripts/test-color-management-luminance.sh
scripts/test-proton-hdr-color-management.sh
zig build -Doptimize=ReleaseSafe -Dxwayland -DllvmThe default build uses the pinned Aqueous wlroots render hook, requires
wlroots' Vulkan renderer at startup, and installs that exact shared library
under lib/aqueous with an origin-relative runtime path. Use
-Dvulkan-effects=false only for the diagnostic build; it also needs the patched
wlroots library for protocol and scene APIs.
Distribution builds should target a suitably generic CPU rather than
inheriting the build machine's instruction set.
The normal build contains only Aqueous's integrated policy. The optional
aqueous_window_manager_v1 external-policy path is available solely for
diagnostic testing with -Dexternal-policy=true; shipped builds disable it
and do not include an external policy client.
Aqueous's compositor-specific Wayland protocols use the aqueous_ namespace.
The inherited River protocol names have been replaced completely. Clients using
those interfaces must regenerate bindings from the Aqueous XML definitions
installed under share/aqueous-protocols/stable/ and update their interface
names. No River aliases or fallback interfaces are provided. Standard Wayland
and upstream extension names are unchanged.
Package builds recreate their generated protocol staging directory. For manual
in-place installations, use a clean staging prefix: zig build install does not
remove XML files left by an older installation.
./launch_aqueous.shThe launcher builds or selects Aqueous, starts it nested,
and launches DMS (dms run) inside the new display. Set
AQUEOUS_COMPOSITOR_BIN=/path/to/aqueous to select a build or
AQUEOUS_DMS_CMD to replace the shell command, including any arguments. Logs
are written to /tmp/aqueous.log and /tmp/dms.log by default.
Packaged sessions use /usr/bin/aqueous-wm to launch /usr/bin/aqueous.
/usr/bin/aqueous-init exports the live Wayland environment and starts
graphical-session services; it does not start another window manager. For a
new Ghostty profile it also seeds window-decoration = none, allowing
Aqueous's compositor-provided rounded border to remain visible. Existing
Ghostty configuration is never overwritten. No greeter-specific configuration
is required beyond selecting the installed Aqueous Wayland session.
cd compositor
zig build test
scripts/test-color-management-luminance.sh
scripts/test-proton-hdr-color-management.sh
scripts/test-policy-parity.sh
scripts/test-server-decoration.sh
scripts/test-rule-output-placement.sh
scripts/test-xdg-fullscreen.sh
scripts/test-xdg-floating.sh
scripts/test-qt-transient-natural-size.sh
scripts/test-floating-outputs.sh
scripts/test-output-rotation-keybinding.sh
python3 scripts/test-output-focus.py
scripts/test-scaling.sh
scripts/test-cursor-theme.shThe xdg fullscreen harness covers application-originated xdg_toplevel
fullscreen requests without relying on rules or compositor keybindings. The
xdg floating harness covers client-side move, edge-aware resize, maximize,
unmaximize, and minimize requests for persistent floats and workspace-floating
windows, and verifies that identical requests do not affect ordinary windows in
non-floating layouts. It also verifies persistent focus raising and hit testing
with overlapping floats. The Qt transient harness verifies that a portal-style
Qt dialog reaches its natural size without pointer input. The floating-output
harness covers active-workspace transfer across mixed scale/transform output
geometry and source-output removal during a drag. The integration harness maps
real Ghostty windows and injects
virtual keyboard and pointer input to exercise layouts, rules, focus, fullscreen,
keybindings, and repeated workspace changes. The scaling harness checks
client-side wl_output events, the embedded output service, and the headless
output commit pipeline.
The output-rotation harness verifies that the runtime quarter-turn keybinding
targets only the display beneath the pointer.
aqueous-config provides canonical configuration
reading, validation, persistence, generation checks, backups and toolkit sync.
Pearl replaces the retired Aqueous Settings GUI. Existing protocol-1 clients and
scripts remain supported; use aqueous-config snapshot --shell none for neutral
operation. The default helper build has no GUI dependency or desktop launcher.
For a minimal stable compositor, including Pearl greeter's aqueous dependency,
use packaging/arch/aqueous/PKGBUILD.
It builds release v1.0.2 and installs aqueous with its private wlroots library,
manual and licenses. Build it with cd packaging/arch/aqueous && makepkg -si.
For the complete stable desktop, use
packaging/arch/aqueous-desktop/PKGBUILD.
It builds aqueous-core, the desktop components and the aqueous-desktop meta
package from v1.0.2 once that tag is published.
See the stable desktop guide
for build and installation instructions. The core provides aqueous for Pearl
and replaces the minimal compositor package because their files overlap.
The root PKGBUILD retains the legacy desktop meta package named aqueous.
Use the recipes under packaging/arch for unambiguous package names.
The old combined Git/Intel,
DMS, Noctalia and application-bundle PKGBUILDs have been retired. See the
component packaging guide for ownership,
explicit shell presets, migrations and release validation.
Arch source packages and x86_64 release binaries target x86-64-v3, shared by supported Intel and AMD CPUs. Older CPUs without v3 support cannot run these builds. The aarch64 source packages retain their baseline CPU target.
For development tools that coexist with stable, build aqueous-core-git
from packaging/arch/. It installs suffixed commands,
private libraries and separate configuration defaults. See the
Git package guide for building and running them.
aqueous-desktop-git adds the matching login
session, native welcome, private portal and optional shell integrations. Follow
the Git desktop installation guide to install a
complete Git desktop alongside stable Aqueous.
Fedora users can build and install the latest Git master as a local RPM:
bash scripts/fedora-install.shRun as your normal user; the script uses sudo for DNF transactions. See the Fedora installation guide for dependencies, DMS repository options, building without installing, and removal.
The full desktop packages install /usr/bin/aqueous and its /usr/bin/aqueousctl inspection
and workspace-layout client, plus the session launcher, environment hook,
default TOML configuration, desktop entry, and systemd user units.
Arch packages also provide /etc/xdg/menus/aqueous-applications.menu for
application menus in sessions using XDG_MENU_PREFIX=aqueous-.
Full Arch desktop packages and the combined release archive include the GTK welcome app,
Shelly, and a terminal without requiring a desktop shell. On first login, choose
Pearl (pearl), DMS (dms-shell), Noctalia, or Nothing. Welcome answers
Shelly's password request through a GTK popup and selects all optional dependencies.
A normal launcher invocation can reopen setup later. Existing completion markers
are honored; upgrades do not force the wizard onto established users.
The selection is stored in ~/.config/aqueous/session.toml and becomes active at
the next login. Conditional Aqueous user units start exactly the selected shell;
upstream shell units are suppressed only inside Aqueous. Existing custom startup
files must be reviewed when they conflict. Shell packages and preferences remain
installed when switching, including when choosing Nothing.
Packaged launcher, screenshot and lock actions follow the active session.
Super+Return opens Ghostty. Open aqueous-welcome to review setup; legacy packages also retain the Super+Shift+F1 shortcut. Pearl and Nothing
use the GTK screen-sharing picker; DMS and Noctalia use their own integration.
Welcome preserves custom commands and updates recognized legacy shell bindings
through aqueous-config, with a recovery journal and backups. See the
welcome documentation for recovery and verification details.
Fedora and NixOS retain their existing installation and declarative shell setup; Shelly installation in welcome currently targets Arch-compatible systems.
Aqueous has no
.NET, aqueous-wm-client, aqueous-outputd, wlr-randr, or
xwayland-satellite runtime dependency.
Aqueous is licensed under GPL-3.0-only. Third-party component texts
are in compositor/LICENSES/. See ORIGIN.md
for upstream provenance and retained River-derived work.