aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-08-21 08:58:18 +0800
committerGitHub <noreply@github.com>2023-08-21 08:58:18 +0800
commita2a226170d178086592967f23c39112811178f0c (patch)
tree4f6e662c7968a674192ef1b60ac7d42099239040
parent694814cdd54ac245d1f4d2c28dce7e9132fcb616 (diff)
downloadrneovim-a2a226170d178086592967f23c39112811178f0c.tar.gz
rneovim-a2a226170d178086592967f23c39112811178f0c.tar.bz2
rneovim-a2a226170d178086592967f23c39112811178f0c.zip
vim-patch:9.0.1772: Cursor may be adjusted in 'splitkeep'ed windows (#24811)
Problem: Cursor is adjusted in window that did not change in size by 'splitkeep'. Solution: Only check that cursor position is valid in a window that has changed in size. closes: vim/vim#12509 https://github.com/vim/vim/commit/16af913eeefb288ce968fb87e09a597413861900 Co-authored-by: Luuk van Baal <luukvbaal@gmail.com>
-rw-r--r--src/nvim/buffer_defs.h1
-rw-r--r--src/nvim/window.c16
-rw-r--r--test/functional/legacy/window_cmd_spec.lua55
-rw-r--r--test/old/testdir/test_window_cmd.vim27
4 files changed, 95 insertions, 4 deletions
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index ca1f791d28..0a7c742798 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -1194,6 +1194,7 @@ struct window_S {
int w_hsep_height; // Number of horizontal separator rows (0 or 1)
int w_vsep_width; // Number of vertical separator columns (0 or 1).
pos_save_T w_save_cursor; // backup of cursor pos and topline
+ bool w_do_win_fix_cursor; // if true cursor may be invalid
int w_winrow_off; ///< offset from winrow to the inner window area
int w_wincol_off; ///< offset from wincol to the inner window area
diff --git a/src/nvim/window.c b/src/nvim/window.c
index e933390363..175a79568c 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -6465,6 +6465,10 @@ void win_fix_scroll(int resize)
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
// Skip when window height has not changed or when floating.
if (!wp->w_floating && wp->w_height != wp->w_prev_height) {
+ // Cursor position in this window may now be invalid. It is kept
+ // potentially invalid until the window is made the current window.
+ wp->w_do_win_fix_cursor = true;
+
// If window has moved update botline to keep the same screenlines.
if (*p_spk == 's' && wp->w_winrow != wp->w_prev_winrow
&& wp->w_botline - 1 <= wp->w_buffer->b_ml.ml_line_count) {
@@ -6488,6 +6492,7 @@ void win_fix_scroll(int resize)
} else if (wp == curwin) {
wp->w_valid &= ~VALID_CROW;
}
+
invalidate_botline_win(wp);
validate_botline(wp);
}
@@ -6505,16 +6510,19 @@ void win_fix_scroll(int resize)
/// Make sure the cursor position is valid for 'splitkeep'.
/// If it is not, put the cursor position in the jumplist and move it.
-/// If we are not in normal mode ("normal" is zero), make it valid by scrolling
+/// If we are not in normal mode ("normal" is false), make it valid by scrolling
/// instead.
-static void win_fix_cursor(int normal)
+static void win_fix_cursor(bool normal)
{
win_T *wp = curwin;
- if (skip_win_fix_cursor || wp->w_buffer->b_ml.ml_line_count < wp->w_height) {
+ if (skip_win_fix_cursor
+ || !wp->w_do_win_fix_cursor
+ || wp->w_buffer->b_ml.ml_line_count < wp->w_height_inner) {
return;
}
+ wp->w_do_win_fix_cursor = false;
// Determine valid cursor range.
int so = MIN(wp->w_height_inner / 2, get_scrolloff_value(wp));
linenr_T lnum = wp->w_cursor.lnum;
@@ -6533,7 +6541,7 @@ static void win_fix_cursor(int normal)
if (lnum > bot && (wp->w_botline - wp->w_buffer->b_ml.ml_line_count) != 1) {
nlnum = bot;
} else if (lnum < top && wp->w_topline != 1) {
- nlnum = (so == wp->w_height / 2) ? bot : top;
+ nlnum = (so == wp->w_height_inner / 2) ? bot : top;
}
if (nlnum != 0) { // Cursor is invalid for current scroll position.
diff --git a/test/functional/legacy/window_cmd_spec.lua b/test/functional/legacy/window_cmd_spec.lua
index 373a9c7163..979b46ae47 100644
--- a/test/functional/legacy/window_cmd_spec.lua
+++ b/test/functional/legacy/window_cmd_spec.lua
@@ -43,6 +43,61 @@ describe('splitkeep', function()
screen:attach()
end)
+ -- oldtest: Test_splitkeep_cursor()
+ it('does not adjust cursor in window that did not change size', function()
+ screen:try_resize(75, 8)
+ -- FIXME: bottom window is different without the "vsplit | close"
+ exec([[
+ vsplit | close
+ set scrolloff=5
+ set splitkeep=screen
+ autocmd CursorMoved * wincmd p | wincmd p
+ call setline(1, range(1, 200))
+ func CursorEqualize()
+ call cursor(100, 1)
+ wincmd =
+ endfunc
+ wincmd s
+ call CursorEqualize()
+ ]])
+
+ screen:expect([[
+ 99 |
+ ^100 |
+ 101 |
+ [No Name] [+] |
+ 5 |
+ 6 |
+ [No Name] [+] |
+ |
+ ]])
+
+ feed('j')
+ screen:expect([[
+ 100 |
+ ^101 |
+ 102 |
+ [No Name] [+] |
+ 5 |
+ 6 |
+ [No Name] [+] |
+ |
+ ]])
+
+ command('set scrolloff=0')
+ feed('G')
+ screen:expect([[
+ 198 |
+ 199 |
+ ^200 |
+ [No Name] [+] |
+ 5 |
+ 6 |
+ [No Name] [+] |
+ |
+ ]])
+ end)
+
-- oldtest: Test_splitkeep_callback()
it('does not scroll when split in callback', function()
exec([[
diff --git a/test/old/testdir/test_window_cmd.vim b/test/old/testdir/test_window_cmd.vim
index 7d4932a2b5..bd4cb44b2b 100644
--- a/test/old/testdir/test_window_cmd.vim
+++ b/test/old/testdir/test_window_cmd.vim
@@ -1805,6 +1805,33 @@ func Test_splitkeep_misc()
set splitkeep&
endfunc
+func Test_splitkeep_cursor()
+ CheckScreendump
+ let lines =<< trim END
+ set splitkeep=screen
+ autocmd CursorMoved * wincmd p | wincmd p
+ call setline(1, range(1, 200))
+ func CursorEqualize()
+ call cursor(100, 1)
+ wincmd =
+ endfunc
+ wincmd s
+ call CursorEqualize()
+ END
+ call writefile(lines, 'XTestSplitkeepCallback', 'D')
+ let buf = RunVimInTerminal('-S XTestSplitkeepCallback', #{rows: 8})
+
+ call VerifyScreenDump(buf, 'Test_splitkeep_cursor_1', {})
+
+ call term_sendkeys(buf, "j")
+ call VerifyScreenDump(buf, 'Test_splitkeep_cursor_2', {})
+
+ call term_sendkeys(buf, ":set scrolloff=0\<CR>G")
+ call VerifyScreenDump(buf, 'Test_splitkeep_cursor_3', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
func Test_splitkeep_callback()
CheckScreendump
let lines =<< trim END