| 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 |
}
|