oxwm

https://git.tonybtw.com/oxwm.git git://git.tonybtw.com/oxwm.git
3,101 bytes raw
1
use super::{GapConfig, Layout, WindowGeometry};
2
use x11rb::protocol::xproto::Window;
3
4
pub struct GridLayout;
5
6
impl Layout for GridLayout {
7
    fn name(&self) -> &'static str {
8
        super::LayoutType::Grid.as_str()
9
    }
10
11
    fn symbol(&self) -> &'static str {
12
        "[#]"
13
    }
14
15
    fn arrange(
16
        &self,
17
        windows: &[Window],
18
        screen_width: u32,
19
        screen_height: u32,
20
        gaps: &GapConfig,
21
    ) -> Vec<WindowGeometry> {
22
        let window_count = windows.len();
23
        if window_count == 0 {
24
            return Vec::new();
25
        }
26
27
        if window_count == 1 {
28
            let x = gaps.outer_horizontal as i32;
29
            let y = gaps.outer_vertical as i32;
30
            let width = screen_width.saturating_sub(2 * gaps.outer_horizontal);
31
            let height = screen_height.saturating_sub(2 * gaps.outer_vertical);
32
33
            return vec![WindowGeometry {
34
                x_coordinate: x,
35
                y_coordinate: y,
36
                width,
37
                height,
38
            }];
39
        }
40
41
        let cols = (window_count as f64).sqrt().ceil() as usize;
42
        let rows = (window_count as f64 / cols as f64).ceil() as usize;
43
44
        let mut geometries = Vec::new();
45
46
        let total_horizontal_gaps =
47
            gaps.outer_horizontal * 2 + gaps.inner_horizontal * (cols as u32 - 1);
48
        let total_vertical_gaps = gaps.outer_vertical * 2 + gaps.inner_vertical * (rows as u32 - 1);
49
50
        let cell_width = screen_width.saturating_sub(total_horizontal_gaps) / cols as u32;
51
        let cell_height = screen_height.saturating_sub(total_vertical_gaps) / rows as u32;
52
53
        for (index, _window) in windows.iter().enumerate() {
54
            let row = index / cols;
55
            let col = index % cols;
56
57
            let is_last_row = row == rows - 1;
58
            let windows_in_last_row = window_count - (rows - 1) * cols;
59
60
            let (x, y, width, height) = if is_last_row && windows_in_last_row < cols {
61
                let last_row_col = index % cols;
62
                let last_row_cell_width =
63
                    screen_width.saturating_sub(total_horizontal_gaps.saturating_sub(
64
                        gaps.inner_horizontal * (cols as u32 - windows_in_last_row as u32),
65
                    )) / windows_in_last_row as u32;
66
67
                let x = gaps.outer_horizontal
68
                    + last_row_col as u32 * (last_row_cell_width + gaps.inner_horizontal);
69
                let y = gaps.outer_vertical + row as u32 * (cell_height + gaps.inner_vertical);
70
71
                (x as i32, y as i32, last_row_cell_width, cell_height)
72
            } else {
73
                let x = gaps.outer_horizontal + col as u32 * (cell_width + gaps.inner_horizontal);
74
                let y = gaps.outer_vertical + row as u32 * (cell_height + gaps.inner_vertical);
75
76
                (x as i32, y as i32, cell_width, cell_height)
77
            };
78
79
            geometries.push(WindowGeometry {
80
                x_coordinate: x,
81
                y_coordinate: y,
82
                width,
83
                height,
84
            });
85
        }
86
87
        geometries
88
    }
89
}