Skip to content

Fix search-active scroll lock (issue #19)#21

Merged
aydiler merged 1 commit into
mainfrom
fix/search-scroll-lock
May 23, 2026
Merged

Fix search-active scroll lock (issue #19)#21
aydiler merged 1 commit into
mainfrom
fix/search-scroll-lock

Conversation

@aydiler
Copy link
Copy Markdown
Owner

@aydiler aydiler commented May 23, 2026

Fixes #19.

Summary

With the find bar open, wheel-scrolling away from the active match snapped the view back every frame, leaving the user locked near the result. Esc to dismiss the bar restored scrolling — the workaround documented on the issue.

Root cause

The post-render corrective scroll in render_tab_content was designed as stage 2 of a two-stage scroll (line-ratio estimate → snap to renderer-recorded active_search_y). After commit 21d43c5 disabled show_scrollable virtualization, the renderer started walking the full event stream every paint, and record_active_search_y_viewport fires unconditionally per Active highlight segment (egui's clip rect culls painting but not widget layout). So active_search_y became perpetually fresh, and the corrective block — which had no guard for "user just scrolled" — snapped back every frame the match was off-screen.

Fix

One-shot correct_active_search_pending: bool on Tab. Set by scroll_to_active_match (called from jump_match / maybe_rebuild_search). The corrective block is now gated on the flag and clears it after running once. Two-stage scroll still converges in 1–2 frames; subsequent wheel input is no longer overridden.

Full root-cause / repro write-up: docs/devlog/031-search-scroll-lock.md. LESSONS entry added.

Test plan

  • Xvfb + xdotool 500 wheel-down events on a 3-page test doc — net scroll went from 16 px (213 snap-back frames) to ~2800 px (0 snap-backs after initial paint).
  • User-confirmed on real display.
  • CI green.

With the find bar open, wheel-scrolling away from the active match snapped
the view back to it every frame, leaving the user locked near the active
result. Esc to close the bar restored scrolling — the documented workaround
on the issue.

Root cause: the post-render corrective scroll block in render_tab_content
was designed as stage 2 of a two-stage scroll (line-ratio estimate, then
snap to the renderer-recorded active_search_y). After commit 21d43c5
disabled show_scrollable virtualization, the renderer started walking the
full event stream every paint — and record_active_search_y_viewport fires
unconditionally per Active highlight segment, since egui's clip rect culls
painting but not widget layout. So active_search_y became perpetually
fresh and accurate, and the corrective block (which had no guard for
\"user just scrolled\") snapped back every frame the match was off-screen.

Fix is a one-shot correct_active_search_pending bool on Tab. Set by
scroll_to_active_match (called from jump_match / maybe_rebuild_search) so
the two-stage scroll still converges; cleared inside the corrective block
after one frame so subsequent wheel input is not overridden.

Verified with Xvfb + xdotool 500 wheel-down events on /tmp/search-repro.md:
net scroll went from 16 px (pre-fix, 213 snap-back frames) to ~2800 px
(post-fix, 0 snap-backs after initial paint). User-confirmed on real
display.
@aydiler aydiler merged commit c2ee24d into main May 23, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

search scroll bug

1 participant