To: vim_dev@googlegroups.com Subject: Patch 9.0.0913 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 9.0.0913 Problem: Only a change in the current window triggers the WinScrolled event. Solution: Trigger WinScrolled if any window scrolled or changed size. (issue #11576) Files: runtime/doc/autocmd.txt, src/window.c, src/proto/window.pro, src/main.c, src/testdir/test_autocmd.vim, src/testdir/dumps/Test_winscrolled_once_only_1.dump *** ../vim-9.0.0912/runtime/doc/autocmd.txt 2022-10-15 11:47:54.213416782 +0100 --- runtime/doc/autocmd.txt 2022-11-19 21:05:58.892154099 +0000 *************** *** 1370,1385 **** *WinScrolled* WinScrolled After scrolling the content of a window or ! resizing a window. ! The pattern is matched against the ! |window-ID|. Both and are ! set to the |window-ID|. ! Non-recursive (the event cannot trigger ! itself). However, if the command causes the ! window to scroll or change size another WinScrolled event will be triggered later. Does not trigger when the command is added, only after the first scroll or resize. ============================================================================== 6. Patterns *autocmd-patterns* *{aupat}* --- 1372,1403 ---- *WinScrolled* WinScrolled After scrolling the content of a window or ! resizing a window in the current tab page. ! ! When more than one window scrolled or resized ! only one WinScrolled event is triggered. You ! can use the `winlayout()` and `getwininfo()` ! functions to see what changed. ! ! The pattern is matched against the |window-ID| ! of the first window that scrolled or resized. ! Both and are set to the ! |window-ID|. ! ! Only starts triggering after startup finished ! and the first screen redraw was done. ! ! Non-recursive: the event will not trigger ! while executing commands for the WinScrolled ! event. However, if the command causes a ! window to scroll or change size, then another WinScrolled event will be triggered later. + Does not trigger when the command is added, only after the first scroll or resize. + *E1312* + It is not allowed to change the window layout + here (split, close or move windows). ============================================================================== 6. Patterns *autocmd-patterns* *{aupat}* *** ../vim-9.0.0912/src/window.c 2022-11-19 13:14:05.741367062 +0000 --- src/window.c 2022-11-19 20:40:31.104818992 +0000 *************** *** 2843,2886 **** } /* ! * Trigger WinScrolled for "curwin" if needed. */ void may_trigger_winscrolled(void) { static int recursive = FALSE; ! if (recursive || !has_winscrolled()) 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)) { ! 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; } - } } /* --- 2843,2918 ---- } /* ! * 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() ! || !did_initial_scroll_size_snapshot) return; ! 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) { ! // 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; } } /* *** ../vim-9.0.0912/src/proto/window.pro 2022-11-19 13:14:05.741367062 +0000 --- src/proto/window.pro 2022-11-19 20:34:36.729047134 +0000 *************** *** 18,23 **** --- 18,24 ---- void close_windows(buf_T *buf, int keep_curwin); int one_window(void); int win_close(win_T *win, int free_buf); + void may_make_initial_scroll_size_snapshot(void); void may_trigger_winscrolled(void); void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp); void win_free_all(void); *** ../vim-9.0.0912/src/main.c 2022-11-09 16:29:20.396373252 +0000 --- src/main.c 2022-11-19 20:32:40.889122817 +0000 *************** *** 1469,1474 **** --- 1469,1477 ---- time_fd = NULL; } #endif + // After the first screen update may start triggering WinScrolled + // autocmd events. Store all the scroll positions and sizes now. + may_make_initial_scroll_size_snapshot(); } #ifdef FEAT_GUI if (need_mouse_correct) *** ../vim-9.0.0912/src/testdir/test_autocmd.vim 2022-11-19 13:14:05.741367062 +0000 --- src/testdir/test_autocmd.vim 2022-11-19 21:14:30.645003458 +0000 *************** *** 407,417 **** call TermWait(buf) call StopVimInTerminal(buf) call assert_equal(['123456'], readfile('Xtestout')) - call delete('Xtestout') endfunc func Test_WinScrolled_long_wrapped() CheckRunVimInTerminal --- 407,444 ---- call TermWait(buf) call StopVimInTerminal(buf) + " check the startup script finished to the end call assert_equal(['123456'], readfile('Xtestout')) call delete('Xtestout') endfunc + func Test_WinScrolled_once_only() + CheckRunVimInTerminal + + let lines =<< trim END + set cmdheight=2 + call setline(1, ['aaa', 'bbb']) + let trigger_count = 0 + func ShowInfo(id) + echo g:trigger_count g:winid winlayout() + endfunc + + vsplit + split + " use a timer to show the info after a redraw + au WinScrolled * let trigger_count += 1 | let winid = expand('') | call timer_start(100, 'ShowInfo') + wincmd j + wincmd l + END + call writefile(lines, 'Xtest_winscrolled_once', 'D') + let buf = RunVimInTerminal('-S Xtest_winscrolled_once', #{rows: 10, cols: 60, statusoff: 2}) + + call term_sendkeys(buf, "\") + call VerifyScreenDump(buf, 'Test_winscrolled_once_only_1', {}) + + call StopVimInTerminal(buf) + endfunc + func Test_WinScrolled_long_wrapped() CheckRunVimInTerminal *************** *** 2916,2921 **** --- 2943,2949 ---- call assert_fails('set spell spelllang=0', 'E937:') au! SpellFileMissing + set nospell spelllang=en bwipe endfunc *** ../vim-9.0.0912/src/testdir/dumps/Test_winscrolled_once_only_1.dump 2022-11-19 21:16:34.589147332 +0000 --- src/testdir/dumps/Test_winscrolled_once_only_1.dump 2022-11-19 21:13:25.048920276 +0000 *************** *** 0 **** --- 1,10 ---- + |a+0&#ffffff0@2| @26||+1&&>b+0&&@2| @25 + |b@2| @26||+1&&|~+0#4040ff13&| @27 + |~| @28||+1#0000000&|~+0#4040ff13&| @27 + |[+1#0000000&|N|o| |N|a|m|e|]| |[|+|]| @1|1|,|1| @8|A|l@1|||~+0#4040ff13&| @27 + |a+0#0000000&@2| @26||+1&&|~+0#4040ff13&| @27 + |b+0#0000000&@2| @26||+1&&|~+0#4040ff13&| @27 + |~| @28||+1#0000000&|~+0#4040ff13&| @27 + |[+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 + |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|,| |[ + |'|l|e|a|f|'|,| |1|0@2|]@2| @44 *** ../vim-9.0.0912/src/version.c 2022-11-19 19:02:33.957452667 +0000 --- src/version.c 2022-11-19 20:05:58.618459708 +0000 *************** *** 697,698 **** --- 697,700 ---- { /* Add new patch number below this line */ + /**/ + 913, /**/ -- I AM THANKFUL... ...for the piles of laundry and ironing because it means I have plenty of clothes to wear. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///