Verification scope: nixpkgs
nixos-unstablemodules and upstream documentation consulted in October 2026. Group lists, package counts, and service defaults change across revisions. When deploying, use the nixpkgs and Home Manager source versions locked by your project as the authority. No builds, activations, or desktop runtime tests were performed for this article.
The Complete Startup Chain#
TTY 登录 (kmscon) → 用户 shell → uwsm start compositor → 桌面
↑ ↑ ↑
握着 DRM master 会话管理器 激活 graphical-session.targetThree layers of coordination sit between a bare TTY and a usable desktop. They govern display-device ownership, the user-service environment, and autostart respectively. Troubleshooting requires checking each layer separately.
Layer One: Handing Over DRM Master#
In some kmscon configurations using the libseat=false raw-VT backend, the terminal may hold DRM master to render the TTY. This depends on the kmscon version, seat backend, and startup mode. For the compositor to take over the display, kmscon must first release master.
- Method: send the terminal the OSC escape
\033]setBackground\a→ kmscon releases master and moves into the background; after the compositor exits, sendsetForegroundto restore it - kmscon builds supporting this interface may provide
kmscon-launch-gui, coordinating the sequencesetBackground → 短暂等待 → 运行合成器 → setForeground(setBackground → wait briefly → run the compositor → setForeground). First check whether the tool exists locally and inspect its implementation; do not treat a fixed wait time as a stable protocol. - If DRM master is still held when the compositor starts, startup may fail. A black screen alone does not establish that this is the cause.
Layer Two: uwsm's Session Model#
uwsm (Universal Wayland Session Manager) wraps the compositor in a systemd user session:
uwsm start hyprland.desktop→ creates units such aswayland-wm@.serviceand activatesgraphical-session.target- Some distribution or patched versions may integrate kmscon coordination. The upstream uwsm main source inspected for this article contained no
setBackground, so automatic coordination cannot be assumed for every version. Inspect the startup wrapper and seat backend in the version actually locked by your configuration. graphical-session.targetrepresents part of the systemd user graphical-session lifecycle. uwsm also waits for environment variables and services to be ready; a single active status does not establish that every desktop feature is healthy.
Layer Three: The Two Roles of graphical-session.target#
This target serves two roles; understanding them explains much of the seemingly mysterious behavior:
1. Detect whether a compositor is running: uwsm check may-start checks whether the target is active and refuses startup if it is, reporting "compositor already running".
Multiple session managers may leave state behind If the relevant target remains active after a desktop exits, uwsm's may-start check may reject the next startup. Check the unit relationships, exit logs, and state for the actual version. Do not infer from one failure that a desktop is permanently incompatible with uwsm, and do not blindly stop the target while another session is active.
2. Trigger XDG autostart: systemd's systemd-xdg-autostart-generator creates user services for compatible .desktop files. Actual unit names and conditions depend on the file ID, OnlyShowIn/NotShowIn, the environment, and package versions. uwsm connects the session to xdg-desktop-autostart.target, launching applications whose conditions are met. Other session managers, including GNOME's, also implement autostart; uwsm is not the only way to start fcitx5.
The Cost of Bypassing uwsm Running a compositor directly with only a display-handoff tool may leave the systemd graphical session and autostart target unestablished. If fcitx5 does not start automatically on such a startup path, first check the targets, user services, environment, and desktop-file conditions. Running
fcitx5 -dmanually is only a diagnostic step, and duplicate instances must be avoided. Input-method failures can also arise from environment variables, protocols, or configuration; they cannot all be reduced to a single cause.
The Correct Procedure for Switching Desktop Environments from a TTY#
# 1. 退出当前 compositor(回 TTY)
# 2. 先检查没有其他活跃图形会话
systemctl --user status graphical-session.target graphical-session-pre.target
loginctl list-sessions
# 3. 确认只是残留后,再清理(会停止相关用户图形服务)
systemctl --user stop graphical-session.target graphical-session-pre.target
# 4. 启动下一个;kmscon 交接依已核验的包装器/后端实现
uwsm start hyprland.desktopWhen the user session can end and be reestablished normally, a system reboot is usually unnecessary. The GNOME example uses GDM + specialisation and is managed by GNOME's session manager; do not additionally wrap its compositor inside another session manager. Driver, kernel, or login-service changes may still require a reboot.
Troubleshooting Quick Reference#
| Symptom | Check first |
|---|---|
| compositor already running | A lingering graphical-session.target (check with systemctl --user status) |
| Compositor fails to start / black screen | DRM/seat permissions, device ownership, display drivers, and compositor logs |
| fcitx5 does not start automatically | Autostart target, desktop-file conditions, user-service environment, input-method configuration, and duplicate instances |
Related Articles#
- NixOS Specialisation: System Variants — the GNOME exception path
- NixOS Declarative and Runtime Layers — sessions are runtime state
Read-Only Evidence Collection#
systemctl --user status graphical-session.target xdg-desktop-autostart.target
systemctl --user list-units --all 'wayland-*' 'app-*fcitx*'
journalctl --user -b --no-pager
loginctl session-statusStart with the specific error to identify the relevant DRM/seat, user-service, or input-method layer. Before sharing logs publicly, redact personal paths, environment values, and device identities.
References & further reading
- Official uwsm repository ↗
- uwsm main implementation ↗
- systemd XDG autostart generator ↗
- Official kmscon project ↗
Adapted from technical notes. Examples use generic names.