i3status_rs/
protocol.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
pub mod i3bar_block;
pub mod i3bar_event;

use std::borrow::Borrow;

use crate::config::SharedConfig;
use crate::themes::color::Color;
use crate::themes::separator::Separator;
use crate::RenderedBlock;

use i3bar_block::I3BarBlock;

pub fn init(never_pause: bool) {
    if never_pause {
        println!("{{\"version\": 1, \"click_events\": true, \"stop_signal\": 0}}\n[");
    } else {
        println!("{{\"version\": 1, \"click_events\": true}}\n[");
    }
}

pub(crate) fn print_blocks<B>(blocks: &[B], config: &SharedConfig)
where
    B: Borrow<RenderedBlock>,
{
    let mut prev_last_bg = Color::None;
    let mut rendered_blocks = vec![];

    // The right most block should never be alternated
    let mut alt = blocks
        .iter()
        .map(|x| x.borrow())
        .filter(|x| !x.segments.is_empty() && !x.merge_with_next)
        .count()
        % 2
        == 0;

    let mut logical_block_i = 0;

    let mut prev_merge_with_next = false;

    for (i, widgets) in blocks
        .iter()
        .map(|x| x.borrow())
        .filter(|x| !x.segments.is_empty())
        .cloned()
        .enumerate()
    {
        let RenderedBlock {
            mut segments,
            merge_with_next,
        } = widgets;

        for segment in &mut segments {
            segment.name = Some(logical_block_i.to_string());

            // Apply tint for all widgets of every second block
            // TODO: Allow for other non-additive tints
            if alt {
                segment.background = segment.background + config.theme.alternating_tint_bg;
                segment.color = segment.color + config.theme.alternating_tint_fg;
            }
        }

        if !merge_with_next {
            alt = !alt;
        }

        let separator = match &config.theme.start_separator {
            Separator::Custom(_) if i == 0 => &config.theme.start_separator,
            _ => &config.theme.separator,
        };

        if let Separator::Custom(separator) = separator {
            if !prev_merge_with_next {
                // The first widget's BG is used to get the FG color for the current separator
                let sep_fg = if config.theme.separator_fg == Color::Auto {
                    segments.first().unwrap().background
                } else {
                    config.theme.separator_fg
                };

                // The separator's BG is the last block's last widget's BG
                let sep_bg = if config.theme.separator_bg == Color::Auto {
                    prev_last_bg
                } else {
                    config.theme.separator_bg
                };

                let separator = I3BarBlock {
                    full_text: separator.clone(),
                    background: sep_bg,
                    color: sep_fg,
                    ..Default::default()
                };

                rendered_blocks.push(separator);
            }
        } else if !merge_with_next {
            // Re-add native separator on last widget for native theme
            segments.last_mut().unwrap().separator = None;
            segments.last_mut().unwrap().separator_block_width = None;
        }

        if !merge_with_next {
            logical_block_i += 1;
        }

        prev_merge_with_next = merge_with_next;
        prev_last_bg = segments.last().unwrap().background;

        rendered_blocks.extend(segments);
    }

    if let Separator::Custom(end_separator) = &config.theme.end_separator {
        // The separator's FG is the last block's last widget's BG
        let sep_fg = if config.theme.separator_fg == Color::Auto {
            prev_last_bg
        } else {
            config.theme.separator_fg
        };

        // The separator has no background color
        let sep_bg = if config.theme.separator_bg == Color::Auto {
            Color::None
        } else {
            config.theme.separator_bg
        };

        let separator = I3BarBlock {
            full_text: end_separator.clone(),
            background: sep_bg,
            color: sep_fg,
            ..Default::default()
        };

        rendered_blocks.push(separator);
    }

    println!("{},", serde_json::to_string(&rendered_blocks).unwrap());
}