diff src/window.c @ 31158:514ab6bdf73d v9.0.0913

patch 9.0.0913: only change in current window triggers the WinScrolled event Commit: https://github.com/vim/vim/commit/0a60f79fd0c328b47b36279a95282e9f8d9e7512 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Nov 19 21:18:11 2022 +0000 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)
author Bram Moolenaar <Bram@vim.org>
date Sat, 19 Nov 2022 22:30:03 +0100
parents bcda71c89776
children 981f7bc781bb
line wrap: on
line diff
--- a/src/window.c
+++ b/src/window.c
@@ -2843,44 +2843,76 @@ trigger_winclosed(win_T *win)
 }
 
 /*
- * 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;
 	}
-    }
 }
 
 /*