oxwm

https://git.tonybtw.com/oxwm.git git://git.tonybtw.com/oxwm.git
5,780 bytes raw
1
use super::{GapConfig, Layout, WindowGeometry};
2
use x11rb::protocol::xproto::Window;
3
4
pub struct TilingLayout;
5
6
struct GapValues {
7
    outer_horizontal: u32,
8
    outer_vertical: u32,
9
    inner_horizontal: u32,
10
    inner_vertical: u32,
11
}
12
13
struct FactValues {
14
    master_facts: f32,
15
    stack_facts: f32,
16
    master_remainder: i32,
17
    stack_remainder: i32,
18
}
19
20
impl TilingLayout {
21
    fn getgaps(gaps: &GapConfig, window_count: usize, smartgaps_enabled: bool) -> GapValues {
22
        let outer_enabled = if smartgaps_enabled && window_count == 1 {
23
            0
24
        } else {
25
            1
26
        };
27
        let inner_enabled = 1;
28
29
        GapValues {
30
            outer_horizontal: gaps.outer_horizontal * outer_enabled,
31
            outer_vertical: gaps.outer_vertical * outer_enabled,
32
            inner_horizontal: gaps.inner_horizontal * inner_enabled,
33
            inner_vertical: gaps.inner_vertical * inner_enabled,
34
        }
35
    }
36
37
    fn getfacts(
38
        window_count: usize,
39
        num_master: i32,
40
        master_size: i32,
41
        stack_size: i32,
42
    ) -> FactValues {
43
        let num_master = num_master.max(0) as usize;
44
        let master_facts = window_count.min(num_master) as f32;
45
        let stack_facts = if window_count > num_master {
46
            (window_count - num_master) as f32
47
        } else {
48
            0.0
49
        };
50
51
        let mut master_total = 0;
52
        let mut stack_total = 0;
53
54
        for i in 0..window_count {
55
            if i < num_master {
56
                master_total += (master_size as f32 / master_facts) as i32;
57
            } else {
58
                if stack_facts > 0.0 {
59
                    stack_total += (stack_size as f32 / stack_facts) as i32;
60
                }
61
            }
62
        }
63
64
        FactValues {
65
            master_facts,
66
            stack_facts,
67
            master_remainder: master_size - master_total,
68
            stack_remainder: stack_size - stack_total,
69
        }
70
    }
71
}
72
73
impl Layout for TilingLayout {
74
    fn name(&self) -> &'static str {
75
        super::LayoutType::Tiling.as_str()
76
    }
77
78
    fn symbol(&self) -> &'static str {
79
        "[]="
80
    }
81
82
    fn arrange(
83
        &self,
84
        windows: &[Window],
85
        screen_width: u32,
86
        screen_height: u32,
87
        gaps: &GapConfig,
88
        master_factor: f32,
89
        num_master: i32,
90
        smartgaps_enabled: bool,
91
    ) -> Vec<WindowGeometry> {
92
        let window_count = windows.len();
93
        if window_count == 0 {
94
            return Vec::new();
95
        }
96
97
        let gap_values = Self::getgaps(gaps, window_count, smartgaps_enabled);
98
99
        let outer_gap_horizontal = gap_values.outer_horizontal;
100
        let outer_gap_vertical = gap_values.outer_vertical;
101
        let inner_gap_horizontal = gap_values.inner_horizontal;
102
        let inner_gap_vertical = gap_values.inner_vertical;
103
104
        let mut stack_x = outer_gap_vertical as i32;
105
        let mut stack_y = outer_gap_horizontal as i32;
106
        let master_x = outer_gap_vertical as i32;
107
        let mut master_y = outer_gap_horizontal as i32;
108
109
        let num_master_usize = num_master.max(0) as usize;
110
        let master_count = window_count.min(num_master_usize);
111
        let stack_count = if window_count > num_master_usize {
112
            window_count - num_master_usize
113
        } else {
114
            0
115
        };
116
117
        let master_height = (screen_height as i32)
118
            - (2 * outer_gap_horizontal) as i32
119
            - (inner_gap_horizontal as i32 * (master_count.saturating_sub(1)) as i32);
120
        let stack_height = (screen_height as i32)
121
            - (2 * outer_gap_horizontal) as i32
122
            - (inner_gap_horizontal as i32 * stack_count.saturating_sub(1) as i32);
123
        let mut stack_width = (screen_width as i32) - (2 * outer_gap_vertical) as i32;
124
        let mut master_width = stack_width;
125
126
        if num_master > 0 && window_count > num_master_usize {
127
            stack_width = ((master_width as f32 - inner_gap_vertical as f32) * (1.0 - master_factor)) as i32;
128
            master_width = master_width - inner_gap_vertical as i32 - stack_width;
129
            stack_x = master_x + master_width + inner_gap_vertical as i32;
130
        }
131
132
        let facts = Self::getfacts(window_count, num_master, master_height, stack_height);
133
134
        let mut geometries = Vec::new();
135
136
        for (i, _window) in windows.iter().enumerate() {
137
            if i < num_master_usize {
138
                let window_height = (master_height as f32 / facts.master_facts) as i32
139
                    + if (i as i32) < facts.master_remainder {
140
                        1
141
                    } else {
142
                        0
143
                    };
144
145
                geometries.push(WindowGeometry {
146
                    x_coordinate: master_x,
147
                    y_coordinate: master_y,
148
                    width: master_width as u32,
149
                    height: window_height as u32,
150
                });
151
152
                master_y += window_height + inner_gap_horizontal as i32;
153
            } else {
154
                let window_height = if facts.stack_facts > 0.0 {
155
                    (stack_height as f32 / facts.stack_facts) as i32
156
                        + if ((i - num_master_usize) as i32) < facts.stack_remainder {
157
                            1
158
                        } else {
159
                            0
160
                        }
161
                } else {
162
                    stack_height
163
                };
164
165
                geometries.push(WindowGeometry {
166
                    x_coordinate: stack_x,
167
                    y_coordinate: stack_y,
168
                    width: stack_width as u32,
169
                    height: window_height as u32,
170
                });
171
172
                stack_y += window_height + inner_gap_horizontal as i32;
173
            }
174
        }
175
176
        geometries
177
    }
178
}