aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-08-12 09:50:17 +0800
committerGitHub <noreply@github.com>2023-08-12 09:50:17 +0800
commit58a1ef8e6a93c615379f6fbe7234697bcdc42b3e (patch)
treec15b5ac2889ceacf923cca47b2954ab291c9dadf
parent6c07a189f2d10a533af8a51819ea96c45e0c567e (diff)
downloadrneovim-58a1ef8e6a93c615379f6fbe7234697bcdc42b3e.tar.gz
rneovim-58a1ef8e6a93c615379f6fbe7234697bcdc42b3e.tar.bz2
rneovim-58a1ef8e6a93c615379f6fbe7234697bcdc42b3e.zip
fix(events): avoid unnecessary CursorMoved (#24675)
Problem: Temporarily changing current window in a script causes CursorMoved to be triggerd. Solution: Don't trigger CursorMoved if neither curwin nor cursor changed between two checks.
-rw-r--r--runtime/doc/vim_diff.txt2
-rw-r--r--src/nvim/autocmd.c3
-rw-r--r--src/nvim/autocmd.h5
-rw-r--r--src/nvim/buffer_defs.h1
-rw-r--r--src/nvim/change.c5
-rw-r--r--src/nvim/edit.c6
-rw-r--r--src/nvim/normal.c6
-rw-r--r--src/nvim/window.c1
-rw-r--r--test/functional/autocmd/cursormoved_spec.lua39
9 files changed, 44 insertions, 24 deletions
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index 15bb13d5a9..9569c38b85 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -455,7 +455,7 @@ coerced to strings. See |id()| for more details, currently it uses
|c_CTRL-R| pasting a non-special register into |cmdline| omits the last <CR>.
-|CursorMoved| always triggers when moving between windows.
+|CursorMoved| triggers when moving between windows.
Lua interface (|lua.txt|):
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index a8c5d00383..c43a59cbb3 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -1030,7 +1030,8 @@ int autocmd_register(int64_t id, event_T event, const char *pat, int patlen, int
// If the event is CursorMoved, update the last cursor position
// position to avoid immediately triggering the autocommand
if (event == EVENT_CURSORMOVED && !has_event(EVENT_CURSORMOVED)) {
- curwin->w_last_cursormoved = curwin->w_cursor;
+ last_cursormoved_win = curwin;
+ last_cursormoved = curwin->w_cursor;
}
// Initialize the fields checked by the WinScrolled and
diff --git a/src/nvim/autocmd.h b/src/nvim/autocmd.h
index 9e6c534581..b3de57311e 100644
--- a/src/nvim/autocmd.h
+++ b/src/nvim/autocmd.h
@@ -80,6 +80,11 @@ typedef kvec_t(AutoCmd) AutoCmdVec;
// apply_autocmds_group.
EXTERN bool au_did_filetype INIT(= false);
+/// For CursorMoved event
+EXTERN win_T *last_cursormoved_win INIT(= NULL);
+/// For CursorMoved event, only used when last_cursormoved_win == curwin
+EXTERN pos_T last_cursormoved INIT(= { 0, 0, 0 });
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "autocmd.h.generated.h"
#endif
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 5708274848..ca1f791d28 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -1101,7 +1101,6 @@ struct window_S {
///< can be different from w_cursor.lnum
///< for closed folds.
linenr_T w_last_cursorline; ///< where last 'cursorline' was drawn
- pos_T w_last_cursormoved; ///< for CursorMoved event
// the next seven are used to update the visual part
char w_old_visual_mode; ///< last known VIsual_mode
diff --git a/src/nvim/change.c b/src/nvim/change.c
index 932de727b5..599e319dde 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -361,9 +361,10 @@ static void changed_common(linenr_T lnum, colnr_T col, linenr_T lnume, linenr_T
}
// when the cursor line is changed always trigger CursorMoved
- if (lnum <= curwin->w_cursor.lnum
+ if (last_cursormoved_win == curwin
+ && lnum <= curwin->w_cursor.lnum
&& lnume + (xtra < 0 ? -xtra : xtra) > curwin->w_cursor.lnum) {
- curwin->w_last_cursormoved.lnum = 0;
+ last_cursormoved.lnum = 0;
}
}
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index e44c49ad0b..b8d2eca810 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -1287,7 +1287,8 @@ void ins_redraw(bool ready)
// Trigger CursorMoved if the cursor moved. Not when the popup menu is
// visible, the command might delete it.
if (ready && has_event(EVENT_CURSORMOVEDI)
- && !equalpos(curwin->w_last_cursormoved, curwin->w_cursor)
+ && (last_cursormoved_win != curwin
+ || !equalpos(last_cursormoved, curwin->w_cursor))
&& !pum_visible()) {
// Need to update the screen first, to make sure syntax
// highlighting is correct after making a change (e.g., inserting
@@ -1300,7 +1301,8 @@ void ins_redraw(bool ready)
// getcurpos()
update_curswant();
ins_apply_autocmds(EVENT_CURSORMOVEDI);
- curwin->w_last_cursormoved = curwin->w_cursor;
+ last_cursormoved_win = curwin;
+ last_cursormoved = curwin->w_cursor;
}
// Trigger TextChangedI if changedtick differs.
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 1e9bc78fe3..edfc62ae17 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -1267,9 +1267,11 @@ static void normal_check_cursor_moved(NormalState *s)
{
// Trigger CursorMoved if the cursor moved.
if (!finish_op && has_event(EVENT_CURSORMOVED)
- && !equalpos(curwin->w_last_cursormoved, curwin->w_cursor)) {
+ && (last_cursormoved_win != curwin
+ || !equalpos(last_cursormoved, curwin->w_cursor))) {
apply_autocmds(EVENT_CURSORMOVED, NULL, NULL, false, curbuf);
- curwin->w_last_cursormoved = curwin->w_cursor;
+ last_cursormoved_win = curwin;
+ last_cursormoved = curwin->w_cursor;
}
}
diff --git a/src/nvim/window.c b/src/nvim/window.c
index d6d677de3f..c475169261 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -4943,7 +4943,6 @@ static void win_enter_ext(win_T *const wp, const int flags)
if (other_buffer) {
apply_autocmds(EVENT_BUFENTER, NULL, NULL, false, curbuf);
}
- curwin->w_last_cursormoved.lnum = 0;
}
maketitle();
diff --git a/test/functional/autocmd/cursormoved_spec.lua b/test/functional/autocmd/cursormoved_spec.lua
index 64b63c3205..854e14b088 100644
--- a/test/functional/autocmd/cursormoved_spec.lua
+++ b/test/functional/autocmd/cursormoved_spec.lua
@@ -3,7 +3,7 @@ local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local eq = helpers.eq
local eval = helpers.eval
-local funcs = helpers.funcs
+local meths = helpers.meths
local source = helpers.source
local command = helpers.command
@@ -12,10 +12,10 @@ describe('CursorMoved', function()
it('is triggered after BufEnter when changing or splitting windows #11878 #12031', function()
source([[
- call setline(1, 'foo')
- let g:log = []
- autocmd BufEnter * let g:log += ['BufEnter' .. expand("<abuf>")]
- autocmd CursorMoved * let g:log += ['CursorMoved' .. expand("<abuf>")]
+ call setline(1, 'foo')
+ let g:log = []
+ autocmd BufEnter * let g:log += ['BufEnter' .. expand("<abuf>")]
+ autocmd CursorMoved * let g:log += ['CursorMoved' .. expand("<abuf>")]
]])
eq({}, eval('g:log'))
command('new')
@@ -24,23 +24,34 @@ describe('CursorMoved', function()
eq({'BufEnter2', 'CursorMoved2', 'BufEnter1', 'CursorMoved1'}, eval('g:log'))
end)
+ it('is not triggered by temporarily switching window', function()
+ source([[
+ let g:cursormoved = 0
+ vnew
+ autocmd CursorMoved * let g:cursormoved += 1
+ ]])
+ command('wincmd w | wincmd p')
+ eq(0, eval('g:cursormoved'))
+ end)
+
it("is not triggered by functions that don't change the window", function()
source([[
- let g:cursormoved = 0
- let g:buf = bufnr('%')
- vsplit foo
- autocmd CursorMoved * let g:cursormoved += 1
- call nvim_buf_set_lines(g:buf, 0, -1, v:true, ['aaa'])
+ let g:cursormoved = 0
+ let g:buf = bufnr('%')
+ vsplit foo
+ autocmd CursorMoved * let g:cursormoved += 1
]])
- eq({'aaa'}, funcs.nvim_buf_get_lines(eval('g:buf'), 0, -1, true))
+ meths.buf_set_lines(eval('g:buf'), 0, -1, true, {'aaa'})
+ eq(0, eval('g:cursormoved'))
+ eq({'aaa'}, meths.buf_get_lines(eval('g:buf'), 0, -1, true))
eq(0, eval('g:cursormoved'))
end)
it("is not triggered by cursor movement prior to first CursorMoved instantiation", function()
source([[
- let g:cursormoved = 0
- autocmd! CursorMoved
- autocmd CursorMoved * let g:cursormoved += 1
+ let g:cursormoved = 0
+ autocmd! CursorMoved
+ autocmd CursorMoved * let g:cursormoved += 1
]])
eq(0, eval('g:cursormoved'))
end)