0
0
mirror of https://github.com/vim/vim.git synced 2025-09-23 03:43:49 -04:00

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)
This commit is contained in:
Bram Moolenaar
2022-11-19 21:18:11 +00:00
parent c896adbcde
commit 0a60f79fd0
7 changed files with 128 additions and 36 deletions

View File

@@ -1372,16 +1372,32 @@ WinNew When a new window was created. Not done for
*WinScrolled*
WinScrolled After scrolling the content of a window or
resizing a window.
The pattern is matched against the
|window-ID|. Both <amatch> and <afile> 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
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 <amatch> and <afile> 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}*

View File

@@ -1469,6 +1469,9 @@ main_loop(
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)

View File

@@ -18,6 +18,7 @@ void curwin_init(void);
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);

View File

@@ -0,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

View File

@@ -407,11 +407,38 @@ func Test_WinScrolled_close_curwin()
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('<amatch>') | 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, "\<C-E>")
call VerifyScreenDump(buf, 'Test_winscrolled_once_only_1', {})
call StopVimInTerminal(buf)
endfunc
func Test_WinScrolled_long_wrapped()
CheckRunVimInTerminal
@@ -2916,6 +2943,7 @@ func Test_SpellFileMissing_bwipe()
call assert_fails('set spell spelllang=0', 'E937:')
au! SpellFileMissing
set nospell spelllang=en
bwipe
endfunc

View File

@@ -695,6 +695,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
913,
/**/
912,
/**/

View File

@@ -2843,36 +2843,14 @@ 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.
*/
void
may_trigger_winscrolled(void)
static void
snapshot_windows_scroll_size(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))
win_T *wp;
FOR_ALL_WINDOWS(wp)
{
wp->w_last_topline = wp->w_topline;
wp->w_last_leftcol = wp->w_leftcol;
@@ -2881,6 +2859,60 @@ may_trigger_winscrolled(void)
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;
}
}
/*