Desktop
Desktop Environment Architecture
A multi-desktop strategy designed for stability, high-performance, and seamless recovery.
🏗️ The Multi-Desktop Strategy
This repository supports having multiple desktop environments (Compositors/WMs) installed simultaneously while maintaining a single “Primary Session.” This allows for advanced debugging and development without risking system lockouts.
1. Enable vs. Session (The Dual-Toggle System)
Each desktop module (Hyprland, Niri, BSPWM) can be installed by enabling it.
modules.desktop.<wm>.enable:- Action: Installs the compositor binary and links dotfiles (e.g.,
~/.config/hypr).
- Action: Installs the compositor binary and links dotfiles (e.g.,
2. Centralized Shell Architecture
To ensure a consistent user experience and reduce configuration duplication, the shell environment is decoupled from the window manager. This is managed via the global modules.desktop.mode option.
dms(Dank Material Shell): A modern, integrated shell experience managed bymodules/desktop/shell/dms.nix. It provides a unified status bar, notification system, and greeter integration.diy(Do It Yourself): A modular, power-user environment managed bymodules/desktop/shell/diy.nix. It defaults to tools like Waybar (Wayland) or Polybar (X11), and Mako or Dunst for notifications.
Each window manager (Hyprland, Niri, BSPWM) focuses purely on compositor-specific logic while automatically inheriting its shell environment based on this global mode.
🔐 Unified Greeter & Display Management
We use a centralized greeter service (modules/services/desktop/greetd.nix) to manage system access.
Supported Greeters
- DMS Greeter: The default for
dmsmode, providing a modern Wayland-native login experience. - tuigreet: A universal, high-performance TUI greeter used for
diymode. - mini: A minimal LightDM greeter used for X11/BSPWM sessions.
- boostgreeter: A pseudo-login path for Wayland sessions that skips a real greeter and boots directly into Hyprland or Niri as the desktop user, then immediately raises
hyprlock.
Security & Stability
The system uses System-Wide Icon/Cursor Themes (/run/current-system/sw/share/icons) for all greeters. This ensures that the display manager remains stable and avoids permission crashes that occur when greeters attempt to access themes in restricted user home directories.
Mode Defaults
diymode defaults totuigreet.dmsmode defaults todms-greeter.- Both defaults are overrideable by setting
modules.services.desktop.greetd.greeter, which is howboostgreetercan be tested under either shell mode.
Startup Rules
- Wayland +
diy+boostgreeter: the compositor runshey hook startup, which imports session variables and immediately raises the lock screen. - Wayland +
diy+tuigreet: no compositor startup hook is needed;tuigreetlaunches the selected session normally. - Wayland +
dms+boostgreeter: the compositor runshey hook startup, which imports session variables, startsdms.service, and then raises the lock screen. - Wayland +
dms+tuigreetordms-greeter: no startup hook is used; the compositor startsdms.servicedirectly during normal session startup. - X11 +
diy+mini: the X session runshey hook startup, which imports X session variables and immediately raises the lock screen. - X11 +
dms: unsupported. - Wallpaper startup hooks are only attached in
diymode.
🧠 The Wayland Startup Architecture (Lessons Learned)
When configuring a custom greeter or compositor on Wayland, it is vital to respect the logind and systemd user session boundaries:
- KMS/DRM and the TTY Requirement: Wayland compositors (like Niri or Hyprland) require direct DRM (Direct Rendering Manager) access to communicate with the GPU.
systemd-logindacts as the gatekeeper for this hardware access (seat0).logindwill only grant seat access to a session if it is attached to a physical Virtual Terminal (VT). Thus, ingreetd.nix, specifyingTTYPath = "/dev/tty1";withinserviceConfigis absolutely critical. Without it,loginddenies seat access, causing the compositor to falsely assume it is running nested. It will then fall back to attempting an X11 connection (e.g.,winittrying todlopenlibXcursor.so.1), which crashes obscurely. - Session Target Orchestration: Simply executing a compositor binary (e.g.,
niri -c <config>) bypassing the display manager’s standard.desktopsession wrappers breaks systemd’s target tree. User-level daemons (likedms.serviceorwaybar) rely ongraphical-session.targetto start. Proper session wrappers (likeniri-session) explicitly executesystemctl --user start niri.service, which natively pulls ingraphical-session.targetvia aBindsTorelationship. Avoid manually executingimport-environmentor manually starting systemd targets from within the compositor’s config file; rely on the session manager to orchestrate the lifecycle naturally.
🎨 Theme Integration
Desktop environments “decorate” the system by injecting settings into shared modules. These are centralized in modules/themes/desktop/.
- Priority: Session-enabled settings take precedence.
- App Reactivity: Apps like Foot or Waybar dynamically adjust their padding, layouts, and font sizes based on which compositor is currently owning the session.