feat(mirada): xdg-decoration — ventanas sin marco en el compositor
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 <noreply@anthropic.com>
This commit is contained in:
@@ -116,9 +116,11 @@ En modo enlazado el socket de control lo abre el Cerebro (la app
|
|||||||
## Qué implementa
|
## Qué implementa
|
||||||
|
|
||||||
`wl_compositor`, `xdg_shell` (toplevels y popups), `wl_shm`, `wl_seat`
|
`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`
|
(teclado, y ratón en el backend DRM), `wl_output`, `wl_data_device`
|
||||||
(selección). Composición con `GlesRenderer` — en `winit` sobre la
|
(selección) y `xdg-decoration` — fuerza decoración del servidor y no
|
||||||
ventana, en `drm` con un `DrmCompositor` por salida.
|
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
|
Reusa `mirada-body` para la contabilidad de salidas y superficies, y
|
||||||
`mirada-link` para el cable hacia un Cerebro externo. Toda la lógica
|
`mirada-link` para el cable hacia un Cerebro externo. Toda la lógica
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ use smithay::backend::winit::{self, WinitEvent};
|
|||||||
use smithay::input::keyboard::{xkb, FilterResult, KeyboardHandle, Keysym, ModifiersState};
|
use smithay::input::keyboard::{xkb, FilterResult, KeyboardHandle, Keysym, ModifiersState};
|
||||||
use smithay::input::pointer::PointerHandle;
|
use smithay::input::pointer::PointerHandle;
|
||||||
use smithay::input::{Seat, SeatHandler, SeatState};
|
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_protocols::xdg::shell::server::xdg_toplevel;
|
||||||
use smithay::reexports::wayland_server::backend::{ClientData, ClientId, DisconnectReason};
|
use smithay::reexports::wayland_server::backend::{ClientData, ClientId, DisconnectReason};
|
||||||
use smithay::reexports::wayland_server::protocol::wl_buffer;
|
use smithay::reexports::wayland_server::protocol::wl_buffer;
|
||||||
@@ -53,6 +54,7 @@ use smithay::wayland::selection::data_device::{
|
|||||||
ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler,
|
ClientDndGrabHandler, DataDeviceHandler, DataDeviceState, ServerDndGrabHandler,
|
||||||
};
|
};
|
||||||
use smithay::wayland::selection::SelectionHandler;
|
use smithay::wayland::selection::SelectionHandler;
|
||||||
|
use smithay::wayland::shell::xdg::decoration::{XdgDecorationHandler, XdgDecorationState};
|
||||||
use smithay::wayland::shell::xdg::{
|
use smithay::wayland::shell::xdg::{
|
||||||
PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState,
|
PopupSurface, PositionerState, ToplevelSurface, XdgShellHandler, XdgShellState,
|
||||||
XdgToplevelSurfaceData,
|
XdgToplevelSurfaceData,
|
||||||
@@ -61,7 +63,7 @@ use smithay::wayland::output::OutputHandler;
|
|||||||
use smithay::wayland::shm::{ShmHandler, ShmState};
|
use smithay::wayland::shm::{ShmHandler, ShmState};
|
||||||
use smithay::{
|
use smithay::{
|
||||||
delegate_compositor, delegate_data_device, delegate_output, delegate_seat, delegate_shm,
|
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};
|
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 {
|
impl SelectionHandler for App {
|
||||||
type SelectionUserData = ();
|
type SelectionUserData = ();
|
||||||
}
|
}
|
||||||
@@ -430,6 +454,7 @@ impl OutputHandler for App {}
|
|||||||
|
|
||||||
delegate_compositor!(App);
|
delegate_compositor!(App);
|
||||||
delegate_xdg_shell!(App);
|
delegate_xdg_shell!(App);
|
||||||
|
delegate_xdg_decoration!(App);
|
||||||
delegate_shm!(App);
|
delegate_shm!(App);
|
||||||
delegate_seat!(App);
|
delegate_seat!(App);
|
||||||
delegate_data_device!(App);
|
delegate_data_device!(App);
|
||||||
@@ -609,6 +634,11 @@ fn build_app() -> Result<Setup, Box<dyn std::error::Error>> {
|
|||||||
let mut seat_state = SeatState::new();
|
let mut seat_state = SeatState::new();
|
||||||
let seat = seat_state.new_wl_seat(&dh, "mirada");
|
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::<App>(&dh);
|
||||||
|
|
||||||
// El keymap del usuario (`~/.config/mirada/keymap.ron`). Sólo lo usa
|
// El keymap del usuario (`~/.config/mirada/keymap.ron`). Sólo lo usa
|
||||||
// el Cerebro embebido; con un Cerebro enlazado, el keymap es asunto suyo.
|
// el Cerebro embebido; con un Cerebro enlazado, el keymap es asunto suyo.
|
||||||
let keymap_path = Keymap::default_path();
|
let keymap_path = Keymap::default_path();
|
||||||
|
|||||||
@@ -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
|
El **Cuerpo** ya existe: `mirada-compositor` es un compositor Wayland
|
||||||
teselante real sobre `smithay`. Habla `wl_compositor`/`xdg_shell`/
|
teselante real sobre `smithay`. Habla `wl_compositor`/`xdg_shell`/
|
||||||
`wl_shm`/`wl_seat`/`wl_output`/`wl_data_device`, compone las superficies
|
`wl_shm`/`wl_seat`/`wl_output`/`wl_data_device`/`xdg-decoration`, compone
|
||||||
de los clientes con `GlesRenderer` y aplica la geometría del Cerebro.
|
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
|
Reusa `mirada-body` (contabilidad) y `mirada-link` (cable). Dos modos de
|
||||||
Cerebro: **autónomo** (`Desktop` embebido) o **enlazado** (`MIRADA_SOCKET`
|
Cerebro: **autónomo** (`Desktop` embebido) o **enlazado** (`MIRADA_SOCKET`
|
||||||
→ la app `mirada`).
|
→ la app `mirada`).
|
||||||
|
|||||||
Reference in New Issue
Block a user