# modules/mirada/ — Compositor Wayland (carmen) **Propósito.** Un compositor Wayland teselante. La decisión de diseño central es partirlo en dos procesos, el **Cerebro** y el **Cuerpo**: - **El Cuerpo** (`mirada-compositor`, sobre `smithay`) habla Wayland con los clientes, posee el hardware (DRM/GPU/libinput) y compone las superficies reales. Los píxeles nunca salen de él — composición *zero-copy*. - **El Cerebro** (la app `mirada`, GPUI) decide *dónde* va cada ventana —pura aritmética de rectángulos— y orquesta el escritorio: layouts, atajos, focos, escritorios virtuales. Los dos hablan por un socket Unix con un contrato mínimo de enums. Así, toda la lógica espacial es agnóstica de Wayland y se prueba sin un servidor gráfico; el Cuerpo queda reducido a "habla el protocolo y ejecuta operaciones de geometría". ## Crates | crate | tipo | rol | | ------------------ | -------- | ---------------------------------------------------------------------- | | `mirada-layout` | lib | Motor de teselado: `Rect`, modos de layout, `Workspace` (ventanas, foco) | | `mirada-protocol` | lib | Contrato Cerebro↔Cuerpo: `BrainCommand`/`BodyEvent` + marco de cable | | `mirada-brain` | lib | Orquestador del escritorio: `Desktop`, eventos→comandos, atajos | | `mirada-link` | lib | Transporte: el socket Unix con hilo lector + canal | | `mirada-body` | lib | Contabilidad del Cuerpo: `BodyState`, traduce comandos a `BodyOp` | | `mirada` (app) | bin/GPUI | El Cerebro: ventana que tesela el escritorio y manda geometría | | `mirada-compositor`| bin/smithay | El Cuerpo: compositor Wayland real (backend `winit`, anidado) | | `mirada-ctl` (app) | bin/CLI | Control externo del Cerebro (estilo `swaymsg`): acciones y consultas | ## Flujo ```text mirada-layout ─► mirada-protocol ─► mirada-brain ─► [app mirada · Cerebro] │ │ │ mirada-link │ │ └────► mirada-body ─► [mirada-compositor · Cuerpo] ``` - El Cuerpo reporta hardware/clientes con `BodyEvent` (salida conectada, ventana abierta, atajo pulsado…). - El Cerebro (`Desktop::on_event`) recalcula y emite `BrainCommand` (`Place` con la geometría completa, `Close`, `GrabKeys`…). - El Cuerpo (`BodyState::apply`) traduce cada comando a `BodyOp` concretas y sólo emite lo que de verdad cambia. ## Detalle por crate - **`mirada-layout`** — `Rect` + `split` (reparto exacto de píxeles), `LayoutMode` con 7 modos (`MasterStack`, `CenteredMaster`, `Spiral` —espiral de Fibonacci—, `Grid`, `Columns`, `Rows`, `Monocle`) y `LayoutMode::next()` para el ciclo, `Workspace` con foco cíclico, reordenado y `promote_focused`. `LayoutParams` lleva `master_ratio` y `master_count` (`nmaster`); *smart gaps* (una sola ventana va a sangre). Determinista. - **`mirada-protocol`** — `WindowPlacement`, los enums `BrainCommand` y `BodyEvent`, el marco `postcard` con prefijo `u32` LE (`write_frame`/`read_frame`, guard `MAX_FRAME`) y el puente `placements(&Workspace, Rect)`. - **`mirada-brain`** — `Desktop`: salidas, 9 escritorios virtuales, registro de ventanas. `on_event(BodyEvent) -> Vec`; `DesktopAction` + `Keymap` configurable. `set_keymap` lo cambia en caliente y devuelve el `GrabKeys` a reenviar. - **`mirada-link`** — `Link` sobre socket Unix; hilo lector de fondo + canal `mpsc` para sondeo no bloqueante. `BrainLink`/`BodyLink`, `connected_pair` (socketpair), `connect`/`listen` por ruta. - **`mirada-body`** — `BodyState`: salidas + superficies; `apply` traduce `BrainCommand`→`BodyOp` (idempotente), los mutadores del backend devuelven los `BodyEvent` a mandar. Ejemplo `headless`: un Cuerpo sin gráficos guiado por stdin para ejercitar el bucle entero. - **`mirada` (app)** — envuelve `Desktop` y lo pinta (barra de escritorios + modo + foco, lienzo teselado). Con `MIRADA_SOCKET` conecta a un Cuerpo; sin él corre en **simulación** (ventanas sintéticas, teclado de la propia ventana). Pips de escritorio y ventanas clicables. - **`mirada-ctl` (app)** — CLI de control: parsea la acción de los argumentos (`DesktopAction: FromStr`) y la manda al Cerebro por el socket de control; `windows` y `actions` para consultar. ## Atajos de teclado configurables El keymap vive **sólo en el Cerebro** (`mirada-brain::Keymap`). El Cuerpo nunca lo ve: recibe únicamente la lista de cadenas a interceptar en un `GrabKeys`, hace un `Vec::contains` ciego y devuelve la combinación pulsada como `Keybind`; es `Desktop` quien la traduce a `DesktopAction`. Esa separación —*qué* interceptar (lista barata, Cuerpo) vs. *qué significa* (el mapa, Cerebro)— hace innecesario cualquier candado o `Arc`: el mapa es monohilo y la lista se reemplaza de golpe. - **Disco** — RON de texto en `~/.config/mirada/keymap.ron`, editable a mano y versionable. La app lo crea documentado en el primer arranque; si está corrupto, avisa y usa el de por defecto sin pisar el archivo. - **Cable** — sólo viaja la lista de cadenas (`GrabKeys`), vía el marco `postcard` que ya existe. No hay formato binario de configuración. - **Vocabulario** — la acción es una cadena estable (`"focus-next"`, `"layout:grid"`, `"workspace:3"`): `DesktopAction: Display + FromStr`. - **Recarga en caliente** — `Keymap::watch` (sobre `notify`) vigila el archivo; al cambiar, el dueño del `Desktop` recarga, llama a `set_keymap` y reenvía el `GrabKeys`. Sin reiniciar. - **Configurador** — no hay ejecutable aparte: el editor de texto del usuario, y la app `mirada` (que a futuro puede dibujar un editor visual sobre el mismo API `Keymap`). `cargo run -p mirada-brain --example keymap-default` imprime el archivo por defecto. ## API de acciones Toda acción de escritorio converge en un único embudo: `Desktop::apply(DesktopAction) -> Vec`. El keymap no es más que un front-end (`Keybind` → `lookup` → `apply`); hay otros tres: - **`DesktopAction::FocusWindow(WindowId)`** — direccionamiento directo de una ventana (no sólo ciclar con `FocusNext`/`Prev`); si está en otro escritorio, salta a él. Lo usan la taskbar y `mirada-ctl`. - **Layout y área maestra por el API** — los 7 modos se intercambian (`SetLayout`/`CycleLayout`, `mirada-ctl layout spiral`); el área maestra se redimensiona (`grow`/`shrink-master`, `Super+l`/`Super+h`); `inc`/`dec-master` cambian `nmaster` (`Super+,`/`Super+.`); y `promote-to-master` lleva la enfocada al puesto maestro (`Super+Return` — `combo_string` ya canoniza teclas con nombre: `Return`, `Tab`, `F5`…). - **HUD interactivo** (app `mirada`) — los pips de escritorio y las ventanas del lienzo son clicables: clic = `apply` de la acción. - **`mirada-ctl`** — control externo por línea de comandos (`mirada-ctl focus-next`, `workspace 3`, `windows`). Habla con el Cerebro por un socket Unix aparte; el módulo `mirada-brain::ctl` define `CtlRequest`/`CtlReply` (marco `postcard`), `CtlServer`/`CtlConn` y `send_request`. El Cerebro (la app `mirada` siempre; `mirada-compositor` sólo embebido) abre el socket y atiende en su bucle. `DesktopAction` viaja como enum serializado: contrato tipado de punta a punta. `cargo run -p mirada-brain --example headless-ctl` levanta un Cerebro sin gráficos para ejercitar `mirada-ctl` en modo desatendido. ## Dependencias - Todos los `lib` con `#![forbid(unsafe_code)]`. Cero Wayland, cero `smithay` en los seis crates de arriba. - El acoplamiento a Wayland/hardware vive sólo en `mirada-compositor`. ## Estado Implementado y verde: `mirada-layout` (30 tests), `mirada-protocol` (9), `mirada-brain` (41), `mirada-link` (7), `mirada-body` (13), las apps `mirada` y `mirada-compositor` (compilan; verificación visual manual) y `mirada-ctl` (CLI, probado vía el ejemplo `headless-ctl`). El **Cuerpo** ya existe: `mirada-compositor` es un compositor Wayland teselante real sobre `smithay`, con backend `winit` — corre **anidado** como una ventana dentro de la sesión gráfica actual. Habla `wl_compositor`/`xdg_shell`/`wl_shm`/`wl_seat`/`wl_data_device`, compone las superficies de los clientes con `GlesRenderer` y aplica la geometría del Cerebro. Reusa `mirada-body` (contabilidad) y `mirada-link` (cable). Dos modos: **autónomo** (Cerebro `Desktop` embebido, un solo proceso) o **enlazado** (`MIRADA_SOCKET` → la app `mirada` decide la geometría). Compila y pasa clippy; verificación visual manual — ver `crates/apps/mirada-compositor/README.md`. **Pendiente** — refinamientos del Cuerpo, no verificables en modo desatendido: | capa pendiente | rol | | -------------------- | -------------------------------------------------------- | | backend DRM/libinput | de `winit` anidado a sesión nativa: superficies KMS, GPU | | `mirada-input` | puntero/ratón completo, repetición de teclas, gestos | | `mirada-sandbox` | aislamiento de clientes sobre `arje-incarnate` | CRIU (congelar/restaurar ventanas) queda anotado como futuro.