docs: record the keyboard-wipe fix, the dp unit and the header fix

docs/IRIS.md's 2026-09-06 entry (public API), docs/LAYOUT.md's "Density:
Len::dp" design section, IRIS_TODO.md's density-unit item ticked, and
docs/RUST.md's P0 box gets the investigation: the keyboard-wipe
hypothesis and confirmation, the blur root cause and why the dp unit
turned out to be the same fix, the header cause, and what remains
unverified (an emulator screenshot of the keyboard fix, and Iris's real
phone).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
irisandClaude Fable 5.1 committed 2026-09-06 00:40:59 -04:00
1 parent 0b587629e6
commit 80c2eadec9
4 files changed
+186 -2

No files matched your search

+52
View File
@@ -861,6 +861,58 @@ unspecified rather than getting them wrong:
conditions, so the remaining slack was accepted rather than chased
further.
## Density: `Len::dp`, resolved at `apply_rest` time (2026-09-06)
Iris asked for a third length kind beside `abs` (physical pixels) and
`rel`/`rest` (a fraction of the parent) — IRIS_TODO.md's "density-
independent length unit" — after the P0 phone pass found 16px text
drawing at roughly a third size on a real phone. The fix that shipped
first (RUST.md's P0 box) was a global stopgap: divide the whole window
into a "logical" coordinate space (physical ÷ `content_scale`) and let
the shader's NDC mapping stretch it back up onto the real framebuffer.
That fixed the *size* but not the *sharpness* — a glyph rasterised at the
small, pre-stretch size and then stretched onto more physical pixels than
it has texels for is blurry, which is exactly what Iris's next report
said.
**The fix**: `Len` gained a `dp` field, resolved against a `density: f32`
(physical pixels per dp) at the one place a `Len` becomes a `UiScalar`
(`Len::apply_rest`) — `abs + dp * density`. `density` lives on
`UiRenderState` (`set_density`/`density()`) and `Painter` (`density()`),
set once from `DisplayMetrics.density` in `android::view::new_peer`; the
desktop backend has no per-monitor density wired up yet and stays at
`1.0`. Every layout call site that used to call `.apply_rest()`/
`.to_uivec2()` now passes `painter.density()` (nine call sites — `Span`,
`Sized`, `MaxSize`, `Aligned`, `Scroll`, `List::place`, and
`UiRenderState::reposition` itself). This also meant the Android
boundary's global logical-space stopgap could come out entirely: window
size, touch coordinates and insets are physical pixels again, matching
`AndroidRenderer`'s own swapchain resolution, with `dp` doing the
per-length work the global divide used to do for everything at once.
**Text is the case that needed more than the `Len` plumbing.** A widget's
`font_size`/`line_height` are plain `f32`, not routed through `Len` at
all (there is no sensible `rel`/`rest` for a font size). `TextBuffer::
shape` now takes `density` directly and multiplies `font_size`/
`line_height` (and any span override) by it before handing them to
parley — so the size that reaches both the line-breaker and the
rasteriser (`TextData::place`, which reads back whatever `shape` set) is
the display's *physical* size, and the glyph atlas holds a bitmap at the
resolution it is actually shown at. `GlyphKey.size` already keys on the
resolved size, so a cache entry is naturally per-physical-size with no
further change. The one caller with no `Painter` to read density from
(`TextEditCtx::layout`, cursor movement and hit-testing) reads a second
copy kept directly on `TextData` (`TextData::density`) instead — an
accepted duplication rather than threading a `Painter` into every input
handler for one field, the same tradeoff `AndroidRenderer::content_scale`
already makes for the Diagnostics page.
**What did not change**: `rel`/`rest` are unaffected (already
resolution-independent, a fraction of the parent). `Span::gap` and
`Padding`'s four sides moved from bare `f32` to `Len` so `dp(...)` works
on them the same as any other size; a bare number is still `abs`,
physical pixels, unchanged.
## For IRIS.md
When this lands, copy this entry into `IRIS.md` (newest first):