1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-01 22:30: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

@@ -75,6 +75,11 @@ pub(crate) struct GridLayout {
curr_state: State,
initial_available: Rect,
/// Are we inside an enclosing sizing pass (e.g. [`crate::Resize`] measuring
/// the minimum content width)? If so we must not remember the (narrow) sizes
/// we measure during it.
sizing_pass: bool,
// Options:
num_columns: Option<usize>,
spacing: Vec2,
@@ -90,6 +95,10 @@ pub(crate) struct GridLayout {
impl GridLayout {
pub(crate) fn new(ui: &Ui, id: Id, prev_state: Option<State>) -> Self {
let is_first_frame = prev_state.is_none();
// An outer sizing pass, we should render as small as possible.
let sizing_pass = ui.is_sizing_pass();
let prev_state = prev_state.unwrap_or_default();
// TODO(emilk): respect current layout
@@ -110,6 +119,7 @@ impl GridLayout {
prev_state,
curr_state: State::default(),
initial_available,
sizing_pass,
num_columns: None,
spacing: ui.spacing().item_spacing,
@@ -180,7 +190,11 @@ impl GridLayout {
}
pub(crate) fn next_cell(&self, cursor: Rect, child_size: Vec2) -> Rect {
let width = self.prev_state.col_width(self.col).unwrap_or(0.0);
let width = if self.sizing_pass {
0.0
} else {
self.prev_state.col_width(self.col).unwrap_or(0.0)
};
let height = self.prev_row_height(self.row);
let size = child_size.max(vec2(width, height));
Rect::from_min_size(cursor.min, size).round_ui()