mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-05-19 18:26:56 +02:00
fix(wm): correct layout rounding for uneven integer division
The grid layout calculates row heights using integer division, which truncates the result when the area height is not evenly divisible by the number of rows in a column. Since every row received this truncated height, columns with an odd row count (e.g. 3 rows in 800px: 266*3=798) would fall short of the full area height, leaving a visible gap at the bottom compared to columns with an even row count (e.g. 2 rows: 400*2=800). The last row in each column now absorbs the remainder pixels from the integer division. The vertical flip position calculation was also updated so that the last row, which becomes the topmost window when flipped, starts at the area top edge instead of being offset by the truncation error. The same integer division truncation also affected column widths in the grid layout when the area width is not evenly divisible by the number of columns. The last column now absorbs the width remainder using the same pattern, and this correction is applied before the flipped column positions are calculated so that horizontal flips also tile correctly. The two shared helper functions columns_with_ratios and rows_with_ratios had the same issue, which propagated to every layout that delegates to them: Columns, Rows, VerticalStack stack rows, RightMainVerticalStack stack rows, HorizontalStack stack columns, and UltrawideVerticalStack tertiary rows. Both functions now correct the last element after the sizing loop so that the total tiled dimension matches the area exactly. The Scrolling layout computes a uniform column width by dividing the area width by the visible column count, which can also leave a remainder gap on the right edge. The last visible column in the current viewport now absorbs this remainder. Since the layout is recalculated on every scroll event, the correction stays accurate regardless of which column is rightmost.
This commit is contained in:
@@ -141,6 +141,15 @@ impl Arrangement for DefaultLayout {
|
||||
});
|
||||
}
|
||||
|
||||
// Last visible column absorbs any remainder from integer division
|
||||
// so that visible columns tile the full area width without gaps
|
||||
let width_remainder = area.right - column_width * visible_columns;
|
||||
if width_remainder > 0 {
|
||||
let last_visible_idx =
|
||||
(first_visible as usize + visible_columns as usize - 1).min(len - 1);
|
||||
layouts[last_visible_idx].right += width_remainder;
|
||||
}
|
||||
|
||||
let adjustment = calculate_scrolling_adjustment(resize_dimensions);
|
||||
layouts
|
||||
.iter_mut()
|
||||
@@ -660,6 +669,16 @@ impl Arrangement for DefaultLayout {
|
||||
current_left += width;
|
||||
}
|
||||
|
||||
// Last column absorbs any remainder from integer division
|
||||
// so that columns tile the full area width without gaps
|
||||
let total_width: i32 = col_widths.iter().sum();
|
||||
let width_remainder = area.right - total_width;
|
||||
if width_remainder > 0
|
||||
&& let Some(last) = col_widths.last_mut()
|
||||
{
|
||||
*last += width_remainder;
|
||||
}
|
||||
|
||||
// Pre-calculate flipped column positions: same widths laid out
|
||||
// in reverse order so that the last column sits at area.left
|
||||
let flipped_col_lefts = if matches!(
|
||||
@@ -691,8 +710,10 @@ impl Arrangement for DefaultLayout {
|
||||
remaining_windows / remaining_columns
|
||||
};
|
||||
|
||||
// Rows within each column are equal height (no row_ratios support for Grid)
|
||||
let win_height = area.bottom / num_rows_in_this_col;
|
||||
// Rows within each column: base height from integer division,
|
||||
// last row absorbs any remainder to cover the full area height
|
||||
let base_height = area.bottom / num_rows_in_this_col;
|
||||
let height_remainder = area.bottom - base_height * num_rows_in_this_col;
|
||||
|
||||
let col_idx = col as usize;
|
||||
let win_width = col_widths[col_idx];
|
||||
@@ -700,19 +721,34 @@ impl Arrangement for DefaultLayout {
|
||||
|
||||
for row in 0..num_rows_in_this_col {
|
||||
if let Some((_idx, win)) = iter.next() {
|
||||
let is_last_row = row == num_rows_in_this_col - 1;
|
||||
let win_height = if is_last_row {
|
||||
base_height + height_remainder
|
||||
} else {
|
||||
base_height
|
||||
};
|
||||
|
||||
let mut left = col_left;
|
||||
let mut top = area.top + win_height * row;
|
||||
let mut top = area.top + base_height * row;
|
||||
|
||||
match layout_flip {
|
||||
Some(Axis::Horizontal) => {
|
||||
left = flipped_col_lefts[col_idx];
|
||||
}
|
||||
Some(Axis::Vertical) => {
|
||||
top = area.bottom - win_height * (row + 1) + area.top;
|
||||
top = if is_last_row {
|
||||
area.top
|
||||
} else {
|
||||
area.top + area.bottom - base_height * (row + 1)
|
||||
};
|
||||
}
|
||||
Some(Axis::HorizontalAndVertical) => {
|
||||
left = flipped_col_lefts[col_idx];
|
||||
top = area.bottom - win_height * (row + 1) + area.top;
|
||||
top = if is_last_row {
|
||||
area.top
|
||||
} else {
|
||||
area.top + area.bottom - base_height * (row + 1)
|
||||
};
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
@@ -948,6 +984,16 @@ fn columns_with_ratios(
|
||||
left += right;
|
||||
}
|
||||
|
||||
// Last column absorbs any remainder from integer division
|
||||
// so that columns tile the full area width without gaps
|
||||
let total_width: i32 = layouts.iter().map(|r| r.right).sum();
|
||||
let remainder = area.right - total_width;
|
||||
if remainder > 0
|
||||
&& let Some(last) = layouts.last_mut()
|
||||
{
|
||||
last.right += remainder;
|
||||
}
|
||||
|
||||
layouts
|
||||
}
|
||||
|
||||
@@ -1019,6 +1065,16 @@ fn rows_with_ratios(
|
||||
top += bottom;
|
||||
}
|
||||
|
||||
// Last row absorbs any remainder from integer division
|
||||
// so that rows tile the full area height without gaps
|
||||
let total_height: i32 = layouts.iter().map(|r| r.bottom).sum();
|
||||
let remainder = area.bottom - total_height;
|
||||
if remainder > 0
|
||||
&& let Some(last) = layouts.last_mut()
|
||||
{
|
||||
last.bottom += remainder;
|
||||
}
|
||||
|
||||
layouts
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user