oxwm

https://git.tonybtw.com/oxwm.git git://git.tonybtw.com/oxwm.git
5,796 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 =
128
                ((master_width as f32 - inner_gap_vertical as f32) * (1.0 - master_factor)) as i32;
129
            master_width = master_width - inner_gap_vertical as i32 - stack_width;
130
            stack_x = master_x + master_width + inner_gap_vertical as i32;
131
        }
132
133
        let facts = Self::getfacts(window_count, num_master, master_height, stack_height);
134
135
        let mut geometries = Vec::new();
136
137
        for (i, _window) in windows.iter().enumerate() {
138
            if i < num_master_usize {
139
                let window_height = (master_height as f32 / facts.master_facts) as i32
140
                    + if (i as i32) < facts.master_remainder {
141
                        1
142
                    } else {
143
                        0
144
                    };
145
146
                geometries.push(WindowGeometry {
147
                    x_coordinate: master_x,
148
                    y_coordinate: master_y,
149
                    width: master_width as u32,
150
                    height: window_height as u32,
151
                });
152
153
                master_y += window_height + inner_gap_horizontal as i32;
154
            } else {
155
                let window_height = if facts.stack_facts > 0.0 {
156
                    (stack_height as f32 / facts.stack_facts) as i32
157
                        + if ((i - num_master_usize) as i32) < facts.stack_remainder {
158
                            1
159
                        } else {
160
                            0
161
                        }
162
                } else {
163
                    stack_height
164
                };
165
166
                geometries.push(WindowGeometry {
167
                    x_coordinate: stack_x,
168
                    y_coordinate: stack_y,
169
                    width: stack_width as u32,
170
                    height: window_height as u32,
171
                });
172
173
                stack_y += window_height + inner_gap_horizontal as i32;
174
            }
175
        }
176
177
        geometries
178
    }
179
}