output_watcher/
output_watcher.rs1use 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}