An infinite canvas Wayland compositor
Arrange windows freely on a zoomable 2D surface — no grids, no tiling constraints. Pan, zoom, and navigate your workspace like a design tool.
CanvasWM is a Wayland compositor that replaces the traditional desktop metaphor with an infinite 2D canvas. Instead of switching between virtual desktops or fighting with tiling layouts, you place windows anywhere on an unbounded surface and navigate with pan and zoom — just like Figma, Miro, or a maps application.
- Infinite canvas — windows live in a continuous 2D coordinate space with no edges
- Zoom to overview — zoom out to see all your windows at once, zoom in to focus
- Momentum scrolling — physics-based pan with natural deceleration
- Spatial memory — remember where things are by their position, not their workspace number
| Category | Features |
|---|---|
| Canvas | Infinite 2D space, smooth zoom (scroll + pinch), momentum scrolling, camera animations |
| Windows | Free placement, 8-direction resize, directional navigation, snap-to-grid, alt-tab cycling |
| Rendering | Custom GLSL shader backgrounds, dot-grid overlay, rounded corners, drop shadows, SSD borders |
| Backgrounds | Animated shaders, still images (PNG/JPEG/WebP), scrolling dot grid, solid colour |
| Minimap | Live overview panel showing all windows and the current viewport |
| Config | TOML/JSON/YAML, hot-reload, per-app window rules, custom keybindings |
| IPC | Unix socket interface for external tooling |
| Backends | Winit (development), DRM/KMS (bare metal, WIP) |
| Protocols | XDG Shell, XDG Decoration, SHM, Compositor, Output, Seat, Data Device, XWayland |
| Shortcut | Action |
|---|---|
| Super + Return | Spawn terminal |
| Super + D | App launcher |
| Super + Q | Close window |
| Super + = / - | Zoom in / out |
| Super + W | Zoom to fit all windows |
| Super + 0 | Reset viewport |
| Super + C | Center focused window |
| Super + F | Toggle fullscreen |
| Super + Home | Toggle home position |
| Super + Arrows | Navigate to nearest window |
| Super + Shift + Arrows | Nudge window |
| Alt + Tab | Cycle windows |
| Super + LMB drag | Pan viewport |
| Super + Scroll | Zoom at cursor |
| Alt + LMB drag | Move window |
| Alt + RMB drag | Resize window |
| Super + R | Reload config |
| Super + Escape | Quit |
- Rust 1.75+ (2021 edition)
- Wayland development libraries
- Linux with a Wayland-capable graphics driver
sudo apt install libwayland-dev libxkbcommon-dev libudev-dev libinput-dev \
libgbm-dev libdrm-dev libseat-dev libsystemd-devsudo dnf install wayland-devel libxkbcommon-devel systemd-devel libinput-devel \
mesa-libgbm-devel libdrm-devel libseat-develsudo pacman -S wayland libxkbcommon libinput libseat mesagit clone https://github.com/Fanaperana/canvaswm.git
cd canvaswm
cargo build --releasecargo run./target/release/canvaswm --backend=drm./target/release/canvaswm --check-configCanvasWM loads configuration from ~/.config/canvaswm/ in TOML, JSON, or YAML format.
Example config.toml
[background]
mode = "dots" # "shader", "image", "dots", or "solid"
color = [0.08, 0.08, 0.12, 1.0]
grid_spacing = 60.0
dot_size = 2.0
dot_color = [0.3, 0.3, 0.4, 0.4]
# shader_path = "~/.config/canvaswm/bg.glsl"
# image_path = "~/.config/canvaswm/wallpaper.png"
[zoom]
step = 1.1
fit_padding = 100.0
max_zoom = 1.0
[scroll]
speed = 1.5
friction = 0.94
[effects]
shadows = true
shadow_radius = 24.0
corner_rounding = true
corner_radius = 12.0
[decorations]
mode = "server" # "server", "client", or "none"
border_width = 2.0
focused_color = [0.4, 0.5, 0.9, 1.0]
unfocused_color = [0.3, 0.3, 0.3, 1.0]
[navigation]
animation_speed = 0.3
nudge_step = 20
pan_step = 100
[snap]
enabled = true
gap = 10
activation_distance = 20
break_force = 50
# Per-app rules
[[window_rules]]
app_id = "firefox"
pinned = true
opacity = 1.0
[[autostart]]
command = "waybar"CanvasWM supports live GLSL fragment shaders as backgrounds with these uniforms:
| Uniform | Type | Description |
|---|---|---|
u_time |
float |
Elapsed seconds since startup |
u_camera |
vec2 |
Camera position on the canvas |
u_zoom |
float |
Current zoom level |
u_resolution |
vec2 |
Output resolution in pixels |
CanvasWM is structured as a Rust workspace with five crates:
canvaswm/
├── canvaswm-canvas # Pure math — viewport transforms, momentum physics, snapping
├── canvaswm-config # TOML/JSON/YAML config parsing with hot-reload
├── canvaswm-input # Action and direction type definitions
├── canvaswm-render # GLSL shaders, decorations, backgrounds, minimap, elements
└── canvaswm-compositor # Main binary — Smithay event loop, input handling, IPC
The canvas and config crates have zero Wayland dependencies, making them independently testable. The render crate depends only on Smithay's renderer types. The compositor crate wires everything together.
- Multi-pass Kawase blur for window backgrounds
- DRM/KMS bare-metal backend (event loop completion)
- Layer-shell protocol (status bars, launchers)
- XWayland window rendering
- Workspace presets (save/restore canvas layouts)
- Touchpad gesture recognition (three-finger pan, pinch zoom)
- Screencopy protocol for screenshots
Contributions are welcome! Please read our Contributing Guide and Code of Conduct before opening a PR.
This project is licensed under the MIT License.