- C 95.8%
- GLSL 1.6%
- Roff 1.4%
- Makefile 1.2%
| .gitea/issue_template | ||
| protocols | ||
| SHADER_EXAMPLE | ||
| .gitignore | ||
| .mailmap | ||
| CHANGELOG.md | ||
| client.h | ||
| config.def.h | ||
| config.mk | ||
| CursorFX.md | ||
| drm_lease.patch | ||
| dwl.1 | ||
| dwl.c | ||
| dwl.desktop | ||
| dwl.so | ||
| LICENSE | ||
| LICENSE.dwm | ||
| LICENSE.sway | ||
| LICENSE.tinywl | ||
| Makefile | ||
| README.md | ||
| SHADERS.md | ||
| util.c | ||
| util.h | ||
UWWM - Unlimited Wayland Window Manager
UWWM is a infinite-spatial grid WM for [Wayland] based on [wlroots]. It is intended to fill the same space in the Wayland world that [vxwm] does in X11, primarily in terms of functionality, and secondarily in terms of philosophy. Like [dwl], UWWM is:
- Easy to understand, hack on, and extend.
- One C source file along with a configurable
config.h - Tied to as few external dependencies as possible
Building UWWM
UWWM has the following dependencies:
- libinput
- wayland
- wlroots (compiled with the libinput backend)
- xkbcommon
- grim
- satty (recommended for default config, see config)
- wmenu (recommendede for default config, see config)
- wayland-protocols (compile-time only)
- pkg-config (compile-time only)
UWWM has the following additional dependencies if XWayland support is enabled:
- libxcb
- libxcb-wm
- wlroots (compiled with X11 support)
- Xwayland (runtime only)
Install these (and their -devel versions if your distro has separate
development packages) and run make. If you wish to build against a released
version of wlroots (you probably do), use a [release] or a [0.x branch]. If
you want to use the unstable development main branch, you need to use the git
version of [wlroots].
XWayland is on by default. It's recommended you use it over something like XWaylnd-Satellite due to how the window management is done. Although, your mileage may vary.
Configuration
All configuration is done by editing config.h and recompiling, in the same
manner as [dwl]. Any changes done in the config can be reapplied upon recompilation
and a hit of the keybind to restart the WM. Sometimes you may need to restart the
window you had open previously to apply more decorative changes.
Performance
I went absolutely wild with the performance. I wanted this to be able to run on as many machines as possible while being as cool as possible. So you may come to notice when you do things like play games, there's quite literally ZERO delay due to how i'm handling the input. Events are done before they're drawn and there's nothing like forced vsync. Meaning applications are able to run as fast and respond as fast as your hardware allows.
Shaders still come with a cost, so use them wisely. I tried to optimize the shader pipeline as reasonably as I could while still letting people do anything they wanted. That being said, enjoy your time with this amazing WM, and I hope you like using it as much as I did making it!
Features + Quick-Start Tutorial
UWWM introduces an infinite-space canvas combined with dynamic physics, interactive window clustering, custom GLSL shader pipelines, and tight D-Bus integrations.
1. Infinite-Space Canvas + Spring Physics
Windows are spawned in a concentric, non-overlapping grid on an infinite canvas rather than being confined to a static monitor boundary.
- Pan the Camera: Hold Left Click on any empty area of the desktop background and drag your mouse. The camera drifts with natural kinetic momentum.
- Camera Zoom: Press
Mod + Minus (-)to zoom out, orMod + Plus (+)to zoom in. You can also zoom by holdingAlt(or your configured modifier) and scrolling the Mouse Wheel [1]. - Physics Animation: Windows and the camera utilize underdamped spring physics. Grabbing, tiling, zooming, or panning results in organic overshoots and elastic bounciness [1].
2. Multi-Pipeline Shader System (ManagerFX, CursorFX, WindowFX)
UWWM integrates three independent GLSL fragment shader pipelines. Shaders are loaded dynamically from directories defined in config.h [1].
- Cycle Shaders:
- Background (
ManagerFX): PressMod + S[1] - Cursor Trails (
CursorFX): PressMod + C[1] - Window Afterimages (
WindowFX): PressMod + W[1]
- Background (
- Toggle Shaders on/off:
- Background: Press
Mod + Shift + S[1] - Cursor: Press
Mod + Ctrl + C[1] - Window: Press
Mod + Ctrl + W[1]
- Background: Press
- Setup: Drop any
.glslfragment shader into your folders (default~/.config/uwwm/shaders/[manager|cursor|window]/) and use the keybinds to hot-swap them instantly.
3. Interactive Window Clustering (Mod + I)
You can visually group and bind windows together to move them as single units across the infinite layout.
- Enter Overview Mode: Press
Mod + I. Floating indicator bubbles will appear above your windows [1]. - Connect Windows: Inside the
Mod + Ioverlay, click the "O" button next to any window and drag a connection line to another window [1]. - Sever Connections: Hover over the midpoint "X" button on any connecting link and Left Click to break the cluster link [1].
- Rename Clusters: Left Click on the cluster name label. An asynchronous Zenity dialog will pop up, allowing you to name the group without stalling compositor frames [1].
4. Smart Embedded Notifications
UWWM intercepts standard system notifications via low-level D-Bus bindings and handles them inside the window manager [1].
- Stealth and Content Modes: Configure
notification_stealth_modeinconfig.h.- In Stealth Mode (
1), notifications show a generic "Notification received!" alert [1]. - In Content Mode (
0), they display the actual text of the alert [1]. Prepend the triggering window's title by enablingnotification_show_sender_window[1].
- In Stealth Mode (
- Reviewing Alerts: When a window receives a notification, its indicator bubble displays a badge count (e.g.,
🔔 [3]) inMod + Ioverview mode [1]. Left Click on the badge to render a vertically stacked list of all pending alerts with their respective app icons and summaries.
5. Ambient MPRIS Music Player
A built-in glassmorphic player tracks your media and renders directly onto your workspace [1].
- Layout Modes: Toggle
mpris_layout_modein your config:0: Standard wide card (Cover Art left, track metadata right, timeline progress) [1].1: Compact vertical card (Centered Cover Art, title and artist below, progress bar, formatted time) [1].
- Real-Time Seeking: The timeline progress bar interpolates playback every 100ms. If you scrub, rewind, or fast-forward inside Audacious or any other player, UWWM catches the D-Bus
Seekedsignal to snap the progress bar instantly [1]. - Monitor Routing: Target the player to a single display by setting
mpris_target_monitorto your screen's index, or use-1to render it across all connected outputs [1]. - Layer Depth Routing: Configure
mpris_player_layerinconfig.hto choose where the card lives:0: Background layer (sits at the absolute bottom of the rendering stack).1: Overlay layer (always on top of active application windows).2: Between layer (rests onLyrBottom— sits above background shaders but cleanly behind active tiled or floating windows).
6. Native Position Coordinate Tracker Overlay
UWWM features a built-in coordinate tracking overlay drawn directly on the bottom right of each output canvas.
- Intelligent Visibility Layers: By default, coordinate tracking is drawn on the background layer (
LyrBottom) so it sits elegantly behind your workspace windows without distracting from active tasks. - Top-Surface Elevation (Mod + I): Pressing
Mod + Iinstantly elevates the coordinate overlay to the topmost layer (LyrOverlay), presenting it on top of all active window borders and popups for immediate reading. - Customizable Polling Rate: Update intervals are rate-limited via
coord_tracker_interval_msinconfig.h(default 100ms), eliminating continuous filesystem write bottlenecks and ensuring stutter-free compositor performance.
7. Native Unix IPC Socket Manager (/tmp/uwwm_ipc)
UWWM implements a high-performance, non-blocking UNIX domain socket at /tmp/uwwm_ipc powered natively by the Wayland event loop. This enables low-latency workspace automation, hotkey dispatching, and external status bar piping without requiring an embedded interpreter or external scripting daemon.
8. Drag-to-Spawn Mouse Chording (Mod + Ctrl + Left Click)
UWWM introduces a native region-definition gesture that allows you to drag out a specific workspace boundary before launching a program.
-
Define a Region: Hold
Mod + Ctrl + Left Clickon any area of the screen (regardless of whether you are clicking on a window or the empty background) and drag to draw a boundary box. -
Launcher Execution: Upon releasing the mouse click, the selection overlay (customized by
chord_colorinconfig.h) is destroyed, and your designated chording menu tool (chord_cmd, defaultwmenu-run) is spawned. If you have nothing selected, the next window spawned will take the sizing of your choice. Without the menu command showing up. This is called pre-chording. -
Canvas-Relative Mapping: The next managed application window that maps to the compositor will bypass standard concentric grid slot placement. It will initialize as a floating client, sized and positioned exactly within the canvas coordinates of the selection region you dragged out.
-
Cancellation: Press
Escapeat any point during an active drag gesture to cancel the action and return to the normal cursor mode. Although, the next opened window will take the coordinates and size you last chose with your chord. Even if you cancel. -
Pre-Chording vs. Post-Chording: Unlike other compositors that rely on external tools (like
slurp) which cannot communicate with the window manager's layout engine, UWWM handles chording natively.- Pre-Chording: Drag out a boundary box first, cancel or accept, and the next spawned application automatically conforms to those exact dimensions on launch.
- Post-Chording: Hold
Mod + Ctrlwhile clicking on an already active window to instantly adjust, drag, or re-chord its placement boundaries dynamically.
9. Edge Panning & Resizing with Monitor Protection
When moving or resizing windows near screen edges, the viewport automatically pans at a controlled rate to keep the action within view.
- Smooth Resizing: Resizing a window near the edge scales smoothly up to your configured panning velocity, avoiding feedback-loop scaling bugs or extreme window expansion crashes.
- Optional Monitor Intersection Panning: Using
edge_pan_between_monitorsinconfig.h, you can control how display boundaries behave:0: Prevents edge panning when dragging windows across borders shared with adjacent monitors, enabling a smooth crossover between displays.1(Default): Edge panning occurs on all boundaries, shifting the active viewport camera even when moving windows across adjacent outputs.
- Acceleration Configuration: Adjust panning threshold, starting speed, limits, and acceleration curves using
edge_pan_threshold,edge_pan_min_speed,edge_pan_max_speed, andedge_pan_accelinsideconfig.h.
Control & State Commands
Commands are evaluated via space-separated parameters. You can send commands to the socket using standard utilities like nc or socat [1]:
- Viewport & Camera Navigation
recenter— Smoothly pans the active viewport back to coordinate(0,0).pancamera <direction>— Triggers camera momentum panning. Directions:0(Left),1(Right),2(Up),3(Down).zoomcamera <factor>— Adjusts viewport zoom. Accepts float modifiers (e.g.,1.1to scale in,0.9to scale out).
- Window Management
focusdirection <direction>— Shifts active focus to an adjacent client window. Directions:0(Left),1(Right),2(Up),3(Down).focusstack <direction>— Focuses next (1) or previous (-1) window in focus history.togglefloating— Toggles active window floating/tiling state.togglefullscreen— Toggles the active window in and out of fullscreen.killclient— Gracefully closes the focused window.
- Workspaces & Tags
view <workspace_num>— Switches viewport tag focus (accepts integers1through9).tag <workspace_num>— Pins the active window to targeted tag (accepts integers1through9).
- Visual Pipelines & Shaders
togglehelpers— Toggles interactive clustering overlays and indicators (matchingMod + I) [1].toggle_shader_manager/toggle_shader_cursor/toggle_shader_window— Enable or disable targeted GLSL FX pipelines dynamically [1].cycle_manager_shader/cycle_cursor_shader/cycle_window_shader— Cycle to the next fragment shader in targeted directory [1].
- System & Execution
spawn <shell_command>— Asynchronously runs arbitrary shell scripts or commands on the compositor thread.quit— Gracefully terminates the window manager.
Querying Compositor State
The socket writes structured layout, window metadata, or telemetry details directly to the client connection [1]:
get_coords— Outputs the current viewport coordinates and active zoom factor:X, Y, Zoom.get_active_window— Returns focused application details orNONEif workspace is empty:appid: <id> title: <window_title> x: <geom_x> y: <geom_y> w: <geom_w> h: <geom_h>get_monitors— Returns a newline-separated list of active monitor viewports, scaling metrics, and screen boundary states.
Quick Scripting Integrations
You can bind commands directly to your custom status bar scripts or hotkey aliases:
# Query focused window title for custom panels (e.g., Waybar, somebar)
focused_title=$(echo "get_active_window" | nc -U /tmp/uwwm_ipc | grep "title:" | cut -d' ' -f2-)
# Switch to workspace 3
echo "view 3" | nc -U /tmp/uwwm_ipc
Problems and Fixes
"Roblox/Sober having strange input problems"
Solution: Run flatpak override --user --nosocket=wayland org.vinegarhq.Sober in a terminal
and open Sober.
"Embedded notifications don't work!"
Ensure you source /tmp/uwwm_dbus_env in your shell of choice. Then run: notify-send "test"
The window should shake and you should get a notification received message!
"Why did the MRPIS Music Module stop working all of a sudden?"
If you pres the keybind to restart the WM after a config change, mpris can get stuck, just stop and play the music/audio. If it doesn't work, you may have to hit "STOP", not pause, and play it again.
"My window manager just crashed when I applied settings! What happened?"
Either you changed the quality level of the shaders while you were running it (the only thing I've noticed that crashes when restarting the WM), or you set a setting far too high or too low and it's causing issues.
The Philosophy: Stop Settling for Duct Tape and Dreams
I didn’t build UWWM to be just another configuration folder you throw into your dotfiles. I built it because I am tired of watching the Wayland scene slide into mediocrity, and I am tired of watching people settle for it.
We used to live in a golden era of desktop ricing where developers made genuine, hard-nosed architectural improvements. Somewhere along the way, we lost that drive. Now, we are expected to praise bloated, laggy compositors held together by duct tape and dreams—software where standard features break the moment a flashy new animation is added. Or, we are told to accept "minimalism" as a convenient excuse for developers being too lazy to implement standard capabilities like hardware DRM leasing or robust input chording.
I am not going to sugarcoat it, and I am not going to let us settle for software that feels like it is constantly struggling to stay alive under load. Here is the reality of the scene today:
- The Flashy But Fragile Bloat: The most popular modern compositors are sluggish, resource-heavy, and built on fragile foundations. They look great in a screen recording, but the moment you push them with intensive, real-world workflows, the cracks show. Features regress, inputs lag, and basic stability is sacrificed for superficial hype.
- The Stalled Sparks: [Niri] was a brilliant concept, a genuine spark of innovation that got people excited. But the momentum stopped. The drive to aggressively develop and expand on its standout spatial features plateaued, leaving a great paradigm frozen in time.
- The Antiques: The only mature, highly functional spatial-grid window manager right now is [vxwm]. But it is chained to X11. Running an infinite-space canvas on an outdated display server that struggles with multi-monitor layouts and feels laggy under load is a compromise you shouldn’t have to make.
- The "Shell" Bloat Epidemic: My god have we have reached a new level of insanity when a modern setup requires an entire separate desktop shell, panel, or widget bar just to display workspace indicators and system coordinates. Spawning a complete JavaScript/TypeScript runtime (like AGS) or running a massive, template-heavy C++ engine (like Waybar) just to draw a flat panel on the screen is a ridiculous waste of resources. It is hundreds of megabytes of memory and constant CPU context-switching wasted on an external event loop that has no business being separate. I designed UWWM to bypass this entirely—coordinates, watermarks, and layout tracking overlays are composited natively onto the canvas, giving you immediate system feedback with zero process overhead. Yes, this WM does still support those kinds of shells since this WM is designed to support everything and people will run whatever they want. But actually think to yourself, what problem does running a shell like that actually solve? Every functionality of it can be replicated by another program or can be done in a more efficient manner that doesn't soak up a bunch of CPU on your 2009 laptop.
I built UWWM from a place of love for this community and for the art of UX design. I wanted to prove that you can have an organic, physics-driven, infinite-space workspace on Wayland that actually works without lag, without broken features, and without lazy compromises.
Stop settling for software that struggles to keep up with your hardware. We can do better, and we should demand better. Wayland itself is an amazing protocol. The fact that I built this up to this point in just FIVE DAYS is a testament to how incredible the protocol is. We just need to push the boundaries of it further. Both literally and figuratively.
Some videos of the beta version (Pre-Forgejo release):
But.. what about VR?
Heh, I got you ~
What is pre-chording?
This:


