0
0
mirror of https://github.com/vim/vim.git synced 2025-09-25 03:54:15 -04:00

patch 9.0.0917: the WinScrolled autocommand event is not enough

Problem:    The WinScrolled autocommand event is not enough.
Solution:   Add WinResized and provide information about what changed.
            (closes #11576)
This commit is contained in:
Bram Moolenaar
2022-11-22 12:40:50 +00:00
parent ce30ccc06a
commit 35fc61cb5b
14 changed files with 461 additions and 60 deletions

View File

@@ -1371,21 +1371,24 @@ WinNew When a new window was created. Not done for
Before a WinEnter event.
*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.
WinScrolled After any window in the current tab page
scrolled the text (horizontally or vertically)
or changed width or height. See
|win-scrolled-resized|.
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|.
|v:event| is set with information about size
and scroll changes. |WinScrolled-event|
Only starts triggering after startup finished
and the first screen redraw was done.
Does not trigger when defining the first
WinScrolled or WinResized event, but may
trigger when adding more.
Non-recursive: the event will not trigger
while executing commands for the WinScrolled
@@ -1393,11 +1396,17 @@ WinScrolled After scrolling the content of a window or
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).
*WinResized*
WinResized After a window in the current tab page changed
width or height.
See |win-scrolled-resized|.
|v:event| is set with information about size
changes. |WinResized-event|
Same behavior as |WinScrolled| for the
pattern, triggering and recursiveness.
==============================================================================
6. Patterns *autocmd-patterns* *{aupat}*

View File

@@ -631,6 +631,54 @@ it).
The minimal height and width of a window is set with 'winminheight' and
'winminwidth'. These are hard values, a window will never become smaller.
WinScrolled and WinResized autocommands ~
*win-scrolled-resized*
If you want to get notified of changes in window sizes, the |WinResized|
autocommand event can be used.
If you want to get notified of text in windows scrolling vertically or
horizontally, the |WinScrolled| autocommand event can be used. This will also
trigger in window size changes.
*WinResized-event*
The |WinResized| event is triggered after updating the display, several
windows may have changed size then. A list of the IDs of windows that changed
since last time is provided in the v:event.windows variable, for example:
[1003, 1006]
*WinScrolled-event*
The |WinScrolled| event is triggered after |WinResized|, and also if a window
was scrolled. That can be vertically (the text at the top of the window
changed) or horizontally (when 'wrap' is off or when the first displayed part
of the first line changes). Note that |WinScrolled| will trigger many more
times than |WinResized|, it may slow down editing a bit.
The information provided by |WinScrolled| is a dictionary for each window that
has changes, using the window ID as the key, and a total count of the changes
with the key "all". Example value for |v:event| (|Vim9| syntax):
{
all: {width: 0, height: 2, leftcol: 0, topline: 1, skipcol: 0},
1003: {width: 0, height: -1, leftcol: 0, topline: 0, skipcol: 0},
1006: {width: 0, height: 1, leftcol: 0, topline: 1, skipcol: 0},
}
Note that the "all" entry has the absolute values of the individual windows
accumulated.
If you need more information about what changed, or you want to "debounce" the
events (not handle every event to avoid doing too much work), you may want to
use the `winlayout()` and `getwininfo()` functions.
|WinScrolled| and |WinResized| do not trigger when the first autocommand is
added, only after the first scroll or resize. They may trigger when switching
to another tab page.
The commands executed are expected to not cause window size or scroll changes.
If this happens anyway, the event will trigger again very soon. In other
words: Just before triggering the event, the current sizes and scroll
positions are stored and used to decide whether there was a change.
*E1312*
It is not allowed to change the window layout here (split, close or move
windows).
==============================================================================
7. Argument and buffer list commands *buffer-list*

View File

