vim-patch:9.2.0885: scroll: 'smoothscroll' position is lost when the window is squeezed

Problem:  With 'smoothscroll' the scroll position in a long line is lost when
          a window is temporarily squeezed to a couple of lines, for example
          when opening and closing a help window.
Solution: When the cursor ends up in the skipped columns, skip up to the
          screen line the cursor is in instead of showing the start of the
          line.

closes: vim/vim#20892

15f8ba5cec

Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
zeertzjq
2026-08-01 08:28:59 +08:00
parent b08c588238
commit 86bbe41459
2 changed files with 34 additions and 3 deletions

View File

@@ -1896,9 +1896,19 @@ void scroll_cursor_top(win_T *wp, int min_scroll, int always)
} else if (wp->w_topline == wp->w_cursor.lnum) {
validate_virtcol(wp);
if (wp->w_skipcol >= wp->w_virtcol) {
// TODO(vim): if the line doesn't fit may optimize w_skipcol instead
// of making it zero
reset_skipcol(wp);
// Skip up to the screen line the cursor is in, so that the
// position in the line is kept.
int width1 = wp->w_width - win_col_off(wp);
int width2 = width1 + win_col_off2(wp);
int plines_off = 0;
if (width2 > 0 && wp->w_virtcol >= width1) {
plines_off = (wp->w_virtcol - width1) / width2 + 1;
}
int skipcol = skipcol_from_plines(wp, plines_off);
if (skipcol != wp->w_skipcol) {
wp->w_skipcol = skipcol;
redraw_later(wp, UPD_SOME_VALID);
}
}
}
if (wp->w_topline != old_topline

View File

@@ -1353,6 +1353,27 @@ func Test_smoothscroll_cursor_back_in_line()
bwipe!
endfunc
func Test_smoothscroll_squeezed_window()
setlocal smoothscroll
call setline(1, [repeat('x', 3000)] + repeat(['line'], 10))
exe "norm! gg10\<C-E>"
redraw
let skipcol = winsaveview().skipcol
call assert_notequal(0, skipcol)
let virtcol = virtcol('.')
" Squeezing the window to one line and restoring it must not scroll back to
" the start of the line.
new
wincmd _
close
redraw
call assert_notequal(0, winsaveview().skipcol)
call assert_equal(virtcol, virtcol('.'))
bwipe!
endfunc
func Test_smoothscroll_long_line_zb()
call NewWindow(10, 40)
call setline(1, 'abcde '->repeat(150))