⎇ be61ddb6eb441193c4374a243fbb00aed47b42de
crates/modules/mirada/mirada-brain/examples/headless-ctl.rs
Ñawpa willay
Pi imata llamkarqan
ch'uya
feat(mirada): pantalla completa real — toggle-fullscreen
1//! Un Cerebro *headless* para probar el API de control sin gráficos.
2//!
3//! Abre el socket de `mirada-ctl`, arranca un [`Desktop`] con una pantalla
4//! y unas ventanas de muestra, y atiende peticiones en bucle, imprimiendo
5//! el estado tras cada una. Útil para ejercitar `mirada-ctl` en modo
6//! desatendido.
7//!
8//! ```sh
9//! cargo run -p mirada-brain --example headless-ctl # terminal 1
10//! mirada-ctl windows # terminal 2
11//! mirada-ctl focus-next
12//! mirada-ctl focus-window 2
13//! ```
14
15use std::thread;
16use std::time::Duration;
17
18use mirada_brain::ctl::{self, CtlReply, CtlRequest, CtlServer};
19use mirada_brain::{BodyEvent, BrainCommand, Desktop};
20
21fn main() {
22 let path = ctl::default_socket_path();
23 let server = match CtlServer::bind(&path) {
24 Ok(s) => s,
25 Err(e) => {
26 eprintln!("Cerebro headless · no pude abrir el control: {e}");
27 std::process::exit(1);
28 }
29 };
30 eprintln!("Cerebro headless · control en {}", path.display());
31
32 // Una pantalla y tres ventanas de muestra.
33 let mut desktop = Desktop::new();
34 desktop.on_event(BodyEvent::OutputAdded { id: 0, width: 1920, height: 1080 });
35 for id in 1..=3 {
36 desktop.on_event(BodyEvent::WindowOpened {
37 id,
38 app_id: format!("org.brahman.app{id}"),
39 title: format!("ventana {id}"),
40 });
41 }
42 print_state(&desktop);
43 eprintln!(" esperando a mirada-ctl …");
44
45 loop {
46 if let Some(mut conn) = server.poll() {
47 if let Ok(Some(req)) = conn.read_request() {
48 let reply = match req {
49 CtlRequest::Do(action) => {
50 eprintln!("· {action}");
51 for cmd in desktop.apply(action) {
52 match cmd {
53 // La geometría que el Cerebro mandaría al Cuerpo.
54 BrainCommand::Place(places) => {
55 for p in places {
56 eprintln!(
57 " win {} → {:>5}×{:<4} @ ({:>5},{:>4}){}{}",
58 p.id,
59 p.rect.w,
60 p.rect.h,
61 p.rect.x,
62 p.rect.y,
63 if p.fullscreen {
64 " ~pantalla"
65 } else if p.floating {
66 " ~flotante"
67 } else {
68 ""
69 },
70 if p.focused { " *" } else { "" },
71 );
72 }
73 }
74 // Sin Cuerpo: simulamos nosotros el cierre.
75 BrainCommand::Close(id) | BrainCommand::Kill(id) => {
76 desktop.on_event(BodyEvent::WindowClosed { id });
77 }
78 _ => {}
79 }
80 }
81 print_state(&desktop);
82 CtlReply::Ok
83 }
84 CtlRequest::ListWindows => CtlReply::Windows(desktop.window_lines()),
85 };
86 let _ = conn.reply(&reply);
87 }
88 }
89 thread::sleep(Duration::from_millis(16));
90 }
91}
92
93fn print_state(d: &Desktop) {
94 let ws = d.active_workspace();
95 eprintln!(
96 " escritorio {} · {:?} (maestra {:.0}%) · foco {:?}",
97 d.active_index() + 1,
98 ws.params().mode,
99 ws.params().master_ratio * 100.0,
100 d.focused_window(),
101 );
102}