diff --git a/recipes/incoming-gnome/adwaita-icon-theme.toml b/recipes/incoming-gnome/adwaita-icon-theme.toml new file mode 100644 index 00000000..8f88d344 --- /dev/null +++ b/recipes/incoming-gnome/adwaita-icon-theme.toml @@ -0,0 +1,59 @@ +# adwaita-icon-theme 48.1 — los iconos y **los cursores** de GNOME. Sólo datos: no compila nada. +# +# POR QUÉ ENTRA: arrancando la sesión, mutter avisa +# +# libmutter-WARNING: No cursor theme available, please install a cursor theme +# +# y eso no es cosmético en un escritorio: **sin tema de cursor no hay puntero visible**. El cursor por +# software (`MUTTER_DEBUG_DISABLE_HW_CURSORS=1`, obligatorio en virtio-gpu con render software) dibuja +# la imagen que le da el tema; si no hay tema, no dibuja nada y el ratón se mueve invisible. +# +# Los cursores viven acá y no en un paquete aparte: `Adwaita/cursors/` trae los XCursor y el +# `meson.build:82` genera además los enlaces de compatibilidad con los nombres X11 heredados +# (`left_ptr`, `watch`, `xterm`…), que es lo que buscan las aplicaciones viejas. +# +# ARRASTRA `hicolor-icon-theme`, y no por gusto: `index.theme` de Adwaita declara +# `Inherits=hicolor`, así que la cadena de fallback termina en un tema que tiene que EXISTIR como +# tema (con su propio `index.theme`), no sólo como directorio. +# +# EL SED, y lo que muestra de upstream: `gtk-update-icon-cache` está declarado `required: true` +# (meson.build:92-96) para un `add_install_script` que **su propio autor marcó +# `skip_if_destdir: true`**. O sea que upstream ya sabe que no hay que correrlo en un build empaquetado +# — y aun así exige el binario en configure. Se borran los dos bloques enteros: el `find_program` y el +# `add_install_script`. No se pierde nada que fuera a ejecutarse. +# +# (`required: false` NO alcanza: meson no propaga el disabler dentro de `add_install_script`, revienta +# con «Unhandled python exception». Medido, no supuesto.) +# +# La otra alternativa era declarar `gtk4` en `[deps].build` (que SÍ trae `gtk4-update-icon-cache`), y +# se descartó a propósito: acoplaría el hash de un paquete de DATOS al de gtk4, o sea que cada rebuild +# del toolkit re-hashearía 5000 PNG que no cambiaron. +# +# El caché de iconos es una optimización de arranque, no un requisito: sin él GTK recorre el árbol. +# Si algún día pesa, se genera en el primer arranque como ya se hace con `gschemas.compiled`. +# +# Es la receta más pesada del frente en bytes de instalación (~5000 ficheros entre PNG, SVG +# simbólicos y cursores) y la más liviana en tiempo: no hay un solo compilador involucrado. +name = "adwaita-icon-theme" +version = "48.1" + +[source] +tarball = "https://download.gnome.org/sources/adwaita-icon-theme/48/adwaita-icon-theme-48.1.tar.xz" +sha256 = "cbfe9b86ebcd14b03ba838c49829f7e86a7b132873803b90ac10be7d318a6e12" + +[build] +compiler = "zig-cc" +target = "x86_64-linux-musl" +link = "dynamic" + +[build.phases] +configure = ''' +set -e +sed -i '/^gtk_update_icon_cache = find_program($/,/^)$/d; /^meson.add_install_script($/,/^)$/d' meson.build +PYTHONPATH=/usr/lib/python3.12/site-packages meson setup output --prefix=/usr --buildtype=release --wrap-mode=nodownload +''' +compile = "PYTHONPATH=/usr/lib/python3.12/site-packages ninja -C output" +install = "PYTHONPATH=/usr/lib/python3.12/site-packages DESTDIR=/out meson install -C output --no-rebuild" + +[deps] +build = ["meson", "samurai", "python3", "pkgconf", "hicolor-icon-theme"] diff --git a/recipes/incoming-gnome/hicolor-icon-theme.toml b/recipes/incoming-gnome/hicolor-icon-theme.toml new file mode 100644 index 00000000..243a9602 --- /dev/null +++ b/recipes/incoming-gnome/hicolor-icon-theme.toml @@ -0,0 +1,33 @@ +# hicolor-icon-theme 0.18 — el tema de iconos BASE del estándar freedesktop, y nada más que su +# esqueleto: un `index.theme` y el árbol de directorios vacíos por tamaño y categoría. +# +# QUÉ ES Y POR QUÉ HACE FALTA: `hicolor` es el tema de FALLBACK obligatorio de la especificación de +# iconos. Cada aplicación instala sus iconos en `/usr/share/icons/hicolor/...`, y todo buscador de +# iconos (GTK, Qt, el shell) termina ahí cuando el tema activo no tiene lo que se pide. Sin su +# `index.theme` el directorio existe pero NO es un tema: la búsqueda no lo recorre y los iconos de +# las aplicaciones quedan invisibles aunque los ficheros estén en su sitio. +# +# No trae ni un icono propio, a propósito — es el contrato, no el contenido. De ahí que sea la receta +# más chica del frente y a la vez la que no se puede saltear. +# +# Ojo con la versión: hasta 0.17 era autotools; **0.18 pasó a meson** y el tarball ya no trae +# `configure` (ni `configure.ac`). Un `./configure` heredado de la receta vieja sale con 127. +name = "hicolor-icon-theme" +version = "0.18" + +[source] +tarball = "https://icon-theme.freedesktop.org/releases/hicolor-icon-theme-0.18.tar.xz" +sha256 = "db0e50a80aa3bf64bb45cbca5cf9f75efd9348cf2ac690b907435238c3cf81d7" + +[build] +compiler = "zig-cc" +target = "x86_64-linux-musl" +link = "dynamic" + +[build.phases] +configure = "PYTHONPATH=/usr/lib/python3.12/site-packages meson setup output --prefix=/usr --buildtype=release --wrap-mode=nodownload" +compile = "PYTHONPATH=/usr/lib/python3.12/site-packages ninja -C output" +install = "PYTHONPATH=/usr/lib/python3.12/site-packages DESTDIR=/out meson install -C output --no-rebuild" + +[deps] +build = ["meson", "samurai", "python3", "pkgconf"] diff --git a/scripts/gnome/gnome-start-qemu.sh b/scripts/gnome/gnome-start-qemu.sh index 194fa4f7..086d3d58 100755 --- a/scripts/gnome/gnome-start-qemu.sh +++ b/scripts/gnome/gnome-start-qemu.sh @@ -38,6 +38,14 @@ export XDG_SESSION_TYPE=wayland export HOME=/root export GSETTINGS_SCHEMA_DIR=/usr/share/glib-2.0/schemas export LANG=C.UTF-8 +# XCURSOR_PATH/XCURSOR_THEME: sin tema de cursor mutter avisa «No cursor theme available» y —con el +# cursor por software, que en virtio-gpu es obligatorio— el puntero se mueve INVISIBLE. Lo provee +# `adwaita-icon-theme`, y el nombre del tema tiene que coincidir con el directorio bajo +# /usr/share/icons. El `org.gnome.desktop.interface cursor-theme` de GSettings dice lo mismo, pero +# estas variables las lee también libXcursor/wayland-cursor sin pasar por GSettings. +export XCURSOR_PATH=/usr/share/icons +export XCURSOR_THEME=Adwaita +export XCURSOR_SIZE=24 # --- render por software sobre virtio-gpu (los mismos fixes que costaron la campaña KDE) --- export LIBGL_ALWAYS_SOFTWARE=1 @@ -221,6 +229,31 @@ else say "!! sin /usr/libexec/accounts-daemon — el menú de usuario del shell va a fallar" fi +# upowerd: el servicio de energía. Mismo caso que accounts-daemon —el shell lo consulta por D-Bus +# para el indicador de batería— y el mismo motivo para lanzarlo a mano: sin esto la activación por bus +# se queda esperando y el log lo dice sin ambigüedad, +# Error calling StartServiceByName for org.freedesktop.UPower: +# Failed to activate service ... timed out (service_start_timeout=25000ms) +# o sea VEINTICINCO SEGUNDOS de arranque tirados esperando algo que nunca iba a venir. +# Los directorios de estado los deriva upower de --prefix (historydir/statedir vacíos ⇒ +# $prefix/var/lib/upower); si no existen, arranca y se muere sin ruido. +mkdir -p /usr/var/lib/upower /var/lib/upower +if [ -x /usr/libexec/upowerd ]; then + /usr/libexec/upowerd >/tmp/upowerd.log 2>&1 & + UPOWERD_PID=$! + say "upowerd lanzado (pid $UPOWERD_PID)" + # Chequeo real, no «lo lancé y confío»: la primera versión reportaba «lanzado» y el shell seguía + # esperando 25s por org.freedesktop.UPower. Un pid no es un servicio. + sleep 1 + if alive $UPOWERD_PID; then + say "upowerd sigue vivo" + else + say "!! upowerd MURIÓ al arrancar:"; dump /tmp/upowerd.log + fi +else + say "!! sin upowerd — el shell va a esperar 25s a su activación D-Bus y seguir sin batería" +fi + if [ "${DIAG:-1}" = 1 ]; then ulimit -c unlimited 2>/dev/null || true echo '/core.%e.%p' > /proc/sys/kernel/core_pattern 2>/dev/null || true diff --git a/scripts/gnome/hydrate-gnome.sh b/scripts/gnome/hydrate-gnome.sh index 7ad475df..454e4211 100755 --- a/scripts/gnome/hydrate-gnome.sh +++ b/scripts/gnome/hydrate-gnome.sh @@ -47,6 +47,10 @@ else # (GTK3/X11) pero el shell lee sus esquemas al construir los quick settings, y si faltan la # excepción ocurre DENTRO de Main.start() ⇒ el panel no se arma y la pantalla queda negra. recipes/incoming-gnome/gsd-schemas.toml + # Ni typelib ni esquema: DATOS. `adwaita-icon-theme` trae los iconos y —lo que importa para que + # el escritorio sea usable— los CURSORES. Con el cursor por software (obligatorio en virtio-gpu) + # y sin tema, el puntero se mueve invisible. Arrastra hicolor-icon-theme por `Inherits=hicolor`. + recipes/incoming-gnome/adwaita-icon-theme.toml ) fi diff --git a/scripts/gnome/qemu-desktop-image.sh b/scripts/gnome/qemu-desktop-image.sh index 13a3b392..81bbba9f 100755 --- a/scripts/gnome/qemu-desktop-image.sh +++ b/scripts/gnome/qemu-desktop-image.sh @@ -140,6 +140,21 @@ for f in passwd:messagebus:x:81:81:messagebus:/dev/null:/sbin/nologin group:mess fi done +# El launch-helper del bus de SISTEMA tiene que ser setuid root. Es el que dbus-daemon ejecuta para +# activar un servicio bajo demanda, y comprueba SUS PROPIOS permisos antes de hacer nada: si no es +# setuid root, se niega, y el cliente recibe +# Error calling StartServiceByName for : The permission of the setuid helper is not correct +# que es exactamente lo que reportaba colord al arrancar la sesión. Sin esto **ninguna** activación +# por bus de sistema funciona; con esto, cualquier servicio con su `.service` instalado arranca solo y +# no hace falta lanzarlo a mano desde `gnome-start`. +for h in usr/libexec/dbus-daemon-launch-helper usr/lib/dbus-1.0/dbus-daemon-launch-helper; do + if [ -f "$MERGED/$h" ]; then + chown 0:81 "$MERGED/$h" 2>/dev/null || true # root:messagebus + chmod 4750 "$MERGED/$h" + echo " ✓ setuid en /$h" + fi +done + # GNOME_MODE se hornea como fichero: el getty ejecuta gnome-start sin ambiente heredable. printf 'GNOME_MODE=%s\n' "${GNOME_MODE:-drm}" > "$MERGED/etc/gnome-mode" echo "==> modo de arranque: ${GNOME_MODE:-drm}"