Skip to main content

output_watcher/
output_watcher.rs

1use std::ffi::CString;
2
3use wayrs_client::global::GlobalExt;
4use wayrs_client::protocol::wl_output::{self, WlOutput};
5use wayrs_client::protocol::wl_registry::{self, GlobalArgs};
6use wayrs_client::{Connection, EventCtx, IoMode};
7
8fn main() {
9    let mut conn = Connection::connect().unwrap();
10    let mut state = State::default();
11
12    conn.add_registry_cb(wl_registry_cb);
13
14    loop {
15        conn.flush(IoMode::Blocking).unwrap();
16        conn.recv_events(IoMode::Blocking).unwrap();
17        conn.dispatch_events(&mut state);
18    }
19}
20
21#[derive(Default)]
22struct State {
23    outputs: Vec<Output>,
24}
25
26#[derive(Debug)]
27struct Output {
28    registry_name: u32,
29    wl_output: WlOutput,
30    name: Option<CString>,
31    desc: Option<CString>,
32    scale: Option<i32>,
33    mode: Option<String>,
34}
35
36impl Output {
37    fn bind(conn: &mut Connection<State>, global: &GlobalArgs) -> Self {
38        Self {
39            registry_name: global.name,
40            wl_output: global.bind_with_cb(conn, 3..=4, wl_output_cb).unwrap(),
41            name: None,
42            desc: None,
43            scale: None,
44            mode: None,
45        }
46    }
47}
48
49fn wl_registry_cb(conn: &mut Connection<State>, state: &mut State, event: &wl_registry::Event) {
50    match event {
51        wl_registry::Event::Global(global) if global.is::<WlOutput>() => {
52            state.outputs.push(Output::bind(conn, global));
53        }
54        wl_registry::Event::GlobalRemove(name) => {
55            if let Some(i) = state.outputs.iter().position(|o| o.registry_name == *name) {
56                let output = state.outputs.swap_remove(i);
57                eprintln!("removed output: {}", output.name.unwrap().to_str().unwrap());
58                output.wl_output.release(conn);
59            }
60        }
61        _ => (),
62    }
63}
64
65fn wl_output_cb(ctx: EventCtx<State, WlOutput>) {
66    let output = &mut ctx
67        .state
68        .outputs
69        .iter_mut()
70        .find(|o| o.wl_output == ctx.proxy)
71        .unwrap();
72    match ctx.event {
73        wl_output::Event::Geometry(_) => (),
74        wl_output::Event::Mode(mode) => {
75            output.mode = Some(format!(
76                "{}x{} @ {}Hz",
77                mode.width,
78                mode.height,
79                mode.refresh as f64 * 1e-3
80            ))
81        }
82        wl_output::Event::Done => {
83            dbg!(output);
84        }
85        wl_output::Event::Scale(scale) => output.scale = Some(scale),
86        wl_output::Event::Name(name) => output.name = Some(name),
87        wl_output::Event::Description(desc) => output.desc = Some(desc),
88        _ => (),
89    }
90}