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*
WinScrolled After scrolling the content of a window or WinScrolled After scrolling the content of a window or
resizing a window. resizing a window in the current tab page.
The pattern is matched against the
|window-ID|. Both <amatch> and <afile> are When more than one window scrolled or resized
set to the |window-ID|. only one WinScrolled event is triggered. You
Non-recursive (the event cannot trigger can use the `winlayout()` and `getwininfo()`
itself). However, if the command causes the functions to see what changed.
window to scroll or change size another
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. WinScrolled event will be triggered later.
Does not trigger when the command is added, Does not trigger when the command is added,
only after the first scroll or resize. 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}* 6. Patterns *autocmd-patterns* *{aupat}*

View File

@@ -1469,6 +1469,9 @@ main_loop(
time_fd = NULL; time_fd = NULL;
} }
#endif #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 #ifdef FEAT_GUI
if (need_mouse_correct) if (need_mouse_correct)

View File

@@ -18,6 +18,7 @@ void curwin_init(void);
void close_windows(buf_T *buf, int keep_curwin); void close_windows(buf_T *buf, int keep_curwin);
int one_window(void); int one_window(void);
int win_close(win_T *win, int free_buf); int win_close(win_T *win, int free_buf);
void may_make_initial_scroll_size_snapshot(void);
void may_trigger_winscrolled(void); void may_trigger_winscrolled(void);
void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp); void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp);
void win_free_all(void); 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 TermWait(buf)
call StopVimInTerminal(buf) call StopVimInTerminal(buf)
" check the startup script finished to the end
call assert_equal(['123456'], readfile('Xtestout')) call assert_equal(['123456'], readfile('Xtestout'))
call delete('Xtestout') call delete('Xtestout')
endfunc 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() func Test_WinScrolled_long_wrapped()
CheckRunVimInTerminal CheckRunVimInTerminal
@@ -2916,6 +2943,7 @@ func Test_SpellFileMissing_bwipe()
call assert_fails('set spell spelllang=0', 'E937:') call assert_fails('set spell spelllang=0', 'E937:')
au! SpellFileMissing au! SpellFileMissing
set nospell spelllang=en
bwipe bwipe
endfunc endfunc

View File

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

View File

@@ -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 void
may_trigger_winscrolled(void) may_trigger_winscrolled(void)
{ {
static int recursive = FALSE; static int recursive = FALSE;
if (recursive || !has_winscrolled()) if (recursive
|| !has_winscrolled()
|| !did_initial_scroll_size_snapshot)
return; return;
win_T *wp = curwin; win_T *wp;
if (wp->w_last_topline != wp->w_topline FOR_ALL_WINDOWS(wp)
|| wp->w_last_leftcol != wp->w_leftcol if (wp->w_last_topline != wp->w_topline
|| wp->w_last_skipcol != wp->w_skipcol || wp->w_last_leftcol != wp->w_leftcol
|| wp->w_last_width != wp->w_width || wp->w_last_skipcol != wp->w_skipcol
|| wp->w_last_height != wp->w_height) || 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; // WinScrolled is triggered only once, even when multiple windows
wp->w_last_leftcol = wp->w_leftcol; // scrolled or changed size. Store the current values before
wp->w_last_skipcol = wp->w_skipcol; // triggering the event, if a scroll or resize happens as a side
wp->w_last_width = wp->w_width; // effect then WinScrolled is triggered again later.
wp->w_last_height = wp->w_height; 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;
} }
}
} }
/* /*