Settle growing layout branches in one frame
This commit is contained in:
1 parent
e212ed8d02
commit
5ece49b8d9
7 files changed
+139
-33
No files matched your search
+16
-11
@@ -281,12 +281,15 @@ always a leaf: `Rect`, `Image`, a fixed glyph). A widget that returns
|
||||
`false` (the default) is redrawn in full whenever `available` changes,
|
||||
which is correct always, just not free.
|
||||
|
||||
**Ancestor propagation** (a resized child changing its own reported size,
|
||||
requiring its parent to re-lay-out) is unchanged in spirit from today's
|
||||
`redraw` (`render_state.rs:270-305`), which already walks up exactly the
|
||||
ancestors whose cached size differs from the new one and stops as soon as
|
||||
a size is unchanged (`:274-286`). That loop moves from consulting
|
||||
`Cache.size` to consulting `ActiveData.size` (§5) but keeps its shape.
|
||||
**Size propagation goes both ways in the same frame.** A resized child first
|
||||
walks upward through exactly the ancestors whose cached size changes. That
|
||||
measurement pass gives each parent the new size but necessarily drew the
|
||||
branch in its old boxes. As the recursion returns, `redraw_and_settle` revisits
|
||||
those changed widgets from the outside in, after their parents have assigned
|
||||
the final boxes. Otherwise a newly appended child can retain the provisional
|
||||
(even inverted) region it was measured in until another update happens. The
|
||||
downward work is confined to the branch that changed; unchanged descendants
|
||||
still take `draw_inner`'s retained fast path.
|
||||
|
||||
### 4. Wrapped text, and "needs child height before choosing width"
|
||||
|
||||
@@ -667,9 +670,11 @@ A move alone cannot fix a changed size; `Painter::place` redraws in that
|
||||
case.
|
||||
|
||||
The cost is bounded and worth stating, because it is what makes the rule
|
||||
safe to apply everywhere: the second draw happens only on the frame a
|
||||
safe to apply everywhere: the settling draw happens only on the frame a
|
||||
widget's own size actually changes, which is a frame that was already
|
||||
redrawing it. A widget whose reported size is a function of the box it
|
||||
was *offered* would disagree every frame and redraw every frame — which
|
||||
is why `LazySpan` requires content-sized rows, and has since long before
|
||||
this.
|
||||
redrawing it. `Sized` also requires its final region before retaining its
|
||||
children: its own reported size may be known exactly while a descendant was
|
||||
drawn in the provisional box, so moving only the wrapper is insufficient. A
|
||||
widget whose reported size is a function of the box it was *offered* would
|
||||
disagree every frame and redraw every frame — which is why `LazySpan` requires
|
||||
content-sized rows, and has since long before this.
|
||||
Reference in new issue
Block a user