SchOS/docs/architecture/desktop.md
Nexoniarz b411836478 libinput, seatd and libseat; sockets from accept() can pass descriptors
Alpine's libinput, libseat, seatd, xf86-input-libinput and usbutils join the
image, and seatd runs from schinit. libinput lists the keyboard and pointer as
an ordinary user, Xorg now drives both through libinput, and a program linked
to libseat running as schos opens seat0 through seatd, is handed
/dev/input/event0 and reads its name through the descriptor.

Two kernel bugs stood in the way, and both would have stopped a Wayland
compositor too. The socket connect() queues for a listener was allocated with
its domain at zero, so sendmsg refused SCM_RIGHTS on the accepted end: a server
could receive descriptors and never send one. And sendmsg treated a control
buffer longer than its messages as an error, where Linux takes a following
header too short to be one as the end; seatd passes a zeroed CMSG_SPACE array
with one descriptor at the front.

Found with /proc/strace and a temporary kinfo in sendmsg's EINVAL sites.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVRhxi9zpdW2uDUN4FVcao
2026-10-26 16:51:39 +01:00

5.1 KiB
Raw Blame History

The desktop: Xorg on the framebuffer

The desktop is X11, on the framebuffer: Alpine's xorg-server with the fbdev video driver and the evdev input driver, Window Maker as the window manager, and xterm. startx runs wmaker. Nothing here is written by SchOS except the kernel interfaces it stands on and four small files in tools/posix/mkaroot.sh.

Xorg is the desktop for now, not for ever. SchOS will not write its own compositor (the one it had, Schcom, was deleted). What comes next is whichever of XLibre (the Xorg fork), Xorg or a Wayland compositor from Alpine suits the machine; the groundwork Wayland needs — udev, /sys/devices, libinput, a DRM device — is in ../plan/roadmap.md §5.

Why X and not Wayland

Every Wayland compositor worth running — labwc, and everything built on wlroots — needs DRM/KMS, libinput, udev and libseat. DRM/KMS is the largest of them by far: a kernel graphics subsystem, and in practice a great deal taken from Linux. Xorg runs on a plain framebuffer through fbdev, which SchOS already had. That is the shorter road to a desktop by a long way, and it brings the window managers with it. udev, libinput and libseat are now in the image (udev.md); DRM/KMS is the part still missing, and it is the GPU plan (../plan/gpu.md).

What it stands on

fbdev /dev/fb0 speaks Linux's fbdev (graphics.md)
evdev /dev/input/event0 (every keyboard) and event1 (every mouse and touchpad) with Linux's queries, LED writes and key/button/relative-axis bits
VTs /dev/tty0, VT_SETMODE(VT_PROCESS), KD_GRAPHICS, the release/acquire handshake (terminals.md)
dlopen Xorg loads its drivers as modules, so exec does dynamic linking (kernel.md)
sysfs /sys/bus/pci/devices/*/{boot_vga,enable,graphics/fb0}, which libpciaccess reads
ptys xterm runs its shell on a pseudo-terminal
Unix sockets the X11 socket, abstract names, SO_PEERCRED, flock
headers <linux/*.h> in the build sysroot, as ports/linux-headers

cmd/xready checks every one of the kernel calls Xorg makes before it draws anything — the evdev queries, the fbdev calls, the console calls, and the /sys files — one at a time, on a terminal of its own, and puts everything back. The calls were written against what the programs are documented to do; each step past it found one that was not, which is what running the real program is for.

The four files

  • /root/.xserverrc starts X on the VT startx was started from (startx works that out only when uname -s says Linux, and SchOS's says SchIFT). It used to add -dumbSched, Xorg's switch for reading input on the main loop, because Xorg normally reads input on a thread of its own and, when SchOS had no threads, the server crashed the first time a client disconnected, in pthread_join on a thread that was never made. Threads exist now and the switch is gone: under QEMU, X starts with Window Maker, xclock and xeyes connect and disconnect, an xterm runs and exits, and the server stays up.
  • /root/.xinitrc is exec wmaker. Without it xinit falls back to twm and an xterm, which are not in the image.
  • /etc/X11/xorg.conf.d/10-schos.conf holds what the defaults do not give: Ctrl+Alt+Backspace enabled, the keyboard options, and the framebuffer driver. Input devices are found, not named: Xorg asks libudev, which reads what udevd wrote to /run/udev (udev.md).
  • /etc/asound.conf is for sound, not X (audio.md).

Using it

Twelve virtual terminals, switched with Ctrl+Alt+F1–F12 — on the console and under X alike, because X owns the keyboard while it runs and switches only with that chord. startx on a terminal runs the desktop there; Ctrl+Alt+Backspace ends the session and gives the terminal back. Window Maker, xterm, xeyes, xclock, xcalc, DejaVu fonts; SDL 2 games (lbreakouthd) and NetSurf, a GTK 3 browser, run in it.

Touchpads that sit on an I2C bus (most laptops) are driven by kernel/acpi/i2c_hid.c, found through ACPI, and reach X as a mouse: pointer, click and tap.

What it does not do

  • No acceleration. Software rendering to the framebuffer: no DRM, no glamor, no DRI, no OpenGL beyond what software gives. GPU drivers are a plan (../plan/gpu.md).
  • udev covers the kernel's own devices only. Input, terminals, memory devices, the framebuffer and disks are announced; PCI and USB devices are in /sys/bus/*/devices but are not yet in the /sys/devices tree or on the uevent socket (udev.md).
  • Touchpads are mice: no two-finger scroll, no gestures, no palm rejection.
  • No resolution change from inside X. The mode is the console's; schmode changes the vgpud head only, and the loader's menu is where a real panel's mode is chosen.
  • Runs as an ordinary user. startx as schos works by group permission alone (users.md); X itself is still a single seat with no logind or seatd.