aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/auevents.lua10
-rw-r--r--src/nvim/fileio.c3
-rw-r--r--src/nvim/window.c38
3 files changed, 42 insertions, 9 deletions
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua
index a52789c795..96e170a9e1 100644
--- a/src/nvim/auevents.lua
+++ b/src/nvim/auevents.lua
@@ -21,12 +21,12 @@ return {
'BufWritePre', -- before writing a buffer
'ChanInfo', -- info was received about channel
'ChanOpen', -- channel was opened
- 'CmdlineChanged', -- command line was modified
- 'CmdlineEnter', -- after entering cmdline mode
- 'CmdlineLeave', -- before leaving cmdline mode
'CmdUndefined', -- command undefined
'CmdWinEnter', -- after entering the cmdline window
'CmdWinLeave', -- before leaving the cmdline window
+ 'CmdlineChanged', -- command line was modified
+ 'CmdlineEnter', -- after entering cmdline mode
+ 'CmdlineLeave', -- before leaving cmdline mode
'ColorScheme', -- after loading a colorscheme
'ColorSchemePre', -- before loading a colorscheme
'CompleteChanged', -- after popup menu changed
@@ -76,8 +76,8 @@ return {
'ShellFilterPost', -- after ":1,2!cmd", ":w !cmd", ":r !cmd".
'Signal', -- after nvim process received a signal
'SourceCmd', -- sourcing a Vim script using command
- 'SourcePre', -- before sourcing a Vim script
'SourcePost', -- after sourcing a Vim script
+ 'SourcePre', -- before sourcing a Vim script
'SpellFileMissing', -- spell file missing
'StdinReadPost', -- after reading from stdin
'StdinReadPre', -- before reading from stdin
@@ -107,6 +107,7 @@ return {
'VimResized', -- after Vim window was resized
'VimResume', -- after Nvim is resumed
'VimSuspend', -- before Nvim is suspended
+ 'WinClosed', -- after closing a window
'WinEnter', -- after entering a window
'WinLeave', -- before leaving a window
'WinNew', -- when entering a new window
@@ -129,5 +130,6 @@ return {
TermOpen=true,
UIEnter=true,
UILeave=true,
+ WinClosed=true,
},
}
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 865da25009..7a46957151 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -6862,7 +6862,8 @@ static bool apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io,
|| event == EVENT_SPELLFILEMISSING
|| event == EVENT_SYNTAX
|| event == EVENT_SIGNAL
- || event == EVENT_TABCLOSED) {
+ || event == EVENT_TABCLOSED
+ || event == EVENT_WINCLOSED) {
fname = vim_strsave(fname);
} else {
fname = (char_u *)FullName_save((char *)fname, false);
diff --git a/src/nvim/window.c b/src/nvim/window.c
index e913d33de0..8181883426 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -2502,9 +2502,10 @@ int win_close(win_T *win, bool free_buf)
return FAIL;
}
win->w_closing = true;
- apply_autocmds(EVENT_WINLEAVE, NULL, NULL, FALSE, curbuf);
- if (!win_valid(win))
+ apply_autocmds(EVENT_WINLEAVE, NULL, NULL, false, curbuf);
+ if (!win_valid(win)) {
return FAIL;
+ }
win->w_closing = false;
if (last_window())
return FAIL;
@@ -2534,6 +2535,12 @@ int win_close(win_T *win, bool free_buf)
}
}
+ // Fire WinClosed just before starting to free window-related resources.
+ do_autocmd_winclosed(win);
+ // autocmd may have freed the window already.
+ if (!win_valid_any_tab(win)) {
+ return OK;
+ }
/* Free independent synblock before the buffer is freed. */
if (win->w_buffer != NULL)
@@ -2576,6 +2583,7 @@ int win_close(win_T *win, bool free_buf)
win_close_othertab(win, false, prev_curtab);
return FAIL;
}
+
// Autocommands may have closed the window already, or closed the only
// other window or moved to another tab page.
if (!win_valid(win) || (!win->w_floating && last_window())
@@ -2585,8 +2593,9 @@ int win_close(win_T *win, bool free_buf)
// let terminal buffers know that this window dimensions may be ignored
win->w_closing = true;
- /* Free the memory used for the window and get the window that received
- * the screen space. */
+
+ // Free the memory used for the window and get the window that received
+ // the screen space.
wp = win_free_mem(win, &dir, NULL);
if (help_window) {
@@ -2678,6 +2687,20 @@ int win_close(win_T *win, bool free_buf)
return OK;
}
+static void do_autocmd_winclosed(win_T *win)
+ FUNC_ATTR_NONNULL_ALL
+{
+ static bool recursive = false;
+ if (recursive || !has_event(EVENT_WINCLOSED)) {
+ return;
+ }
+ recursive = true;
+ char_u winid[NUMBUFLEN];
+ vim_snprintf((char *)winid, sizeof(winid), "%i", win->handle);
+ apply_autocmds(EVENT_WINCLOSED, winid, winid, false, win->w_buffer);
+ recursive = false;
+}
+
/*
* Close window "win" in tab page "tp", which is not the current tab page.
* This may be the last window in that tab page and result in closing the tab,
@@ -2698,6 +2721,13 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
return; // window is already being closed
}
+ // Fire WinClosed just before starting to free window-related resources.
+ do_autocmd_winclosed(win);
+ // autocmd may have freed the window already.
+ if (!win_valid_any_tab(win)) {
+ return;
+ }
+
if (win->w_buffer != NULL) {
// Close the link to the buffer.
close_buffer(win, win->w_buffer, free_buf ? DOBUF_UNLOAD : 0, false);