]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0896: scroll: 'smoothscroll' position is lost when splitting a window
authorHirohito Higashi <h.east.727@gmail.com>
Sun, 2 Aug 2026 17:25:35 +0000 (17:25 +0000)
committerChristian Brabandt <cb@256bit.org>
Sun, 2 Aug 2026 17:25:35 +0000 (17:25 +0000)
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) <noreply@anthropic.com>
Signed-off-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
runtime/doc/todo.txt
src/testdir/test_window_cmd.vim
src/window.c

index 3b2f65a9c9a88080964352daffe3398eeb92303b..a277a260f6bea8f778edc7ab1f28317918b2e53f 100644 (file)
@@ -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.
index f3aa38dc4a3169bf705b5b84003e529bd1763d8f..dc670fa7c1a8f0ff3d5202d4407e7334edea9cf0 100644 (file)
@@ -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\<C-E>"
+  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.
index 04d3d86c4ef98a0d0b62cac7b3157a8bcfafd6aa..8ac5b8f5ea0590cbda2afd2658773991b7b3ff88 100644 (file)
@@ -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;