aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/win_config.c
diff options
context:
space:
mode:
authorSean Dewar <seandewar@users.noreply.github.com>2024-02-11 22:53:37 +0000
committerSean Dewar <6256228+seandewar@users.noreply.github.com>2024-03-08 23:24:04 +0000
commita70eae57bd44208a77b5ac29839e8a39ab3c9cd8 (patch)
tree3dcb9475b8ffb425b42d5497063c22bd700217f8 /src/nvim/api/win_config.c
parentb1577d371a6db43222de9e3a525def82320ebdb1 (diff)
downloadrneovim-a70eae57bd44208a77b5ac29839e8a39ab3c9cd8.tar.gz
rneovim-a70eae57bd44208a77b5ac29839e8a39ab3c9cd8.tar.bz2
rneovim-a70eae57bd44208a77b5ac29839e8a39ab3c9cd8.zip
fix(api): make open_win block only enter/leave events if !enter && !noautocmd
Problem: nvim_open_win blocking all win_set_buf autocommands when !enter && !noautocmd is too aggressive. Solution: temporarily block WinEnter/Leave and BufEnter/Leave events when setting the buffer. Delegate the firing of BufWinEnter back to win_set_buf, which also has the advantage of keeping the timing consistent (e.g: before the epilogue in enter_buffer, which also handles restoring the cursor position if autocommands didn't change it, among other things). Reword the documentation for noautocmd a bit. I pondered modifying do_buffer and callees to allow for BufEnter/Leave being conditionally disabled, but it seems too invasive (and potentially error-prone, especially if new code paths to BufEnter/Leave are added in the future). Unfortunately, doing this has the drawback of blocking ALL such events for the duration, which also means blocking unrelated such events; like if window switching occurs in a ++nested autocmd fired by win_set_buf. If this turns out to be a problem in practice, a different solution specialized for nvim_open_win could be considered. :-)
Diffstat (limited to 'src/nvim/api/win_config.c')
-rw-r--r--src/nvim/api/win_config.c30
1 files changed, 15 insertions, 15 deletions
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c
index 21d6d59b1e..8608b0dde9 100644
--- a/src/nvim/api/win_config.c
+++ b/src/nvim/api/win_config.c
@@ -199,9 +199,9 @@
/// - footer_pos: Footer position. Must be set with `footer` option.
/// Value can be one of "left", "center", or "right".
/// Default is `"left"`.
-/// - noautocmd: If true then no buffer-related autocommand events such as
-/// |BufEnter|, |BufLeave| or |BufWinEnter| may fire from
-/// calling this function.
+/// - noautocmd: If true then autocommands triggered from setting the
+/// `buffer` to display are blocked (e.g: |BufEnter|, |BufLeave|,
+/// |BufWinEnter|).
/// - fixed: If true when anchor is NW or SW, the float window
/// would be kept fixed even if the window would be truncated.
/// - hide: If true the floating window will be hidden.
@@ -302,20 +302,20 @@ Window nvim_open_win(Buffer buffer, Boolean enter, Dict(win_config) *config, Err
tp = win_find_tabpage(wp);
}
if (tp && bufref_valid(&bufref) && buf != wp->w_buffer) {
- const bool noautocmd = curwin != wp || fconfig.noautocmd;
- win_set_buf(wp, buf, noautocmd, err);
- if (!noautocmd) {
+ // win_set_buf temporarily makes `wp` the curwin to set the buffer.
+ // If not entering `wp`, block Enter and Leave events. (cringe)
+ const bool au_no_enter_leave = curwin != wp && !fconfig.noautocmd;
+ if (au_no_enter_leave) {
+ autocmd_no_enter++;
+ autocmd_no_leave++;
+ }
+ win_set_buf(wp, buf, fconfig.noautocmd, err);
+ if (!fconfig.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 (au_no_enter_leave) {
+ autocmd_no_enter--;
+ autocmd_no_leave--;
}
}
if (!tp) {