Files
brahman/crates/modules/mirada/SDD.md
T
sergio 4719f7c9f9 feat(mirada): ventanas flotantes — toggle-float
Una ventana puede salir del teselado y flotar: conserva su propio
rectángulo y se compone por encima de las teseladas.

- Workspace guarda las flotantes en un mapa aparte; layout() tesela
  sólo las no-flotantes y añade las flotantes al final (orden de
  pintado). set_floating / is_floating.
- WindowPlacement y BodyOp::Configure llevan floating: bool. BodyState
  detecta el cambio de floating como cualquier otro reconfigure.
- DesktopAction::ToggleFloat (Super+f): saca la enfocada a un
  rectángulo centrado al 60 % de la pantalla, o la devuelve al teselado.
  En Monocle, una flotante sigue visible.
- mirada-compositor ordena las flotantes al frente de la lista
  front-to-back de elementos → se pintan encima.
- HUD de mirada marca las flotantes; mirada-ctl toggle-float.

Verificado end-to-end con headless-ctl. mirada-layout 30->32,
mirada-protocol 9->10, mirada-body 13->14, mirada-brain 41->42.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 00:55:33 +00:00

9.6 KiB

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

  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-layoutRect + 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-protocolWindowPlacement, 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-brainDesktop: salidas, 9 escritorios virtuales, registro de ventanas. on_event(BodyEvent) -> Vec<BrainCommand>; DesktopAction + Keymap configurable. set_keymap lo cambia en caliente y devuelve el GrabKeys a reenviar.
  • mirada-linkLink<Out,In> sobre socket Unix; hilo lector de fondo + canal mpsc para sondeo no bloqueante. BrainLink/BodyLink, connected_pair (socketpair), connect/listen por ruta.
  • mirada-bodyBodyState: salidas + superficies; apply traduce BrainCommandBodyOp (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 calienteKeymap::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<BrainCommand>. El keymap no es más que un front-end (Keybindlookupapply); 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.
  • Ventanas flotantesToggleFloat (Super+f) saca la enfocada del teselado a un rectángulo libre (centrado, 60 %); Workspace guarda las flotantes aparte, layout() las pone al final y WindowPlacement /BodyOp::Configure llevan floating: bool para que el Cuerpo las componga por encima.
  • 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+Returncombo_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 (32 tests), mirada-protocol (10), mirada-brain (42), mirada-link (7), mirada-body (14), 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.