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