i3status_rs/
protocol.rs

1pub mod i3bar_block;
2pub mod i3bar_event;
3
4use std::borrow::Borrow;
5
6use crate::RenderedBlock;
7use crate::config::SharedConfig;
8use crate::themes::color::Color;
9use crate::themes::separator::Separator;
10
11use i3bar_block::I3BarBlock;
12
13pub fn init(never_pause: bool) {
14    if never_pause {
15        println!("{{\"version\": 1, \"click_events\": true, \"stop_signal\": 0}}\n[");
16    } else {
17        println!("{{\"version\": 1, \"click_events\": true}}\n[");
18    }
19}
20
21pub(crate) fn print_blocks<B>(blocks: &[B], config: &SharedConfig)
22where
23    B: Borrow<RenderedBlock>,
24{
25    let mut prev_last_bg = Color::None;
26    let mut rendered_blocks = vec![];
27
28    // The right most block should never be alternated
29    let mut alt = blocks
30        .iter()
31        .map(|x| x.borrow())
32        .filter(|x| !x.segments.is_empty() && !x.merge_with_next)
33        .count()
34        % 2
35        == 0;
36
37    let mut logical_block_i = 0;
38
39    let mut prev_merge_with_next = false;
40
41    for (i, widgets) in blocks
42        .iter()
43        .map(|x| x.borrow())
44        .filter(|x| !x.segments.is_empty())
45        .cloned()
46        .enumerate()
47    {
48        let RenderedBlock {
49            mut segments,
50            merge_with_next,
51        } = widgets;
52
53        for segment in &mut segments {
54            segment.name = Some(logical_block_i.to_string());
55
56            // Apply tint for all widgets of every second block
57            // TODO: Allow for other non-additive tints
58            if alt {
59                segment.background = segment.background + config.theme.alternating_tint_bg;
60                segment.color = segment.color + config.theme.alternating_tint_fg;
61            }
62        }
63
64        if !merge_with_next {
65            alt = !alt;
66        }
67
68        let separator = match &config.theme.start_separator {
69            Separator::Custom(_) if i == 0 => &config.theme.start_separator,
70            _ => &config.theme.separator,
71        };
72
73        if let Separator::Custom(separator) = separator {
74            if !prev_merge_with_next {
75                // The first widget's BG is used to get the FG color for the current separator
76                let sep_fg = if config.theme.separator_fg == Color::Auto {
77                    segments.first().unwrap().background
78                } else {
79                    config.theme.separator_fg
80                };
81
82                // The separator's BG is the last block's last widget's BG
83                let sep_bg = if config.theme.separator_bg == Color::Auto {
84                    prev_last_bg
85                } else {
86                    config.theme.separator_bg
87                };
88
89                let separator = I3BarBlock {
90                    full_text: separator.clone(),
91                    background: sep_bg,
92                    color: sep_fg,
93                    ..Default::default()
94                };
95
96                rendered_blocks.push(separator);
97            }
98        } else if !merge_with_next {
99            // Re-add native separator on last widget for native theme
100            segments.last_mut().unwrap().separator = None;
101            segments.last_mut().unwrap().separator_block_width = None;
102        }
103
104        if !merge_with_next {
105            logical_block_i += 1;
106        }
107
108        prev_merge_with_next = merge_with_next;
109        prev_last_bg = segments.last().unwrap().background;
110
111        rendered_blocks.extend(segments);
112    }
113
114    if let Separator::Custom(end_separator) = &config.theme.end_separator {
115        // The separator's FG is the last block's last widget's BG
116        let sep_fg = if config.theme.separator_fg == Color::Auto {
117            prev_last_bg
118        } else {
119            config.theme.separator_fg
120        };
121
122        // The separator has no background color
123        let sep_bg = if config.theme.separator_bg == Color::Auto {
124            Color::None
125        } else {
126            config.theme.separator_bg
127        };
128
129        let separator = I3BarBlock {
130            full_text: end_separator.clone(),
131            background: sep_bg,
132            color: sep_fg,
133            ..Default::default()
134        };
135
136        rendered_blocks.push(separator);
137    }
138
139    println!("{},", serde_json::to_string(&rendered_blocks).unwrap());
140}