2ec0fee84c1abf5599a3c4bd0ad10381aa45ea84
docs/REVIEW-2026-09-07.md's D4. `on_touch_event` took its one anchor as `(Instant::now(), event.event_time_nanos())` from the first MotionEvent the view ever sees, and dated every later sample as `anchor_at + (sample - anchor).max(0)`. An event's historical samples are by definition *older* than its own event_time, so if that first event is a Move -- the Down went to another view, or the view was attached mid-gesture -- its whole batch clamps onto one instant: three samples at the same time make the Lsq2 fit degenerate and the flick reads 0 px/s. In a debug build the ordering debug_assert fired first, and it was comparing against `anchor_nanos`, a value from a different event, so it was also the wrong comparison for the first sample of every later event. The arithmetic moves into `sense::PointerClock`, which anchors at `now - (event_time - oldest_sample)` and carries the last sample seen across events, so `sample()`'s ordering assert compares against the previous event's last sample. It lives in `sense` rather than in the android backend because `iris::android` is cfg'd out everywhere but the device, and this is exactly the arithmetic that wanted a test off one: `the_first_events_batched_samples_are_dated_apart` reports [0ns, 0ns, 0ns] against the old anchoring. The assert stays a `debug_assert!` and now says why in a comment: it runs once per touch sample, hundreds a second on a batching 120Hz screen, and a mis-ordered sample degrades a velocity rather than drawing something wrong. Also drops the stale reference to `VelocityTracker::add_sample` in the comment above it (the review's rule finding); the method is `add_position`. Verified: `cargo test --lib -p iris` and `cargo ndk -t x86_64 -P 29 check -p iris` clean, fmt and clippy clean. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Languages
Rust
53%
Kotlin
44.4%
Shell
2.6%