Important
This repository is archived. The code moved to Crown-OS/crownOs.
It is now crates/crownpositor and crates/crownpositor-config in the CrownOS workspace, with its history intact. The
crate name on crates.io is unchanged -- cargo add crownpositor is unaffected by
where the source lives.
The nine desktop crates were merged because a change crossing two of them used to be two pull requests in two repositories that nothing built together. A schema change once broke the compositor for eight days before anyone noticed. One workspace, one lockfile, one CI run.
Issues and pull requests: https://github.com/Crown-OS/crownOs
This repository stays read-only so existing links keep resolving. Everything below describes the state at the time of the merge.
A tiling Wayland compositor for CrownOS, built on Smithay.
crownpositor is not only a window manager — it is the CrownOS session. It
creates the Wayland socket, exports WAYLAND_DISPLAY, and spawns the rest of the
desktop itself.
Status: Early. It builds, runs and is actively developed, but the API and internals move, and several features are stubbed. See Known limitations.
- Three layouts — master-stack (dwm/xmonad), scrolling columns (niri/PaperWM) and floating, switchable per workspace
- Two backends — DRM/KMS on a bare TTY, and winit for a nested development session
- wlr-layer-shell, so
crownbar,crowndock,crownotifyandcrowndictatorcan attach - XWayland for X11 clients
- Trackpad gestures that resolve to the same action vocabulary as keyboard chords
- Spring animations, critically damped, integrated at a fixed 1/240 s substep
- Live configuration — a rebind takes effect without a restart
Cargo workspace with two members:
| Crate | Role |
|---|---|
compositor |
Everything. main.rs is three lines calling compositor::run(). |
config |
The compositor's compiled configuration — regexes, chords, geometry |
crownos-config is an ordinary crates.io dependency
({ version = "0.2", default-features = false }), but 0.2 is not published —
nothing in the CrownOS organization is on crates.io except crownshell 0.1.0 and
0.2.0. A fresh clone fails at cargo metadata until Cargo is pointed at a local
checkout.
crownos-setup's ./bootstrap.sh --dev clones the repos side by side and writes
a [patch.crates-io] overlay into a .cargo/config.toml one directory above
them:
~/crownos/
├── .cargo/config.toml # [patch.crates-io] crownos-config = { path = "crownos-config" }
├── crownpositor/
└── crownos-config/
Cargo walks up from the working directory to find that file, and the paths in it
are relative to the file's own directory. No particular directory layout is
required — the repository itself contains no [patch] section.
Native dependencies (Arch):
sudo pacman -S --needed base-devel pkgconf \
wayland wayland-protocols libxkbcommon \
libdrm libinput seatd systemd-libs pixman \
vulkan-icd-loader vulkan-headers mesa libglvnd \
fontconfig dbus xorg-xwaylandDebian/Ubuntu equivalents and the full list: Prerequisites.
Rust 1.88+ (set by the dependency graph, not the edition; pinned in rust-toolchain.toml).
smithay-drm-extrasis deliberately declareddefault-features = falsebecause thedisplay-infosys crate does not accept the version oflibdisplay-infoon current systems. Do not re-enable it.
cargo build
cargo test # 183 unit tests
# Nested inside your existing session — what you want for development
CROWN_BACKEND=winit cargo run
# On real hardware, from a bare TTY, with seatd running
CROWN_BACKEND=kms cargo run --releaseSuper+Return spawns foot. Super+Shift+E quits. Have a second TTY available
before running on hardware.
To attach a client to a nested session, use the socket name it logs:
WAYLAND_DISPLAY=wayland-2 cargo run # in crownbar, for example| Variable | Values |
|---|---|
CROWN_BACKEND |
winit, or kms/drm/udev. Unset autodetects. |
CROWN_RENDER_API |
egl/gles/gles3 (default), or vulkan/vk |
XCURSOR_THEME, XCURSOR_SIZE |
Cursor theme and size |
CROWN_CONFIG_DIR |
Overrides ~/.config/crownos |
Unknown values for the first two log a warning and fall back rather than failing.
~/.config/crownos/compositor.ron, watched live. Also reads appearance.ron and
display.ron.
(
layout: ScrollingColumns,
focus_follows_mouse: true,
keybinds: [
(keys: "Super+Return", action: "spawn foot"),
],
window_rules: [
(app_id: "Nautilus", floating: true),
],
outputs: [
(name: "eDP-1", scale: 2.0, position: (0, 0)),
],
)An empty keybinds list means "use the built-in defaults", not "nothing bound".
Full schema and the 32 default bindings: Configuration schema · Keybindings
Two boundaries worth respecting when adding code:
layout/is surface-blind. Nothing there can see aWlSurface, aWindow, anOutputor theShell. That is why the tiling algorithms are unit-testable.- One action vocabulary. Chords and gestures both produce the same
Actionenum and go down one dispatch path — deliberately, so that "swipe left" andSuper+Tabcannot drift apart.
backend/mod.rs carries a four-step guide to adding a backend.
- Blur is not implemented.
handlers/background_effect.rsis entirely commented out, soext-background-effect-v1is never advertised and every CrownOS surface requesting blur degrades silently. - The workspace overview does not exist.
shell/windows_view/andshell/workspaces_view/are zero-byte files;OpenWorkspaceViewandCloseWorkspaceViewlog "not implemented yet" — and the four-finger gestures are bound to them. shm_formatsis empty and the dmabuf global is never created.privileged_client_filterreturnstruefor every client.- Fractional scale sends the wrong scale; CSD is not honoured; popups are not unconstrained; session lock confirms early.
- No pinch, hold, touch, tablet or output hotplug handling.
See the organization-wide
contribution guide.
Default branch here is main.
Licensed under the MIT License.