bspc_rs/
events.rs

1use std::collections::HashMap;
2use std::io::BufRead;
3use std::io::BufReader;
4use std::os::unix::net::UnixStream;
5use std::string::ToString;
6use strum_macros::Display;
7
8use crate::errors::ReplyError;
9use crate::properties::*;
10use crate::socket::{self, BspcCommunication};
11use crate::Id;
12
13#[derive(Display, Debug)]
14#[strum(serialize_all = "snake_case")]
15pub enum Subscription {
16    All,
17    Report,
18    Monitor,
19    Desktop,
20    Node,
21    MonitorAdd,
22    MonitorRename,
23    MonitorSwap,
24    MonitorFocus,
25    MonitorGeometry,
26    DesktopAdd,
27    DesktopRename,
28    DesktopRemove,
29    DesktopSwap,
30    DesktopTransfer,
31    DesktopFocus,
32    DesktopActivate,
33    DesktopLayout,
34    NodeAdd,
35    NodeRemove,
36    NodeSwap,
37    NodeTransfer,
38    NodeFocus,
39    NodeActivate,
40    NodePresel,
41    NodeStack,
42    NodeGeometry,
43    NodeState,
44    NodeFlag,
45    NodeLayer,
46    PointerAction,
47}
48
49#[derive(Debug)]
50pub struct MonitorAddInfo {
51    pub monitor_id: Id,
52    pub monitor_name: String,
53    pub monitor_geometry: Rectangle,
54}
55
56#[derive(Debug)]
57pub struct MonitorRenameInfo {
58    pub monitor_id: Id,
59    pub old_name: String,
60    pub new_name: String,
61}
62
63#[derive(Debug)]
64pub struct MonitorRemoveInfo {
65    pub monitor_id: Id,
66}
67
68#[derive(Debug)]
69pub struct MonitorSwapInfo {
70    pub src_monitor_id: Id,
71    pub dst_monitor_id: Id,
72}
73
74#[derive(Debug)]
75pub struct MonitorFocusInfo {
76    pub monitor_id: Id,
77}
78
79#[derive(Debug)]
80pub struct MonitorGeometryInfo {
81    pub monitor_id: Id,
82    pub monitor_geometry: Rectangle,
83}
84
85#[derive(Debug)]
86pub enum MonitorEvent {
87    MonitorAdd(MonitorAddInfo),
88    MonitorRename(MonitorRenameInfo),
89    MonitorRemove(MonitorRemoveInfo),
90    MonitorSwap(MonitorSwapInfo),
91    MonitorFocus(MonitorFocusInfo),
92    MonitorGeometry(MonitorGeometryInfo),
93}
94
95#[derive(Debug)]
96pub struct DesktopAddInfo {
97    pub monitor_id: Id,
98    pub desktop_id: Id,
99    pub desktop_name: String,
100}
101
102#[derive(Debug)]
103pub struct DesktopRenameInfo {
104    pub monitor_id: Id,
105    pub desktop_id: Id,
106    pub old_name: String,
107    pub new_name: String,
108}
109
110#[derive(Debug)]
111pub struct DesktopRemoveInfo {
112    pub monitor_id: Id,
113    pub desktop_id: Id,
114}
115
116#[derive(Debug)]
117pub struct DesktopSwapInfo {
118    pub src_monitor_id: Id,
119    pub src_desktop_id: Id,
120    pub dst_monitor_id: Id,
121    pub dst_desktop_id: Id,
122}
123
124#[derive(Debug)]
125pub struct DesktopTransferInfo {
126    pub src_monitor_id: Id,
127    pub src_desktop_id: Id,
128    pub dst_monitor_id: Id,
129}
130
131#[derive(Debug)]
132pub struct DesktopFocusInfo {
133    pub monitor_id: Id,
134    pub desktop_id: Id,
135}
136
137#[derive(Debug)]
138pub struct DesktopActivateInfo {
139    pub monitor_id: Id,
140    pub desktop_id: Id,
141}
142
143#[derive(Debug)]
144pub struct DesktopLayoutInfo {
145    pub monitor_id: Id,
146    pub desktop_id: Id,
147    pub layout: Layout,
148}
149
150#[derive(Debug)]
151pub enum DesktopEvent {
152    DesktopAdd(DesktopAddInfo),
153    DesktopRename(DesktopRenameInfo),
154    DesktopRemove(DesktopRemoveInfo),
155    DesktopSwap(DesktopSwapInfo),
156    DesktopTransfer(DesktopTransferInfo),
157    DesktopFocus(DesktopFocusInfo),
158    DesktopActivate(DesktopActivateInfo),
159    DesktopLayout(DesktopLayoutInfo),
160}
161
162#[derive(Debug)]
163pub struct NodeAddInfo {
164    pub monitor_id: Id,
165    pub desktop_id: Id,
166    pub ip_id: Id,
167    pub node_id: Id,
168}
169
170#[derive(Debug)]
171pub struct NodeRemoveInfo {
172    pub monitor_id: Id,
173    pub desktop_id: Id,
174    pub node_id: Id,
175}
176
177#[derive(Debug)]
178pub struct NodeSwapInfo {
179    pub src_monitor_id: Id,
180    pub src_desktop_id: Id,
181    pub src_node_id: Id,
182    pub dst_monitor_id: Id,
183    pub dst_desktop_id: Id,
184    pub dst_node_id: Id,
185}
186
187#[derive(Debug)]
188pub struct NodeTransferInfo {
189    pub src_monitor_id: Id,
190    pub src_desktop_id: Id,
191    pub src_node_id: Id,
192    pub dst_monitor_id: Id,
193    pub dst_desktop_id: Id,
194    pub dst_node_id: Id,
195}
196
197#[derive(Debug)]
198pub struct NodeFocusInfo {
199    pub monitor_id: Id,
200    pub desktop_id: Id,
201    pub node_id: Id,
202}
203
204#[derive(Debug)]
205pub struct NodeActivateInfo {
206    pub monitor_id: Id,
207    pub desktop_id: Id,
208    pub node_id: Id,
209}
210
211#[derive(Debug)]
212pub struct NodePreselInfo {
213    pub monitor_id: Id,
214    pub desktop_id: Id,
215    pub node_id: Id,
216    pub presel: Presel,
217}
218
219#[derive(Debug)]
220pub struct NodeStackInfo {
221    pub node_id_1: Id,
222    pub stack: Stack,
223    pub node_id_2: Id,
224}
225
226#[derive(Debug)]
227pub struct NodeGeometryInfo {
228    pub monitor_id: Id,
229    pub desktop_id: Id,
230    pub node_id: Id,
231    pub node_geometry: Rectangle,
232}
233
234#[derive(Debug)]
235pub struct NodeStateInfo {
236    pub monitor_id: Id,
237    pub desktop_id: Id,
238    pub node_id: Id,
239    pub state: State,
240    pub switch: Switch,
241}
242
243#[derive(Debug)]
244pub struct NodeFlagInfo {
245    pub monitor_id: Id,
246    pub desktop_id: Id,
247    pub node_id: Id,
248    pub flag: Flag,
249    pub switch: Switch,
250}
251
252#[derive(Debug)]
253pub struct NodeLayerInfo {
254    pub monitor_id: Id,
255    pub desktop_id: Id,
256    pub node_id: Id,
257    pub layer: Layer,
258}
259
260#[derive(Debug)]
261pub enum NodeEvent {
262    NodeAdd(NodeAddInfo),
263    NodeRemove(NodeRemoveInfo),
264    NodeSwap(NodeSwapInfo),
265    NodeTransfer(NodeTransferInfo),
266    NodeFocus(NodeFocusInfo),
267    NodeActivate(NodeActivateInfo),
268    NodePresel(NodePreselInfo),
269    NodeStack(NodeStackInfo),
270    NodeGeometry(NodeGeometryInfo),
271    NodeState(NodeStateInfo),
272    NodeFlag(NodeFlagInfo),
273    NodeLayer(NodeLayerInfo),
274}
275
276#[derive(Debug)]
277pub struct PointerActionInfo {
278    pub monitor_id: Id,
279    pub desktop_id: Id,
280    pub node_id: Id,
281    pub action: Action,
282    pub action_state: ActionState,
283}
284
285#[derive(Debug)]
286pub enum ReportDesktopState {
287    Free,
288    Occupied,
289    Urgent,
290}
291
292#[derive(Debug)]
293pub struct ReportDesktopInfo {
294    pub state: ReportDesktopState,
295    pub focused: bool,
296}
297
298#[derive(Debug)]
299pub struct ReportMonitorInfo {
300    pub desktops: HashMap<String, ReportDesktopInfo>,
301    pub focused: bool,
302}
303
304#[derive(Debug)]
305// TODO: implement it
306pub struct ReportInfo(HashMap<String, ReportMonitorInfo>);
307
308#[derive(Debug)]
309pub enum Event {
310    Report(ReportInfo),
311    MonitorEvent(MonitorEvent),
312    DesktopEvent(DesktopEvent),
313    NodeEvent(NodeEvent),
314    PointerAction(PointerActionInfo),
315}
316
317#[derive(Debug)]
318pub struct Subscriber {
319    stream_buf: BufReader<UnixStream>,
320}
321
322impl Subscriber {
323    pub fn events(&mut self) -> EventIterator {
324        EventIterator { subscriber: self }
325    }
326}
327
328impl<'a> IntoIterator for &'a mut Subscriber {
329    type Item = Result<Event, ReplyError>;
330    type IntoIter = EventIterator<'a>;
331
332    fn into_iter(self) -> EventIterator<'a> {
333        self.events()
334    }
335}
336
337#[derive(Debug)]
338pub struct EventIterator<'a> {
339    subscriber: &'a mut Subscriber,
340}
341
342impl<'a> Iterator for EventIterator<'a> {
343    type Item = Result<Event, ReplyError>;
344
345    fn next(&mut self) -> Option<Self::Item> {
346        let mut reply = String::new();
347        let result = self.subscriber.stream_buf.read_line(&mut reply);
348
349        match result {
350            Ok(_) => {
351                let event = reply.parse::<Event>().map_err(From::from);
352                Some(event)
353            }
354
355            Err(e) => Some((Err(e)).map_err(From::from)),
356        }
357    }
358}
359
360/// Subscribes to the given events.
361///
362/// If `fifo_flag` is set to `true`, then returns a path to a FIFO from which
363/// events can be read and return.
364///
365/// If `count` is `Some(x)`, then it stops returning subscription events
366/// after having received `x` events.
367pub fn subscribe(
368    fifo_flag: bool,
369    count: Option<u32>,
370    subscriptions: &[Subscription],
371) -> Result<Subscriber, ReplyError> {
372    let mut conn = socket::connect()?;
373
374    let all_subscriptions = subscriptions
375        .iter()
376        .map(|x| x.to_string())
377        .collect::<Vec<_>>()
378        .join("\x00");
379
380    let mut count_option = String::new();
381    let mut fifo_option = "";
382
383    if let Some(x) = count {
384        count_option = format!("--count\x00{}\x00", x);
385    }
386
387    if fifo_flag {
388        fifo_option = "--fifo\x00";
389    }
390
391    let subscribe_message = format!(
392        "subscribe\x00{}{}{}\x00",
393        fifo_option, count_option, all_subscriptions
394    );
395
396    conn.send_message(&subscribe_message)?;
397
398    Ok(Subscriber {
399        stream_buf: BufReader::new(conn),
400    })
401}