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
+62
-11
@@ -535,22 +535,31 @@ agent ticks it here with the evidence.
|
||||
`row.rs`'s `build_text_row` is where one would go, keyed to something
|
||||
stable per row (its sender + a short excerpt, matching what a screen
|
||||
reader announcing a chat message would say).
|
||||
- [ ] **A tappable link and a background chip behind inline code.**
|
||||
Both need per-range glyph geometry that `TextEditCtx` does not expose
|
||||
outside `iris::widget::text` (`edit.rs`'s `layout()` helper is
|
||||
private) — see `markdown.rs`'s module doc for the exact shape the fix
|
||||
would take (the same primitive `TextEdit::draw`'s own selection
|
||||
highlight already uses internally,
|
||||
`iris/src/widget/text/edit.rs:99`).
|
||||
- [x] **A tappable link** — done 2026-09-06 (P1a). `TextEditCtx::
|
||||
byte_at(pos, size)` answers which byte a tap landed on without
|
||||
handing out the parley layout, `GestureOutcome::Tapped` says the
|
||||
press committed to neither a pan nor a selection, and
|
||||
`iris::platform::OpenUrl` is the capability each backend implements
|
||||
(`xdg-open`/`open`/`start`; an `ACTION_VIEW` intent on Android,
|
||||
deferred to `after_input` the way `pending_show_keyboard` is).
|
||||
- [ ] **A background chip behind inline code.** Still needs per-range
|
||||
glyph *geometry* — a run's boxes, not one offset — which
|
||||
`TextEditCtx` does not expose outside `iris::widget::text`
|
||||
(`edit.rs`'s `layout()` helper is private). The same primitive
|
||||
`TextEdit::draw`'s own selection highlight uses internally,
|
||||
`iris/src/widget/text/edit.rs:99`. `byte_at` above deliberately did
|
||||
not open that up: a tap needs one offset and a chip needs the run.
|
||||
- [ ] **`Selection`'s anchor-row shortcut.** The row a drag started in
|
||||
is selected in full (`select_all`) the moment the drag leaves it,
|
||||
rather than "from the click point to whichever edge points away from
|
||||
the drag" — needs the same private `layout()` access as the item
|
||||
above. `selection.rs`'s module doc has the exact reasoning.
|
||||
- [ ] **No syntax highlighting inside a fenced code block.**
|
||||
`client_core::highlight` exists (built for the file explorer) and
|
||||
could feed per-token `SpanStyle`s into a code block's span; wiring it
|
||||
in was not attempted this pass.
|
||||
- [x] **Syntax highlighting inside a fenced code block** — done
|
||||
2026-09-06 (P1a). `client_core::highlight::spans_of` by language,
|
||||
converted from its char indices to `SpanStyle`'s byte offsets, in
|
||||
the same Catppuccin palette `Theme.kt` uses. A language the scanner
|
||||
has no rules for stays plain rather than being coloured by the
|
||||
nearest one's.
|
||||
|
||||
- [ ] **Masks defined relative to each other.** Wanted: mask A multiplies
|
||||
by something *and also* applies mask B — a mask can reference a parent
|
||||
@@ -570,6 +579,48 @@ agent ticks it here with the evidence.
|
||||
everything, the same way input is**. Whatever the mechanism, a widget
|
||||
that does not animate must pay nothing and import nothing for it.
|
||||
|
||||
## Found by P1a (2026-09-06)
|
||||
|
||||
- [x] **`Rect` claimed to be size-independent, and it is not.** A `Rect`
|
||||
fills whatever region it is handed, so `draw_inner`'s size-independent
|
||||
fast path -- which rewrites primitives with
|
||||
`r.outside(&from).within(®ion)` rather than redrawing -- could not
|
||||
reproduce its `draw`, and a `.background(rect(..))` kept the size of
|
||||
the *provisional* full-region pass `Span` does in phase 1. One fenced
|
||||
code block's panel covered every block below it and every row below
|
||||
that. Fixed in `iris/src/widget/rect.rs`; the reason is written at the
|
||||
definition. Suspect the same cause for anything else tinted with a
|
||||
background rect.
|
||||
- [ ] **A wrapped transcript row trips `reposition`'s debug assert.**
|
||||
*"widget ... is both moved by its parent's own layout (`mov`) and
|
||||
repositioned within it"*, raised from `List::place`. Repro: change
|
||||
`.wrap(!verbatim)` to `.wrap(true)` in `transcript-ui/src/row.rs`'s
|
||||
`build_block` and run `iris/run-headless.sh transcript --shot
|
||||
/tmp/x.png -- -p transcript-ui`. Survives the `Rect` fix above and is
|
||||
not specific to any block kind -- it appears once the row is tall
|
||||
enough. The shipping configuration does not reach it (verbatim blocks
|
||||
do not wrap) and the Android bench runs clean with assertions live,
|
||||
but it is a real disagreement about who owns a widget's move slot and
|
||||
should be settled before more of P1 leans on `List`.
|
||||
- [ ] **Desktop colours are washed out: the winit surface is sRGB and
|
||||
the shader writes the palette's bytes as linear.** Mocha Crust
|
||||
(17,17,27) is drawn as (73,73,91), measured off
|
||||
`run-headless.sh --shot`. Android is correct, so this is the surface
|
||||
format rather than the palette -- but it makes the desktop build
|
||||
useless as a colour reference, which is exactly what P1a needed it for
|
||||
when the emulator could not draw glyphs.
|
||||
- [ ] **The emulator cannot draw iris's glyphs.** Under `-gpu host` with
|
||||
Vulkan disabled (Mesa 26.2.2 / virgl -- what `emu` does on this
|
||||
machine) every character renders as a solid filled box: the atlas
|
||||
sample's alpha reads 1, which is what an incomplete GL texture returns
|
||||
(0,0,0,1). Not new (`20303e0` does it too) and not the platform's
|
||||
(Compose draws text perfectly on the same AVD in the same minute).
|
||||
Enabling host Vulkan still dies at boot in gfxstream, and
|
||||
`EMU_GPU=software` gives SwiftShader Vulkan on which iris **SIGSEGVs
|
||||
in `surface_changed`**. Either of the last two would restore
|
||||
appearance testing on Android; today it has to be done on the desktop
|
||||
backend or on Iris's phone.
|
||||
|
||||
## Build (for the port)
|
||||
|
||||
Widgets `RUST.md`'s "The port, in order (decided 2026-09-05)" needs and
|
||||
|
||||
Reference in new issue
Block a user