test #23

Merged
brian merged 2 commits from test into main 2026-08-28 06:20:29 +00:00
Owner
No description provided.
The front-buffered layer is raised by a repaint, and a repaint was being asked
for on every recomposition of the day screen. `setPalette` invalidated
unconditionally, and the host pushes the palette into every surface on each
`AndroidView` update pass — with the palette itself rebuilt from theme colours
each time, so even an unchanged one arrived as a fresh instance. Scrolling a day
composes rows as they arrive, so the layer was going up with nobody drawing into
it, and it sits above the whole window where no Compose clip reaches it: the page
was painted over the toolbar and the day's files for as long as it stayed up.

The engine now holds the palette it is drawing in and takes a new one only when
it differs; `pageType` gets the same guard, for the same reason. The screen
remembers the palette instead of rebuilding it, and the front-buffered surface
asks the engine before touching its render thread's copy.

Folding is quicker too, for the repaints that are real. A page scrolled back into
the list repaints with no pen behind it, and holding the layer up for the full
150 ms settle wore it across the toolbar on the way past; those fold after one
frame instead. The pen's own settle is untouched — committing between letters is
what that delay exists to avoid.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Measured on the tablet, not reasoned about: with low-latency ink on, the
front-buffered layer was composited at displayFrame [21 162 1419 2139] with no
crop, indefinitely, with nobody touching the screen. That layer sits above the
whole window and Compose cannot clip it — SurfaceView only honours ancestor
clipping under Android 15's clip_surfaceviews flag — so the page was painted over
the toolbar and the day's files for the rest of the session.

The cause is in graphics-core 1.0.2. `commit()` refuses while the view thinks a
render is outstanding, and returns having done nothing: no exception, no
callback, no return value. Its count of outstanding renders is only ever cleared
by a completion that matches it exactly, so as soon as renders are asked for
faster than they complete — which is what handwriting does — the count sticks
above zero for the life of the view. Logging it showed four renders against one
completion and the count pinned at four; from there every commit was a no-op, and
`onDraw` stopped drawing the scene bitmap too, since that is guarded on the same
answer. So the page was only visible *because* the layer was stuck up.

`cancel()` resets the count but is gated on a flag `commit()` clears, so it was
dead on arrival too. Clearing the count directly and then committing does work:
the layer folds on the first try, the count returns to zero, the snapshot lands,
and the page goes back to being drawn — and clipped — like any other view.
Reflection into a library we ship ourselves is a poor thing to need; it is at
least checked, and reads back whether the layer really went down.

Two more holes closed. The fold is verified rather than trusted, and a layer that
will not go down after a second of asking stands the fast path down instead of
leaving the page over the toolbar. And detaching folds first: a row scrolled out
of the day with its buffer up left an orphaned layer hanging over the app with
nothing alive to fold it.

Verified on a Tab S9 FE over adb: twelve scroll passes and two strokes leave no
FrontBufferedLayer composited at all, ink draws and survives the fold, and the
toolbar, the files row and the pinned page header stay visible throughout.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
brian merged commit 7f51cf66b4 into main 2026-08-28 06:20:29 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
brian/Journal!23
No description provided.