patch 9.0.0913: only change in current window triggers the WinScrolled event
Problem: Only a change in the current window triggers the WinScrolled
event.
Solution: Trigger WinScrolled if any window scrolled or changed size.
(issue #11576)
diff --git a/src/window.c b/src/window.c
index 422f4fa..b5166db 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2843,44 +2843,76 @@
}
/*
- * Trigger WinScrolled for "curwin" if needed.
+ * Make a snapshot of all the window scroll positions and sizes of the current
+ * tab page.
+ */
+ static void
+snapshot_windows_scroll_size(void)
+{
+ win_T *wp;
+ FOR_ALL_WINDOWS(wp)
+ {
+ wp->w_last_topline = wp->w_topline;
+ wp->w_last_leftcol = wp->w_leftcol;
+ wp->w_last_skipcol = wp->w_skipcol;
+ wp->w_last_width = wp->w_width;
+ wp->w_last_height = wp->w_height;
+ }
+}
+
+static int did_initial_scroll_size_snapshot = FALSE;
+
+ void
+may_make_initial_scroll_size_snapshot(void)
+{
+ if (!did_initial_scroll_size_snapshot)
+ {
+ did_initial_scroll_size_snapshot = TRUE;
+ snapshot_windows_scroll_size();
+ }
+}
+
+/*
+ * Trigger WinScrolled if any window scrolled or changed size.
*/
void
may_trigger_winscrolled(void)
{
static int recursive = FALSE;
- if (recursive || !has_winscrolled())
+ if (recursive
+ || !has_winscrolled()
+ || !did_initial_scroll_size_snapshot)
return;
- win_T *wp = curwin;
- if (wp->w_last_topline != wp->w_topline
- || wp->w_last_leftcol != wp->w_leftcol
- || wp->w_last_skipcol != wp->w_skipcol
- || wp->w_last_width != wp->w_width
- || wp->w_last_height != wp->w_height)
- {
- // "curwin" may be different from the actual current window, make sure
- // it can be restored.
- window_layout_lock();
-
- recursive = TRUE;
- char_u winid[NUMBUFLEN];
- vim_snprintf((char *)winid, sizeof(winid), "%d", wp->w_id);
- apply_autocmds(EVENT_WINSCROLLED, winid, winid, FALSE, wp->w_buffer);
- recursive = FALSE;
- window_layout_unlock();
-
- // an autocmd may close the window, "wp" may be invalid now
- if (win_valid_any_tab(wp))
+ win_T *wp;
+ FOR_ALL_WINDOWS(wp)
+ if (wp->w_last_topline != wp->w_topline
+ || wp->w_last_leftcol != wp->w_leftcol
+ || wp->w_last_skipcol != wp->w_skipcol
+ || wp->w_last_width != wp->w_width
+ || wp->w_last_height != wp->w_height)
{
- wp->w_last_topline = wp->w_topline;
- wp->w_last_leftcol = wp->w_leftcol;
- wp->w_last_skipcol = wp->w_skipcol;
- wp->w_last_width = wp->w_width;
- wp->w_last_height = wp->w_height;
+ // WinScrolled is triggered only once, even when multiple windows
+ // scrolled or changed size. Store the current values before
+ // triggering the event, if a scroll or resize happens as a side
+ // effect then WinScrolled is triggered again later.
+ snapshot_windows_scroll_size();
+
+ // "curwin" may be different from the actual current window, make
+ // sure it can be restored.
+ window_layout_lock();
+
+ recursive = TRUE;
+ char_u winid[NUMBUFLEN];
+ vim_snprintf((char *)winid, sizeof(winid), "%d", wp->w_id);
+ apply_autocmds(EVENT_WINSCROLLED, winid, winid, FALSE,
+ wp->w_buffer);
+ recursive = FALSE;
+ window_layout_unlock();
+
+ break;
}
- }
}
/*