Settle growing layout branches in one frame

This commit is contained in:
iris committed 2026-09-09 16:54:39 -04:00
1 parent f95835593f
commit 46e6edfd0b
3 files changed
+90 -4

No files matched your search

+18 -4
View File
@@ -1207,6 +1207,16 @@ impl UiRenderState {
/// redraws a widget that's currently active (drawn)
pub fn redraw(&mut self, id: WidgetId, rsc: &mut dyn UiRsc) {
self.redraw_and_settle(id, rsc);
}
/// Measure a changed branch toward the root, then revisit each widget
/// whose reported size changed on the way back down. The upward pass gives
/// every parent the new child size; the downward pass is what lets those
/// children draw inside the final boxes their parents chose. Without it a
/// newly grown subtree can retain the provisional (even inverted) region
/// it was measured in until an unrelated later update redraws it.
fn redraw_and_settle(&mut self, id: WidgetId, rsc: &mut dyn UiRsc) {
rsc.widgets_mut().needs_redraw.remove(&id);
// An ancestor is drawing this widget right now, and that draw is
// about to write fresh primitives for it. Drawing it a second time
@@ -1248,11 +1258,15 @@ impl UiRenderState {
// relay out too. Checked after the real draw, not before it --
// there is no query left that answers "what size would this be"
// without actually drawing (LAYOUT.md section 5).
if let Some(pid) = parent {
let new_size = self.active.get(&id).map(|a| a.size);
if new_size != Some(old_size) {
self.redraw(pid, rsc);
let changed = self.active.get(&id).map(|a| a.size) != Some(old_size);
if changed {
if let Some(pid) = parent {
self.redraw_and_settle(pid, rsc);
}
// The parent pass above has now placed this widget in its final
// region. Draw it once more there; unchanged descendants still
// take draw_inner's retained fast path.
self.redraw_and_settle(id, rsc);
}
}
}