Two bugs made the search jump land in the wrong place:
1. Double-counted visual lines. The visual line at which logical line li
starts is exactly VisualsBefore(li); the code computed li +
VisualsBefore(li), i.e. 2x the intended depth with the all-ones
pre-shape estimates. The MaxScroll clamp masked it on small files;
long files landed far off. Now uses VisualsBefore(li) (fallback li).
2. Truncation vs non-integer line height. Line height is 16.8dp, so
floor(V*lh) sits just above the target line's top and the window
decomposition floors to the line above it. The target now rounds UP:
ceil(V*lh) is always in [V*lh, (V+1)*lh), so the viewport top
decomposes to exactly V. The line-height source now also prefers the
shaped GlyphLayout.LineHeight like scrollVisualDecompose/MaxScroll.
3. Estimate settle. On long wrapped files the lines above the target are
still estimated at 1 visual line when the jump happens, so the landing
can be short. The scroll now arms a bounded settle (SettleByte /
SettleScroll / SettlePasses on FindState); after each layout-feedback
wrap-count correction the logic goroutine re-runs the target and
re-scrolls until it converges, is exhausted (4 passes), or the user /
the MaxScroll clamp moves the viewport (which cancels it). Edits,
query changes, close, and file open disarm the settle.
Tests: round-trip scroll-target on a 2000-line wrapped file, the
no-wrap identity, settle correction/convergence, and settle cancellation
on user scroll.
- pool: SearchTask + FindSubstring (case-insensitive substring scan with
query generation for stale-result dropping)
- editor: FindState on EditorState; find bar handlers (ToggleFind/FindNext/
FindPrev/FindClose); worker-pool scan of the in-memory content; edit-aware
offset remapping (shift after, drop overlapping); next/prev with
wrap-around, selection + scroll to match; main-owned find_bar input
forwarded via FindQueryChan (browser search_bar precedent)
- ui: find-bar layout below the margin-free top bar; search icon on the top
bar right; new search/close/chevron_up/chevron_down icons
- logic: findQueryChan, TypeSearch result handling, findReset on open
- frame: FindQuery field (main syncs the widget text like Query)
- tests: pool scan tests, find-state unit tests (remap, nav, gen gate,
focus), e2e find bar + navigation + edit-survival on real files
- docs: spec/architecture/development_plan updated (search implemented,
channel/task tables)