oxwm

https://git.tonybtw.com/oxwm.git git://git.tonybtw.com/oxwm.git
5,680 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 if stack_facts > 0.0 {
58
                stack_total += (stack_size as f32 / stack_facts) as i32;
59
            }
60
        }
61
62
        FactValues {
63
            master_facts,
64
            stack_facts,
65
            master_remainder: master_size - master_total,
66
            stack_remainder: stack_size - stack_total,
67
        }
68
    }
69
}
70
71
impl Layout for TilingLayout {
72
    fn name(&self) -> &'static str {
73
        super::LayoutType::Tiling.as_str()
74
    }
75
76
    fn symbol(&self) -> &'static str {
77
        "[]="
78
    }
79
80
    fn arrange(
81
        &self,
82
        windows: &[Window],
83
        screen_width: u32,
84
        screen_height: u32,
85
        gaps: &GapConfig,
86
        master_factor: f32,
87
        num_master: i32,
88
        smartgaps_enabled: bool,
89
    ) -> Vec<WindowGeometry> {
90
        let window_count = windows.len();
91
        if window_count == 0 {
92
            return Vec::new();
93
        }
94
95
        let gap_values = Self::getgaps(gaps, window_count, smartgaps_enabled);
96
97
        let outer_gap_horizontal = gap_values.outer_horizontal;
98
        let outer_gap_vertical = gap_values.outer_vertical;
99
        let inner_gap_horizontal = gap_values.inner_horizontal;
100
        let inner_gap_vertical = gap_values.inner_vertical;
101
102
        let mut stack_x = outer_gap_vertical as i32;
103
        let mut stack_y = outer_gap_horizontal as i32;
104
        let master_x = outer_gap_vertical as i32;
105
        let mut master_y = outer_gap_horizontal as i32;
106
107
        let num_master_usize = num_master.max(0) as usize;
108
        let master_count = window_count.min(num_master_usize);
109
        let stack_count = window_count.saturating_sub(num_master_usize);
110
111
        let master_height = (screen_height as i32)
112
            - (2 * outer_gap_horizontal) as i32
113
            - (inner_gap_horizontal as i32 * (master_count.saturating_sub(1)) as i32);
114
        let stack_height = (screen_height as i32)
115
            - (2 * outer_gap_horizontal) as i32
116
            - (inner_gap_horizontal as i32 * stack_count.saturating_sub(1) as i32);
117
        let mut stack_width = (screen_width as i32) - (2 * outer_gap_vertical) as i32;
118
        let mut master_width = stack_width;
119
120
        if num_master > 0 && window_count > num_master_usize {
121
            stack_width =
122
                ((master_width as f32 - inner_gap_vertical as f32) * (1.0 - master_factor)) as i32;
123
            master_width = master_width - inner_gap_vertical as i32 - stack_width;
124
            stack_x = master_x + master_width + inner_gap_vertical as i32;
125
        }
126
127
        let facts = Self::getfacts(window_count, num_master, master_height, stack_height);
128
129
        let mut geometries = Vec::new();
130
131
        for (i, _window) in windows.iter().enumerate() {
132
            if i < num_master_usize {
133
                let window_height = (master_height as f32 / facts.master_facts) as i32
134
                    + if (i as i32) < facts.master_remainder {
135
                        1
136
                    } else {
137
                        0
138
                    };
139
140
                geometries.push(WindowGeometry {
141
                    x_coordinate: master_x,
142
                    y_coordinate: master_y,
143
                    width: master_width as u32,
144
                    height: window_height as u32,
145
                });
146
147
                master_y += window_height + inner_gap_horizontal as i32;
148
            } else {
149
                let window_height = if facts.stack_facts > 0.0 {
150
                    (stack_height as f32 / facts.stack_facts) as i32
151
                        + if ((i - num_master_usize) as i32) < facts.stack_remainder {
152
                            1
153
                        } else {
154
                            0
155
                        }
156
                } else {
157
                    stack_height
158
                };
159
160
                geometries.push(WindowGeometry {
161
                    x_coordinate: stack_x,
162
                    y_coordinate: stack_y,
163
                    width: stack_width as u32,
164
                    height: window_height as u32,
165
                });
166
167
                stack_y += window_height + inner_gap_horizontal as i32;
168
            }
169
        }
170
171
        geometries
172
    }
173
}