1use std::string::ToString;
6use strum_macros::Display;
7use strum_macros::EnumString;
8
9use crate::errors::{ParseError, ReplyError};
10use crate::selectors::{DesktopSelector, MonitorSelector, NodeSelector};
11use crate::socket::{self, BspcCommunication};
12
13#[derive(Debug, Clone, Copy, EnumString, Display)]
14#[strum(serialize_all = "snake_case")]
15pub enum Scheme {
16 LongestSide,
17 Alternate,
18 Spiral,
19}
20
21#[derive(Debug, Clone, Copy, EnumString, Display)]
22#[strum(serialize_all = "snake_case")]
23pub enum Polarity {
24 FirstChild,
25 SecondChild,
26}
27
28#[derive(Debug, Clone, Copy, EnumString, Display)]
29#[strum(serialize_all = "snake_case")]
30pub enum Tightness {
31 High,
32 Low,
33}
34
35#[derive(Debug, Clone, Copy, EnumString, Display)]
36#[strum(serialize_all = "snake_case")]
37pub enum PointerModifier {
38 Shift,
39 Control,
40 Lock,
41 Mod1,
42 Mod2,
43 Mod3,
44 Mod4,
45 Mod5,
46}
47
48#[derive(Debug, Clone, Copy, EnumString, Display)]
49#[strum(serialize_all = "snake_case")]
50pub enum PointerAction {
51 Move,
52 ResizeSide,
53 ResizeCorner,
54 Focus,
55 None,
56}
57
58#[derive(Debug, Clone, Copy, EnumString, Display)]
59#[strum(serialize_all = "snake_case")]
60pub enum ClickToFocus {
61 Button1,
62 Button2,
63 Button3,
64 Any,
65 None,
66}
67
68trait ConfigProperties {
111 fn get_config_property(
112 &mut self,
113 property: &str,
114 ) -> Result<String, ReplyError>;
115
116 fn set_config_property(
117 &mut self,
118 property: &str,
119 value: &str,
120 ) -> Result<(), ReplyError>;
121}
122
123impl<T: BspcCommunication> ConfigProperties for T {
124 fn get_config_property(
125 &mut self,
126 property: &str,
127 ) -> Result<String, ReplyError> {
128 self.send_message(&format!("config\x00{}\x00", property))?;
129 let reply = self.receive_message()?;
130
131 if reply.len() > 1 {
132 panic!("{}", format!("Something is weird, reply has more than one element, this is debug log: {:#?}", reply));
134 }
135
136 let reply = &reply[0];
137
138 Ok(reply.to_string())
139 }
140
141 fn set_config_property(
142 &mut self,
143 property: &str,
144 value: &str,
145 ) -> Result<(), ReplyError> {
146 self.send_message(&format!("config\x00{}\x00{}\x00", property, value))?;
147 let reply = self.receive_message()?;
148
149 if reply.is_empty() {
150 return Ok(());
151 }
152
153 Err(ParseError::ConversionFailed)?
154 }
155}
156
157pub fn get_normal_border_color() -> Result<String, ReplyError> {
158 let mut conn = socket::connect()?;
159
160 conn.get_config_property("normal_border_color")
161}
162
163pub fn get_active_border_color() -> Result<String, ReplyError> {
164 let mut conn = socket::connect()?;
165
166 conn.get_config_property("active_border_color")
167}
168
169pub fn get_focused_border_color() -> Result<String, ReplyError> {
170 let mut conn = socket::connect()?;
171
172 conn.get_config_property("focused_border_color")
173}
174
175pub fn get_presel_feedback_color() -> Result<String, ReplyError> {
176 let mut conn = socket::connect()?;
177
178 conn.get_config_property("presel_feedback_color")
179}
180
181pub fn get_split_ratio() -> Result<f32, ReplyError> {
182 let mut conn = socket::connect()?;
183
184 conn.get_config_property("split_ratio")?
185 .parse()
186 .map_err(From::from)
187}
188
189pub fn get_status_prefix() -> Result<String, ReplyError> {
190 let mut conn = socket::connect()?;
191
192 conn.get_config_property("status_prefix")
193}
194
195pub fn get_external_rules_command() -> Result<String, ReplyError> {
196 let mut conn = socket::connect()?;
197
198 conn.get_config_property("external_rules_command")
199}
200
201pub fn get_automatic_scheme() -> Result<Scheme, ReplyError> {
202 let mut conn = socket::connect()?;
203
204 conn.get_config_property("automatic_scheme")?
205 .parse()
206 .map_err(From::from)
207}
208
209pub fn get_initial_polarity() -> Result<Polarity, ReplyError> {
210 let mut conn = socket::connect()?;
211
212 conn.get_config_property("initial_polarity")?
213 .parse()
214 .map_err(From::from)
215}
216
217pub fn get_directional_focus_tightness() -> Result<Tightness, ReplyError> {
218 let mut conn = socket::connect()?;
219
220 conn.get_config_property("directional_focus_tightness")?
221 .parse()
222 .map_err(From::from)
223}
224
225pub fn get_removal_adjustment() -> Result<bool, ReplyError> {
226 let mut conn = socket::connect()?;
227
228 conn.get_config_property("removal_adjustment")?
229 .parse()
230 .map_err(From::from)
231}
232
233pub fn get_presel_feedback() -> Result<bool, ReplyError> {
234 let mut conn = socket::connect()?;
235
236 conn.get_config_property("presel_feedback")?
237 .parse()
238 .map_err(From::from)
239}
240
241pub fn get_borderless_monocle() -> Result<bool, ReplyError> {
242 let mut conn = socket::connect()?;
243
244 conn.get_config_property("borderless_monocle")?
245 .parse()
246 .map_err(From::from)
247}
248
249pub fn get_gapless_monocle() -> Result<bool, ReplyError> {
250 let mut conn = socket::connect()?;
251
252 conn.get_config_property("gapless_monocle")?
253 .parse()
254 .map_err(From::from)
255}
256
257pub fn get_top_monocle_padding() -> Result<i16, ReplyError> {
258 let mut conn = socket::connect()?;
259
260 conn.get_config_property("top_monocle_padding")?
261 .parse()
262 .map_err(From::from)
263}
264
265pub fn get_right_monocle_padding() -> Result<i16, ReplyError> {
266 let mut conn = socket::connect()?;
267
268 conn.get_config_property("right_monocle_padding")?
269 .parse()
270 .map_err(From::from)
271}
272
273pub fn get_bottom_monocle_padding() -> Result<i16, ReplyError> {
274 let mut conn = socket::connect()?;
275
276 conn.get_config_property("bottom_monocle_padding")?
277 .parse()
278 .map_err(From::from)
279}
280
281pub fn get_left_monocle_padding() -> Result<i16, ReplyError> {
282 let mut conn = socket::connect()?;
283
284 conn.get_config_property("left_monocle_padding")?
285 .parse()
286 .map_err(From::from)
287}
288
289pub fn get_single_monocle() -> Result<bool, ReplyError> {
290 let mut conn = socket::connect()?;
291
292 conn.get_config_property("single_monocle")?
293 .parse()
294 .map_err(From::from)
295}
296
297pub fn get_pointer_motion_interval() -> Result<u16, ReplyError> {
298 let mut conn = socket::connect()?;
299
300 conn.get_config_property("pointer_motion_interval")?
301 .parse()
302 .map_err(From::from)
303}
304
305pub fn get_pointer_modifier() -> Result<PointerModifier, ReplyError> {
306 let mut conn = socket::connect()?;
307
308 conn.get_config_property("pointer_modifier")?
309 .parse()
310 .map_err(From::from)
311}
312
313pub fn get_pointer_action1() -> Result<PointerAction, ReplyError> {
314 let mut conn = socket::connect()?;
315
316 conn.get_config_property("pointer_action1")?
317 .parse()
318 .map_err(From::from)
319}
320
321pub fn get_pointer_action2() -> Result<PointerAction, ReplyError> {
322 let mut conn = socket::connect()?;
323
324 conn.get_config_property("pointer_action2")?
325 .parse()
326 .map_err(From::from)
327}
328
329pub fn get_pointer_action3() -> Result<PointerAction, ReplyError> {
330 let mut conn = socket::connect()?;
331
332 conn.get_config_property("pointer_action3")?
333 .parse()
334 .map_err(From::from)
335}
336
337pub fn get_click_to_focus() -> Result<ClickToFocus, ReplyError> {
338 let mut conn = socket::connect()?;
339
340 conn.get_config_property("click_to_focus")?
341 .parse()
342 .map_err(From::from)
343}
344
345pub fn get_swallow_first_click() -> Result<bool, ReplyError> {
346 let mut conn = socket::connect()?;
347
348 conn.get_config_property("swallow_first_click")?
349 .parse()
350 .map_err(From::from)
351}
352
353pub fn get_focus_follows_pointer() -> Result<bool, ReplyError> {
354 let mut conn = socket::connect()?;
355
356 conn.get_config_property("focus_follows_pointer")?
357 .parse()
358 .map_err(From::from)
359}
360
361pub fn get_pointer_follows_focus() -> Result<bool, ReplyError> {
362 let mut conn = socket::connect()?;
363
364 conn.get_config_property("pointer_follows_focus")?
365 .parse()
366 .map_err(From::from)
367}
368
369pub fn get_pointer_follows_monitor() -> Result<bool, ReplyError> {
370 let mut conn = socket::connect()?;
371
372 conn.get_config_property("pointer_follows_monitor")?
373 .parse()
374 .map_err(From::from)
375}
376
377pub fn get_mapping_events_count() -> Result<i32, ReplyError> {
378 let mut conn = socket::connect()?;
379
380 conn.get_config_property("mapping_events_count")?
381 .parse()
382 .map_err(From::from)
383}
384
385pub fn get_ignore_ewmh_focus() -> Result<bool, ReplyError> {
386 let mut conn = socket::connect()?;
387
388 conn.get_config_property("ignore_ewmh_focus")?
389 .parse()
390 .map_err(From::from)
391}
392
393pub fn get_ignore_ewmh_fullscreen() -> Result<bool, ReplyError> {
394 let mut conn = socket::connect()?;
395
396 conn.get_config_property("ignore_ewmh_fullscreen")?
397 .parse()
398 .map_err(From::from)
399}
400
401pub fn get_ignore_ewmh_struts() -> Result<bool, ReplyError> {
402 let mut conn = socket::connect()?;
403
404 conn.get_config_property("ignore_ewmh_struts")?
405 .parse()
406 .map_err(From::from)
407}
408
409pub fn get_center_pseudo_tiled() -> Result<bool, ReplyError> {
410 let mut conn = socket::connect()?;
411
412 conn.get_config_property("center_pseudo_tiled")?
413 .parse()
414 .map_err(From::from)
415}
416
417pub fn get_honor_size_hints() -> Result<bool, ReplyError> {
418 let mut conn = socket::connect()?;
419
420 conn.get_config_property("honor_size_hints")?
421 .parse()
422 .map_err(From::from)
423}
424
425pub fn get_remove_disabled_monitors() -> Result<bool, ReplyError> {
426 let mut conn = socket::connect()?;
427
428 conn.get_config_property("remove_disabled_monitors")?
429 .parse()
430 .map_err(From::from)
431}
432
433pub fn get_remove_unplugged_monitors() -> Result<bool, ReplyError> {
434 let mut conn = socket::connect()?;
435
436 conn.get_config_property("remove_unplugged_monitors")?
437 .parse()
438 .map_err(From::from)
439}
440
441pub fn get_merge_overlapping_monitors() -> Result<bool, ReplyError> {
442 let mut conn = socket::connect()?;
443
444 conn.get_config_property("merge_overlapping_monitors")?
445 .parse()
446 .map_err(From::from)
447}
448
449pub fn set_normal_border_color(value: String) -> Result<(), ReplyError> {
450 let mut conn = socket::connect()?;
451
452 conn.set_config_property("normal_border_color", &value)
453}
454
455pub fn set_active_border_color(value: String) -> Result<(), ReplyError> {
456 let mut conn = socket::connect()?;
457
458 conn.set_config_property("active_border_color", &value)
459}
460
461pub fn set_focused_border_color(value: String) -> Result<(), ReplyError> {
462 let mut conn = socket::connect()?;
463
464 conn.set_config_property("focused_border_color", &value)
465}
466
467pub fn set_presel_feedback_color(value: String) -> Result<(), ReplyError> {
468 let mut conn = socket::connect()?;
469
470 conn.set_config_property("presel_feedback_color", &value)
471}
472
473pub fn set_split_ratio(value: f32) -> Result<(), ReplyError> {
474 let mut conn = socket::connect()?;
475
476 conn.set_config_property("split_ratio", &value.to_string())
477}
478
479pub fn set_status_prefix(value: String) -> Result<(), ReplyError> {
480 let mut conn = socket::connect()?;
481
482 conn.set_config_property("status_prefix", &value)
483}
484
485pub fn set_external_rules_command(value: String) -> Result<(), ReplyError> {
486 let mut conn = socket::connect()?;
487
488 conn.set_config_property("external_rules_command", &value)
489}
490
491pub fn set_automatic_scheme(value: Scheme) -> Result<(), ReplyError> {
492 let mut conn = socket::connect()?;
493
494 conn.set_config_property("automatic_scheme", &value.to_string())
495}
496
497pub fn set_initial_polarity(value: Polarity) -> Result<(), ReplyError> {
498 let mut conn = socket::connect()?;
499
500 conn.set_config_property("initial_polarity", &value.to_string())
501}
502
503pub fn set_directional_focus_tightness(
504 value: Tightness,
505) -> Result<(), ReplyError> {
506 let mut conn = socket::connect()?;
507
508 conn.set_config_property("directional_focus_tightness", &value.to_string())
509}
510
511pub fn set_removal_adjustment(value: bool) -> Result<(), ReplyError> {
512 let mut conn = socket::connect()?;
513
514 conn.set_config_property("removal_adjustment", &value.to_string())
515}
516
517pub fn set_presel_feedback(value: bool) -> Result<(), ReplyError> {
518 let mut conn = socket::connect()?;
519
520 conn.set_config_property("presel_feedback", &value.to_string())
521}
522
523pub fn set_borderless_monocle(value: bool) -> Result<(), ReplyError> {
524 let mut conn = socket::connect()?;
525
526 conn.set_config_property("borderless_monocle", &value.to_string())
527}
528
529pub fn set_gapless_monocle(value: bool) -> Result<(), ReplyError> {
530 let mut conn = socket::connect()?;
531
532 conn.set_config_property("gapless_monocle", &value.to_string())
533}
534
535pub fn set_top_monocle_padding(value: i16) -> Result<(), ReplyError> {
536 let mut conn = socket::connect()?;
537
538 conn.set_config_property("top_monocle_padding", &value.to_string())
539}
540
541pub fn set_right_monocle_padding(value: i16) -> Result<(), ReplyError> {
542 let mut conn = socket::connect()?;
543
544 conn.set_config_property("right_monocle_padding", &value.to_string())
545}
546
547pub fn set_bottom_monocle_padding(value: i16) -> Result<(), ReplyError> {
548 let mut conn = socket::connect()?;
549
550 conn.set_config_property("bottom_monocle_padding", &value.to_string())
551}
552
553pub fn set_left_monocle_padding(value: i16) -> Result<(), ReplyError> {
554 let mut conn = socket::connect()?;
555
556 conn.set_config_property("left_monocle_padding", &value.to_string())
557}
558
559pub fn set_single_monocle(value: bool) -> Result<(), ReplyError> {
560 let mut conn = socket::connect()?;
561
562 conn.set_config_property("single_monocle", &value.to_string())
563}
564
565pub fn set_pointer_motion_interval(value: u16) -> Result<(), ReplyError> {
566 let mut conn = socket::connect()?;
567
568 conn.set_config_property("pointer_motion_interval", &value.to_string())
569}
570
571pub fn set_pointer_modifier(value: PointerModifier) -> Result<(), ReplyError> {
572 let mut conn = socket::connect()?;
573
574 conn.set_config_property("pointer_modifier", &value.to_string())
575}
576
577pub fn set_pointer_action1(value: PointerAction) -> Result<(), ReplyError> {
578 let mut conn = socket::connect()?;
579
580 conn.set_config_property("pointer_action1", &value.to_string())
581}
582
583pub fn set_pointer_action2(value: PointerAction) -> Result<(), ReplyError> {
584 let mut conn = socket::connect()?;
585
586 conn.set_config_property("pointer_action2", &value.to_string())
587}
588
589pub fn set_pointer_action3(value: PointerAction) -> Result<(), ReplyError> {
590 let mut conn = socket::connect()?;
591
592 conn.set_config_property("pointer_action3", &value.to_string())
593}
594
595pub fn set_click_to_focus(value: ClickToFocus) -> Result<(), ReplyError> {
596 let mut conn = socket::connect()?;
597
598 conn.set_config_property("click_to_focus", &value.to_string())
599}
600
601pub fn set_swallow_first_click(value: bool) -> Result<(), ReplyError> {
602 let mut conn = socket::connect()?;
603
604 conn.set_config_property("swallow_first_click", &value.to_string())
605}
606
607pub fn set_focus_follows_pointer(value: bool) -> Result<(), ReplyError> {
608 let mut conn = socket::connect()?;
609
610 conn.set_config_property("focus_follows_pointer", &value.to_string())
611}
612
613pub fn set_pointer_follows_focus(value: bool) -> Result<(), ReplyError> {
614 let mut conn = socket::connect()?;
615
616 conn.set_config_property("pointer_follows_focus", &value.to_string())
617}
618
619pub fn set_pointer_follows_monitor(value: bool) -> Result<(), ReplyError> {
620 let mut conn = socket::connect()?;
621
622 conn.set_config_property("pointer_follows_monitor", &value.to_string())
623}
624
625pub fn set_mapping_events_count(value: i32) -> Result<(), ReplyError> {
626 let mut conn = socket::connect()?;
627
628 conn.set_config_property("mapping_events_count", &value.to_string())
629}
630
631pub fn set_ignore_ewmh_focus(value: bool) -> Result<(), ReplyError> {
632 let mut conn = socket::connect()?;
633
634 conn.set_config_property("ignore_ewmh_focus", &value.to_string())
635}
636
637pub fn set_ignore_ewmh_fullscreen(value: bool) -> Result<(), ReplyError> {
638 let mut conn = socket::connect()?;
639
640 conn.set_config_property("ignore_ewmh_fullscreen", &value.to_string())
641}
642
643pub fn set_ignore_ewmh_struts(value: bool) -> Result<(), ReplyError> {
644 let mut conn = socket::connect()?;
645
646 conn.set_config_property("ignore_ewmh_struts", &value.to_string())
647}
648
649pub fn set_center_pseudo_tiled(value: bool) -> Result<(), ReplyError> {
650 let mut conn = socket::connect()?;
651
652 conn.set_config_property("center_pseudo_tiled", &value.to_string())
653}
654
655pub fn set_honor_size_hints(value: bool) -> Result<(), ReplyError> {
656 let mut conn = socket::connect()?;
657
658 conn.set_config_property("honor_size_hints", &value.to_string())
659}
660
661pub fn set_remove_disabled_monitors(value: bool) -> Result<(), ReplyError> {
662 let mut conn = socket::connect()?;
663
664 conn.set_config_property("remove_disabled_monitors", &value.to_string())
665}
666
667pub fn set_remove_unplugged_monitors(value: bool) -> Result<(), ReplyError> {
668 let mut conn = socket::connect()?;
669
670 conn.set_config_property("remove_unplugged_monitors", &value.to_string())
671}
672
673pub fn set_merge_overlapping_monitors(value: bool) -> Result<(), ReplyError> {
674 let mut conn = socket::connect()?;
675
676 conn.set_config_property("merge_overlapping_monitors", &value.to_string())
677}
678
679pub fn set_border_width(
681 monitor_selector: Option<MonitorSelector>,
682 desktop_selector: Option<DesktopSelector>,
683 node_selector: Option<NodeSelector>,
684 border_width: i32,
685) -> Result<(), ReplyError> {
686 let mut conn = socket::connect()?;
687
688 todo!();
689}
690
691pub fn set_window_gap(
693 monitor_selector: Option<MonitorSelector>,
694 desktop_selector: Option<DesktopSelector>,
695 window_gap: i32,
696) -> Result<(), ReplyError> {
697 let mut conn = socket::connect()?;
698
699 todo!();
700}
701
702pub fn top_padding(
704 monitor_selector: Option<MonitorSelector>,
705 desktop_selector: Option<DesktopSelector>,
706 top_padding: i32,
707) -> Result<(), ReplyError> {
708 let mut conn = socket::connect()?;
709
710 todo!();
711}
712
713pub fn right_padding(
715 monitor_selector: Option<MonitorSelector>,
716 desktop_selector: Option<DesktopSelector>,
717 right_padding: i32,
718) -> Result<(), ReplyError> {
719 let mut conn = socket::connect()?;
720
721 todo!();
722}
723
724pub fn bottom_padding(
726 monitor_selector: Option<MonitorSelector>,
727 desktop_selector: Option<DesktopSelector>,
728 bottom_padding: i32,
729) -> Result<(), ReplyError> {
730 let mut conn = socket::connect()?;
731
732 todo!();
733}
734
735pub fn left_padding(
737 monitor_selector: Option<MonitorSelector>,
738 desktop_selector: Option<DesktopSelector>,
739 left_padding: i32,
740) -> Result<(), ReplyError> {
741 let mut conn = socket::connect()?;
742
743 todo!();
744}