bspc_rs/
settings.rs

1//! This module is dedicated to various settings of bspwm. Its functions are
2//! equivalent to those, which are run by `bspc config <setting>` command in
3//! your shell.
4
5use 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
68// Template for generating function for handling events
69// pub struct Settings {
70//     normal_border_color: String,
71//     active_border_color: String,
72//     focused_border_color: String,
73//     presel_feedback_color: String,
74//     split_ratio: f32,
75//     status_prefix: String,
76//     external_rules_command: String,
77//     automatic_scheme: Scheme,
78//     initial_polarity: Polarity,
79//     directional_focus_tightness: Tightness,
80//     removal_adjustment: bool,
81//     presel_feedback: bool,
82//     borderless_monocle: bool,
83//     gapless_monocle: bool,
84//     top_monocle_padding: i16,
85//     right_monocle_padding: i16,
86//     bottom_monocle_padding: i16,
87//     left_monocle_padding: i16,
88//     single_monocle: bool,
89//     pointer_motion_interval: u16,
90//     pointer_modifier: PointerModifier,
91//     pointer_action1: PointerAction,
92//     pointer_action2: PointerAction,
93//     pointer_action3: PointerAction,
94//     click_to_focus: ClickToFocus,
95//     swallow_first_click: bool,
96//     focus_follows_pointer: bool,
97//     pointer_follows_focus: bool,
98//     pointer_follows_monitor: bool,
99//     mapping_events_count: i32,
100//     ignore_ewmh_focus: bool,
101//     ignore_ewmh_fullscreen: bool,
102//     ignore_ewmh_struts: bool,
103//     center_pseudo_tiled: bool,
104//     honor_size_hints: bool,
105//     remove_disabled_monitors: bool,
106//     remove_unplugged_monitors: bool,
107//     merge_overlapping_monitors: bool,
108// }
109
110trait 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            // TODO: Test if this can happen
133            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
679/// Sets `border_width` for nodes, that satisfy given conditions.
680pub 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
691/// Sets `window_gap` for desktops, that satisfy given conditions.
692pub 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
702/// Sets `top_padding` for desktops/monitors, that satisfy given conditions.
703pub 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
713/// Sets `right_padding` for deskrights/monitors, that satisfy given conditions.
714pub 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
724/// Sets `bottom_padding` for deskbottoms/monitors, that satisfy given conditions.
725pub 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
735/// Sets `left_padding` for desklefts/monitors, that satisfy given conditions.
736pub 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}