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)]
305pub 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
360pub 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}