fix(ui): raise pad redraw threshold above buffer cap to fix history scroll #133
Reference in New Issue
Block a user
No description provided.
Delete Branch "fix/history-scroll-pad-redraw-storm"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Paging up through a long chat history (flat-file backend) regressed after the upstream sync merge: scrolling lagged ~10 s per page, the view jumped/“got stuck”, and a block of messages was never drawn (reported ~30–170 missing, depending on history length). This restores smooth, lossless history scrolling with a one-line behavioural change plus a small
win_redraw()cleanup.Root cause
The merge replaced the fixed
PAD_SIZE = 10000pad with a dynamically grown pad and added_win_ensure_pad_capacity()withPAD_THRESHOLD = 3000. When the pad grows past the threshold, that helper triggers a fullwin_redraw()to reclaim space — but it is called from the hot print path (_win_print_internal) on every message.PAD_THRESHOLD (3000)sits below the buffer line cap (PAD_SIZE - PAD_SIZE/10 = 9000, enforced by trimming inbuffer.c). So for any chat longer than 3000 rendered lines, every print during a history fetch re-enteredwin_redraw():chatwin_db_history()prepends a batch (MESSAGES_TO_RETRIEVE = 100) and normally does one redraw per fetch; the storm turned that into dozens of full-buffer redraws per page-up → the ~10 s lag.y_start_pos/_linesbookkeeping.win_page_up()then computed the smooth-scroll offset from a stalefirst_entry->y_start_pos, so*page_startsnapped to 0 — the viewport jumped to the top and skipped the messages in between (the “missing” block + the*page_start adjusted to 0 ... Previous value: -Nlog line firing mid-history).The flat-file backend (
_flatfile_get_previous_chat) is byte-identical across the regression range (SHA1 unchanged; last touched in an ancestor of the healthy commit). The empty-vs-success decision behaves the same in both builds, soWIN_SCROLL_REACHED_TOPis the real top, not a premature stop — the fault is entirely in the UI pad path.Fix
PAD_THRESHOLD3000 → 12000. Above the ~9000 buffer cap, so the reclaim redraw can never fire during legitimate scrolling (pad in the scroll steady state isbuffer->lines + 100 ≤ ~9100, and a 100-message prepend batch climbs at most ~a few hundred lines above that). It only fires to drop dead pad space accumulated by a long, append-only session that never scrolls or switches windows — which is exactly the bound the pre-merge code got from the fixedPAD_SIZEoverflow-reset.win_redraw()sizes the pad once tobuffer->lines + 100instead of shrinking toPAD_MIN_HEIGHTand regrowing+100per entry, removing the residual ~90wresize()calls per redraw and restoring pre-merge smoothness.Net diff: 4 insertions / 3 deletions in
src/ui/window.c._win_ensure_pad_capacity()and all call sites are unchanged vsmaster.Parity with pre-merge (no regression)
3b673150)The only residual edge — a single message that renders ≥
PAD_THRESHOLDlines could re-enter the per-print redraw — already existed pre-merge (at ≥10000, via the overflow branch) and is tracked as a separate hardening task (see the dead-space reclaim issue).Testing
./bootstrap.sh && ./configure && make,-Werrorclean).Risk
Low. Restores the pre-merge mechanism at a safe threshold; single file; no API/header changes.
@@ -2176,2 +2176,3 @@int cols = getmaxx(window->layout->win);wresize(window->layout->win, PAD_MIN_HEIGHT, cols);int needed = window->layout->buffer->lines + 100;wresize(window->layout->win, needed > PAD_MIN_HEIGHT ? needed : PAD_MIN_HEIGHT, cols);why not use
MAXmacro from GLib?b54b64b223to3f6b8f69fd