Mirror of the Vim source from https://github.com/vim/vim
Revision | 514ab6bdf73da73bf6f7da5b017d85279fc9238c (tree) |
---|---|
Time | 2022-11-20 06:30:03 |
Author | Bram Moolenaar <Bram@vim....> |
Commiter | Bram Moolenaar |
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
@@ -1372,16 +1372,32 @@ | ||
1372 | 1372 | |
1373 | 1373 | *WinScrolled* |
1374 | 1374 | 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 | |
1382 | 1394 | WinScrolled event will be triggered later. |
1395 | + | |
1383 | 1396 | Does not trigger when the command is added, |
1384 | 1397 | 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). | |
1385 | 1401 | |
1386 | 1402 | ============================================================================== |
1387 | 1403 | 6. Patterns *autocmd-patterns* *{aupat}* |
@@ -1469,6 +1469,9 @@ | ||
1469 | 1469 | time_fd = NULL; |
1470 | 1470 | } |
1471 | 1471 | #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(); | |
1472 | 1475 | } |
1473 | 1476 | #ifdef FEAT_GUI |
1474 | 1477 | if (need_mouse_correct) |
@@ -18,6 +18,7 @@ | ||
18 | 18 | void close_windows(buf_T *buf, int keep_curwin); |
19 | 19 | int one_window(void); |
20 | 20 | int win_close(win_T *win, int free_buf); |
21 | +void may_make_initial_scroll_size_snapshot(void); | |
21 | 22 | void may_trigger_winscrolled(void); |
22 | 23 | void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp); |
23 | 24 | void win_free_all(void); |
@@ -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 |
@@ -407,11 +407,38 @@ | ||
407 | 407 | call TermWait(buf) |
408 | 408 | call StopVimInTerminal(buf) |
409 | 409 | |
410 | + " check the startup script finished to the end | |
410 | 411 | call assert_equal(['123456'], readfile('Xtestout')) |
411 | - | |
412 | 412 | call delete('Xtestout') |
413 | 413 | endfunc |
414 | 414 | |
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 | + | |
415 | 442 | func Test_WinScrolled_long_wrapped() |
416 | 443 | CheckRunVimInTerminal |
417 | 444 |
@@ -2916,6 +2943,7 @@ | ||
2916 | 2943 | call assert_fails('set spell spelllang=0', 'E937:') |
2917 | 2944 | |
2918 | 2945 | au! SpellFileMissing |
2946 | + set nospell spelllang=en | |
2919 | 2947 | bwipe |
2920 | 2948 | endfunc |
2921 | 2949 |
@@ -696,6 +696,8 @@ | ||
696 | 696 | static int included_patches[] = |
697 | 697 | { /* Add new patch number below this line */ |
698 | 698 | /**/ |
699 | + 913, | |
700 | +/**/ | |
699 | 701 | 912, |
700 | 702 | /**/ |
701 | 703 | 911, |
@@ -2843,44 +2843,76 @@ | ||
2843 | 2843 | } |
2844 | 2844 | |
2845 | 2845 | /* |
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. | |
2847 | 2877 | */ |
2848 | 2878 | void |
2849 | 2879 | may_trigger_winscrolled(void) |
2850 | 2880 | { |
2851 | 2881 | static int recursive = FALSE; |
2852 | 2882 | |
2853 | - if (recursive || !has_winscrolled()) | |
2883 | + if (recursive | |
2884 | + || !has_winscrolled() | |
2885 | + || !did_initial_scroll_size_snapshot) | |
2854 | 2886 | return; |
2855 | 2887 | |
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) | |
2876 | 2895 | { |
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; | |
2882 | 2915 | } |
2883 | - } | |
2884 | 2916 | } |
2885 | 2917 | |
2886 | 2918 | /* |