*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}*
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)
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);
--- /dev/null
+|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
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
call assert_fails('set spell spelllang=0', 'E937:')
au! SpellFileMissing
+ set nospell spelllang=en
bwipe
endfunc
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 913,
/**/
912,
/**/
}
/*
- * 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
may_trigger_winscrolled(void)
{
static int recursive = FALSE;
- if (recursive || !has_winscrolled())
+ if (recursive
+ || !has_winscrolled()
+ || !did_initial_scroll_size_snapshot)
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)
+ 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)
{
- 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;
}
- }
}
/*