commit ef5c5dc99b486b53b35a2a46e28c2739c187ae4e
parent 23bf4c0531acef4e8252f4db13fcd90ad5aa91bf
Author: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Date: Sun, 11 May 2025 15:54:24 +0100
vim-patch:9.1.1380: 'eventignorewin' only checked for current buffer
Problem: When an autocommand executes for a non-current buffer,
'eventignorewin' is only checked from the buffer's last
wininfo (overwrites win_ignore in the loop), not from the
value of 'eventignorewin' in all windows showing the buffer as
described (after v9.1.1084)
Solution: Fix the check and don't use wininfo, as that may only contain
windows that recently showed the buffer. Consider all the
buffer's windows in all tabpages (Sean Dewar).
closes: vim/vim#17294
https://github.com/vim/vim/commit/d4110e06952be7d06ba39cf0434626bbd7301a9d
Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Diffstat:
2 files changed, 82 insertions(+), 5 deletions(-)
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
@@ -1635,11 +1635,12 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
// into "buf" are ignoring the event.
if (buf == curbuf && event_names[event].event <= 0) {
win_ignore = event_ignored(event, curwin->w_p_eiw);
- } else if (buf != NULL && event_names[event].event <= 0) {
- for (size_t i = 0; i < kv_size(buf->b_wininfo); i++) {
- WinInfo *wip = kv_A(buf->b_wininfo, i);
- if (wip->wi_win != NULL && wip->wi_win->w_buffer == buf) {
- win_ignore = event_ignored(event, wip->wi_win->w_p_eiw);
+ } else if (buf != NULL && event_names[event].event <= 0 && buf->b_nwindows > 0) {
+ win_ignore = true;
+ FOR_ALL_TAB_WINDOWS(tp, wp) {
+ if (wp->w_buffer == buf && !event_ignored(event, wp->w_p_eiw)) {
+ win_ignore = false;
+ break;
}
}
}
diff --git a/test/old/testdir/test_autocmd.vim b/test/old/testdir/test_autocmd.vim
@@ -4406,4 +4406,80 @@ func Test_WinScrolled_Resized_eiw()
call StopVimInTerminal(buf)
endfunc
+func Test_eventignorewin_non_current()
+ defer CleanUpTestAuGroup()
+ let s:triggered = ''
+ augroup testing
+ " Will set <abuf> to the buffer of the closing window.
+ autocmd WinClosed * let s:triggered = 'WinClosed'
+ augroup END
+ let initial_win = win_getid()
+
+ new
+ let new_buf = bufnr()
+ " Only set for one of the windows into the new buffer.
+ setlocal eventignorewin=all
+ split
+ setlocal eventignorewin=
+ let close_winnr = winnr()
+
+ " Return to the window where the buffer is non-current. WinClosed should
+ " trigger as not all windows into new_buf have 'eventignorewin' set for it.
+ call win_gotoid(initial_win)
+ call assert_notequal(new_buf, bufnr())
+ execute close_winnr 'close'
+ call assert_equal('WinClosed', s:triggered)
+
+ wincmd w
+ call assert_equal(new_buf, bufnr())
+ tab split
+ setlocal eventignorewin=
+ let close_winnr = win_getid()
+
+ " Ensure that new_buf's window in the other tabpage with 'eventignorewin'
+ " unset allows WinClosed to run when new_buf is non-current.
+ call win_gotoid(initial_win)
+ call assert_notequal(new_buf, bufnr())
+ let s:triggered = ''
+ only!
+ call assert_equal('WinClosed', s:triggered)
+ call assert_equal(1, win_findbuf(new_buf)->len())
+
+ " Create an only window to new_buf with 'eventignorewin' set.
+ tabonly!
+ execute new_buf 'sbuffer'
+ setlocal eventignorewin=all
+ wincmd p
+ call assert_equal(1, win_findbuf(new_buf)->len())
+ call assert_notequal(new_buf, bufnr())
+
+ " Closing a window unrelated to new_buf should not block WinClosed.
+ split
+ let s:triggered = ''
+ close
+ call assert_equal('WinClosed', s:triggered)
+ call assert_equal(1, win_findbuf(new_buf)->len())
+
+ " Check WinClosed is blocked when we close the only window to new_buf (that
+ " has 'eventignorewin' set) while new_buf is non-current.
+ call assert_notequal(new_buf, bufnr())
+ let s:triggered = ''
+ only!
+ call assert_equal('', s:triggered)
+ call assert_equal(0, win_findbuf(new_buf)->len())
+
+ augroup testing
+ autocmd!
+ autocmd BufNew * ++once let s:triggered = 'BufNew'
+ augroup END
+
+ " Buffer not shown in a window, 'eventignorewin' should not block (and
+ " can't even be set for it anyway in this case).
+ badd foo
+ call assert_equal('BufNew', s:triggered)
+
+ unlet! s:triggered
+ %bw!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab