From 51398f89cf364d786aaa9ddb20f69e6798844b35 Mon Sep 17 00:00:00 2001 From: sergio Date: Wed, 20 May 2026 23:25:44 +0000 Subject: [PATCH] fix(mirada-compositor): no pisar WAYLAND_DISPLAY antes de winit::init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit winit lee WAYLAND_DISPLAY/DISPLAY para encontrar la sesión gráfica anfitriona donde anidarse. El código publicaba antes su propio socket en WAYLAND_DISPLAY, así que winit intentaba anidarse en el propio compositor —un socket que aún no atiende a nadie— y se colgaba. Ahora winit::init() va primero (conecta a la sesión real) y el socket propio + set_var se publican después. Si no hay sesión gráfica, aborta con un mensaje claro en vez de colgarse o fallar en seco. README: sección Requisitos — hace falta sesión X11/Wayland anfitriona; receta Xvfb + VNC para cajas headless. Co-Authored-By: Claude Opus 4.7 --- crates/apps/mirada-compositor/README.md | 21 ++++++++++++++++ crates/apps/mirada-compositor/src/main.rs | 29 ++++++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/crates/apps/mirada-compositor/README.md b/crates/apps/mirada-compositor/README.md index c49d6ef..c48d195 100644 --- a/crates/apps/mirada-compositor/README.md +++ b/crates/apps/mirada-compositor/README.md @@ -10,6 +10,27 @@ Backend `winit`: corre **anidado** — una ventana dentro de tu sesión gráfica actual, X11 o Wayland. No toca DRM/KMS, así que es seguro de arrancar sin dejar la sesión. +## Requisitos + +Hace falta una **sesión gráfica anfitriona** (X11 o Wayland) donde +dibujar la ventana del compositor — es donde `winit` se anida. En un +servidor *headless* (SSH a una caja sin escritorio, `XDG_SESSION_TYPE=tty`, +sin `/dev/dri`) no hay dónde mostrar nada y el arranque aborta con un +mensaje que lo explica. + +Para verlo en una caja headless: levanta un servidor X virtual y +conéctate por VNC. + +```sh +Xvfb :99 -screen 0 1280x800x24 & +x11vnc -display :99 -localhost -nopw & # luego túnel SSH al :5900 +DISPLAY=:99 cargo run -p mirada-compositor +``` + +El backend nativo DRM/KMS —que pintaría directo en la pantalla sin +sesión anfitriona— está pendiente (ver el SDD), y de todos modos +necesitaría un `/dev/dri`. + ## Dos modos - **Autónomo** (por defecto) — lleva un `Desktop` (de `mirada-brain`) diff --git a/crates/apps/mirada-compositor/src/main.rs b/crates/apps/mirada-compositor/src/main.rs index 67094cd..754d02e 100644 --- a/crates/apps/mirada-compositor/src/main.rs +++ b/crates/apps/mirada-compositor/src/main.rs @@ -475,6 +475,34 @@ fn run() -> Result<(), Box> { state.apply_commands(vec![grab]); } + // El backend gráfico va primero. winit abre la ventana del compositor + // dentro de tu sesión gráfica anfitriona, y para encontrarla lee + // `WAYLAND_DISPLAY` / `DISPLAY` del entorno. Si publicáramos antes + // nuestro propio socket en `WAYLAND_DISPLAY`, winit intentaría + // anidarse en nosotros mismos —un socket que aún no atiende a nadie— + // y se quedaría colgado para siempre. + let (mut backend, mut winit) = match winit::init::() { + Ok(pair) => pair, + Err(e) => { + eprintln!("mirada-compositor · no pude abrir la ventana: {e}"); + eprintln!( + " El backend `winit` necesita una sesión gráfica anfitriona\n \ + (X11 o Wayland) donde dibujar la ventana del compositor.\n \ + Aquí no hay ninguna: DISPLAY='{}', WAYLAND_DISPLAY='{}',\n \ + XDG_SESSION_TYPE='{}'.\n \ + Lánzalo desde un escritorio gráfico, o desde un servidor X\n \ + virtual (Xvfb) al que te conectes por VNC.", + std::env::var("DISPLAY").unwrap_or_default(), + std::env::var("WAYLAND_DISPLAY").unwrap_or_default(), + std::env::var("XDG_SESSION_TYPE").unwrap_or_else(|_| "tty".into()), + ); + return Err(e.into()); + } + }; + + // Ahora sí, nuestro propio socket Wayland — y `WAYLAND_DISPLAY` se + // publica *después* de winit, sólo para los clientes que lancemos + // como procesos hijos. let listener = ListeningSocket::bind_auto("wayland", 1..32)?; let socket_name = listener .socket_name() @@ -485,7 +513,6 @@ fn run() -> Result<(), Box> { println!("mirada-compositor · escuchando en WAYLAND_DISPLAY={socket_name}"); println!(" lanza un cliente: WAYLAND_DISPLAY={socket_name} foot"); - let (mut backend, mut winit) = winit::init::()?; let start = Instant::now(); let mut clients = Vec::new();