gnome: 🏔🏔 EL ESCRITORIO PINTA — Overview de GNOME desde fuente, con captura

docs/evidencia/gnome-shell-qemu-2026-07-29.png: el conmutador de espacios de trabajo,
el reloj en el panel, la miniatura del escritorio, el dash, y la notificación estándar
de GNOME por sesión de root. Todo construido desde fuente sobre el kernel de hammer,
arje-zero como PID1 y musl.

**EL MURO NO ERA DE KMS.** El diagnóstico anterior culpaba al plano primario de
virtio-gpu («no advertised formats», sólo `Queue mode set`, ningún page flip). Era
correlación. Se probó quitando MUTTER_DEBUG_FORCE_KMS_MODE=simple —el log pasó a decir
`using atomic mode setting`, o sea que el cambio SÍ tomó efecto— y la pantalla siguió
con exactamente 2 colores. Refutada. Mutter no tenía un frame que presentar; no es que
no supiera presentarlo.

La causa estaba en el stack trace, en el log, desde el principio: la excepción por el
gschema `org.gnome.settings-daemon.peripherals.touchscreen` ocurre DENTRO de
`Main.start()`, construyendo los quick settings ⇒ el panel nunca se arma. Proceso vivo,
compositor con DRM master, nada que pintar.

Receta `gsd-schemas`: los gschemas de gnome-settings-daemon SIN g-s-d, que sigue
aparcada por GTK3/X11. **Tercera vez que aparece la misma lección** (tras la política
D-Bus de login1 y el `org.gnome.login-screen` de libgdm): un gschema no es un fichero de
datos del demonio, es una interfaz publicada que consume otro programa.

Dos trampas de diagnóstico, las dos ahora blindadas:
- **`glib-compile-schemas` sale con 0 aunque RECHACE un esquema.** Instalé los once XML,
  el log dijo `esquemas OK` y el shell seguía diciendo `not found`: faltaba
  `org.gnome.settings-daemon.enums.xml`, que meson genera con glib-mkenums y no es uno
  de los `.in`. Sin los `<enum>`, glib descarta el esquema entero, avisa por stderr y
  sigue. `gnome-start` ahora vuelca ese stderr SIEMPRE, no sólo al fallar.
- El log serial persiste entre arranques y me hizo leer dos veces un `STATUS +30s` de una
  VM ya muerta. Truncarlo antes de arrancar; `Failed to get "write" lock` avisa de que
  hay otro QEMU con el disco tomado.

Y queda escrito cómo validar CON PANTALLA sin humano delante: screendump por el monitor
de QEMU, con una métrica barata previa a mirar — contar colores distintos. Negro = 2;
pintando = 582, con el azul GNOME (2,60,136) al frente.

Lo que falta son detalles, ninguno impide el escritorio: lanzar upowerd desde gnome-start,
un tema de cursor, el setuid de colord y gnome-control-center.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-29 18:05:20 -04:00
co-authored by Claude Opus 5
parent 517c1bb4ff
commit 723f3ead33
6 changed files with 179 additions and 41 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

