-
-
Notifications
You must be signed in to change notification settings - Fork 0
synui
The Wayland compositor, on wlroots 0.20 and rendering through scenefx
0.5's fx_renderer. Written for this system rather than adapted to it: it
draws its own display-settings panel, wallpaper picker, dock, cursor picker,
sound panel and control panel, renders an optional CRT post-process pass, and
holds live subscriptions to synguard's verdict feed and synapd's activity.
Tiling + monocle layouts, per-output workspaces, XWayland, layer-shell.
All shortcuts: Keybindings. Roadmap:
synui/ROADMAP.md.
Deeper dives: The Desktop (bar, widgets, icons, themes) · Window Effects (glass, blur, shadows, CRT) · Cursor Themes · Sound Themes.
Control panel (Super+C) — the front door. Lists every shortcut, generated
from the live bind table, so it can't drift from the actual bindings.
The bar — a native quickshell bar, one per monitor, with per-monitor settings, a right-click menu and auto-hide. It replaced waybar in pkgrel 154, and the start button and menu moved into it in 163. See The Desktop.
Dock — auto-hide with hover-slide and a reveal dwell, right-click context menu, runtime pin/unpin, drag to any edge (vertical on left/right).
Desktop — optional ~/Desktop icons with drag-to-place, persistent placement
and arrange-by name/type/size/date; a desktop right-click menu; and four optional
widgets (visualiser, sysmon, big clock, quick-launch), all off by default.
Wallpapers (Super+W) — built-in Synapse (static) and
Matrix (animated GLES2 rain, ported from the KDE matrix shader), a browser
for ~/Pictures and friends, per-monitor choices and scaling modes on Tab
(pkgrel 192), and Steam Workshop wallpapers through the optional
linux-wallpaperengine package, driven by synui-wpengine.
Mixer — right-click the bar's volume module for per-device and per-application levels, drawn by the bar itself (pkgrel 197). See The Desktop.
Themes (Super+T) — SYNAPSE / Dark / XP / 95 plus six riced palettes,
applied across synui's own chrome, the bar, GTK, Qt/KDE, the terminal
(kitty, and foot where present) and Firefox.
Cursor themes (Super+Shift+P) — picker panel plus synui-cursor to
install them. Event sounds (Super+S) — ten events, all silent by default,
plus synui-sound to install sound themes.
Window effects — glass, backdrop blur, rounded corners, drop shadows with a
shadow_spread knob, an optional glass_halo ring, and clip_csd_margin to
crop clients that paint their own shadow. Plus the CRT pass (Super+E):
scanline, curvature, aberration, glitch, and amber/green/white phosphor with
bloom. Off by default as of pkgrel 183.
Display (Super+D) — per-output mode, position, scale, 10-bit colour and
HDR detection from the EDID (not from the plane's bit depth). Monitor grid
with aligned columns. Night light on the output state.
Power management (Super+P) — compositor-native dim / blank / lock /
suspend. Retired swayidle entirely. Includes media idle-inhibit: it won't
blank the screen while audio is playing. Explicit laptop lid policy, brightness
keys, battery.
Lock screen (Super+L) and a graphical greeter over greetd IPC, drawn
in-process and mirroring the lock screen.
Task manager (Ctrl+Alt+Delete) — process table with CPU/RAM/GPU
overview and per-process VRAM via dlopen'd NVML (no CUDA headers needed at
build time).
Game mode (Super+G) — detects a fullscreen Xwayland client, stops synapd
to free its VRAM, and holds off idle. The bar shows an indicator
($XDG_RUNTIME_DIR/synui-game).
Screenshots and recording — Print and friends
(Keybindings); Super+Shift+R records.
Clipboard history — Super+V.
Security feed from synguard, neural overlay (Super+A) fed live from
synapd, system tray (SNI), news reader (Super+R), ISO mounter
(udisks2, no root), and cat mode (Super+Shift+C) — a procedurally-drawn
cairo kitty that wanders your monitors on top of everything, because why not.
Compositor-specific traps that cost real days. The cross-cutting ones — signal inheritance, silent staleness, shadowed units — are in Development Notes.
Xwayland is itself a client of that event loop, and it starts lazily. A blocking xcb round-trip made from the event loop deadlocked the entire compositor at login — black screen, dead input, no core dump. Use a ready-flag plus a worker thread.
SIG_IGN and the blocked mask survive exec(). This burned us three separate
times: synui's SIGCHLD=SIG_IGN leaked into Xwayland and made it abort itself;
and synui's signalfd blocked mask was inherited by every child, making every
app synui launched immune to SIGTERM.
Or they swallow clicks. (Discovered via cat mode, of all things.) The QML
equivalent is mask: Region {} on a desktop widget — without it the widget is an
invisible rectangle that eats every click over it.
Two click sites passed the raw (sub)surface to focus_view, sending
wl_keyboard.enter to a render subsurface. Firefox therefore never made its
persistent-storage doorhanger the active modal, so the panel was unresponsive and
Tab skipped it. A doorhanger is a subsurface, not a popup — none of the
popup/grab machinery applies to it.
It disrupts the xdg_popup grab, which broke menu activation in Firefox.
parent_view is only set for toplevel-parented popups, so nested ones were never
unconstrained and every submenu got its full requested size — an application list
ran off-screen instead of scrolling.
Without wl_pointer.motion while a button is held, region-select (slurp) and
every client-side drag are broken.
Anything on the unmap or decoration path that reaches for xdg_surface
unconditionally will SEGV the moment an X11 window is involved. And when you need
to crop something, crop the buffer, not the tree —
wlr_scene_subsurface_tree_set_clip() recurses into every subsurface tree below
the node it is given, and xdg popups are parented beside the client tree, so
clipping the parent crops the menus.
The bar reserved its strip while auto-hidden and lost the reservation when it should have had it, because the zone was set too early. The same ordering is why desktop-icon layout pass 1 saw the whole output: the bar reserves its strip after startup, so anything laid out at startup must re-run once the zone lands.
Committing whole-output damage after the state is built shows the previous frame's buffer for one frame — the "flash on focus change" bug.
A blur node that keeps its old size after a resize is the "shadow ghost" people report as a rendering artifact. It is a scenefx blur node that was never resized.
A decorated window is two stacked buffers whose corner radii encode the
titlebar/content seam. Anything built by growing those per-buffer boxes
inherits the seam and comes out square where it should be round. Frame-level
effects belong on view->frame, not on the buffers. See
Window Effects.
~/.config/synui/synuirc (or /etc/synui/synuirc), plus outputs.conf for
monitor layout — where primary=1 marks the primary output for Xwayland, which is
what stops SDL games opening on the wrong monitor. outputs.conf x/y are taken
verbatim; synui does not repack them into rows.
State files live beside it: wallpaper.state, wpengine.state, dock.state,
power.state, filters.state, welcome.state, cursor.state, cursor.env,
sounds.state, widgets.state, theme.json.
A state file wins over synuirc — that is what makes a choice made in a
panel survive both a restart and a packaged config update. See
Wallpapers for the one people meet first.
The file is
synuirc, notsynui.conf. Every state file resolves through one helper (syn_config_path) so they all honourXDG_CONFIG_HOME— they used to hardcode~/.config/synuiwhilesynuirchonoured the env var, so pointingXDG_CONFIG_HOMEelsewhere read settings from one directory and persisted choices from another.
Session env vars live in three places: the live
/usr/local/bin/synui-sessionand two blocks insyn-install.sh. Change one, change all three. (XCURSOR_SIZElives here — unset, libXcursor sizes the cursor from the virtual screen width, which on a multi-monitor setup is thousands of pixels and gives Xwayland clients a huge pointer. The wrapper sourcescursor.envafter the defaults.)
Most rendering work is verified in a nested headless compositor rather than on a
real seat. Three rules that are not optional — scenefx's renderer is GLES2-only
so software rendering has to be forced, synui-apply-theme must be stubbed or a
nested session re-themes the live desktop, and you have to confirm which
compositor you are actually talking to before trusting any result.
Full recipe and traps: Development Notes.
See also: Keybindings, The Desktop, Window Effects, Architecture.
Using it
- Installation
- Updating
- Software
- Files
- Keybindings
- Commands
- Nix
- Gaming
- DaVinci Resolve
- Secure Boot
- Troubleshooting
Customising it
Components
Apps
Hacking on it