From 16c39f42211ee4e6050f771b26c0061bee6ae0f6 Mon Sep 17 00:00:00 2001 From: Greg Pomerantz Date: Sun, 16 Aug 2026 20:59:42 -0400 Subject: [PATCH] doc: note GlyphLayout window-relative offset invariant Add the invariant that GlyphLayout offsets are relative to IMEWindowStartByte and that cursor positioning must add/subtract the window base. Record the second tap-to-cursor fix (base offset) alongside the earlier tapLocalY fix in the development plan. --- doc/architecture.md | 8 ++++++++ doc/development_plan.md | 11 +++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/doc/architecture.md b/doc/architecture.md index 44cd46a..d9e1012 100644 --- a/doc/architecture.md +++ b/doc/architecture.md @@ -210,6 +210,14 @@ Only the visible byte range is shaped and drawn each frame: memory to ~1 GB for a 10 MB file. Shaping ~50 lines keeps it small and flat. - The renderer reports `GlyphLayout` back via `LayoutChan`; logic derives `LastLineY` for scroll clamping and the max scroll offset. +- **`GlyphLayout` offsets are window-relative.** The shaper only sees the + visible window, so `GlyphLayout.ByteOffsets` (and `VisualLineStarts`, `Y`) + are relative to `IMEWindowStartByte`, not the file start. Any logic-goroutine + code that maps a glyph offset to the absolute `CursorPosition` (tap-to-position, + Home/End, vertical cursor move) must add the window base + (`IMEWindowStartByte`) before storing the cursor and subtract it before + searching the offsets. For a whole-file window the base is 0 (a no-op). + Getting this wrong snaps the cursor to the window top on scrolled large files. ### 6.3 IME (Android soft keyboard) diff --git a/doc/development_plan.md b/doc/development_plan.md index aa80ea7..398317f 100644 --- a/doc/development_plan.md +++ b/doc/development_plan.md @@ -16,11 +16,14 @@ rapid-commit desync fix (snippet/selection dedup). Phase 6 (2026-08-16) added a default-off in-app performance profiler and verified: scroll does not degrade at large offsets (10 MB file), scroll clamping is exact across 2→130,955-line files, and memory plateaus ~250 MB (no leak). Phase 7 (2026-08-16) verified -tap-to-position-cursor on-device and found + fixed a real bug: for large files -scrolled deep, `SetCursorFromPoint` clamped the cursor to the bottom of the +tap-to-position-cursor on-device and found + fixed two real bugs: (1) for large +files scrolled deep, `SetCursorFromPoint` clamped the cursor to the bottom of the viewport (a content-space vs window-relative Y mismatch from the Phase 3 windowing -refactor); it only worked on small files by luck. Fixed (`tapLocalY`), with -regression tests. Remaining: real-device swipe/autocorrect sign-off (the +refactor); fixed with `tapLocalY`. (2) the `GlyphLayout` byte offsets are +window-relative but the four cursor functions (tap, Home, End, vertical move) +treated them as absolute, so the cursor snapped to the window top; fixed by adding +the `IMEWindowStartByte` window base at each cursor boundary (`glyphBase`). Both +have regression tests. Remaining: real-device swipe/autocorrect sign-off (the emulator's AOSP/Gboard keyboard is a proxy). ## 1. Decision summary (updated)