From: Hirohito Higashi Date: Sun, 2 Aug 2026 17:25:35 +0000 (+0000) Subject: patch 9.2.0896: scroll: 'smoothscroll' position is lost when splitting a window X-Git-Tag: v9.2.0897~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bd2970b041871bea99626c5ef701ae02216bc8c3;p=thirdparty%2Fvim.git patch 9.2.0896: scroll: 'smoothscroll' position is lost when splitting a window Problem: With 'smoothscroll' the position in a long line is lost when a window is split and closed again. Solution: With 'splitkeep' "screen" keep the skipped columns, they are part of keeping the same screen lines. Otherwise put the cursor in the row that keeps its relative position, instead of the last row. closes: #20912 Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: Hirohito Higashi Signed-off-by: Christian Brabandt --- diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index 3b2f65a9c9..a277a260f6 100644 --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -1,4 +1,4 @@ -*todo.txt* For Vim version 9.2. Last change: 2026 Aug 01 +*todo.txt* For Vim version 9.2. Last change: 2026 Aug 02 VIM REFERENCE MANUAL by Bram Moolenaar @@ -41,9 +41,6 @@ squeezed to a couple of lines, for example ":help" followed by ":close". In restore_snapshot_rec() restore more values from the snapshot, instead of calling frame_new_height() and frame_new_width(), especially w_skipcol. -With 'splitkeep' "screen" the scroll position is lost when splitting and -closing a window, win_fix_cursor() moves the cursor to another line. - When a help item can't be found, then open 'helpfile'. Search for the tag in that file and gtive E149 only when not found. Helps for a tiny Vim installed without all the help files. diff --git a/src/testdir/test_window_cmd.vim b/src/testdir/test_window_cmd.vim index f3aa38dc4a..dc670fa7c1 100644 --- a/src/testdir/test_window_cmd.vim +++ b/src/testdir/test_window_cmd.vim @@ -2034,6 +2034,25 @@ func Test_splitkeep_cmdheight() set splitkeep& cmdheight& endfunc +func Test_splitkeep_screen_smoothscroll() + set splitkeep=screen + setlocal smoothscroll + call setline(1, [repeat('x', 3000)] + repeat(['line'], 10)) + exe "normal! gg10\" + redraw + let skipcol = winsaveview().skipcol + call assert_notequal(0, skipcol) + + " Keeping the same screen lines also keeps the position in a long line. + split + close + redraw + call assert_equal(skipcol, winsaveview().skipcol) + + %bwipeout! + set splitkeep& +endfunc + func Test_aucmd_win_scroll_multibyte() " Using the autocommand window must not scroll the current window when the " cursor is behind multi-byte characters. diff --git a/src/window.c b/src/window.c index 04d3d86c4e..8ac5b8f5ea 100644 --- a/src/window.c +++ b/src/window.c @@ -7287,6 +7287,9 @@ win_fix_scroll(int resize) int diff = (wp->w_winrow - wp->w_prev_winrow) + (wp->w_height - wp->w_prev_height); pos_T cursor = wp->w_cursor; + linenr_T topline = wp->w_topline; + colnr_T skipcol = wp->w_skipcol; + wp->w_cursor.lnum = wp->w_botline - 1; // Add difference in height and row to botline. @@ -7301,6 +7304,9 @@ win_fix_scroll(int resize) scroll_to_fraction(wp, wp->w_prev_height); wp->w_cursor = cursor; + // Keeping the same screen lines includes the skipped columns. + if (wp->w_topline == topline) + wp->w_skipcol = skipcol; wp->w_valid &= ~VALID_WCOL; } else if (wp == curwin) @@ -7468,15 +7474,17 @@ scroll_to_fraction(win_T *wp, int prev_height) * Make cursor line the first line in the window. If not enough * room use w_skipcol; */ + int want_row = wp->w_wrow; // where the cursor should be + wp->w_wrow = line_size; if (wp->w_wrow >= wp->w_height && (wp->w_width - win_col_off(wp)) > 0) { - // The cursor must be visible, override the scroll position. + // Skip columns to get the cursor in the wanted row. colnr_T skipcol = wp->w_width - win_col_off(wp); --wp->w_wrow; - while (wp->w_wrow >= wp->w_height) + while (wp->w_wrow > want_row) { skipcol += wp->w_width - win_col_off(wp) + win_col_off2(wp); --wp->w_wrow;