docs: the 22:16 report reconciled with what was actually run
RUST.md's "Shell lost" section and IRIS_TODO.md's matching paragraph both
said item 4's fix was written but never built or tested. It was committed
in ba2afba with its test passing, so both were stale the moment that
landed and read as if nothing had been run at all.
Replaced with one section per item, saying what was fixed, what was
measured on this checkout's emulator and what the phone still has to
settle: items 2 and 3 ticked with their numbers, item 4 ticked on the code
with phone confirmation still owed (no Vulkan adapter here), item 1 left
open with the exact logcat line for Iris to look at. The two pre-existing
faults found on the way -- the 16-deep move chain and the API-29 JNI calls
-- are recorded where the next reader will hit them.
IRIS.md gains the public-surface entry: `Widget::tick`,
`UiData::animate`/`tick_animations`, `FlingCalculator`'s density and
coefficient, and `MOVE_CHAIN_LIMIT`.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
ed04d4c735
commit
ba0f2ea93f
3 files changed
+306
-5
No files matched your search
@@ -8,6 +8,59 @@ capability that moved. Small and trivial changes do not go here.
|
||||
An entry gives the date, what changed, why, and a short before/after where
|
||||
it helps judge the change without the session that made it. Newest first.
|
||||
|
||||
## 2026-09-07: widgets can animate, and a fling finally moves
|
||||
|
||||
Iris's phone said "fling still doesn't work" twice. The velocity was only
|
||||
half of it: **nothing in iris advanced an animation between input
|
||||
events**, so `List::fling` stored a speed that nothing ever applied. Three
|
||||
public changes come out of fixing that.
|
||||
|
||||
**`Widget::tick(&mut self, now: Instant) -> bool`** is a new trait method,
|
||||
defaulted to `false`, so no existing widget changes. A widget that
|
||||
overrides it is animating; answering `false` is how it stops.
|
||||
|
||||
**`UiData::animate(id)` and `UiData::tick_animations(now) -> bool`** are
|
||||
the registry and its driver. A gesture that starts an animation registers
|
||||
the widget; each backend calls `tick_animations` once per frame before the
|
||||
draw and asks for another frame while it answers `true`. That answer is
|
||||
the *only* thing in iris that makes a frame happen without an input event,
|
||||
and an animation's path out is its own `tick` returning false -- nothing
|
||||
has to remember to unregister it.
|
||||
|
||||
// before: the velocity was stored and never applied
|
||||
list(ui).fling(-v);
|
||||
// after
|
||||
list(ui).fling(-v);
|
||||
let id = list.id();
|
||||
ui.ui_mut().animate(id);
|
||||
|
||||
The two calls are deliberate rather than folded into `fling`: the velocity
|
||||
is the list's business and whether anything animates at all is the frame
|
||||
loop's, and a caller driving its own frames (the benchmark, the headless
|
||||
tests) still calls `tick_fling` directly.
|
||||
|
||||
**`FlingCalculator` needs the real display density, and its coefficient
|
||||
was wrong.** `new(density)` takes physical pixels per `dp` and the
|
||||
velocity handed to it must be in those same physical pixels -- the
|
||||
density does *not* cancel out, contrary to what that type's doc used to
|
||||
claim. Separately, `physical_coefficient` multiplied by the scroll
|
||||
friction (0.015) where AOSP multiplies by its own tuning constant 0.84, a
|
||||
factor of 56 inside an exponential. Together they gave an ordinary flick a
|
||||
**45-second** coast, which nobody could see while flings never animated.
|
||||
`List` reads its density from the painter now, and
|
||||
`a_flick_lasts_what_aosps_own_formula_says_it_does` pins the absolute
|
||||
numbers (0.59s and 621px for 3000px/s at density 2.75) against AOSP's
|
||||
formula -- the check every previous test could not make, because they all
|
||||
compared the calculator with itself.
|
||||
|
||||
**`MOVE_CHAIN_LIMIT` is 64, not 16**, in `render_state.rs` and
|
||||
`shader.wgsl` alike. It bounds a walk so a cyclic `parent` cannot hang
|
||||
either side; it was never meant as a claim about tree depth, and the
|
||||
transcript screen's composer field sits 17 slots below the root. Past the
|
||||
bound both walks silently stop summing, so a widget draws and hit-tests
|
||||
short with nothing to say so; the CPU assert now prints the chain, so a
|
||||
cycle and a deep tree can be told apart.
|
||||
|
||||
## 2026-09-06: tool cards, `ToolState`, and a screen that knows whether its session is working
|
||||
|
||||
`transcript_ui::tool` is new: a card per tool call, a group per run
|
||||
|
||||
Reference in new issue
Block a user