⎇ b31f98883379a172efd309cd2cec98d16eb591db
crates/modules/mirada/mirada-brain/examples/headless-ctl.rs
Historia
Quién tocó qué
crudo
feat(mirada): API de acciones — mirada-ctl + HUD interactivo
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 println!("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 println!(" 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 let cmds = desktop.apply(action);
51 // Sin Cuerpo: simulamos nosotros el cierre.
52 for cmd in cmds {
53 if let BrainCommand::Close(id) | BrainCommand::Kill(id) = cmd {
54 desktop.on_event(BodyEvent::WindowClosed { id });
55 }
56 }
57 println!("· {action}");
58 print_state(&desktop);
59 CtlReply::Ok
60 }
61 CtlRequest::ListWindows => CtlReply::Windows(desktop.window_lines()),
62 };
63 let _ = conn.reply(&reply);
64 }
65 }
66 thread::sleep(Duration::from_millis(16));
67 }
68}
69
70fn print_state(d: &Desktop) {
71 println!(
72 " escritorio {} · foco {:?} · ventanas/escritorio {:?}",
73 d.active_index() + 1,
74 d.focused_window(),
75 d.workspace_loads(),
76 );
77}