The X server, its start and its tools as one module. It provides x11-display with the machine's reach, gated by the host's seat capability. It writes a block at the start of ~/.xinitrc: the account's environment, an explicit import into the user manager, the mesh's X resources merged without cpp, autorandr, the xinitrc slots, ~/.xinitrc.local, and the session's exec from the last slot. Its Go tools serve the seat's displays and layout (autorandr profiles keyed by EDID), and set-mode, primary, dpi, input devices and settings, keyboard, a screenshot (xwd decoded in Go) and the server's log. internal/desktop is how every desktop tool finds the operator's session from the runtime, which has none: from the session's own processes, reading only its words, confirmed with logind.
12 KiB
xorg
The X display server as a module (novox/hq ADR 0208, research 026, to-be 42 phase 2 step 2).
- Claims
node-display-serverand serves its verbsdisplaysandlayout. - Provides
x11-displaywith the machine's reach: i3, xterm, picom and the X lock screen require it, and a requirement for it is met only by this module on the same machine. It is never pulled in for whatever asked. - Gated by the capability
seat, which the host reports for a machine with a graphics device and a connected display. See Blockers for why notgraphical-session. - Packages:
xorg-server,xorg-xinit,xorg-xrandr,xorg-xset,xorg-xrdb,xorg-xinput,xorg-setxkbmap,xorg-xwdandautorandr. The GPU's driver is not here. It follows the machine, so it belongs to that machine model's hardware module.
What it owns
| path | class (ADR 0182) | what |
|---|---|---|
~/.xinitrc, a block at the start |
written into (block, at: start) |
the session's start, below |
~/.config/xorg/ |
owned directory | |
~/.config/xorg/xresources |
owned | the mesh's X resources: font rendering (Xft.*, DPI 96) and the three xresources slots |
The session's start, in ADR 0208 §5's order:
- It sources
~/.config/mesh/environment.sh(ADR 0203). If pam did not hand over a session bus, it takes the user manager's socket, never a second bus. - It imports an explicit list of the session's words into the user manager and D-Bus activation,
only those that are set. The list is
DISPLAY,XAUTHORITY,XDG_SESSION_TYPE,XDG_CURRENT_DESKTOP,XDG_SESSION_DESKTOP,XDG_CONFIG_HOME,XDG_DATA_DIRS,GTK_THEME,GTK2_RC_FILES,QT_QPA_PLATFORMTHEME,QT_STYLE_OVERRIDE,QT_SELECT,XCURSOR_THEME,XCURSOR_SIZEandTERMINAL. It never uses--all. - It merges
~/.config/xorg/xresourceswithxrdb -nocpp, then~/.Xresourcesif you keep one, so yours win. - It runs
autorandr --change, which applies the saved profile matching the connected monitors. - It runs the
xinitrcslotsfirstandnormal, then sources~/.xinitrc.localif it exists. - It runs the
lastslot, where the holder ofnode-display-sessionstarts the session (exec i3).
Who contributes where, among the desktop's modules:
| slot | module | what |
|---|---|---|
first |
gnome-keyring |
SSH_AUTH_SOCK |
normal |
adwaita |
its GSettings keys |
normal |
clipmenu |
clipmenud & |
normal |
feh |
the wallpaper |
normal |
i3status-rust |
the bar watchdog |
normal |
screen-lock |
the timeouts and the xss-lock loop |
last |
i3 |
exec i3 |
Slot last is the session's. A module contributing session lines uses first or normal.
Code in last that sorts after the session holder's name would come after its exec and never run.
Why ~/.xinitrc.local. The block ends by starting the session, so no line below it runs. Your own
session lines go into ~/.xinitrc.local. Like ~/.zshrc.local, it is yours: found, never written.
This is the one step this module adds to ADR 0208 §5. Without it, a line no module carries yet (a
DOTNET_ROOT, a wallpaper) would have nowhere to run.
Resources without the preprocessor. xrdb -nocpp needs no C compiler on the machine, and it
skips a line starting with #. The controller precedes each contribution with a # <module> line,
which is a cpp directive error under plain xrdb -merge but is skipped here.
Tools
| tool | what | |
|---|---|---|
node-display-server.displays |
r | the screen and every output: position, rotation, size, DPI, the monitor's EDID identity (manufacturer, product, serial, name, fingerprint), current and preferred mode, every mode and rate, the autorandr profile in force |
node-display-server.layout |
r/a | autorandr profiles: list (each with the monitors it is for, which match now, which is current), save (replace to overwrite), apply |
xorg_set_mode |
a | one output's mode, rate, rotation, scale, position (x/y or beside another), off, primary; dry_run |
xorg_primary |
r/a | which output is primary; set it |
xorg_dpi |
r/a | Xft.dpi beside each monitor's physical DPI; set it for the running session |
xorg_input_devices |
r | the input devices, and each pointer's libinput settings |
xorg_input_set |
a | tap, tap drag, natural scroll, disable while typing, left handed, middle emulation, enabled, acceleration, by device id or name |
xorg_keyboard |
r/a | the XKB map; set layout, variant, model, options |
xorg_screenshot |
d | a PNG of the screen, one output or one window, inside the home (default ~/Pictures/Screenshots/) |
xorg_x_log |
r | the X server's log for the running session: version, start, errors (and warnings) |
All answers are structured. Each tool that changes the running server says how long the change lasts.
How a tool reaches the session (internal/desktop, the same copy in every desktop module). The
runtime is a system service running as the operator account. It has no DISPLAY, no XAUTHORITY and
no session bus. The tool reads them from the session's own processes:
- It looks at the account's processes, preferring the window manager.
- It reads only a fixed list of words, never the rest. A session's environment held secrets on these machines.
- It asks logind whether that session is active and local.
- It checks that the display's socket still exists.
The bus it hands on is the user manager's (unix:path=/run/user/<uid>/bus). With no session, a tool
answers {"error": "no-graphical-session", "reason": …, "looked": […]}.
The screenshot needs no screenshot program. xwd dumps the screen, and the module turns the dump
into a PNG itself.
What it improves
- One environment. The session sources the shells' environment file. It no longer exports a hand-kept second copy, and never sources the predecessor's secrets file.
- No compiler needed for the mesh's resources, and contributions are placed in order rather than
#included. - Monitor layouts by the monitors' identity (autorandr, research 026/04), not scripts with port names baked in. The package's own udev rule and service apply the matching profile on hotplug.
- No second bus. The
dbus-launchfallback that once ran the whole session on a private bus is gone. That stale session can still be seen today on one workstation:session_busin a tool's answer shows it.
What it leaves found
~/.xprofile, ~/.Xresources, ~/.Xresources.d/, ~/.screenlayout/, the arandr scripts, every
line of yours below the block, and /etc/X11/xinit/xinitrc.d/.
The one-off migration (ADR 0182)
Assign the desktop's modules together (xorg, lemurs, i3, xterm, adwaita and the
companions above) and do this migration first. Until i3 is assigned, nothing changes for you. The block's last slot is empty, so the block
runs and falls through to your own lines below it, which still end in exec i3. The environment is
sourced twice and the import runs twice, which is harmless.
Once i3 is assigned, nothing below the block runs. Before that push, sort today's
~/.xinitrc lines (both workstations hold the same file):
| today's line | where it goes |
|---|---|
the /etc/X11/xinit/xinitrc.d/?*.sh loop |
delete: the block imports DISPLAY and XAUTHORITY itself, and the login manager's X setup runs that directory too |
eval $(gnome-keyring-daemon --start …) and export SSH_AUTH_SOCK |
delete once gnome-keyring is assigned. PAM starts and unlocks the keyring, and that module names the ssh agent's socket in the xinitrc slot first. Until then, ~/.xinitrc.local |
export PATH=… (nine entries) |
~/.local/bin, ~/scripts and ~/scripts/bin come from zsh's environment already. Delete ~/scripts/i3-sessions/commands and ~/scripts/mediahuis: neither exists on either workstation. Move ~/.cargo/bin, ~/.config/rofi/scripts, ~/.dotnet and ~/.dotnet/tools to ~/.xinitrc.local until a module carries them |
DOTNET_ROOT, DOTNET_CLI_TELEMETRY_OPTOUT |
~/.xinitrc.local |
XDG_CONFIG_HOME |
delete: zsh contributes it |
XDG_DATA_DIRS with the flatpak directories |
~/.xinitrc.local until the flatpak module |
QT_QPA_PLATFORMTHEME, GTK_THEME, QT_STYLE_OVERRIDE, GTK2_RC_FILES, QT_SELECT |
delete once adwaita is assigned (its environment contributions) |
XDG_SESSION_DESKTOP, XDG_CURRENT_DESKTOP and their comment |
delete once i3 is assigned |
dbus-update-activation-environment --systemd … and its comment |
delete: the block's step 2 |
~/scripts/xdg-appearance || true |
delete once adwaita is assigned |
MY_KV_PATH, MY_LIB_PATH, MY_STREAMING_PATH |
~/.xinitrc.local (they are yours) |
[ -f "$HOME/.config/hal/env" ] && . … (the secrets file) |
delete (ADR 0208 §5, research 027 Q2). Whatever in the session needed one of those tokens gets it the way research 027 settles |
xset s 1800, xset dpms 1800 1800 3600 |
delete once screen-lock is assigned (its normal slot line). Until then, ~/.xinitrc.local |
~/.fehbg & |
delete once feh is assigned (its normal slot line). Until then, ~/.xinitrc.local |
the xss-lock respawn loop |
delete once screen-lock is assigned. Until then, ~/.xinitrc.local |
exec i3 --shmlog-size=26214400 |
delete: i3 contributes exec i3 to the last slot |
Then delete everything below the block. The old #!/bin/sh line now sits below the block too and
means nothing there. The file is run with sh (by the login manager's entry and by startx), never
executed by its first line.
~/.xprofile. The login manager's X setup sources it, and it sources ~/.xinitrc. Once i3 and
lemurs are assigned, the session entry /etc/lemurs/wms/i3 runs ~/.xinitrc itself, so delete
~/.xprofile. Its bus logic is the block's now. If you keep it, delete its . ~/.xinitrc line, or
the session starts from .xprofile and the login manager's entry is never reached. Either way works
once, but only one should.
~/.Xresources holds #include ".Xresources.d/xterm", #include ".Xresources.d/xft" and the
two Xcursor lines:
- The
xftinclude and~/.Xresources.d/xftare deleted now. This module's file carries the same five values. - The
xterminclude and~/.Xresources.d/xtermare deleted oncextermis assigned. Kept, they win over the module's font and colours. - The
Xcursorlines are deleted onceadwaitais assigned. - A file left empty is deleted.
Monitor layouts. For each place you use, arrange the monitors (xorg_set_mode, or arandr once
more), then layout save it under a name. Once every place has a profile, these retire: the
~/.screenlayout/ and ~/scripts/.screenlayouts/ scripts, the laptop's hotplug rule, and its i3
bindings. Those bindings belong to that machine's hardware module, not here.
What changes when it is assigned
| g14 (laptop) | shanks (desktop) | |
|---|---|---|
| packages | autorandr installed; the rest are there already |
the same |
| files | ~/.config/xorg/xresources new; a block added at the start of ~/.xinitrc |
the same |
| running session | nothing: everything takes effect at the next login | nothing |
next login, before i3 is assigned |
the block runs, then the old file below it. Fonts unchanged (96 DPI); autorandr --change does nothing with no profiles |
the same. Its session moves to the user manager's bus at the next login, as it should have |
next login, after i3 is assigned |
only the block: what the table above did not move is gone | the same |
Blockers
- The capability. ADR 0208 §3 says
graphical-sessiongates the display server. The host reports that capability from its own environment. It is a root daemon with noDISPLAY, so the capability is no on both workstations (node show, 2026-10-04). Gated on it,xorgcould never be assigned. This manifest usesseatinstead: graphics hardware with a connected display, yes on both. The ADR's wording needs a progressive insight, or the host needs a probe that finds the session the wayinternal/desktopdoes. - Unassigning removes the packages. The host takes a package away when its declaration goes,
and
xorg-serveris among them. Do not unassignxorgfrom a workstation you are sitting at without another display server assigned. - The
# <module>naming lines in thexresourcesslots are safe only because this module merges with-nocpp. If the controller rendered!forxresources, that would be the format's own comment.