From 51f1447d2a094ae0a7e1749da6e2dafe6fdc1883 Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Mon, 11 May 2026 16:29:27 +0000 Subject: [PATCH] patch 9.2.0472: popup: column jitters when scrolled outside viewport Problem: popup: column jitters horizontally when textprop is scrolled above the host window's top (after v9.2.0469) Solution: Compute the virtual column from the prop's actual line via getvcol() and translate it through prop_win's win_col_off / leftcol / wincol (Yasuhiro Matsumoto). popup_screenpos_above_top() probed textpos2screenpos() at prop_win->w_topline using the prop's own tp_col, so the returned screen_scol picked up topline's tab stops and multi-byte widths instead of the prop line's own. Once the textprop scrolled above the host's top, the popup's wincol jittered left/right every time a wider or narrower line rotated into the topmost slot. Compute the virtual column from the prop's actual line via getvcol() and translate it through prop_win's win_col_off / leftcol / wincol. Row extrapolation from topline is unchanged. closes: #20187 Signed-off-by: Yasuhiro Matsumoto Signed-off-by: Christian Brabandt --- src/popupwin.c | 24 +++++++++++++++++------- src/version.c | 2 ++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/popupwin.c b/src/popupwin.c index 5bd156367e..685c3cae7c 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -1482,11 +1482,15 @@ popup_geom_restore(win_T *wp, popup_geom_save_T *sv) /* * Compute a screen row for a textprop that has scrolled above the host - * window's top. textpos2screenpos() cannot return a row above topline, so we - * probe at topline to fill the screen_{scol,ccol,ecol} column mapping, then - * extrapolate a (possibly-negative) row by counting how many buffer lines lie - * between the prop and topline. The popup_topoff clip path then turns the + * window's top. textpos2screenpos() cannot return a row above topline, so + * compute the virtual column directly from the prop's *own* line and then + * extrapolate a (possibly-negative) row by counting how many buffer lines + * lie between the prop and topline. The popup_topoff clip path turns the * negative row into a top-clip animation as the prop rolls off the top edge. + * + * Probing at topline with the prop's tp_col would inherit topline's tab + * stops / multi-byte widths, so the popup's wincol would jitter every time + * a wider/narrower line scrolled into the topmost position. */ static void popup_screenpos_above_top( @@ -1499,10 +1503,16 @@ popup_screenpos_above_top( int *screen_ecol) { pos_T probe = *pos; + colnr_T scol = 0, ccol = 0, ecol = 0; + int coloff; - probe.lnum = prop_win->w_topline; - textpos2screenpos(prop_win, &probe, - screen_row, screen_scol, screen_ccol, screen_ecol); + probe.lnum = prop_lnum; + getvcol(prop_win, &probe, &scol, &ccol, &ecol, 0); + coloff = (int)win_col_off(prop_win) - (int)prop_win->w_leftcol + + prop_win->w_wincol + 1; + *screen_scol = (int)scol + coloff; + *screen_ccol = (int)ccol + coloff; + *screen_ecol = (int)ecol + coloff; *screen_row = prop_win->w_winrow + 1 - (int)(prop_win->w_topline - prop_lnum); } diff --git a/src/version.c b/src/version.c index 875c6f6740..3aff29a296 100644 --- a/src/version.c +++ b/src/version.c @@ -729,6 +729,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 472, /**/ 471, /**/