i3status_rs/blocks/
scratchpad.rs1use swayipc_async::{Connection, Event as SwayEvent, EventType, Node, WindowChange};
25
26use super::prelude::*;
27
28#[derive(Deserialize, Debug, SmartDefault)]
29#[serde(deny_unknown_fields, default)]
30pub struct Config {
31 pub format: FormatConfig,
32}
33
34fn count_scratchpad_windows(node: &Node) -> usize {
35 node.find_as_ref(|n| n.name.as_deref() == Some("__i3_scratch"))
36 .map_or(0, |node| node.floating_nodes.len())
37}
38
39pub async fn run(config: &Config, api: &CommonApi) -> Result<()> {
40 let format = config
41 .format
42 .with_default(" $icon $count.eng(range:1..) |")?;
43
44 let connection_for_events = Connection::new()
45 .await
46 .error("failed to open connection with swayipc")?;
47
48 let mut connection_for_tree = Connection::new()
49 .await
50 .error("failed to open connection with swayipc")?;
51
52 let mut events = connection_for_events
53 .subscribe(&[EventType::Window])
54 .await
55 .error("could not subscribe to window events")?;
56
57 loop {
58 let mut widget = Widget::new().with_format(format.clone());
59
60 let root_node = connection_for_tree
61 .get_tree()
62 .await
63 .error("could not get windows tree")?;
64 let count = count_scratchpad_windows(&root_node);
65
66 widget.set_values(map! {
67 "icon" => Value::icon("scratchpad"),
68 "count" => Value::number(count),
69 });
70
71 api.set_widget(widget)?;
72
73 loop {
74 let event = events
75 .next()
76 .await
77 .error("swayipc channel closed")?
78 .error("bad event")?;
79
80 match event {
81 SwayEvent::Window(e) if e.change == WindowChange::Move => break,
82 _ => continue,
83 }
84 }
85 }
86}