vim-patch:9.2.0881: 'smoothscroll' position is lost when the window height changes

Problem:  With 'smoothscroll' the scroll position of a window is lost when
          its height changes.
Solution: Only reset the skipped columns when 'smoothscroll' is off, where
          they just serve to keep the cursor visible.

closes: vim/vim#20885

17f3923b8c

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-07-31 10:52:37 +08:00
parent f9040dbe03
commit f7cc79edf4
3 changed files with 34 additions and 6 deletions

View File

@@ -6946,13 +6946,14 @@ void scroll_to_fraction(win_T *wp, int prev_height)
wp->w_wrow = line_size;
if (wp->w_wrow >= wp->w_view_height
&& (wp->w_view_width - win_col_off(wp)) > 0) {
wp->w_skipcol += wp->w_view_width - win_col_off(wp);
// The cursor must be visible, override the scroll position.
colnr_T skipcol = wp->w_view_width - win_col_off(wp);
wp->w_wrow--;
while (wp->w_wrow >= wp->w_view_height) {
wp->w_skipcol += wp->w_view_width - win_col_off(wp)
+ win_col_off2(wp);
skipcol += wp->w_view_width - win_col_off(wp) + win_col_off2(wp);
wp->w_wrow--;
}
wp->w_skipcol = skipcol;
}
} else if (sline > 0) {
while (sline > 0 && lnum > 1) {
@@ -7032,7 +7033,11 @@ void win_set_inner_size(win_T *wp, bool valid_cursor)
// There is no point in adjusting the scroll position when exiting. Some
// values might be invalid.
if (valid_cursor && !exiting && (*p_spk == 'c' || wp->w_floating)) {
wp->w_skipcol = 0;
// With 'smoothscroll' w_skipcol is the scroll position, keep it.
// Otherwise it only keeps the cursor visible and is computed again.
if (!wp->w_p_sms) {
wp->w_skipcol = 0;
}
scroll_to_fraction(wp, prev_height);
}
redraw_later(wp, UPD_SOME_VALID);

View File

@@ -1245,7 +1245,6 @@ describe('smoothscroll', function()
|
]])
exec('set showtabline=2')
feed('<C-E>')
screen:expect([[
{5: }{100:2}{5:+ [No Name] }{2: }|
{1:<<<}e text with some text with some text |
@@ -1261,7 +1260,7 @@ describe('smoothscroll', function()
|
]])
exec('set winbar=winbar')
feed('<C-w>k<C-E>')
feed('<C-w>k')
screen:expect([[
{5: }{100:2}{5:+ [No Name] }{2: }|
{5:winbar }|

View File

@@ -1310,6 +1310,30 @@ func Test_smoothscroll_next_topline()
bwipe!
endfunc
func Test_smoothscroll_keep_skipcol()
call NewWindow(10, 40)
setlocal smoothscroll
call setline(1, ['abcde '->repeat(150)]->repeat(2))
exe "norm! 10\<C-E>"
redraw
let skipcol = winsaveview().skipcol
call assert_notequal(0, skipcol)
" Changing the height of the window must not reset the scroll position.
resize -3
resize +3
redraw
call assert_equal(skipcol, winsaveview().skipcol)
" Using the autocommand window changes the height as well.
call bufload(bufadd(''))
redraw
call assert_equal(skipcol, winsaveview().skipcol)
bwipe!
endfunc
func Test_smoothscroll_long_line_zb()
call NewWindow(10, 40)
call setline(1, 'abcde '->repeat(150))