+60 -38
View File
@@ -1,20 +1,16 @@
# Runbook — arrancar gnome-shell en QEMU (y dónde está el muro hoy)
# Runbook — GNOME en QEMU: el escritorio PINTA
Estado al 2026-07-29: **el compositor SUBE ENTERO sobre DRM real.** gnome-shell toma el DRM master
y los tres dispositivos de input por logind, realiza el stage `MetaStageNative`, asigna los planos
primario y de cursor, y expone `wayland-0`:
Estado al 2026-07-29: **cerrado.** gnome-shell arranca desde fuente sobre el kernel de hammer, toma
el DRM master y los tres dispositivos de input por logind, expone `wayland-0`, y **dibuja el Overview
de GNOME**. Cinco muros caídos, cada uno por medición y no por conjetura:
```
BACKEND: Opening and taking control of device file '/dev/input/event0' ← y event2, y event1
BACKEND: Realizing stage 'MetaStageNative'
KMS: Plane 33 … primary for CRTC 37 · Plane 34 … cursor
Using Wayland display name 'wayland-0'
== gnome-qemu :: compositor OK (wayland-0) — el shell ES el display server
```
**Y la capa JS también está cerrada**: gnome-shell corre cinco minutos seguidos sin una sola
`JS ERROR`. Lo que falta es que PINTE — la pantalla sigue en negro. Ni cuelgues ni SIGSEGV: los
cuatro muros anteriores están cerrados, cada uno por medición y no por conjetura.
| muro | causa real | cómo se midió |
|---|---|---|
| SIGSEGV en `get_seat_proxy` | object path de la Session mal escapado (`_1` en vez de `_31`) | el cliente calcula el path solo y no pregunta |
| cuelgue de la hebra de input | el fd de `TakeDevice` sin `O_NONBLOCK` | `wchan=evdev_read` en `/proc`, no el core |
| `Requiring <X>` en bucle | 7 typelibs de runtime + 2 capas más abajo | `js/misc/dependencies.js` + cierre de `<include>` |
| pantalla negra | `Main.start()` abortaba por un gschema de g-s-d | el stack trace, que estaba en el log desde el principio |
| (descartado) KMS legacy | NO era la causa | atomic tomó efecto y la pantalla siguió con 2 colores |
Hermano de [`kde-qemu-desktop.md`](kde-qemu-desktop.md), del que reusa el andamiaje: la base
`work/metal-rootfs`, la inyección de mesa-llvmpipe/LLVM/musl, el truco del console-getty y el propio
@@ -48,43 +44,69 @@ gdb -batch -q -ex "set sysroot $PWD/work/gnome-qemu-rootfs" \
-ex "core-file /tmp/core.gnome-shell" -ex "bt 25" work/gnome-qemu-rootfs/usr/bin/gnome-shell
```
## EL MURO DE HOY — la sesión VIVE pero la pantalla está NEGRA
## 🏔 GNOME PINTA (2026-07-29)
```
== gnome-qemu :: compositor OK (wayland-0) — el shell ES el display server
== gnome-qemu :: STATUS +15s … +315s: gnome-shell=2 ← cinco minutos, sin una sola JS ERROR
```
![gnome-shell en QEMU](../evidencia/gnome-shell-qemu-2026-07-29.png)
La capa JS está cerrada: gnome-shell arranca entero y se queda corriendo. Pero la captura del
framebuffer (`screendump` por el monitor de QEMU) muestra **la consola del kernel, en negro** — el
último `[ 0.813456] arje-zero:` del boot. O sea que mutter nunca presentó un frame al CRTC.
El Overview de GNOME Shell, construido entero desde fuente sobre el kernel de hammer, arje-zero como
PID1 y musl: el conmutador de espacios de trabajo arriba a la izquierda, el reloj en el panel, la
miniatura del escritorio, el dash abajo, y la notificación estándar de GNOME por sesión de root
(«Logged in as a privileged user»).
**Validar con captura, no con serial.** Es la regla heredada de KDE ([[metal-dual-desktop-en-curso]])
y acá se cumple sin humano delante:
**Cómo se validó, y es la parte reusable**: `screendump` por el monitor de QEMU, sin humano delante.
```sh
printf 'screendump /tmp/gnome.ppm\n' | socat - UNIX-CONNECT:work/gnome-monitor.sock
python3 -c "from PIL import Image; Image.open('/tmp/gnome.ppm').save('/tmp/gnome.png')"
```
La pista está en el log de KMS, y es concreta:
Métrica barata para saber si pinta antes de mirar: **contar colores distintos**. Con la pantalla
negra eran **2** (negro + el gris de la consola del kernel); pintando son **582**, con el azul GNOME
`(2,60,136)` y los grises del shell `(34,34,38)` al frente.
### El muro que parecía de KMS y era de GSettings
El diagnóstico anterior de este runbook culpaba al KMS: «el plano primario de virtio-gpu no publica
formatos, sólo hay `Queue mode set` y ningún page flip». **Era una correlación, no la causa.** Se
probó quitando `MUTTER_DEBUG_FORCE_KMS_MODE=simple` —el log pasó a decir `using atomic mode setting`,
o sea que el cambio SÍ tomó efecto— y la pantalla siguió con exactamente 2 colores. Refutada.
La causa estaba en el stack trace, en el log, desde el principio:
```
KMS: Adding primary plane 33 (/dev/dri/card0)
KMS: Plane has no advertised formats ← virtio-gpu sin 3D no publica IN_FORMATS
KMS: Queue mode set ← ×3, y nunca hay page flip ni scanout
GNOME Shell-CRITICAL: Failed to setup quick settings:
Error: GSettings schema org.gnome.settings-daemon.peripherals.touchscreen not found
Stack trace: systemActions.js:156 → status/system.js:236 → quickSettings.js:29
```
Hipótesis por orden de costo, todas de una sola variable:
1. **Quitar `MUTTER_DEBUG_FORCE_KMS_MODE=simple`** de `gnome-start-qemu.sh`. Ese forzado se heredó de
la campaña KDE, donde kwin fallaba con atomic; mutter puede comportarse distinto, y el modo
legacy es justo el que no sabe qué hacer con un plano sin formatos publicados.
2. Encender 3D en el virtio-gpu de QEMU (`virtio-vga-gl` + virgl) y sacar `GBM_ALWAYS_SOFTWARE`.
3. Mirar si `MUTTER_DEBUG_SEND_KMS_MODIFIERS=0` sigue haciendo falta ahora que hay scanout real.
Esa excepción ocurre **dentro de `Main.start()`**, construyendo los quick settings: el panel nunca se
termina de armar, así que no hay nada que pintar. El proceso queda vivo y el compositor con DRM
master — de ahí la pantalla negra con `gnome-shell=2`. **Mutter no tenía un frame que presentar; no
es que no supiera presentarlo.**
Lo demás del log son avisos, no muros: falta un tema de cursor, colord no arranca (el helper setuid
no tiene los permisos) y `org.gnome.settings-daemon.peripherals.touchscreen` no existe porque
gnome-settings-daemon está aparcada — eso rompe quick-settings, no la sesión.
Lo resolvió la receta `gsd-schemas`: los gschemas de gnome-settings-daemon **sin** g-s-d (que sigue
aparcada por GTK3/X11). Tercera vez que aparece la misma lección — un gschema no es un fichero de
datos del demonio, es una interfaz publicada que consume otro programa.
### Dos trampas del camino, las dos de diagnóstico
1. **`glib-compile-schemas` sale con 0 aunque RECHACE un esquema.** Instalé los once XML, el log dijo
`esquemas OK`, y el shell seguía diciendo `schema ... not found`. Lo que faltaba era
`org.gnome.settings-daemon.enums.xml` —que meson genera con `glib-mkenums` y no es uno de los
`.in`—: sin los `<enum>`, glib descarta el esquema entero, avisa por stderr y sigue. `gnome-start`
ahora **vuelca ese stderr siempre**, no sólo cuando el comando falla.
2. **El log serial persiste entre arranques.** Dos veces leí un `STATUS +30s` que era del arranque
anterior y saqué conclusiones de una VM muerta. Truncar (`: > serial.log`) antes de arrancar, y
esperar a que la imagen esté hecha Y no haya otro QEMU con el disco tomado (`Failed to get "write"
lock` es el aviso de que hay uno vivo).
### Lo que queda, y ninguno impide el escritorio
- `Failed to activate service 'org.freedesktop.UPower': timed out` — falta lanzar `upowerd` en
`gnome-start`, como se hace con `accounts-daemon`.
- `No cursor theme available` — falta un tema de cursor (adwaita-icon-theme).
- colord no arranca: su helper setuid no tiene los permisos correctos en la imagen.
- `Missing required core component Settings` — es gnome-control-center, que no está en el corpus.
## CÓMO SE CERRÓ LA CAPA JS (2026-07-29)