Compare commits

...

2 Commits

Author SHA1 Message Date
3fd48a1f44 fix(ui): reclaim pad by dead space instead of absolute height
All checks were successful
CI Code / Check spelling (pull_request) Successful in 18s
CI Code / Check coding style (pull_request) Successful in 31s
CI Code / Linux (debian) (pull_request) Successful in 4m34s
CI Code / Linux (ubuntu) (pull_request) Successful in 4m46s
CI Code / Code Coverage (pull_request) Successful in 8m12s
CI Code / Linux (arch) (pull_request) Successful in 10m47s
Variant A (PAD_THRESHOLD=12000) bounds the pad but still re-enters win_redraw() from the print path on every message once the *live* buffer renders >= the threshold — reachable with a single oversized message (huge paste, narrow terminal, crafted incoming), reintroducing the per-message redraw storm.

Trigger the reclaim redraw on dead space (getcury - buffer->lines) instead of absolute pad height. After a redraw the cursor equals buffer->lines, so dead space is 0 regardless of buffer size: the reclaim can never fire while scrolling, and an oversized message no longer storms (and is shown in full rather than clipped). Dead space only accrues in a long append-only session that trimmed old entries — exactly when reclaiming is wanted.
2026-06-09 14:24:35 +03:00
3f6b8f69fd fix(ui): raise pad redraw threshold above buffer cap to fix history scroll
All checks were successful
CI Code / Check spelling (pull_request) Successful in 19s
CI Code / Check coding style (pull_request) Successful in 30s
CI Code / Code Coverage (pull_request) Successful in 3m21s
CI Code / Linux (debian) (pull_request) Successful in 4m49s
CI Code / Linux (ubuntu) (pull_request) Successful in 4m55s
CI Code / Check coding style (push) Successful in 31s
CI Code / Check spelling (push) Successful in 19s
CI Code / Linux (arch) (pull_request) Successful in 6m39s
CI Code / Linux (debian) (push) Successful in 4m16s
CI Code / Code Coverage (push) Successful in 3m29s
CI Code / Linux (ubuntu) (push) Successful in 4m32s
CI Code / Linux (arch) (push) Successful in 10m51s
PAD_THRESHOLD (3000) sat below the buffer line cap (PAD_SIZE - PAD_SIZE/10 = 9000), so _win_ensure_pad_capacity() fired a full win_redraw() from the hot print path on every message once a chat exceeded 3000 rendered lines. During history paging this turned one redraw per fetch into dozens, corrupting per-entry y_start_pos (offset jumps, dropped/skipped messages) and causing ~10s lag per page. The flat-file backend was byte-identical across the regression; the fault was purely in the UI pad path from the upstream merge.

Raise PAD_THRESHOLD to 12000 (above the cap) so the reclaim redraw only fires to drop dead pad space in long append-only sessions, never during scrolling. Also size the pad once to buffer->lines+100 in win_redraw() instead of shrinking to PAD_MIN_HEIGHT and regrowing per entry, removing the residual per-redraw wresize churn.
2026-06-08 16:03:33 +03:00

View File

@@ -43,7 +43,7 @@
#include "ai/ai_client.h"
static const int PAD_MIN_HEIGHT = 100;
static const int PAD_THRESHOLD = 3000;
static const int PAD_DEAD_SPACE_LIMIT = 2000; // reclaim once the pad holds this much dead space (cursor past live buffer); size-independent, so it never fires while scrolling
static gboolean _in_redraw = FALSE;
static void
@@ -56,9 +56,10 @@ _win_ensure_pad_capacity(ProfWin* window, WINDOW* win, int lines_needed)
int cur_height = getmaxy(win);
int cur_width = getmaxx(win);
if (lines_needed >= cur_height - 1) {
// If we are getting too large, trigger a redraw to clean up old lines
// but only if we are not already in a redraw process.
if (window && cur_height >= PAD_THRESHOLD && !_in_redraw) {
// redraw to reclaim dead pad space (cursor far past live buffer, e.g. a long
// append-only session); dead space never accrues while scrolling, only here
int dead = window ? lines_needed - window->layout->buffer->lines : 0;
if (window && dead > PAD_DEAD_SPACE_LIMIT && !_in_redraw) {
win_redraw(window);
} else {
// resize to required lines + some buffer for next messages
@@ -2172,9 +2173,10 @@ win_redraw(ProfWin* window)
unsigned int size = buffer_size(window->layout->buffer);
_in_redraw = TRUE;
// shrink pad back to minimum size and erase it
// size the pad to fit the whole buffer (plus headroom) and erase it
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, MAX(needed, PAD_MIN_HEIGHT), cols);
werase(window->layout->win);
for (unsigned int i = 0; i < size; i++) {