mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00
Merge pull request #21136 from zeertzjq/vim-9.0.0913
vim-patch:9.0.{partial:0913,0915}: only change in current window triggers the WinScrolled event
This commit is contained in:
@@ -1096,22 +1096,35 @@ 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.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
6. Patterns *autocmd-pattern* *{aupat}*
|
6. Patterns *autocmd-pattern* *{aupat}*
|
||||||
|
|
||||||
The {aupat} argument of `:autocmd` can be a comma-separated list. This works
|
The {aupat} argument of `:autocmd` can be a comma-separated list. This works as
|
||||||
as if the command was given with each pattern separately. Thus this command: >
|
if the command was given with each pattern separately. Thus this command: >
|
||||||
:autocmd BufRead *.txt,*.info set et
|
:autocmd BufRead *.txt,*.info set et
|
||||||
Is equivalent to: >
|
Is equivalent to: >
|
||||||
:autocmd BufRead *.txt set et
|
:autocmd BufRead *.txt set et
|
||||||
|
@@ -1142,13 +1142,17 @@ int autocmd_register(int64_t id, event_T event, char *pat, int patlen, int group
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the fields checked by the WinScrolled trigger to
|
// Initialize the fields checked by the WinScrolled trigger to
|
||||||
// stop it from firing right after the first autocmd is defined.
|
// prevent it from firing right after the first autocmd is
|
||||||
|
// defined.
|
||||||
if (event == EVENT_WINSCROLLED && !has_event(EVENT_WINSCROLLED)) {
|
if (event == EVENT_WINSCROLLED && !has_event(EVENT_WINSCROLLED)) {
|
||||||
curwin->w_last_topline = curwin->w_topline;
|
tabpage_T *save_curtab = curtab;
|
||||||
curwin->w_last_leftcol = curwin->w_leftcol;
|
FOR_ALL_TABS(tp) {
|
||||||
curwin->w_last_skipcol = curwin->w_skipcol;
|
unuse_tabpage(curtab);
|
||||||
curwin->w_last_width = curwin->w_width;
|
use_tabpage(tp);
|
||||||
curwin->w_last_height = curwin->w_height;
|
snapshot_windows_scroll_size();
|
||||||
|
}
|
||||||
|
unuse_tabpage(curtab);
|
||||||
|
use_tabpage(save_curtab);
|
||||||
}
|
}
|
||||||
|
|
||||||
ap->cmds = NULL;
|
ap->cmds = NULL;
|
||||||
|
@@ -1397,6 +1397,9 @@ static int normal_check(VimState *state)
|
|||||||
fclose(time_fd);
|
fclose(time_fd);
|
||||||
time_fd = NULL;
|
time_fd = NULL;
|
||||||
}
|
}
|
||||||
|
// 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
// May perform garbage collection when waiting for a character, but
|
// May perform garbage collection when waiting for a character, but
|
||||||
|
@@ -311,7 +311,7 @@ func Test_WinScrolled()
|
|||||||
au WinScrolled * let g:amatch = str2nr(expand('<amatch>'))
|
au WinScrolled * let g:amatch = str2nr(expand('<amatch>'))
|
||||||
au WinScrolled * let g:afile = str2nr(expand('<afile>'))
|
au WinScrolled * let g:afile = str2nr(expand('<afile>'))
|
||||||
END
|
END
|
||||||
call writefile(lines, 'Xtest_winscrolled')
|
call writefile(lines, 'Xtest_winscrolled', 'D')
|
||||||
let buf = RunVimInTerminal('-S Xtest_winscrolled', {'rows': 6})
|
let buf = RunVimInTerminal('-S Xtest_winscrolled', {'rows': 6})
|
||||||
|
|
||||||
call term_sendkeys(buf, ":echo g:scrolled\<CR>")
|
call term_sendkeys(buf, ":echo g:scrolled\<CR>")
|
||||||
@@ -346,7 +346,36 @@ func Test_WinScrolled()
|
|||||||
call WaitForAssert({-> assert_match('^v:true ', term_getline(buf, 6))}, 1000)
|
call WaitForAssert({-> assert_match('^v:true ', term_getline(buf, 6))}, 1000)
|
||||||
|
|
||||||
call StopVimInTerminal(buf)
|
call StopVimInTerminal(buf)
|
||||||
call delete('Xtest_winscrolled')
|
endfunc
|
||||||
|
|
||||||
|
func Test_WinScrolled_mouse()
|
||||||
|
CheckRunVimInTerminal
|
||||||
|
|
||||||
|
let lines =<< trim END
|
||||||
|
set nowrap scrolloff=0
|
||||||
|
set mouse=a term=xterm ttymouse=sgr mousetime=200 clipboard=
|
||||||
|
call setline(1, ['foo']->repeat(32))
|
||||||
|
split
|
||||||
|
let g:scrolled = 0
|
||||||
|
au WinScrolled * let g:scrolled += 1
|
||||||
|
END
|
||||||
|
call writefile(lines, 'Xtest_winscrolled_mouse', 'D')
|
||||||
|
let buf = RunVimInTerminal('-S Xtest_winscrolled_mouse', {'rows': 10})
|
||||||
|
|
||||||
|
" With the upper split focused, send a scroll-down event to the unfocused one.
|
||||||
|
call test_setmouse(7, 1)
|
||||||
|
call term_sendkeys(buf, "\<ScrollWheelDown>")
|
||||||
|
call TermWait(buf)
|
||||||
|
call term_sendkeys(buf, ":echo g:scrolled\<CR>")
|
||||||
|
call WaitForAssert({-> assert_match('^1', term_getline(buf, 10))}, 1000)
|
||||||
|
|
||||||
|
" Again, but this time while we're in insert mode.
|
||||||
|
call term_sendkeys(buf, "i\<ScrollWheelDown>\<Esc>")
|
||||||
|
call TermWait(buf)
|
||||||
|
call term_sendkeys(buf, ":echo g:scrolled\<CR>")
|
||||||
|
call WaitForAssert({-> assert_match('^2', term_getline(buf, 10))}, 1000)
|
||||||
|
|
||||||
|
call StopVimInTerminal(buf)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_WinScrolled_close_curwin()
|
func Test_WinScrolled_close_curwin()
|
||||||
@@ -359,7 +388,7 @@ func Test_WinScrolled_close_curwin()
|
|||||||
au WinScrolled * close
|
au WinScrolled * close
|
||||||
au VimLeave * call writefile(['123456'], 'Xtestout')
|
au VimLeave * call writefile(['123456'], 'Xtestout')
|
||||||
END
|
END
|
||||||
call writefile(lines, 'Xtest_winscrolled_close_curwin')
|
call writefile(lines, 'Xtest_winscrolled_close_curwin', 'D')
|
||||||
let buf = RunVimInTerminal('-S Xtest_winscrolled_close_curwin', {'rows': 6})
|
let buf = RunVimInTerminal('-S Xtest_winscrolled_close_curwin', {'rows': 6})
|
||||||
|
|
||||||
" This was using freed memory
|
" This was using freed memory
|
||||||
@@ -367,12 +396,64 @@ 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('Xtest_winscrolled_close_curwin')
|
|
||||||
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
|
||||||
|
|
||||||
|
" Check that WinScrolled is not triggered immediately when defined and there
|
||||||
|
" are split windows.
|
||||||
|
func Test_WinScrolled_not_when_defined()
|
||||||
|
CheckRunVimInTerminal
|
||||||
|
|
||||||
|
let lines =<< trim END
|
||||||
|
call setline(1, ['aaa', 'bbb'])
|
||||||
|
echo 'nothing happened'
|
||||||
|
func ShowTriggered(id)
|
||||||
|
echo 'triggered'
|
||||||
|
endfunc
|
||||||
|
END
|
||||||
|
call writefile(lines, 'Xtest_winscrolled_not', 'D')
|
||||||
|
let buf = RunVimInTerminal('-S Xtest_winscrolled_not', #{rows: 10, cols: 60, statusoff: 2})
|
||||||
|
call term_sendkeys(buf, ":split\<CR>")
|
||||||
|
call TermWait(buf)
|
||||||
|
" use a timer to show the message after redrawing
|
||||||
|
call term_sendkeys(buf, ":au WinScrolled * call timer_start(100, 'ShowTriggered')\<CR>")
|
||||||
|
call VerifyScreenDump(buf, 'Test_winscrolled_not_when_defined_1', {})
|
||||||
|
|
||||||
|
call term_sendkeys(buf, "\<C-E>")
|
||||||
|
call VerifyScreenDump(buf, 'Test_winscrolled_not_when_defined_2', {})
|
||||||
|
|
||||||
|
call StopVimInTerminal(buf)
|
||||||
|
endfunc
|
||||||
|
|
||||||
func Test_WinScrolled_long_wrapped()
|
func Test_WinScrolled_long_wrapped()
|
||||||
CheckRunVimInTerminal
|
CheckRunVimInTerminal
|
||||||
|
|
||||||
@@ -385,7 +466,7 @@ func Test_WinScrolled_long_wrapped()
|
|||||||
call setline(1, repeat('foo', height * width))
|
call setline(1, repeat('foo', height * width))
|
||||||
call cursor(1, height * width)
|
call cursor(1, height * width)
|
||||||
END
|
END
|
||||||
call writefile(lines, 'Xtest_winscrolled_long_wrapped')
|
call writefile(lines, 'Xtest_winscrolled_long_wrapped', 'D')
|
||||||
let buf = RunVimInTerminal('-S Xtest_winscrolled_long_wrapped', {'rows': 6})
|
let buf = RunVimInTerminal('-S Xtest_winscrolled_long_wrapped', {'rows': 6})
|
||||||
|
|
||||||
call term_sendkeys(buf, ":echo g:scrolled\<CR>")
|
call term_sendkeys(buf, ":echo g:scrolled\<CR>")
|
||||||
@@ -402,8 +483,6 @@ func Test_WinScrolled_long_wrapped()
|
|||||||
call term_sendkeys(buf, '$')
|
call term_sendkeys(buf, '$')
|
||||||
call term_sendkeys(buf, ":echo g:scrolled\<CR>")
|
call term_sendkeys(buf, ":echo g:scrolled\<CR>")
|
||||||
call WaitForAssert({-> assert_match('^3 ', term_getline(buf, 6))}, 1000)
|
call WaitForAssert({-> assert_match('^3 ', term_getline(buf, 6))}, 1000)
|
||||||
|
|
||||||
call delete('Xtest_winscrolled_long_wrapped')
|
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_WinClosed()
|
func Test_WinClosed()
|
||||||
@@ -2788,6 +2867,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
|
||||||
|
|
||||||
|
@@ -3868,6 +3868,27 @@ void close_others(int message, int forceit)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Store the relevant window pointers for tab page "tp". To be used before
|
||||||
|
/// use_tabpage().
|
||||||
|
void unuse_tabpage(tabpage_T *tp)
|
||||||
|
{
|
||||||
|
tp->tp_topframe = topframe;
|
||||||
|
tp->tp_firstwin = firstwin;
|
||||||
|
tp->tp_lastwin = lastwin;
|
||||||
|
tp->tp_curwin = curwin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the relevant pointers to use tab page "tp". May want to call
|
||||||
|
/// unuse_tabpage() first.
|
||||||
|
void use_tabpage(tabpage_T *tp)
|
||||||
|
{
|
||||||
|
curtab = tp;
|
||||||
|
topframe = curtab->tp_topframe;
|
||||||
|
firstwin = curtab->tp_firstwin;
|
||||||
|
lastwin = curtab->tp_lastwin;
|
||||||
|
curwin = curtab->tp_curwin;
|
||||||
|
}
|
||||||
|
|
||||||
// Allocate the first window and put an empty buffer in it.
|
// Allocate the first window and put an empty buffer in it.
|
||||||
// Only called from main().
|
// Only called from main().
|
||||||
void win_alloc_first(void)
|
void win_alloc_first(void)
|
||||||
@@ -3878,11 +3899,8 @@ void win_alloc_first(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
first_tabpage = alloc_tabpage();
|
first_tabpage = alloc_tabpage();
|
||||||
first_tabpage->tp_topframe = topframe;
|
|
||||||
curtab = first_tabpage;
|
curtab = first_tabpage;
|
||||||
curtab->tp_firstwin = firstwin;
|
unuse_tabpage(first_tabpage);
|
||||||
curtab->tp_lastwin = lastwin;
|
|
||||||
curtab->tp_curwin = curwin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init `aucmd_win`. This can only be done after the first window
|
// Init `aucmd_win`. This can only be done after the first window
|
||||||
@@ -4253,10 +4271,7 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, bool trigger_enter_a
|
|||||||
win_T *next_prevwin = tp->tp_prevwin;
|
win_T *next_prevwin = tp->tp_prevwin;
|
||||||
tabpage_T *old_curtab = curtab;
|
tabpage_T *old_curtab = curtab;
|
||||||
|
|
||||||
curtab = tp;
|
use_tabpage(tp);
|
||||||
firstwin = tp->tp_firstwin;
|
|
||||||
lastwin = tp->tp_lastwin;
|
|
||||||
topframe = tp->tp_topframe;
|
|
||||||
|
|
||||||
if (old_curtab != curtab) {
|
if (old_curtab != curtab) {
|
||||||
tabpage_check_windows(old_curtab);
|
tabpage_check_windows(old_curtab);
|
||||||
@@ -5263,35 +5278,60 @@ void win_new_screen_cols(void)
|
|||||||
win_reconfig_floats(); // The size of floats might change
|
win_reconfig_floats(); // The size of floats might change
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trigger WinScrolled for "curwin" if needed.
|
/// Make a snapshot of all the window scroll positions and sizes of the current
|
||||||
|
/// tab page.
|
||||||
|
void snapshot_windows_scroll_size(void)
|
||||||
|
{
|
||||||
|
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
||||||
|
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 bool 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)
|
void may_trigger_winscrolled(void)
|
||||||
{
|
{
|
||||||
static bool recursive = false;
|
static bool recursive = false;
|
||||||
|
|
||||||
if (recursive || !has_event(EVENT_WINSCROLLED)) {
|
if (recursive
|
||||||
|
|| !has_event(EVENT_WINSCROLLED)
|
||||||
|
|| !did_initial_scroll_size_snapshot) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
win_T *wp = curwin;
|
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
||||||
if (wp->w_last_topline != wp->w_topline
|
if (wp->w_last_topline != wp->w_topline
|
||||||
|| wp->w_last_leftcol != wp->w_leftcol
|
|| wp->w_last_leftcol != wp->w_leftcol
|
||||||
|| wp->w_last_skipcol != wp->w_skipcol
|
|| wp->w_last_skipcol != wp->w_skipcol
|
||||||
|| wp->w_last_width != wp->w_width
|
|| wp->w_last_width != wp->w_width
|
||||||
|| wp->w_last_height != wp->w_height) {
|
|| wp->w_last_height != wp->w_height) {
|
||||||
char winid[NUMBUFLEN];
|
// WinScrolled is triggered only once, even when multiple windows
|
||||||
vim_snprintf(winid, sizeof(winid), "%d", wp->handle);
|
// 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();
|
||||||
|
|
||||||
recursive = true;
|
char winid[NUMBUFLEN];
|
||||||
apply_autocmds(EVENT_WINSCROLLED, winid, winid, false, wp->w_buffer);
|
vim_snprintf(winid, sizeof(winid), "%d", wp->handle);
|
||||||
recursive = false;
|
|
||||||
|
|
||||||
// an autocmd may close the window, "wp" may be invalid now
|
recursive = true;
|
||||||
if (win_valid_any_tab(wp)) {
|
apply_autocmds(EVENT_WINSCROLLED, winid, winid, false, wp->w_buffer);
|
||||||
wp->w_last_topline = wp->w_topline;
|
recursive = false;
|
||||||
wp->w_last_leftcol = wp->w_leftcol;
|
|
||||||
wp->w_last_skipcol = wp->w_skipcol;
|
break;
|
||||||
wp->w_last_width = wp->w_width;
|
|
||||||
wp->w_last_height = wp->w_height;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,10 @@
|
|||||||
local helpers = require('test.functional.helpers')(after_each)
|
local helpers = require('test.functional.helpers')(after_each)
|
||||||
|
local Screen = require('test.functional.ui.screen')
|
||||||
|
|
||||||
local clear = helpers.clear
|
local clear = helpers.clear
|
||||||
local eq = helpers.eq
|
local eq = helpers.eq
|
||||||
local eval = helpers.eval
|
local eval = helpers.eval
|
||||||
|
local exec = helpers.exec
|
||||||
local command = helpers.command
|
local command = helpers.command
|
||||||
local feed = helpers.feed
|
local feed = helpers.feed
|
||||||
local meths = helpers.meths
|
local meths = helpers.meths
|
||||||
@@ -89,11 +91,72 @@ describe('WinScrolled', function()
|
|||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('closing window in WinScrolled does not cause use-after-free #13265', function()
|
describe('WinScrolled', function()
|
||||||
local lines = {'aaa', 'bbb'}
|
-- oldtest: Test_WinScrolled_mouse()
|
||||||
meths.buf_set_lines(0, 0, -1, true, lines)
|
it('is triggered by mouse scrolling in another window', function()
|
||||||
command('vsplit')
|
local screen = Screen.new(75, 10)
|
||||||
command('autocmd WinScrolled * close')
|
screen:attach()
|
||||||
feed('<C-E>')
|
exec([[
|
||||||
assert_alive()
|
set nowrap scrolloff=0
|
||||||
|
set mouse=a
|
||||||
|
call setline(1, ['foo']->repeat(32))
|
||||||
|
split
|
||||||
|
let g:scrolled = 0
|
||||||
|
au WinScrolled * let g:scrolled += 1
|
||||||
|
]])
|
||||||
|
eq(0, eval('g:scrolled'))
|
||||||
|
|
||||||
|
-- With the upper split focused, send a scroll-down event to the unfocused one.
|
||||||
|
meths.input_mouse('wheel', 'down', '', 0, 6, 0)
|
||||||
|
eq(1, eval('g:scrolled'))
|
||||||
|
|
||||||
|
-- Again, but this time while we're in insert mode.
|
||||||
|
feed('i')
|
||||||
|
meths.input_mouse('wheel', 'down', '', 0, 6, 0)
|
||||||
|
feed('<Esc>')
|
||||||
|
eq(2, eval('g:scrolled'))
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- oldtest: Test_WinScrolled_close_curwin()
|
||||||
|
it('closing window does not cause use-after-free #13265', function()
|
||||||
|
exec([[
|
||||||
|
set nowrap scrolloff=0
|
||||||
|
call setline(1, ['aaa', 'bbb'])
|
||||||
|
vsplit
|
||||||
|
au WinScrolled * close
|
||||||
|
]])
|
||||||
|
|
||||||
|
-- This was using freed memory
|
||||||
|
feed('<C-E>')
|
||||||
|
assert_alive()
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('is triggered by mouse scrolling in unfocused floating window #18222', function()
|
||||||
|
local screen = Screen.new(80, 24)
|
||||||
|
screen:attach()
|
||||||
|
local buf = meths.create_buf(true, true)
|
||||||
|
meths.buf_set_lines(buf, 0, -1, false, {'a', 'b', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'})
|
||||||
|
local win = meths.open_win(buf, false, {
|
||||||
|
height = 5,
|
||||||
|
width = 10,
|
||||||
|
col = 0,
|
||||||
|
row = 1,
|
||||||
|
relative = 'editor',
|
||||||
|
style = 'minimal'
|
||||||
|
})
|
||||||
|
exec([[
|
||||||
|
let g:scrolled = 0
|
||||||
|
autocmd WinScrolled * let g:scrolled += 1
|
||||||
|
autocmd WinScrolled * let g:amatch = expand('<amatch>')
|
||||||
|
]])
|
||||||
|
eq(0, eval('g:scrolled'))
|
||||||
|
|
||||||
|
meths.input_mouse('wheel', 'down', '', 0, 3, 3)
|
||||||
|
eq(1, eval('g:scrolled'))
|
||||||
|
eq(tostring(win.id), eval('g:amatch'))
|
||||||
|
|
||||||
|
meths.input_mouse('wheel', 'down', '', 0, 3, 3)
|
||||||
|
eq(2, eval('g:scrolled'))
|
||||||
|
eq(tostring(win.id), eval('g:amatch'))
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
Reference in New Issue
Block a user