• R/O
  • SSH

vim: Commit

Mirror of the Vim source from https://github.com/vim/vim


Commit MetaInfo

Revision514ab6bdf73da73bf6f7da5b017d85279fc9238c (tree)
Time2022-11-20 06:30:03
AuthorBram Moolenaar <Bram@vim....>
CommiterBram Moolenaar

Log Message

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)

Change Summary

Incremental Difference

diff -r d8464195a927 -r 514ab6bdf73d runtime/doc/autocmd.txt
--- a/runtime/doc/autocmd.txt Sat Nov 19 20:15:03 2022 +0100
+++ b/runtime/doc/autocmd.txt Sat Nov 19 22:30:03 2022 +0100
@@ -1372,16 +1372,32 @@
13721372
13731373 *WinScrolled*
13741374 WinScrolled After scrolling the content of a window or
1375- resizing a window.
1376- The pattern is matched against the
1377- |window-ID|. Both <amatch> and <afile> are
1378- set to the |window-ID|.
1379- Non-recursive (the event cannot trigger
1380- itself). However, if the command causes the
1381- window to scroll or change size another
1375+ resizing a window in the current tab page.
1376+
1377+ When more than one window scrolled or resized
1378+ only one WinScrolled event is triggered. You
1379+ can use the `winlayout()` and `getwininfo()`
1380+ functions to see what changed.
1381+
1382+ The pattern is matched against the |window-ID|
1383+ of the first window that scrolled or resized.
1384+ Both <amatch> and <afile> are set to the
1385+ |window-ID|.
1386+
1387+ Only starts triggering after startup finished
1388+ and the first screen redraw was done.
1389+
1390+ Non-recursive: the event will not trigger
1391+ while executing commands for the WinScrolled
1392+ event. However, if the command causes a
1393+ window to scroll or change size, then another
13821394 WinScrolled event will be triggered later.
1395+
13831396 Does not trigger when the command is added,
13841397 only after the first scroll or resize.
1398+ *E1312*
1399+ It is not allowed to change the window layout
1400+ here (split, close or move windows).
13851401
13861402 ==============================================================================
13871403 6. Patterns *autocmd-patterns* *{aupat}*
diff -r d8464195a927 -r 514ab6bdf73d src/main.c
--- a/src/main.c Sat Nov 19 20:15:03 2022 +0100
+++ b/src/main.c Sat Nov 19 22:30:03 2022 +0100
@@ -1469,6 +1469,9 @@
14691469 time_fd = NULL;
14701470 }
14711471 #endif
1472+ // After the first screen update may start triggering WinScrolled
1473+ // autocmd events. Store all the scroll positions and sizes now.
1474+ may_make_initial_scroll_size_snapshot();
14721475 }
14731476 #ifdef FEAT_GUI
14741477 if (need_mouse_correct)
diff -r d8464195a927 -r 514ab6bdf73d src/proto/window.pro
--- a/src/proto/window.pro Sat Nov 19 20:15:03 2022 +0100
+++ b/src/proto/window.pro Sat Nov 19 22:30:03 2022 +0100
@@ -18,6 +18,7 @@
1818 void close_windows(buf_T *buf, int keep_curwin);
1919 int one_window(void);
2020 int win_close(win_T *win, int free_buf);
21+void may_make_initial_scroll_size_snapshot(void);
2122 void may_trigger_winscrolled(void);
2223 void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp);
2324 void win_free_all(void);
diff -r d8464195a927 -r 514ab6bdf73d src/testdir/dumps/Test_winscrolled_once_only_1.dump
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/testdir/dumps/Test_winscrolled_once_only_1.dump Sat Nov 19 22:30:03 2022 +0100
@@ -0,0 +1,10 @@
1+|a+0&#ffffff0@2| @26||+1&&>b+0&&@2| @25
2+|b@2| @26||+1&&|~+0#4040ff13&| @27
3+|~| @28||+1#0000000&|~+0#4040ff13&| @27
4+|[+1#0000000&|N|o| |N|a|m|e|]| |[|+|]| @1|1|,|1| @8|A|l@1|||~+0#4040ff13&| @27
5+|a+0#0000000&@2| @26||+1&&|~+0#4040ff13&| @27
6+|b+0#0000000&@2| @26||+1&&|~+0#4040ff13&| @27
7+|~| @28||+1#0000000&|~+0#4040ff13&| @27
8+|[+1#0000000&|N|o| |N|a|m|e|]| |[|+|]| @1|1|,|1| @8|A|l@1| |[+3&&|N|o| |N|a|m|e|]| |[|+|]| @1|2|,|1| @7|B|o|t
9+|1+0&&| |1|0@2| |[|'|r|o|w|'|,| |[@1|'|c|o|l|'|,| |[@1|'|l|e|a|f|'|,| |1|0@1|2|]|,| |[|'|l|e|a|f|'|,| |1|0@1|1|]@2|,| |[
10+|'|l|e|a|f|'|,| |1|0@2|]@2| @44
diff -r d8464195a927 -r 514ab6bdf73d src/testdir/test_autocmd.vim
--- a/src/testdir/test_autocmd.vim Sat Nov 19 20:15:03 2022 +0100
+++ b/src/testdir/test_autocmd.vim Sat Nov 19 22:30:03 2022 +0100
@@ -407,11 +407,38 @@
407407 call TermWait(buf)
408408 call StopVimInTerminal(buf)
409409
410+ " check the startup script finished to the end
410411 call assert_equal(['123456'], readfile('Xtestout'))
411-
412412 call delete('Xtestout')
413413 endfunc
414414
415+func Test_WinScrolled_once_only()
416+ CheckRunVimInTerminal
417+
418+ let lines =<< trim END
419+ set cmdheight=2
420+ call setline(1, ['aaa', 'bbb'])
421+ let trigger_count = 0
422+ func ShowInfo(id)
423+ echo g:trigger_count g:winid winlayout()
424+ endfunc
425+
426+ vsplit
427+ split
428+ " use a timer to show the info after a redraw
429+ au WinScrolled * let trigger_count += 1 | let winid = expand('<amatch>') | call timer_start(100, 'ShowInfo')
430+ wincmd j
431+ wincmd l
432+ END
433+ call writefile(lines, 'Xtest_winscrolled_once', 'D')
434+ let buf = RunVimInTerminal('-S Xtest_winscrolled_once', #{rows: 10, cols: 60, statusoff: 2})
435+
436+ call term_sendkeys(buf, "\<C-E>")
437+ call VerifyScreenDump(buf, 'Test_winscrolled_once_only_1', {})
438+
439+ call StopVimInTerminal(buf)
440+endfunc
441+
415442 func Test_WinScrolled_long_wrapped()
416443 CheckRunVimInTerminal
417444
@@ -2916,6 +2943,7 @@
29162943 call assert_fails('set spell spelllang=0', 'E937:')
29172944
29182945 au! SpellFileMissing
2946+ set nospell spelllang=en
29192947 bwipe
29202948 endfunc
29212949
diff -r d8464195a927 -r 514ab6bdf73d src/version.c
--- a/src/version.c Sat Nov 19 20:15:03 2022 +0100
+++ b/src/version.c Sat Nov 19 22:30:03 2022 +0100
@@ -696,6 +696,8 @@
696696 static int included_patches[] =
697697 { /* Add new patch number below this line */
698698 /**/
699+ 913,
700+/**/
699701 912,
700702 /**/
701703 911,
diff -r d8464195a927 -r 514ab6bdf73d src/window.c
--- a/src/window.c Sat Nov 19 20:15:03 2022 +0100
+++ b/src/window.c Sat Nov 19 22:30:03 2022 +0100
@@ -2843,44 +2843,76 @@
28432843 }
28442844
28452845 /*
2846- * Trigger WinScrolled for "curwin" if needed.
2846+ * Make a snapshot of all the window scroll positions and sizes of the current
2847+ * tab page.
2848+ */
2849+ static void
2850+snapshot_windows_scroll_size(void)
2851+{
2852+ win_T *wp;
2853+ FOR_ALL_WINDOWS(wp)
2854+ {
2855+ wp->w_last_topline = wp->w_topline;
2856+ wp->w_last_leftcol = wp->w_leftcol;
2857+ wp->w_last_skipcol = wp->w_skipcol;
2858+ wp->w_last_width = wp->w_width;
2859+ wp->w_last_height = wp->w_height;
2860+ }
2861+}
2862+
2863+static int did_initial_scroll_size_snapshot = FALSE;
2864+
2865+ void
2866+may_make_initial_scroll_size_snapshot(void)
2867+{
2868+ if (!did_initial_scroll_size_snapshot)
2869+ {
2870+ did_initial_scroll_size_snapshot = TRUE;
2871+ snapshot_windows_scroll_size();
2872+ }
2873+}
2874+
2875+/*
2876+ * Trigger WinScrolled if any window scrolled or changed size.
28472877 */
28482878 void
28492879 may_trigger_winscrolled(void)
28502880 {
28512881 static int recursive = FALSE;
28522882
2853- if (recursive || !has_winscrolled())
2883+ if (recursive
2884+ || !has_winscrolled()
2885+ || !did_initial_scroll_size_snapshot)
28542886 return;
28552887
2856- win_T *wp = curwin;
2857- if (wp->w_last_topline != wp->w_topline
2858- || wp->w_last_leftcol != wp->w_leftcol
2859- || wp->w_last_skipcol != wp->w_skipcol
2860- || wp->w_last_width != wp->w_width
2861- || wp->w_last_height != wp->w_height)
2862- {
2863- // "curwin" may be different from the actual current window, make sure
2864- // it can be restored.
2865- window_layout_lock();
2866-
2867- recursive = TRUE;
2868- char_u winid[NUMBUFLEN];
2869- vim_snprintf((char *)winid, sizeof(winid), "%d", wp->w_id);
2870- apply_autocmds(EVENT_WINSCROLLED, winid, winid, FALSE, wp->w_buffer);
2871- recursive = FALSE;
2872- window_layout_unlock();
2873-
2874- // an autocmd may close the window, "wp" may be invalid now
2875- if (win_valid_any_tab(wp))
2888+ win_T *wp;
2889+ FOR_ALL_WINDOWS(wp)
2890+ if (wp->w_last_topline != wp->w_topline
2891+ || wp->w_last_leftcol != wp->w_leftcol
2892+ || wp->w_last_skipcol != wp->w_skipcol
2893+ || wp->w_last_width != wp->w_width
2894+ || wp->w_last_height != wp->w_height)
28762895 {
2877- wp->w_last_topline = wp->w_topline;
2878- wp->w_last_leftcol = wp->w_leftcol;
2879- wp->w_last_skipcol = wp->w_skipcol;
2880- wp->w_last_width = wp->w_width;
2881- wp->w_last_height = wp->w_height;
2896+ // WinScrolled is triggered only once, even when multiple windows
2897+ // scrolled or changed size. Store the current values before
2898+ // triggering the event, if a scroll or resize happens as a side
2899+ // effect then WinScrolled is triggered again later.
2900+ snapshot_windows_scroll_size();
2901+
2902+ // "curwin" may be different from the actual current window, make
2903+ // sure it can be restored.
2904+ window_layout_lock();
2905+
2906+ recursive = TRUE;
2907+ char_u winid[NUMBUFLEN];
2908+ vim_snprintf((char *)winid, sizeof(winid), "%d", wp->w_id);
2909+ apply_autocmds(EVENT_WINSCROLLED, winid, winid, FALSE,
2910+ wp->w_buffer);
2911+ recursive = FALSE;
2912+ window_layout_unlock();
2913+
2914+ break;
28822915 }
2883- }
28842916 }
28852917
28862918 /*
Show on old repository browser