feat(mirada): fullscreen iniciado por el cliente + HUD multi-salida

Dos remates de la tanda WM.

Fullscreen del cliente:
- BodyEvent::FullscreenRequest { id, fullscreen }. mirada-compositor
  implementa XdgShellHandler::fullscreen_request / unfullscreen_request
  y avisa al Cerebro; Desktop::on_event fija el fullscreen en el
  escritorio que tiene la ventana. Así un reproductor o un juego que
  llama a xdg set_fullscreen entra a pantalla completa solo.

HUD multi-salida (app mirada):
- El lienzo dibuja todas las salidas a escala (encaja su caja
  envolvente en el lienzo fijo; con una salida, 1:1), cada una con su
  marco y su número/escritorio. En simulación, Shift+n añade un monitor.

mirada-brain 63->65 tests.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
sergio
2026-05-21 01:32:08 +00:00
parent 13d2ae71fb
commit f9c4bf594e
6 changed files with 143 additions and 9 deletions
@@ -188,6 +188,27 @@ impl Desktop {
Some(action) => self.apply(action),
None => Vec::new(),
},
BodyEvent::FullscreenRequest { id, fullscreen } => {
// El cliente (un reproductor, un juego) pidió pantalla
// completa: la fijamos en el escritorio que tiene la ventana.
let mut changed = false;
for ws in &mut self.workspaces {
if ws.windows().contains(&id) {
if fullscreen {
ws.set_fullscreen(Some(id));
} else if ws.fullscreen() == Some(id) {
ws.set_fullscreen(None);
}
changed = true;
break;
}
}
if changed {
self.relayout()
} else {
Vec::new()
}
}
}
}
@@ -985,6 +1006,27 @@ mod tests {
assert!(d.apply(DesktopAction::ToggleScratchpad).is_empty());
}
#[test]
fn a_client_fullscreen_request_is_honoured() {
let mut d = desktop_with_screen();
open(&mut d, 1);
open(&mut d, 2);
let cmds = d.on_event(BodyEvent::FullscreenRequest { id: 1, fullscreen: true });
assert!(places(&cmds).iter().find(|x| x.id == 1).unwrap().fullscreen);
// El cliente la suelta.
let cmds = d.on_event(BodyEvent::FullscreenRequest { id: 1, fullscreen: false });
assert!(!places(&cmds).iter().find(|x| x.id == 1).unwrap().fullscreen);
}
#[test]
fn a_fullscreen_request_for_an_unknown_window_does_nothing() {
let mut d = desktop_with_screen();
open(&mut d, 1);
assert!(d
.on_event(BodyEvent::FullscreenRequest { id: 99, fullscreen: true })
.is_empty());
}
#[test]
fn window_lines_show_a_stashed_window_as_workspace_zero() {
let mut d = desktop_with_screen();