feat(mirada): mover/redimensionar ventanas con el ratón
`Super`+arrastre interactivo en el backend DRM: botón izquierdo mueve
la ventana, botón derecho la redimensiona. Al arrastrarla, la ventana
pasa a flotar — comportamiento estilo dwm.
La verdad geométrica vive en el Cerebro, así que el arrastre viaja
hasta él:
- `mirada-protocol`: nuevo `BodyEvent::WindowFloatTo { id, rect }`.
- `mirada-brain`: `Desktop::on_event` lo atiende — busca el escritorio
de la ventana y la hace flotar en ese rectángulo
(`Workspace::set_floating`). Dos tests nuevos.
- `mirada-compositor`: `DragGrab`/`DragMode` en `App`; `handle_input`
arranca el arrastre con `Super`+botón sobre una ventana
(`keyboard.modifier_state().logo`), traga los botones mientras dura y
lo cierra al soltar. `drag_update` recalcula el rectángulo (mover =
esquina sigue al puntero; redimensionar = esquina inferior-derecha,
con un mínimo de 120 px) y emite `WindowFloatTo`. Durante el arrastre
el puntero no llega al cliente.
De paso, arregla un test de `mirada-link` que construía un
`WindowPlacement` sin los campos `floating`/`fullscreen`.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -209,6 +209,23 @@ impl Desktop {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
BodyEvent::WindowFloatTo { id, rect } => {
|
||||
// Arrastre interactivo: la ventana pasa a flotar en el
|
||||
// rectángulo dado, en el escritorio donde viva.
|
||||
let mut changed = false;
|
||||
for ws in &mut self.workspaces {
|
||||
if ws.windows().contains(&id) {
|
||||
ws.set_floating(id, Some(rect));
|
||||
changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if changed {
|
||||
self.relayout()
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -844,6 +861,32 @@ mod tests {
|
||||
assert_eq!(d.focused_window(), Some(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dragging_floats_a_window_at_the_given_rect() {
|
||||
let mut d = desktop_with_screen();
|
||||
open(&mut d, 1);
|
||||
open(&mut d, 2);
|
||||
assert!(!d.active_workspace().is_floating(2));
|
||||
let target = Rect::new(300, 200, 640, 480);
|
||||
let cmds = d.on_event(BodyEvent::WindowFloatTo { id: 2, rect: target });
|
||||
// La 2 ahora flota exactamente en el rectángulo pedido.
|
||||
assert!(d.active_workspace().is_floating(2));
|
||||
let p = places(&cmds).iter().find(|p| p.id == 2).unwrap();
|
||||
assert!(p.floating);
|
||||
assert_eq!(p.rect, target);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dragging_an_unknown_window_does_nothing() {
|
||||
let mut d = desktop_with_screen();
|
||||
open(&mut d, 1);
|
||||
let cmds = d.on_event(BodyEvent::WindowFloatTo {
|
||||
id: 99,
|
||||
rect: Rect::new(0, 0, 100, 100),
|
||||
});
|
||||
assert!(cmds.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn retitling_updates_the_registry_without_relayout() {
|
||||
let mut d = desktop_with_screen();
|
||||
|
||||
Reference in New Issue
Block a user