aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/win_config.c39
-rw-r--r--src/nvim/window.c6
2 files changed, 35 insertions, 10 deletions
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c
index e53e13e2a3..9d63a1997c 100644
--- a/src/nvim/api/win_config.c
+++ b/src/nvim/api/win_config.c
@@ -261,8 +261,8 @@ Window nvim_open_win(Buffer buffer, Boolean enter, Dict(win_config) *config, Err
switchwin_T switchwin;
// `parent` is valid in `tp`, so switch_win should not fail.
const int result = switch_win(&switchwin, parent, tp, true);
- (void)result;
assert(result == OK);
+ (void)result;
wp = win_split_ins(0, flags, NULL, 0);
restore_win(&switchwin, true);
}
@@ -276,18 +276,41 @@ Window nvim_open_win(Buffer buffer, Boolean enter, Dict(win_config) *config, Err
api_set_error(err, kErrorTypeException, "Failed to create window");
return 0;
}
+
+ // Autocommands may close `wp` or move it to another tabpage, so update and check `tp` after each
+ // event. In each case, `wp` should already be valid in `tp`, so switch_win should not fail.
switchwin_T switchwin;
- if (switch_win_noblock(&switchwin, wp, tp, true) == OK) {
- apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf);
+ {
+ const int result = switch_win_noblock(&switchwin, wp, tp, true);
+ assert(result == OK);
+ (void)result;
+ if (apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf)) {
+ tp = win_find_tabpage(wp);
+ }
+ restore_win_noblock(&switchwin, true);
}
- restore_win_noblock(&switchwin, true);
- if (enter) {
+ if (tp && enter) {
goto_tabpage_win(tp, wp);
+ tp = win_find_tabpage(wp);
}
- if (win_valid_any_tab(wp) && buf != wp->w_buffer) {
- win_set_buf(wp, buf, !enter || fconfig.noautocmd, err);
+ if (tp && buf != wp->w_buffer) {
+ const bool noautocmd = !enter || fconfig.noautocmd;
+ win_set_buf(wp, buf, noautocmd, err);
+ if (!noautocmd) {
+ tp = win_find_tabpage(wp);
+ }
+ // win_set_buf autocommands were blocked if we didn't enter, but we still want BufWinEnter.
+ if (noautocmd && !fconfig.noautocmd && wp->w_buffer == buf) {
+ const int result = switch_win_noblock(&switchwin, wp, tp, true);
+ assert(result == OK);
+ (void)result;
+ if (apply_autocmds(EVENT_BUFWINENTER, NULL, NULL, false, buf)) {
+ tp = win_find_tabpage(wp);
+ }
+ restore_win_noblock(&switchwin, true);
+ }
}
- if (!win_valid_any_tab(wp)) {
+ if (!tp) {
api_set_error(err, kErrorTypeException, "Window was closed immediately");
return 0;
}
diff --git a/src/nvim/window.c b/src/nvim/window.c
index e2c4524eaa..d5a6e347e7 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -718,6 +718,7 @@ void win_set_buf(win_T *win, buf_T *buf, bool noautocmd, Error *err)
kErrorTypeException,
"Failed to switch to window %d",
win->handle);
+ goto cleanup;
}
try_start();
@@ -729,10 +730,11 @@ void win_set_buf(win_T *win, buf_T *buf, bool noautocmd, Error *err)
buf->handle);
}
- // If window is not current, state logic will not validate its cursor.
- // So do it now.
+ // If window is not current, state logic will not validate its cursor. So do it now.
+ // Still needed if do_buffer returns FAIL (e.g: autocmds abort script after buffer was set).
validate_cursor();
+cleanup:
restore_win_noblock(&switchwin, true);
if (noautocmd) {
unblock_autocmds();