Alignment was not accounted for. Glyphs anchored to the start of an axis
stay where they are when that extent changes, but the default is
`CENTER_LEFT`: a label in a box that grows taller has to re-centre, even
though its shaping is untouched. Saying `Internal` there would keep a
drawing that belongs somewhere else once the retained path can act on it.
It costs nothing today, since neither `Internal` nor `External` reuses
anything yet. It would be silent when the move chain lands, which is why
the classification wants to be right while it is being written rather
than when something starts trusting it.
`desired_width`/`desired_height`, `WidgetAxisFns`, `SizeCtx` and the size
cache are gone. A widget states what it used with `Painter::set_size`
while it draws, and `Painter::widget` hands back a `DrawResult` whose
`size()` both reads the child and records that this widget's size depends
on it. Reading nothing keeps the parent independent of what the child came
to.
`Span` is what the change is for. It takes each child's `size_hint` where
there is one, draws only the children that cannot answer, allocates the
flexible space, then places everything -- which deletes `desired_ortho`,
whose own comment said it "literally copies draw ... which makes this slow
and not cool".
Invalidation follows the dependency edges the draw recorded: a widget that
needs redrawing hands off to the highest ancestor that read its size,
instead of re-running a measurement to find out whether anything changed.
`Widget::size_dependence(axis)` says how much of its box a widget's
drawing depends on -- none of it, its own extent, or the whole box -- so
the retained path can keep a drawing and write a new box into it. Asked
per axis, because wrapped text depends on the width it is offered and not
on the height. `Internal` does not yet buy more than `External`: keeping a
drawing when only the room around it changed is a translation, which waits
for the move chain.
`tests/retained.rs` covers the second frame rather than the first, which
is where the bugs were: a placed child that was not recorded as one got
pruned as departed on the next draw.
`examples/text.rs` is new, since wrapping was the one thing here with no
way to see it on its own.
`update` redrew everything when `resized` was set, but `needs_redraw` --
which is what decides whether to request a frame at all -- did not know
about `resized`. A condition in one and not the other is a frame nobody
asks for and a stale window. The two share one `needs_redraw_all` now.
Latent on Wayland, because winit requests a redraw after a resize by
itself; a resize changes neither the root nor any widget, so nothing else
here would have asked. It stops being latent on Android, where the
surface work will not have winit underneath it and every rotation and
keyboard open is a resize.
This is not a fix for the startup defect recorded in RUST.md, where the
window keeps its pre-configure layout: that reproduces with this change
in place, and the frame it needs is requested and drawn.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>