1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-29 04:40:03 -04:00

Fix window with a Grid being widenable but not shrinkable again (#8386)

## Related

* Fixes a regression from #8152
* Part of #2921

Reported symptom: you can widen the Widget Gallery window, but it won't
shrink again.

I'm not sure this fix is the best one, but it does work.

# Claude says
## Cause

A `Grid` gives its **last** column all the available width, so a
width-filling widget in it (`Separator`, `TextEdit`, `ProgressBar`, …)
makes the `Grid` remember a `col_width` that is really just "however
wide we happened to be".

At the start of a resize drag, `Resize` runs a one-frame sizing pass
(#8152) to measure the minimum content width and clamps the drag against
it. But `GridLayout::next_cell` inflated every cell to
`prev_state.col_width`, so the `Grid` reported its previous width as its
minimum — even though it was only offered `min_size.x`. The clamp is a
lower bound, so widening kept working while shrinking was blocked at the
widened width.

## Fix

During an enclosing sizing pass, don't inflate the stretchy last column
to its remembered width, and don't store the measured (narrow) widths.

Minimal repro (fails before, passes after — added as a regression test):

```rust
Window::new("x").default_width(280.0).show(ctx, |ui| {
    egui::Grid::new("grid").num_columns(2).show(ui, |ui| {
        ui.label("Separator");
        ui.separator(); // fills the last column
        ui.end_row();
    });
});
```

`Panel` is unaffected — it clamps only against the user's `min_size`,
with no content-min sizing pass.

* [x] I have followed the instructions in the PR template

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Lucas Meurer <hi@lucasmerlin.me>
This commit is contained in:
Emil Ernerfeldt
2026-08-04 07:54:06 -07:00
committed by GitHub
parent 622bbbeccc
commit 5347b0a4ac
2 changed files with 70 additions and 1 deletions

View File

@@ -513,6 +513,61 @@ fn window_resize_wraps_to_content_min_width() {
);
}
/// A `Grid` gives its last column all the available width, so a width-filling widget in it
/// (here a `Separator`) makes the grid remember a column width that is really just
/// "however wide the window happened to be".
///
/// When `Resize` then measures the minimum content width in a sizing pass, that remembered
/// width must not be reported as the minimum — otherwise the window can be widened but
/// never shrunk again.
#[test]
fn window_with_grid_can_shrink_after_being_widened() {
let window_title = "grid_shrink_regression";
let mut harness = Harness::builder()
.with_size(Vec2::new(800.0, 600.0))
.build_ui(move |ui| {
Window::new(window_title)
.default_pos([20.0, 20.0])
.default_width(280.0)
.show(ui.ctx(), |ui| {
egui::Grid::new("grid").num_columns(2).show(ui, |ui| {
ui.label("Separator");
ui.separator(); // Fills the available width
ui.end_row();
});
});
});
harness.run();
let drag_right_edge = |harness: &mut Harness<'_>, dx: f32| {
let rect = harness
.get_by_role_and_label(Role::Window, window_title)
.rect();
let grab = Pos2::new(rect.right(), rect.center().y);
harness.hover_at(grab);
harness.run();
harness.drag_at(grab);
harness.run();
harness.hover_at(grab + Vec2::new(dx, 0.0));
harness.run();
harness.drop_at(grab + Vec2::new(dx, 0.0));
harness.run();
harness
.get_by_role_and_label(Role::Window, window_title)
.rect()
.width()
};
let widened = drag_right_edge(&mut harness, 300.0);
let shrunk = drag_right_edge(&mut harness, -300.0);
assert!(
shrunk < widened - 200.0,
"window could not be shrunk again after being widened: \
widened to {widened}, then only shrunk to {shrunk}"
);
}
/// Ensure that the size passed to window is actually treated as outer size (including
/// margins and borders).
#[test]