`depend_on_size` took a bare `WidgetId`, which any id at all satisfies.
It takes a `&StrongWidget` now, so `DrawResult` carries the handle it
was drawn from rather than an id copied out of it and nothing can claim
a dependency on a widget it does not hold.
`UiSpan::outside` matched on a pair of `Option`s where `?` says it. It
was written that way while the method was still `const`, and it is not.
No call site changed. Checked: fmt, clippy and 35 tests; `tabs`, `view`,
`minimal` and `text` render unchanged, and the live sway resize round
trip still matches a cold start at each size.
`lerp_inv` returns `Option`. Inverting a lerp over a range of zero
length has no one answer, and `div_or`'s fallback picked one: the start
of the range. Measured, that is not a wrong number so much as a
plausible one -- taking a part out of a box fixed at the top of the
window hands back exactly what went in, and out of a box fixed at the
middle hands back the parent's own `rel` of 0.5 as if it were the
child's fraction. Either way the caller cannot tell that nothing was
recovered, which is the defect; the previous commit's claim that it
"returns a rel of 0" is right only for the first case.
`UiScalar::outside` and `UiSpan::outside` follow it to `Option`, and
`Remap` is the answer at the region level: `new` says whether a drawing
in one box can be put in another and `apply` then cannot fail, so
`try_reuse` asks once for a whole subtree and `reusable` goes back to
reporting only what the widget claims. That replaces the predicate the
last commit put in `reusable`, which stated the same rule in a second
place.
`DivOr` existed only for the fallback and is gone, along with
`UiRegion::outside` and `UiVec2::outside`, which had no callers once
`Remap` owned the operation. `UiRegion::axis` took `&mut self` to
return a shared reference; `Remap::new` needs it on a shared one.
This does not redraw less. `Remap::new` refuses exactly what the
predicate refused; what it buys is one statement of the rule and a
remap that cannot half-apply. Counted on a resize, with the old
wipe-everything for comparison:
20 padded rows, 101 widgets 101 draws -> 0
the `tabs` example 73 draws -> 0
the `text` example 49 draws -> 48
So the saving is whole where a resize does not change any widget's
size, and nil in `text`, where both paragraphs rewrap to a different
height and the relayout that forces reaches the root. The last commit's
message oversold that case.
Checked: fmt, clippy and 35 tests. `tabs` (with the image replay),
`view` and `minimal` still byte-identical to `upstream/main`, `text`
unchanged, and the live sway resize round trip still matches a cold
start at each size.
Small, and disjoint from #12 — this touches `task.rs`, `harness.rs` and `render_state.rs`, none of which #12 goes near.
`Tasks` held an `Arc<Window>` only to call `request_redraw` when a task finished, which made the task queue, and so `DefaultRsc`, impossible to build without a window. It now takes an `Arc<dyn WakeTaskQueue>`, and `Window` implements it.
Waking also moves from *the task ended* to *an update was sent*, which is when there is actually something for the host to apply. A task that keeps running after sending one no longer holds it until it finishes, and a task that sends none no longer asks for a frame nothing needs.
`iris::harness` is what that buys. `UiRenderState` already does layout, hit testing and primitive building with no surface, so a test can build a tree, run frames, move a pointer and read back where widgets landed. `tests/harness.rs` covers span layout, resize relayout, press routing, hover start and end, wheel scrolling with its clamp, and a task update reaching the tree. None of them could be written before, since the only way into layout was a window.
It does not draw. A claim about pixels still needs a real surface — I checked this one against the rig rather than asserting it: `examples/task` under headless sway, centre pixel `ff0000` before the click and `0000ff` after, so the windowed path still applies task updates under the new wake.
The only core change is `UiRenderState::output_size()`, so that a host reading back the size it set does not have to keep a second copy.
---------
Co-authored-by: iris <2+iris@noreply.localhost>
Reviewed-on: iris/iris#15
Reviewed-by: iris <2+iris@noreply.localhost>
Co-authored-by: AIris <4+iris-ai@noreply.localhost>