@@ -191,6 +191,7 @@ static struct event_name
{"WinClosed", EVENT_WINCLOSED},
{"WinEnter", EVENT_WINENTER},
{"WinLeave", EVENT_WINLEAVE},
{"WinResized", EVENT_WINRESIZED},
{"WinScrolled", EVENT_WINSCROLLED},
{"VimResized", EVENT_VIMRESIZED},
{"TextYankPost", EVENT_TEXTYANKPOST},
@@ -1263,10 +1264,11 @@ do_autocmd_event(
if (event == EVENT_MODECHANGED && !has_modechanged())
get_mode(last_mode);
#endif
// Initialize the fields checked by the WinScrolled trigger to
// prevent it from firing right after the first autocmd is
// defined.
if (event == EVENT_WINSCROLLED && !has_winscrolled())
// Initialize the fields checked by the WinScrolled and
// WinResized trigger to prevent them from firing right after
// the first autocmd is defined.
if ((event == EVENT_WINSCROLLED || event == EVENT_WINRESIZED)
&& !(has_winscrolled() || has_winresized()))
{
tabpage_T *save_curtab = curtab;
tabpage_T *tp;
@@ -1810,6 +1812,15 @@ trigger_cursorhold(void)
return FALSE;
}
/*
* Return TRUE when there is a WinResized autocommand defined.
*/
int
has_winresized(void)
{
return (first_autopat[(int)EVENT_WINRESIZED] != NULL);
}
/*
* Return TRUE when there is a WinScrolled autocommand defined.
*/
@@ -2117,6 +2128,7 @@ apply_autocmds_group(
|| event == EVENT_MENUPOPUP
|| event == EVENT_USER
|| event == EVENT_WINCLOSED
|| event == EVENT_WINRESIZED
|| event == EVENT_WINSCROLLED)
{
fname = vim_strsave(fname);

View File

@@ -1082,13 +1082,14 @@ failret:
* Go over all entries in "d2" and add them to "d1".
* When "action" is "error" then a duplicate key is an error.
* When "action" is "force" then a duplicate key is overwritten.
* When "action" is "move" then move items instead of copying.
* Otherwise duplicate keys are ignored ("action" is "keep").
* "func_name" is used for reporting where an error occurred.
*/
void
dict_extend(dict_T *d1, dict_T *d2, char_u *action, char *func_name)
{
dictitem_T *di1;
hashitem_T *hi2;
int todo;
char_u *arg_errmsg = (char_u *)N_("extend() argument");
type_T *type;
@@ -1098,8 +1099,11 @@ dict_extend(dict_T *d1, dict_T *d2, char_u *action, char *func_name)
else
type = NULL;
if (*action == 'm')
hash_lock(&d2->dv_hashtab); // don't rehash on hash_remove()
todo = (int)d2->dv_hashtab.ht_used;
for (hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2)
for (hashitem_T *hi2 = d2->dv_hashtab.ht_array; todo > 0; ++hi2)
{
if (!HASHITEM_EMPTY(hi2))
{
@@ -1116,9 +1120,19 @@ dict_extend(dict_T *d1, dict_T *d2, char_u *action, char *func_name)
if (di1 == NULL)
{
di1 = dictitem_copy(HI2DI(hi2));
if (di1 != NULL && dict_add(d1, di1) == FAIL)
dictitem_free(di1);
if (*action == 'm')
{
// cheap way to move a dict item from "d2" to "d1"
di1 = HI2DI(hi2);
dict_add(d1, di1);
hash_remove(&d2->dv_hashtab, hi2);
}
else
{
di1 = dictitem_copy(HI2DI(hi2));
if (di1 != NULL && dict_add(d1, di1) == FAIL)
dictitem_free(di1);
}
}
else if (*action == 'e')
{
@@ -1138,6 +1152,9 @@ dict_extend(dict_T *d1, dict_T *d2, char_u *action, char *func_name)
}
}
}
if (*action == 'm')
hash_unlock(&d2->dv_hashtab);
}
/*
@@ -1272,7 +1289,7 @@ dict_extend_func(
action = (char_u *)"force";
if (type != NULL && check_typval_arg_type(type, &argvars[1],
func_name, 2) == FAIL)
func_name, 2) == FAIL)
return;
dict_extend(d1, d2, action, func_name);

View File

@@ -1510,7 +1510,7 @@ ins_redraw(int ready) // not busy with something
}
if (ready)
may_trigger_winscrolled();
may_trigger_win_scrolled_resized();
// Trigger SafeState if nothing is pending.
may_trigger_safestate(ready

View File

@@ -5097,7 +5097,7 @@ gui_update_screen(void)
}
if (!finish_op)
may_trigger_winscrolled();
may_trigger_win_scrolled_resized();
# ifdef FEAT_CONCEAL
if (conceal_update_lines

View File

@@ -1358,7 +1358,7 @@ main_loop(
validate_cursor();
if (!finish_op)
may_trigger_winscrolled();
may_trigger_win_scrolled_resized();
// If nothing is pending and we are going to wait for the user to
// type a character, trigger SafeState.

View File

@@ -1171,7 +1171,7 @@ do_mousescroll(cmdarg_T *cap)
leftcol = 0;
do_mousescroll_horiz((long_u)leftcol);
}
may_trigger_winscrolled();
may_trigger_win_scrolled_resized();
}
/*

View File

@@ -16,6 +16,7 @@ int apply_autocmds(event_T event, char_u *fname, char_u *fname_io, int force, bu
int apply_autocmds_exarg(event_T event, char_u *fname, char_u *fname_io, int force, buf_T *buf, exarg_T *eap);
int apply_autocmds_retval(event_T event, char_u *fname, char_u *fname_io, int force, buf_T *buf, int *retval);
int trigger_cursorhold(void);
int has_winresized(void);
int has_winscrolled(void);
int has_cursormoved(void);
int has_cursormovedI(void);

View File

@@ -20,7 +20,7 @@ int one_window(void);
int win_close(win_T *win, int free_buf);
void snapshot_windows_scroll_size(void);
void may_make_initial_scroll_size_snapshot(void);
void may_trigger_winscrolled(void);
void may_trigger_win_scrolled_resized(void);
void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp);
void win_free_all(void);
win_T *winframe_remove(win_T *win, int *dirp, tabpage_T *tp);

View File

@@ -306,6 +306,61 @@ func Test_win_tab_autocmd()
unlet g:record
endfunc
func Test_WinResized()
CheckRunVimInTerminal
let lines =<< trim END
set scrolloff=0
call setline(1, ['111', '222'])
vnew
call setline(1, ['aaa', 'bbb'])
new
call setline(1, ['foo', 'bar'])
let g:resized = 0
au WinResized * let g:resized += 1
func WriteResizedEvent()
call writefile([json_encode(v:event)], 'XresizeEvent')
endfunc
au WinResized * call WriteResizedEvent()
END
call writefile(lines, 'Xtest_winresized', 'D')
let buf = RunVimInTerminal('-S Xtest_winresized', {'rows': 10})
" redraw now to avoid a redraw after the :echo command
call term_sendkeys(buf, ":redraw!\<CR>")
call TermWait(buf)
call term_sendkeys(buf, ":echo g:resized\<CR>")
call WaitForAssert({-> assert_match('^0$', term_getline(buf, 10))}, 1000)
" increase window height, two windows will be reported
call term_sendkeys(buf, "\<C-W>+")
call TermWait(buf)
call term_sendkeys(buf, ":echo g:resized\<CR>")
call WaitForAssert({-> assert_match('^1$', term_getline(buf, 10))}, 1000)
let event = readfile('XresizeEvent')[0]->json_decode()
call assert_equal({
\ 'windows': [1002, 1001],
\ }, event)
" increase window width, three windows will be reported
call term_sendkeys(buf, "\<C-W>>")
call TermWait(buf)
call term_sendkeys(buf, ":echo g:resized\<CR>")
call WaitForAssert({-> assert_match('^2$', term_getline(buf, 10))}, 1000)
let event = readfile('XresizeEvent')[0]->json_decode()
call assert_equal({
\ 'windows': [1002, 1001, 1000],
\ }, event)
call delete('XresizeEvent')
call StopVimInTerminal(buf)
endfunc
func Test_WinScrolled()
CheckRunVimInTerminal
@@ -316,11 +371,15 @@ func Test_WinScrolled()
endfor
let win_id = win_getid()
let g:matched = v:false
func WriteScrollEvent()
call writefile([json_encode(v:event)], 'XscrollEvent')
endfunc
execute 'au WinScrolled' win_id 'let g:matched = v:true'
let g:scrolled = 0
au WinScrolled * let g:scrolled += 1
au WinScrolled * let g:amatch = str2nr(expand('<amatch>'))
au WinScrolled * let g:afile = str2nr(expand('<afile>'))
au WinScrolled * call WriteScrollEvent()
END
call writefile(lines, 'Xtest_winscrolled', 'D')
let buf = RunVimInTerminal('-S Xtest_winscrolled', {'rows': 6})
@@ -332,15 +391,33 @@ func Test_WinScrolled()
call term_sendkeys(buf, "zlzh:echo g:scrolled\<CR>")
call WaitForAssert({-> assert_match('^2 ', term_getline(buf, 6))}, 1000)
let event = readfile('XscrollEvent')[0]->json_decode()
call assert_equal({
\ 'all': {'leftcol': 1, 'topline': 0, 'width': 0, 'height': 0, 'skipcol': 0},
\ '1000': {'leftcol': -1, 'topline': 0, 'width': 0, 'height': 0, 'skipcol': 0}
\ }, event)
" Scroll up/down in Normal mode.
call term_sendkeys(buf, "\<c-e>\<c-y>:echo g:scrolled\<CR>")
call WaitForAssert({-> assert_match('^4 ', term_getline(buf, 6))}, 1000)
let event = readfile('XscrollEvent')[0]->json_decode()
call assert_equal({
\ 'all': {'leftcol': 0, 'topline': 1, 'width': 0, 'height': 0, 'skipcol': 0},
\ '1000': {'leftcol': 0, 'topline': -1, 'width': 0, 'height': 0, 'skipcol': 0}
\ }, event)
" Scroll up/down in Insert mode.
call term_sendkeys(buf, "Mi\<c-x>\<c-e>\<Esc>i\<c-x>\<c-y>\<Esc>")
call term_sendkeys(buf, ":echo g:scrolled\<CR>")
call WaitForAssert({-> assert_match('^6 ', term_getline(buf, 6))}, 1000)
let event = readfile('XscrollEvent')[0]->json_decode()
call assert_equal({
\ 'all': {'leftcol': 0, 'topline': 1, 'width': 0, 'height': 0, 'skipcol': 0},
\ '1000': {'leftcol': 0, 'topline': -1, 'width': 0, 'height': 0, 'skipcol': 0}
\ }, event)
" Scroll the window horizontally to focus the last letter of the third line
" containing only six characters. Moving to the previous and shorter lines
" should trigger another autocommand as Vim has to make them visible.
@@ -348,6 +425,12 @@ func Test_WinScrolled()
call term_sendkeys(buf, ":echo g:scrolled\<CR>")
call WaitForAssert({-> assert_match('^8 ', term_getline(buf, 6))}, 1000)
let event = readfile('XscrollEvent')[0]->json_decode()
call assert_equal({
\ 'all': {'leftcol': 5, 'topline': 0, 'width': 0, 'height': 0, 'skipcol': 0},
\ '1000': {'leftcol': -5, 'topline': 0, 'width': 0, 'height': 0, 'skipcol': 0}
\ }, event)
" Ensure the command was triggered for the specified window ID.
call term_sendkeys(buf, ":echo g:matched\<CR>")
call WaitForAssert({-> assert_match('^v:true ', term_getline(buf, 6))}, 1000)
@@ -356,6 +439,7 @@ func Test_WinScrolled()
call term_sendkeys(buf, ":echo g:amatch == win_id && g:afile == win_id\<CR>")
call WaitForAssert({-> assert_match('^v:true ', term_getline(buf, 6))}, 1000)
call delete('XscrollEvent')
call StopVimInTerminal(buf)
endfunc

View File

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

View File

@@ -1407,7 +1407,8 @@ enum auto_event
EVENT_WINCLOSED, // after closing a window
EVENT_VIMSUSPEND, // before Vim is suspended
EVENT_VIMRESUME, // after Vim is resumed
EVENT_WINSCROLLED, // after Vim window was scrolled
EVENT_WINRESIZED, // after a window was resized
EVENT_WINSCROLLED, // after a window was scrolled or resized
NUM_EVENTS // MUST be the last one
};

View File

@@ -2873,46 +2873,273 @@ may_make_initial_scroll_size_snapshot(void)
}
/*
* Trigger WinScrolled if any window scrolled or changed size.
* Create a dictionary with information about size and scroll changes in a
* window.
* Returns the dictionary with refcount set to one.
* Returns NULL when out of memory.
*/
void
may_trigger_winscrolled(void)
static dict_T *
make_win_info_dict(
int width,
int height,
int topline,
int leftcol,
int skipcol)
{
static int recursive = FALSE;
dict_T *d = dict_alloc();
if (d == NULL)
return NULL;
d->dv_refcount = 1;
if (recursive
|| !has_winscrolled()
|| !did_initial_scroll_size_snapshot)
return;
// not actually looping, for breaking out on error
while (1)
{
typval_T tv;
tv.v_lock = 0;
tv.v_type = VAR_NUMBER;
tv.vval.v_number = width;
if (dict_add_tv(d, "width", &tv) == FAIL)
break;
tv.vval.v_number = height;
if (dict_add_tv(d, "height", &tv) == FAIL)
break;
tv.vval.v_number = topline;
if (dict_add_tv(d, "topline", &tv) == FAIL)
break;
tv.vval.v_number = leftcol;
if (dict_add_tv(d, "leftcol", &tv) == FAIL)
break;
tv.vval.v_number = skipcol;
if (dict_add_tv(d, "skipcol", &tv) == FAIL)
break;
return d;
}
dict_unref(d);
return NULL;
}
// Return values of check_window_scroll_resize():
#define CWSR_SCROLLED 1 // at least one window scrolled
#define CWSR_RESIZED 2 // at least one window size changed
/*
* This function is used for three purposes:
* 1. Goes over all windows in the current tab page and returns:
* 0 no scrolling and no size changes found
* CWSR_SCROLLED at least one window scrolled
* CWSR_RESIZED at least one window changed size
* CWSR_SCROLLED + CWSR_RESIZED both
* "size_count" is set to the nr of windows with size changes.
* "first_scroll_win" is set to the first window with any relevant changes.
* "first_size_win" is set to the first window with size changes.
*
* 2. When the first three arguments are NULL and "winlist" is not NULL,
* "winlist" is set to the list of window IDs with size changes.
*
* 3. When the first three arguments are NULL and "v_event" is not NULL,
* information about changed windows is added to "v_event".
*/
static int
check_window_scroll_resize(
int *size_count,
win_T **first_scroll_win,
win_T **first_size_win,
list_T *winlist,
dict_T *v_event)
{
int result = 0;
int listidx = 0;
int tot_width = 0;
int tot_height = 0;
int tot_topline = 0;
int tot_leftcol = 0;
int tot_skipcol = 0;
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)
{
int size_changed = wp->w_last_width != wp->w_width
|| wp->w_last_height != wp->w_height;
if (size_changed)
{
// 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;
result |= CWSR_RESIZED;
if (winlist != NULL)
{
// Add this window to the list of changed windows.
typval_T tv;
tv.v_lock = 0;
tv.v_type = VAR_NUMBER;
tv.vval.v_number = wp->w_id;
list_set_item(winlist, listidx++, &tv);
}
else if (size_count != NULL)
{
++*size_count;
if (*first_size_win == NULL)
*first_size_win = wp;
// For WinScrolled the first window with a size change is used
// even when it didn't scroll.
if (*first_scroll_win == NULL)
*first_scroll_win = wp;
}
}
int scroll_changed = wp->w_last_topline != wp->w_topline
|| wp->w_last_leftcol != wp->w_leftcol
|| wp->w_last_skipcol != wp->w_skipcol;
if (scroll_changed)
{
result |= CWSR_SCROLLED;
if (first_scroll_win != NULL && *first_scroll_win == NULL)
*first_scroll_win = wp;
}
if ((size_changed || scroll_changed) && v_event != NULL)
{
// Add info about this window to the v:event dictionary.
int width = wp->w_width - wp->w_last_width;
int height = wp->w_height - wp->w_last_height;
int topline = wp->w_topline - wp->w_last_topline;
int leftcol = wp->w_leftcol - wp->w_last_leftcol;
int skipcol = wp->w_skipcol - wp->w_last_skipcol;
dict_T *d = make_win_info_dict(width, height,
topline, leftcol, skipcol);
if (d == NULL)
break;
char winid[NUMBUFLEN];
vim_snprintf(winid, sizeof(winid), "%d", wp->w_id);
if (dict_add_dict(v_event, winid, d) == FAIL)
{
dict_unref(d);
break;
}
--d->dv_refcount;
tot_width += abs(width);
tot_height += abs(height);
tot_topline += abs(topline);
tot_leftcol += abs(leftcol);
tot_skipcol += abs(skipcol);
}
}
if (v_event != NULL)
{
dict_T *alldict = make_win_info_dict(tot_width, tot_height,
tot_topline, tot_leftcol, tot_skipcol);
if (alldict != NULL)
{
if (dict_add_dict(v_event, "all", alldict) == FAIL)
dict_unref(alldict);
else
--alldict->dv_refcount;
}
}
return result;
}
/*
* Trigger WinScrolled and/or WinResized if any window in the current tab page
* scrolled or changed size.
*/
void
may_trigger_win_scrolled_resized(void)
{
static int recursive = FALSE;
int do_resize = has_winresized();
int do_scroll = has_winscrolled();
// Do not trigger WinScrolled or WinResized recursively. Do not trigger
// before the initial snapshot of the w_last_ values was made.
if (recursive
|| !(do_scroll || do_resize)
|| !did_initial_scroll_size_snapshot)
return;
int size_count = 0;
win_T *first_scroll_win = NULL, *first_size_win = NULL;
int cwsr = check_window_scroll_resize(&size_count,
&first_scroll_win, &first_size_win,
NULL, NULL);
int trigger_resize = do_resize && size_count > 0;
int trigger_scroll = do_scroll && cwsr != 0;
if (!trigger_resize && !trigger_scroll)
return; // no relevant changes
list_T *windows_list = NULL;
if (trigger_resize)
{
// Create the list for v:event.windows before making the snapshot.
windows_list = list_alloc_with_items(size_count);
(void)check_window_scroll_resize(NULL, NULL, NULL, windows_list, NULL);
}
dict_T *scroll_dict = NULL;
if (trigger_scroll)
{
// Create the dict with entries for v:event before making the snapshot.
scroll_dict = dict_alloc();
if (scroll_dict != NULL)
{
scroll_dict->dv_refcount = 1;
(void)check_window_scroll_resize(NULL, NULL, NULL, NULL,
scroll_dict);
}
}
// WinScrolled/WinResized are 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/WinResized is triggered for that 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;
// If both are to be triggered do WinResized first.
if (trigger_resize)
{
save_v_event_T save_v_event;
dict_T *v_event = get_v_event(&save_v_event);
if (dict_add_list(v_event, "windows", windows_list) == OK)
{
dict_set_items_ro(v_event);
char_u winid[NUMBUFLEN];
vim_snprintf((char *)winid, sizeof(winid), "%d",
first_size_win->w_id);
apply_autocmds(EVENT_WINRESIZED, winid, winid, FALSE,
first_size_win->w_buffer);
}
restore_v_event(v_event, &save_v_event);
}
if (trigger_scroll)
{
save_v_event_T save_v_event;
dict_T *v_event = get_v_event(&save_v_event);
// Move the entries from scroll_dict to v_event.
dict_extend(v_event, scroll_dict, (char_u *)"move", NULL);
dict_set_items_ro(v_event);
dict_unref(scroll_dict);
char_u winid[NUMBUFLEN];
vim_snprintf((char *)winid, sizeof(winid), "%d",
first_scroll_win->w_id);
apply_autocmds(EVENT_WINSCROLLED, winid, winid, FALSE,
first_scroll_win->w_buffer);
restore_v_event(v_event, &save_v_event);
}
recursive = FALSE;
window_layout_unlock();
}
/*