iris: the fling curve was the identity function, and the keyboard was a targetSdk
Iris's 2026-09-07 phone report on ed04d4c: the resume glyph corruption is
fixed (item 4 closed with her evidence), flinging "seems to just be linear
velocity with an abrupt stop", and the keyboard still does not push
anything up. docs/RUST.md's new "The 2026-09-07 phone report" section has
the derivation and every number.
**The fling was arithmetically linear.** `android_fling_spline::
distance_fraction(t)` returned `t` for every `t`. Two halves of AOSP's
`SplineOverScroller` static initialiser had been transposed -- the
bisection solved the tension curve and the sample evaluated the P1/P2 one,
where AOSP does the opposite -- which made SPLINE_POSITION and SPLINE_TIME
identical; the lookup then bracketed `t` between SPLINE_TIME entries
instead of between even time steps, and the two cancelled to the identity.
Ported exactly now from OverScroller.java and androidx.compose.animation
1.12.0's SplineBasedDecay.kt, which agree line for line, as one table
indexed by even steps of time (AOSP's second table serves only
`adjustDuration`, which nothing here has, so it is deliberately not built
-- one array, one indexing rule). `FlingCalculator::velocity_at` is new
beside `position_at`, and `List::tick_fling` logs `iris fling tick:` with
the per-frame delta and speed.
Every existing test compared the calculator with itself -- monotonic,
signed, integrates to the closed form, deltas non-increasing -- and all of
them pass on a straight line. iris/benches/fling_spline_reference.py is an
independent hand transcription of both sources and supplies the numbers
now checked into `the_spline_matches_aosps_own_table` and
`a_flick_decelerates_the_way_aosp_says_it_does`;
`tick_fling_applies_shrinking_incremental_deltas` went from
"non-increasing" to "the last delta is under 80% of the first". Negative
control: with `sample` forced back to `t`, exactly those three fail.
Emulator (API 36, debug, force-gles): a released v=3750 decelerates
3746 -> 2624 -> 1834 -> 1144 -> 752 -> 449 -> 243 -> 83px/s over 32 frames
to t=0.664s; a flick into the end of the list stops there in one tick with
no overshoot; a tap 200ms into a fling ends it at 11 ticks.
**The keyboard: `targetSdk = 34`** in iris/android-app/app/build.gradle,
against compileSdk 37 and the Compose app's 37 -- and that app's keyboard
does push up on her phone. Below target 35 a window keeps the legacy
behaviour where adjustResize shrinks it for the IME, so
getInsets(ime()).bottom measures an already-shrunk window and is zero;
setDecorFitsSystemWindows(false) opts out of that and still takes on the
API 36 emulator here, which is why every test run passed. Now targetSdk 37.
That is a reading and not a measurement, so the other half is making the
phone able to answer it. MainActivity also registers a
WindowInsetsAnimation.Callback (onEnd re-reads getRootWindowInsets, so an
interrupted animation cannot freeze a value), which delivers the height
where only the animation path carries it and makes the push-up animate:
ime_bottom now arrives 509, 663, 833, 881, 883 instead of one jump.
`insets::Shared::updates` counts every dispatch and
`AndroidUiState::insets_report()` puts it in the Diagnostics pane --
screenshot-verified, `insets: dispatches=27 left=0 top=142 right=0
bottom=63 ime_bottom=0 ime_visible=false`. Iris has no logcat, and "the
listener never fired" and "it fired with a zero height" are otherwise the
same picture; dispatches=0 says so in words rather than showing defaults.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
7f4ea7e8fd
commit
73f956f8e0
11 files changed
+720
-120
No files matched your search
+50
-17
@@ -351,13 +351,27 @@ agent ticks it here with the evidence.
|
||||
Iris's report, verbatim, with a screenshot. Phone: Mali-G715 (Vulkan),
|
||||
`content_scale: 2.55`, 120Hz. Open until ticked with phone-side evidence.
|
||||
|
||||
- [ ] **"Fling still doesn't work."** *(Three defects fixed 2026-09-07;
|
||||
open until the phone says so. **The line to look for:**
|
||||
`adb logcat | grep "iris drag release"` -- `samples=1` or `span=0.0ms`
|
||||
means the batched samples are not reaching the tracker there, while a
|
||||
sensible span with `v=` in the thousands and
|
||||
`outcome=Released(Some(…))` means the gesture was measured right and
|
||||
anything still wrong is downstream.)* Second report; the emulator's
|
||||
- [ ] **"Fling still doesn't work."** -> on `ed04d4c`, 2026-09-07:
|
||||
*"flinging now does technically do something, but it seems to just be
|
||||
linear velocity with an abrupt stop."* **It was exactly that, and the
|
||||
arithmetic said so.** `distance_fraction(t)` returned `t` for every `t`
|
||||
-- a constant-speed slide for the whole duration, then a stop at full
|
||||
distance -- because two halves of AOSP's spline build loop were
|
||||
transposed, which made `SPLINE_POSITION` and `SPLINE_TIME` identical, and
|
||||
the lookup bracketed `t` between `SPLINE_TIME` entries rather than
|
||||
between even time steps. The two cancelled to the identity. Ported
|
||||
exactly now from `OverScroller.java` and
|
||||
`androidx.compose.animation:animation:1.12.0`'s `SplineBasedDecay.kt`
|
||||
(they agree line for line), with `iris/benches/fling_spline_reference.py`
|
||||
as an independent transcription supplying the numbers the tests assert
|
||||
on. Emulator, 2026-09-07: a released `v=3750` decelerates
|
||||
`3746 -> 2624 -> 1834 -> 1144 -> 752 -> 449 -> 243 -> 83px/s` across 32
|
||||
frames; a flick into the end of the list stops there in one tick with no
|
||||
overshoot; a tap 200ms into a fling ends it at 11 ticks instead of 32.
|
||||
**Open until the phone says so** -- a flick should now visibly slow
|
||||
before it stops. Its earlier three defects (the velocity, the missing
|
||||
animation registration, the 56x coefficient) are all still fixed and were
|
||||
never the linear part.* Second report; the emulator's
|
||||
`ui-trace` swipe flings (verified 2026-09-06 with `render()` counts),
|
||||
a finger on the phone does not. What differs: a real flick at 120Hz is
|
||||
batched by Android into few `MotionEvent`s with *historical* samples
|
||||
@@ -383,11 +397,29 @@ Iris's report, verbatim, with a screenshot. Phone: Mali-G715 (Vulkan),
|
||||
`EditText` shows the IME on every tap of a focused field; do the same
|
||||
(`FocusHost`: a tap on a focused field requests the IME, idempotent
|
||||
when it is already shown).
|
||||
- [x] **"Message box does not push up the scroll area."** *(Fixed
|
||||
2026-09-07: height and visibility are two JNI values now. Emulator:
|
||||
`iris insets: … bottom=883 ime_bottom=883 ime_visible=true`, composer
|
||||
box `31,2277..1048,2329` -> `31,1457..1048,1509`, and the list follows
|
||||
because it is `rest(1)` in the same `Span`.)* Since
|
||||
- [ ] **"Message box does not push up the scroll area."**
|
||||
**Reopened by the phone on 2026-09-07** -- *"similarly, the keyboard
|
||||
raising up does not push things upwards"* -- after being ticked on
|
||||
emulator evidence the day before (`ime_bottom=883`, composer box
|
||||
`31,2277..1048,2329` -> `31,1457..1048,1509`). The JNI half was right;
|
||||
what was wrong is one line of `iris/android-app/app/build.gradle`:
|
||||
**`targetSdk = 34`** against `compileSdk = 37`, while the Compose app in
|
||||
`app/` targets 37 and *does* push up on her phone. Below target 35 the
|
||||
window keeps the legacy behaviour, where `adjustResize` shrinks it for
|
||||
the IME and `getInsets(ime()).bottom` therefore measures zero;
|
||||
`setDecorFitsSystemWindows(false)` opts out of that and still takes on
|
||||
the API 36 emulator here, which is why every test run passed. Now
|
||||
`targetSdk = 37`, plus a `WindowInsetsAnimation.Callback` for the devices
|
||||
where only the animation path carries the height -- which also makes the
|
||||
push-up animate (`ime_bottom=509, 663, 833, 881, 883` instead of one
|
||||
jump). **This is a reading, not a measurement**: no Android 17 device is
|
||||
reachable from here. So the Diagnostics pane now prints
|
||||
`insets: dispatches=N left=… ime_bottom=… ime_visible=…` --
|
||||
**screenshot that line with the keyboard open.** `ime_bottom` in the
|
||||
hundreds and the composer risen means fixed; `dispatches` climbing with
|
||||
`ime_bottom=0` means the reading was wrong and the window is still being
|
||||
resized; `dispatches=0` means the listener is not firing at all, which is
|
||||
a third thing again.* Since
|
||||
`MainActivity` went edge-to-edge (`e12c708`), `adjustResize` no
|
||||
longer resizes the window, so the app owns the IME inset -- but
|
||||
`ime_bottom` is passed through JNI as the boolean `1`/`0` (the
|
||||
@@ -418,11 +450,12 @@ Iris's report, verbatim, with a screenshot. Phone: Mali-G715 (Vulkan),
|
||||
screenshotted the emulator's GLES path, where a resume may not
|
||||
destroy the surface at all.
|
||||
|
||||
**Fixed in `ba2afba`, with `clearing_the_atlas_re_renders_cached_text_
|
||||
instead_of_reusing_it` run and passing (2026-09-07). Ticked on the
|
||||
code; still wants phone-side confirmation** -- no emulator here has a
|
||||
Vulkan adapter, and the GLES path may not destroy the surface at all,
|
||||
so the emulator cannot reproduce the state Iris photographed.
|
||||
**Fixed in `ba2afba` and confirmed on the phone (Iris, 2026-09-07:
|
||||
"the resume glyph corruption is fixed").** Closed. The emulator could
|
||||
never have settled it -- no Vulkan adapter here, and the GLES path may
|
||||
not destroy the surface at all -- so the phone was the only place this
|
||||
could be answered, and it has been. `clearing_the_atlas_re_renders_
|
||||
cached_text_instead_of_reusing_it` is what keeps it.
|
||||
|
||||
The reading above is right and the mechanism is one step narrower than
|
||||
"cached text primitives". `IrisViewPeer::surface_changed`
|
||||
|
||||
Reference in new issue
Block a user