iris: a Rect is not size-independent, and P1a's block appearance verified
The defect P1a's screenshots found, and the one that mattered: `Rect::is_size_independent()` answered `true`. A `Rect` fills whatever region it is handed, so its content *is* the region -- and `draw_inner`'s fast path, which rewrites a widget's primitives with `r.outside(&from).within(®ion)` instead of redrawing it, cannot reproduce that once a region carries both `rel` and `abs`. What it looked like: a fenced code block's background kept the height of the provisional full-region draw `Span` does in its first phase, so one fence's panel covered every block below it and every row below that, with the text underneath laid out correctly. Likely the same cause as RUST.md's older "the composer bar's grey background is not drawn". Also here: a quote's bar is a `Stack` background behind padded text rather than a two-child `Span(Dir::RIGHT)` (one widget fewer and no provisional pass), and `transcript-ui`'s `transcript` example gains a row holding one of every block kind -- the fixture's own heading, paragraph, fence and table source, plus a list and a quote, which the fixture has neither of. docs/bench/p1a-2026-09-06/ has the pairs and docs/RUST.md's P1a box names what still differs. The iris half is from the desktop backend because this emulator cannot draw iris's glyphs at all (solid boxes, reproduced on the previous commit, with Compose drawing text correctly on the same AVD); both routes to Vulkan on this AVD were tried and both fail. Bench stream phase, assertions live, no abort: p50 53.0ms p90 108.6ms p99 132.0ms against 52.8/108.1/137.3 before -- unchanged. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
64f64b54e5
commit
69525bd131
11 files changed
+355
-34
No files matched your search
@@ -8,6 +8,55 @@ 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-06: a tap is its own gesture outcome, and opening a URL is a backend capability
|
||||
|
||||
Three related additions, all for following a markdown link.
|
||||
|
||||
**`iris::platform::OpenUrl`** is a new trait beside `attr::FocusHost`, and
|
||||
has the same shape: declared in `iris`, implemented once per backend (a
|
||||
detached `xdg-open`/`open`/`start` on the desktop, an `ACTION_VIEW` intent
|
||||
on Android, deferred to the next view callback exactly the way
|
||||
`pending_show_keyboard` is). A widget asks for the capability by bound --
|
||||
`Rsc::State: FocusHost + OpenUrl` -- instead of a caller threading a
|
||||
callback down through every builder. One method, not a general "run an
|
||||
intent": a narrower capability is a narrower thing to get wrong. Nothing
|
||||
is returned; the platform either shows a browser or does not, and both
|
||||
are outside the process.
|
||||
|
||||
**`GestureOutcome::Tapped`** is new. `Released(None)` used to mean both
|
||||
"the press ended having selected something" and "the press ended having
|
||||
done nothing at all", and only the second is a tap. Any caller that acts
|
||||
on a tap -- following a link -- must not also act when the finger was
|
||||
panning the list past that link, so the distinction is made once, in the
|
||||
gesture machine every widget already shares, rather than timed again per
|
||||
widget. `DragArbiter::is_undecided()` is what answers it.
|
||||
`Selection::drag` returns the outcome now instead of `()`.
|
||||
|
||||
**`DragArbiter`/`DragGesture` take an axis** (`::on(Axis)`; `::new()` is
|
||||
still vertical). A code fence pans across its own long lines exactly the
|
||||
way a transcript pans down its rows, and the two were the same state
|
||||
machine with `dx` and `dy` swapped. `WidgetLike::scrollable_on(axis)`
|
||||
joins `scrollable()` for the same reason. Before this, a horizontal
|
||||
`Scroll` existed but could not be dragged by a finger at all -- its
|
||||
arbiter only ever committed on the vertical axis.
|
||||
|
||||
Two smaller ones in the same pass. **`TextEditCtx::byte_at(pos, size)`**
|
||||
answers which byte of the text a tap landed on, doing the same
|
||||
region-relative transform `select` does, without handing out the parley
|
||||
layout a caller could shape against stale text. And **`Rect::radius` now
|
||||
takes a `Len`**, so a corner can be written in `dp` and come out the same
|
||||
physical size on every display; a bare number still means physical pixels.
|
||||
|
||||
**One behaviour change worth knowing about**: `Rect::is_size_independent()`
|
||||
answers `false` now. It answered `true`, and a `Rect` fills whatever
|
||||
region it is given -- so `draw_inner`'s fast path, which rewrites a
|
||||
widget's primitives in place instead of redrawing it, could not reproduce
|
||||
what `draw` would have done. A `.background(rect(..))` behind
|
||||
variable-height content kept the size of the provisional pass its parent
|
||||
`Span` had drawn it at, which on the transcript screen meant one code
|
||||
block's panel covering every block below it. Costs one primitive's redraw
|
||||
when a rect is resized.
|
||||
|
||||
## 2026-09-06: a transcript row is a column of blocks, and a block is the selection unit
|
||||
|
||||
`transcript-ui`'s row builder used to make **one** `TextEdit` per message.
|
||||
|
||||
Reference in new issue
Block a user