diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-08-12 09:50:17 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-12 09:50:17 +0800 |
commit | 58a1ef8e6a93c615379f6fbe7234697bcdc42b3e (patch) | |
tree | c15b5ac2889ceacf923cca47b2954ab291c9dadf | |
parent | 6c07a189f2d10a533af8a51819ea96c45e0c567e (diff) | |
download | rneovim-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.txt | 2 | ||||
-rw-r--r-- | src/nvim/autocmd.c | 3 | ||||
-rw-r--r-- | src/nvim/autocmd.h | 5 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/change.c | 5 | ||||
-rw-r--r-- | src/nvim/edit.c | 6 | ||||
-rw-r--r-- | src/nvim/normal.c | 6 | ||||
-rw-r--r-- | src/nvim/window.c | 1 | ||||
-rw-r--r-- | test/functional/autocmd/cursormoved_spec.lua | 39 |
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) |