feat(mirada): pantalla completa real — toggle-fullscreen

ToggleFullscreen (Super+Shift+f) lleva la ventana enfocada a pantalla
completa: cubre toda la salida sin gap, oculta al resto y se lleva el
foco. Distinto del modo Monocle (un modo de teselado): es un estado
por ventana que ignora el layout.

- Workspace.fullscreen: Option<WindowId>; set_fullscreen / fullscreen();
  remove() lo limpia si se cierra esa ventana.
- placements() da a la fullscreen el rect completo y marca al resto
  visible: false. WindowPlacement y BodyOp::Configure llevan
  fullscreen: bool.
- mirada-compositor fija el estado xdg_toplevel::Fullscreen en la
  superficie, para que el cliente lo sepa.
- Cableado en keymap, HUD de mirada y mirada-ctl.

Verificado end-to-end con headless-ctl. mirada-protocol 10->11,
mirada-brain 51->52.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
sergio
2026-05-21 01:07:01 +00:00
parent 6dfd9e62ac
commit be61ddb6eb
12 changed files with 133 additions and 11 deletions
@@ -218,6 +218,18 @@ impl Desktop {
}
self.relayout()
}
DesktopAction::ToggleFullscreen => {
let Some(id) = self.workspaces[self.active].focused() else {
return Vec::new();
};
let ws = &mut self.workspaces[self.active];
if ws.fullscreen() == Some(id) {
ws.set_fullscreen(None);
} else {
ws.set_fullscreen(Some(id));
}
self.relayout()
}
DesktopAction::CycleLayout => {
let next = self.workspaces[self.active].params().mode.next();
self.workspaces[self.active].set_mode(next);
@@ -475,6 +487,23 @@ mod tests {
assert!(!places(&cmds).iter().find(|x| x.id == 2).unwrap().floating);
}
#[test]
fn toggle_fullscreen_covers_the_screen_and_hides_the_rest() {
let mut d = desktop_with_screen();
for id in [1, 2, 3] {
open(&mut d, id);
}
let cmds = d.apply(DesktopAction::ToggleFullscreen); // sobre la 3
let p = places(&cmds);
let fs = p.iter().find(|x| x.id == 3).unwrap();
assert!(fs.fullscreen && fs.visible);
assert_eq!(fs.rect, d.screen().unwrap());
assert!(p.iter().filter(|x| x.id != 3).all(|x| !x.visible));
// Alternar de nuevo restaura el teselado: las tres visibles.
let cmds = d.apply(DesktopAction::ToggleFullscreen);
assert_eq!(places(&cmds).iter().filter(|x| x.visible).count(), 3);
}
#[test]
fn a_rule_sends_a_new_window_to_its_workspace() {
let mut d = desktop_with_screen();