From ae813998570147f347deadd5b58b8bce64d2102e Mon Sep 17 00:00:00 2001 From: sergio Date: Thu, 21 May 2026 03:37:56 +0000 Subject: [PATCH] =?UTF-8?q?feat(mirada):=20xdg-decoration=20=E2=80=94=20ve?= =?UTF-8?q?ntanas=20sin=20marco=20en=20el=20compositor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Un escritorio teselante no quiere barras de título de cliente. El compositor anuncia ahora `xdg-decoration` y a todo toplevel le impone `Mode::ServerSide`; como el servidor no dibuja decoración alguna, las ventanas quedan sin marco. Sin esto, clientes como `foot` se dibujan su propia barra (CSD) con botones de minimizar/maximizar/cerrar — ruido en un WM teselante. - `XdgDecorationHandler` para `App`: `new_decoration`, `request_mode` y `unset_mode` fijan siempre `ServerSide` y reenvían el configure. - `delegate_xdg_decoration!(App)`; el global se anuncia en `build_app`. Co-Authored-By: Claude Opus 4.7 --- crates/apps/mirada-compositor/README.md | 8 +++--- crates/apps/mirada-compositor/src/main.rs | 32 ++++++++++++++++++++++- crates/modules/mirada/SDD.md | 6 +++-- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/crates/apps/mirada-compositor/README.md b/crates/apps/mirada-compositor/README.md index 90d9d08..5fe07c0 100644 --- a/crates/apps/mirada-compositor/README.md +++ b/crates/apps/mirada-compositor/README.md @@ -116,9 +116,11 @@ En modo enlazado el socket de control lo abre el Cerebro (la app ## Qué implementa `wl_compositor`, `xdg_shell` (toplevels y popups), `wl_shm`, `wl_seat` -(teclado, y ratón en el backend DRM), `wl_output` y `wl_data_device` -(selección). Composición con `GlesRenderer` — en `winit` sobre la -ventana, en `drm` con un `DrmCompositor` por salida. +(teclado, y ratón en el backend DRM), `wl_output`, `wl_data_device` +(selección) y `xdg-decoration` — fuerza decoración del servidor y no +dibuja ninguna, así las ventanas van sin barra de título. Composición +con `GlesRenderer` — en `winit` sobre la ventana, en `drm` con un +`DrmCompositor` por salida. Reusa `mirada-body` para la contabilidad de salidas y superficies, y `mirada-link` para el cable hacia un Cerebro externo. Toda la lógica diff --git a/crates/apps/mirada-compositor/src/main.rs b/crates/apps/mirada-compositor/src/main.rs index d8d1100..2d55b7e 100644 --- a/crates/apps/mirada-compositor/src/main.rs +++ b/crates/apps/mirada-compositor/src/main.rs @@ -34,6 +34,7 @@ use smithay::backend::winit::{self, WinitEvent}; use smithay::input::keyboard::{xkb, FilterResult, KeyboardHandle, Keysym, ModifiersState}; use smithay::input::pointer::PointerHandle; use smithay::input::{Seat, SeatHandler, SeatState}; +use smithay::reexports::wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode as DecorationMode; use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel; use smithay::reexports::wayland_server::backend::{ClientData, ClientId, DisconnectReason}; use smithay::reexports::wayland_server::protocol::wl_buffer; @@ -53,6 +54,7 @@ use smithay::wayland::selection::data_device::{ ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler, }; use smithay::wayland::selection::SelectionHandler; +use smithay::wayland::shell::xdg::decoration::{XdgDecorationHandler, XdgDecorationState}; use smithay::wayland::shell::xdg::{ PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState, XdgToplevelSurfaceData, @@ -61,7 +63,7 @@ use smithay::wayland::output::OutputHandler; use smithay::wayland::shm::{ShmHandler, ShmState}; use smithay::{ delegate_compositor, delegate_data_device, delegate_output, delegate_seat, delegate_shm, - delegate_xdg_shell, + delegate_xdg_decoration, delegate_xdg_shell, }; use mirada_body::{BodyOp, BodyState}; @@ -392,6 +394,28 @@ impl XdgShellHandler for App { } } +/// Decoración de ventana: carmen tesela, así que las ventanas no llevan +/// barra de título. Le decimos a todo cliente que la decoración la pone +/// el servidor (`ServerSide`) — y como el servidor no dibuja ninguna, la +/// ventana queda sin marco. Sin esto, clientes como `foot` se dibujan su +/// propia barra (CSD), que estorba en un escritorio teselante. +impl XdgDecorationHandler for App { + fn new_decoration(&mut self, toplevel: ToplevelSurface) { + toplevel.with_pending_state(|s| s.decoration_mode = Some(DecorationMode::ServerSide)); + toplevel.send_configure(); + } + + fn request_mode(&mut self, toplevel: ToplevelSurface, _mode: DecorationMode) { + toplevel.with_pending_state(|s| s.decoration_mode = Some(DecorationMode::ServerSide)); + toplevel.send_configure(); + } + + fn unset_mode(&mut self, toplevel: ToplevelSurface) { + toplevel.with_pending_state(|s| s.decoration_mode = Some(DecorationMode::ServerSide)); + toplevel.send_configure(); + } +} + impl SelectionHandler for App { type SelectionUserData = (); } @@ -430,6 +454,7 @@ impl OutputHandler for App {} delegate_compositor!(App); delegate_xdg_shell!(App); +delegate_xdg_decoration!(App); delegate_shm!(App); delegate_seat!(App); delegate_data_device!(App); @@ -609,6 +634,11 @@ fn build_app() -> Result> { let mut seat_state = SeatState::new(); let seat = seat_state.new_wl_seat(&dh, "mirada"); + // Anuncia el gestor de decoración: las ventanas van sin marco (ver + // `XdgDecorationHandler`). El `XdgDecorationState` sólo serviría para + // retirar el global más tarde, cosa que nunca hacemos. + let _ = XdgDecorationState::new::(&dh); + // El keymap del usuario (`~/.config/mirada/keymap.ron`). Sólo lo usa // el Cerebro embebido; con un Cerebro enlazado, el keymap es asunto suyo. let keymap_path = Keymap::default_path(); diff --git a/crates/modules/mirada/SDD.md b/crates/modules/mirada/SDD.md index 5180be1..916eed3 100644 --- a/crates/modules/mirada/SDD.md +++ b/crates/modules/mirada/SDD.md @@ -184,8 +184,10 @@ 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`. Habla `wl_compositor`/`xdg_shell`/ -`wl_shm`/`wl_seat`/`wl_output`/`wl_data_device`, compone las superficies -de los clientes con `GlesRenderer` y aplica la geometría del Cerebro. +`wl_shm`/`wl_seat`/`wl_output`/`wl_data_device`/`xdg-decoration`, compone +las superficies de los clientes con `GlesRenderer` y aplica la geometría +del Cerebro. Fuerza decoración `ServerSide` y no dibuja ninguna: las +ventanas teseladas van sin marco (nada de barras de título de cliente). Reusa `mirada-body` (contabilidad) y `mirada-link` (cable). Dos modos de Cerebro: **autónomo** (`Desktop` embebido) o **enlazado** (`MIRADA_SOCKET` → la app `mirada`).