aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorluukvbaal <luukvbaal@gmail.com>2023-04-25 05:05:04 +0200
committerGitHub <noreply@github.com>2023-04-25 11:05:04 +0800
commita4b2400804355e99813f39a6b38d8f38667f8bdd (patch)
treeed515da7d5c9ffcd46e06822fb1c076aa9c4920f
parentbab4bcdefbdad7f175f7f31c230de3d066963542 (diff)
downloadrneovim-a4b2400804355e99813f39a6b38d8f38667f8bdd.tar.gz
rneovim-a4b2400804355e99813f39a6b38d8f38667f8bdd.tar.bz2
rneovim-a4b2400804355e99813f39a6b38d8f38667f8bdd.zip
fix(statusline): also allow right click when 'mousemodel' is "popup*" (#23258)
Problem: The 'statusline'-format ui elements do not receive right click events when "mousemodel" is "popup*" Solution: Do not draw popupmenu and handle click event instead.
-rw-r--r--src/nvim/mouse.c46
-rw-r--r--test/functional/ui/mouse_spec.lua10
-rw-r--r--test/functional/ui/statuscolumn_spec.lua82
-rw-r--r--test/functional/ui/statusline_spec.lua348
4 files changed, 248 insertions, 238 deletions
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index 28b40994a1..c00ccdd51a 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -212,22 +212,31 @@ static int get_fpos_of_mouse(pos_T *mpos)
if (wp == NULL) {
return IN_UNKNOWN;
}
+ int winrow = row;
+ int wincol = col;
+
+ // compute the position in the buffer line from the posn on the screen
+ bool below_buffer = mouse_comp_pos(wp, &row, &col, &mpos->lnum);
+
+ if (!below_buffer && *wp->w_p_stc != NUL && mouse_col < win_col_off(wp)) {
+ return MOUSE_STATUSCOL;
+ }
// winpos and height may change in win_enter()!
- if (row + wp->w_winbar_height >= wp->w_height) { // In (or below) status line
+ if (winrow + wp->w_winbar_height >= wp->w_height) { // In (or below) status line
return IN_STATUS_LINE;
}
- if (col >= wp->w_width) { // In vertical separator line
- return IN_SEP_LINE;
+
+ if (winrow == -1 && wp->w_winbar_height != 0) {
+ return MOUSE_WINBAR;
}
- if (wp != curwin) {
- return IN_UNKNOWN;
+ if (wincol >= wp->w_width) { // In vertical separator line
+ return IN_SEP_LINE;
}
- // compute the position in the buffer line from the posn on the screen
- if (mouse_comp_pos(curwin, &row, &col, &mpos->lnum)) {
- return IN_STATUS_LINE; // past bottom
+ if (wp != curwin || below_buffer) {
+ return IN_UNKNOWN;
}
mpos->col = vcol2col(wp, mpos->lnum, col);
@@ -530,6 +539,11 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
// shift-left button -> right button
// alt-left button -> alt-right button
if (mouse_model_popup()) {
+ pos_T m_pos;
+ int m_pos_flag = get_fpos_of_mouse(&m_pos);
+ if (m_pos_flag & (IN_STATUS_LINE|MOUSE_WINBAR|MOUSE_STATUSCOL)) {
+ goto popupexit;
+ }
if (which_button == MOUSE_RIGHT
&& !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))) {
if (!is_click) {
@@ -539,17 +553,14 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
}
jump_flags = 0;
if (strcmp(p_mousem, "popup_setpos") == 0) {
- // First set the cursor position before showing the popup
- // menu.
+ // First set the cursor position before showing the popup menu.
if (VIsual_active) {
- pos_T m_pos;
- // set MOUSE_MAY_STOP_VIS if we are outside the
- // selection or the current window (might have false
- // negative here)
+ // set MOUSE_MAY_STOP_VIS if we are outside the selection
+ // or the current window (might have false negative here)
if (mouse_row < curwin->w_winrow
|| mouse_row > (curwin->w_winrow + curwin->w_height)) {
jump_flags = MOUSE_MAY_STOP_VIS;
- } else if (get_fpos_of_mouse(&m_pos) != IN_BUFFER) {
+ } else if (m_pos_flag != IN_BUFFER) {
jump_flags = MOUSE_MAY_STOP_VIS;
} else {
if (VIsual_mode == 'V') {
@@ -593,6 +604,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
mod_mask &= ~MOD_MASK_SHIFT;
}
}
+popupexit:
if ((State & (MODE_NORMAL | MODE_INSERT))
&& !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))) {
@@ -644,7 +656,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
in_sep_line = (jump_flags & IN_SEP_LINE);
if ((in_winbar || in_status_line || in_statuscol) && is_click) {
- // Handle click event on window bar or status lin
+ // Handle click event on window bar, status line or status column
int click_grid = mouse_grid;
int click_row = mouse_row;
int click_col = mouse_col;
@@ -672,7 +684,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
call_click_def_func(click_defs, click_col, which_button);
break;
default:
- assert(false && "winbar and statusline only support %@ for clicks");
+ assert(false && "winbar, statusline and statuscolumn only support %@ for clicks");
break;
}
}
diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua
index f705678bd5..c7f6861c12 100644
--- a/test/functional/ui/mouse_spec.lua
+++ b/test/functional/ui/mouse_spec.lua
@@ -1840,16 +1840,6 @@ describe('ui/mouse/input', function()
eq({2, 9}, meths.win_get_cursor(0))
eq('', funcs.getreg('"'))
- -- Try clicking on the status line
- funcs.setreg('"', '')
- meths.win_set_cursor(0, {1, 9})
- feed('vee')
- meths.input_mouse('right', 'press', '', 0, 5, 1)
- meths.input_mouse('right', 'release', '', 0, 5, 1)
- feed('<Down><CR>')
- eq({1, 9}, meths.win_get_cursor(0))
- eq('ran away', funcs.getreg('"'))
-
-- Try clicking outside the window
funcs.setreg('"', '')
meths.win_set_cursor(0, {2, 1})
diff --git a/test/functional/ui/statuscolumn_spec.lua b/test/functional/ui/statuscolumn_spec.lua
index c4b055d289..3b41d3684a 100644
--- a/test/functional/ui/statuscolumn_spec.lua
+++ b/test/functional/ui/statuscolumn_spec.lua
@@ -9,6 +9,8 @@ local feed = helpers.feed
local meths = helpers.meths
local pcall_err = helpers.pcall_err
+local mousemodels = { "extend", "popup", "popup_setpos" }
+
describe('statuscolumn', function()
local screen
before_each(function()
@@ -420,45 +422,47 @@ describe('statuscolumn', function()
]])
end)
- it("works with 'statuscolumn' clicks", function()
- command('set mousemodel=extend')
- command([[
- function! MyClickFunc(minwid, clicks, button, mods)
- let g:testvar = printf("%d %d %s %d", a:minwid, a:clicks, a:button, getmousepos().line)
- if a:mods !=# ' '
- let g:testvar ..= '(' .. a:mods .. ')'
- endif
- endfunction
- set stc=%0@MyClickFunc@%=%l%T
- ]])
- meths.input_mouse('left', 'press', '', 0, 0, 0)
- eq('0 1 l 4', eval("g:testvar"))
- meths.input_mouse('left', 'press', '', 0, 0, 0)
- eq('0 2 l 4', eval("g:testvar"))
- meths.input_mouse('left', 'press', '', 0, 0, 0)
- eq('0 3 l 4', eval("g:testvar"))
- meths.input_mouse('left', 'press', '', 0, 0, 0)
- eq('0 4 l 4', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 3, 0)
- eq('0 1 r 7', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 3, 0)
- eq('0 2 r 7', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 3, 0)
- eq('0 3 r 7', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 3, 0)
- eq('0 4 r 7', eval("g:testvar"))
- command('set laststatus=2 winbar=%f')
- command('let g:testvar=""')
- -- Check that winbar click doesn't register as statuscolumn click
- meths.input_mouse('right', 'press', '', 0, 0, 0)
- eq('', eval("g:testvar"))
- -- Check that statusline click doesn't register as statuscolumn click
- meths.input_mouse('right', 'press', '', 0, 12, 0)
- eq('', eval("g:testvar"))
- -- Check that cmdline click doesn't register as statuscolumn click
- meths.input_mouse('right', 'press', '', 0, 13, 0)
- eq('', eval("g:testvar"))
- end)
+ for _, model in ipairs(mousemodels) do
+ it("works with 'statuscolumn' clicks with mousemodel=" .. model, function()
+ command('set mousemodel=' .. model)
+ command([[
+ function! MyClickFunc(minwid, clicks, button, mods)
+ let g:testvar = printf("%d %d %s %d", a:minwid, a:clicks, a:button, getmousepos().line)
+ if a:mods !=# ' '
+ let g:testvar ..= '(' .. a:mods .. ')'
+ endif
+ endfunction
+ set stc=%0@MyClickFunc@%=%l%T
+ ]])
+ meths.input_mouse('left', 'press', '', 0, 0, 0)
+ eq('0 1 l 4', eval("g:testvar"))
+ meths.input_mouse('left', 'press', '', 0, 0, 0)
+ eq('0 2 l 4', eval("g:testvar"))
+ meths.input_mouse('left', 'press', '', 0, 0, 0)
+ eq('0 3 l 4', eval("g:testvar"))
+ meths.input_mouse('left', 'press', '', 0, 0, 0)
+ eq('0 4 l 4', eval("g:testvar"))
+ meths.input_mouse('right', 'press', '', 0, 3, 0)
+ eq('0 1 r 7', eval("g:testvar"))
+ meths.input_mouse('right', 'press', '', 0, 3, 0)
+ eq('0 2 r 7', eval("g:testvar"))
+ meths.input_mouse('right', 'press', '', 0, 3, 0)
+ eq('0 3 r 7', eval("g:testvar"))
+ meths.input_mouse('right', 'press', '', 0, 3, 0)
+ eq('0 4 r 7', eval("g:testvar"))
+ command('set laststatus=2 winbar=%f')
+ command('let g:testvar=""')
+ -- Check that winbar click doesn't register as statuscolumn click
+ meths.input_mouse('right', 'press', '', 0, 0, 0)
+ eq('', eval("g:testvar"))
+ -- Check that statusline click doesn't register as statuscolumn click
+ meths.input_mouse('right', 'press', '', 0, 12, 0)
+ eq('', eval("g:testvar"))
+ -- Check that cmdline click doesn't register as statuscolumn click
+ meths.input_mouse('right', 'press', '', 0, 13, 0)
+ eq('', eval("g:testvar"))
+ end)
+ end
it('click labels do not leak memory', function()
command([[
diff --git a/test/functional/ui/statusline_spec.lua b/test/functional/ui/statusline_spec.lua
index c41d4983a7..5ea4eade4e 100644
--- a/test/functional/ui/statusline_spec.lua
+++ b/test/functional/ui/statusline_spec.lua
@@ -12,178 +12,182 @@ local exec_lua = helpers.exec_lua
local eval = helpers.eval
local sleep = helpers.sleep
-describe('statusline clicks', function()
- local screen
-
- before_each(function()
- clear()
- screen = Screen.new(40, 8)
- screen:attach()
- command('set laststatus=2 mousemodel=extend')
- exec([=[
- function! MyClickFunc(minwid, clicks, button, mods)
- let g:testvar = printf("%d %d %s", a:minwid, a:clicks, a:button)
- if a:mods !=# ' '
- let g:testvar ..= '(' .. a:mods .. ')'
- endif
- endfunction
- ]=])
- end)
-
- it('works', function()
- meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
- meths.input_mouse('left', 'press', '', 0, 6, 17)
- eq('0 1 l', eval("g:testvar"))
- meths.input_mouse('left', 'press', '', 0, 6, 17)
- eq('0 2 l', eval("g:testvar"))
- meths.input_mouse('left', 'press', '', 0, 6, 17)
- eq('0 3 l', eval("g:testvar"))
- meths.input_mouse('left', 'press', '', 0, 6, 17)
- eq('0 4 l', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 6, 17)
- eq('0 1 r', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 6, 17)
- eq('0 2 r', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 6, 17)
- eq('0 3 r', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 6, 17)
- eq('0 4 r', eval("g:testvar"))
- end)
-
- it('works for winbar', function()
- meths.set_option('winbar', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
- meths.input_mouse('left', 'press', '', 0, 0, 17)
- eq('0 1 l', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 0, 17)
- eq('0 1 r', eval("g:testvar"))
- end)
-
- it('works for winbar in floating window', function()
- meths.open_win(0, true, { width=30, height=4, relative='editor', row=1, col=5,
- border = "single" })
- meths.set_option_value('winbar', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T',
- { scope = 'local' })
- meths.input_mouse('left', 'press', '', 0, 2, 23)
- eq('0 1 l', eval("g:testvar"))
- end)
-
- it('works when there are multiple windows', function()
- command('split')
- meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
- meths.set_option('winbar', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
- meths.input_mouse('left', 'press', '', 0, 0, 17)
- eq('0 1 l', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 4, 17)
- eq('0 1 r', eval("g:testvar"))
- meths.input_mouse('middle', 'press', '', 0, 3, 17)
- eq('0 1 m', eval("g:testvar"))
- meths.input_mouse('left', 'press', '', 0, 6, 17)
- eq('0 1 l', eval("g:testvar"))
- end)
-
- it('works with Lua function', function()
- exec_lua([[
- function clicky_func(minwid, clicks, button, mods)
- vim.g.testvar = string.format("%d %d %s", minwid, clicks, button)
- end
- ]])
- meths.set_option('statusline', 'Not clicky stuff %0@v:lua.clicky_func@Clicky stuff%T')
- meths.input_mouse('left', 'press', '', 0, 6, 17)
- eq('0 1 l', eval("g:testvar"))
- end)
-
- it('ignores unsupported click items', function()
- command('tabnew | tabprevious')
- meths.set_option('statusline', '%2TNot clicky stuff%T')
- meths.input_mouse('left', 'press', '', 0, 6, 0)
- eq(1, meths.get_current_tabpage().id)
- meths.set_option('statusline', '%2XNot clicky stuff%X')
- meths.input_mouse('left', 'press', '', 0, 6, 0)
- eq(2, #meths.list_tabpages())
- end)
-
- it("right click works when statusline isn't focused #18994", function()
- meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
- meths.input_mouse('right', 'press', '', 0, 6, 17)
- eq('0 1 r', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 6, 17)
- eq('0 2 r', eval("g:testvar"))
- end)
-
- it("works with modifiers #18994", function()
- meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
- -- Note: alternate between left and right mouse buttons to avoid triggering multiclicks
- meths.input_mouse('left', 'press', 'S', 0, 6, 17)
- eq('0 1 l(s )', eval("g:testvar"))
- meths.input_mouse('right', 'press', 'S', 0, 6, 17)
- eq('0 1 r(s )', eval("g:testvar"))
- meths.input_mouse('left', 'press', 'A', 0, 6, 17)
- eq('0 1 l( a )', eval("g:testvar"))
- meths.input_mouse('right', 'press', 'A', 0, 6, 17)
- eq('0 1 r( a )', eval("g:testvar"))
- meths.input_mouse('left', 'press', 'AS', 0, 6, 17)
- eq('0 1 l(s a )', eval("g:testvar"))
- meths.input_mouse('right', 'press', 'AS', 0, 6, 17)
- eq('0 1 r(s a )', eval("g:testvar"))
- meths.input_mouse('left', 'press', 'T', 0, 6, 17)
- eq('0 1 l( m)', eval("g:testvar"))
- meths.input_mouse('right', 'press', 'T', 0, 6, 17)
- eq('0 1 r( m)', eval("g:testvar"))
- meths.input_mouse('left', 'press', 'TS', 0, 6, 17)
- eq('0 1 l(s m)', eval("g:testvar"))
- meths.input_mouse('right', 'press', 'TS', 0, 6, 17)
- eq('0 1 r(s m)', eval("g:testvar"))
- meths.input_mouse('left', 'press', 'C', 0, 6, 17)
- eq('0 1 l( c )', eval("g:testvar"))
- -- <C-RightMouse> is for tag jump
- end)
-
- it("works for global statusline with vertical splits #19186", function()
- command('set laststatus=3')
- meths.set_option('statusline', '%0@MyClickFunc@Clicky stuff%T %= %0@MyClickFunc@Clicky stuff%T')
- command('vsplit')
- screen:expect([[
- ^ │ |
- ~ │~ |
- ~ │~ |
- ~ │~ |
- ~ │~ |
- ~ │~ |
- Clicky stuff Clicky stuff|
- |
- ]])
-
- -- clickable area on the right
- meths.input_mouse('left', 'press', '', 0, 6, 35)
- eq('0 1 l', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 6, 35)
- eq('0 1 r', eval("g:testvar"))
-
- -- clickable area on the left
- meths.input_mouse('left', 'press', '', 0, 6, 5)
- eq('0 1 l', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 6, 5)
- eq('0 1 r', eval("g:testvar"))
- end)
-
- it('no memory leak with zero-width click labels', function()
- command([[
- let &stl = '%@Test@%T%@MyClickFunc@%=%T%@Test@'
- ]])
- meths.input_mouse('left', 'press', '', 0, 6, 0)
- eq('0 1 l', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 6, 39)
- eq('0 1 r', eval("g:testvar"))
- end)
-
- it('no memory leak with truncated click labels', function()
- command([[
- let &stl = '%@MyClickFunc@foo%X' .. repeat('a', 40) .. '%<t%@Test@bar%X%@Test@baz'
- ]])
- meths.input_mouse('left', 'press', '', 0, 6, 2)
- eq('0 1 l', eval("g:testvar"))
- end)
-end)
+local mousemodels = { "extend", "popup", "popup_setpos" }
+
+for _, model in ipairs(mousemodels) do
+ describe('statusline clicks with mousemodel=' .. model, function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new(40, 8)
+ screen:attach()
+ command('set laststatus=2 mousemodel=' .. model)
+ exec([=[
+ function! MyClickFunc(minwid, clicks, button, mods)
+ let g:testvar = printf("%d %d %s", a:minwid, a:clicks, a:button)
+ if a:mods !=# ' '
+ let g:testvar ..= '(' .. a:mods .. ')'
+ endif
+ endfunction
+ ]=])
+ end)
+
+ it('works', function()
+ meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
+ meths.input_mouse('left', 'press', '', 0, 6, 17)
+ eq('0 1 l', eval("g:testvar"))
+ meths.input_mouse('left', 'press', '', 0, 6, 17)
+ eq('0 2 l', eval("g:testvar"))
+ meths.input_mouse('left', 'press', '', 0, 6, 17)
+ eq('0 3 l', eval("g:testvar"))
+ meths.input_mouse('left', 'press', '', 0, 6, 17)
+ eq('0 4 l', eval("g:testvar"))
+ meths.input_mouse('right', 'press', '', 0, 6, 17)
+ eq('0 1 r', eval("g:testvar"))
+ meths.input_mouse('right', 'press', '', 0, 6, 17)
+ eq('0 2 r', eval("g:testvar"))
+ meths.input_mouse('right', 'press', '', 0, 6, 17)
+ eq('0 3 r', eval("g:testvar"))
+ meths.input_mouse('right', 'press', '', 0, 6, 17)
+ eq('0 4 r', eval("g:testvar"))
+ end)
+
+ it('works for winbar', function()
+ meths.set_option('winbar', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
+ meths.input_mouse('left', 'press', '', 0, 0, 17)
+ eq('0 1 l', eval("g:testvar"))
+ meths.input_mouse('right', 'press', '', 0, 0, 17)
+ eq('0 1 r', eval("g:testvar"))
+ end)
+
+ it('works for winbar in floating window', function()
+ meths.open_win(0, true, { width=30, height=4, relative='editor', row=1, col=5,
+ border = "single" })
+ meths.set_option_value('winbar', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T',
+ { scope = 'local' })
+ meths.input_mouse('left', 'press', '', 0, 2, 23)
+ eq('0 1 l', eval("g:testvar"))
+ end)
+
+ it('works when there are multiple windows', function()
+ command('split')
+ meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
+ meths.set_option('winbar', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
+ meths.input_mouse('left', 'press', '', 0, 0, 17)
+ eq('0 1 l', eval("g:testvar"))
+ meths.input_mouse('right', 'press', '', 0, 4, 17)
+ eq('0 1 r', eval("g:testvar"))
+ meths.input_mouse('middle', 'press', '', 0, 3, 17)
+ eq('0 1 m', eval("g:testvar"))
+ meths.input_mouse('left', 'press', '', 0, 6, 17)
+ eq('0 1 l', eval("g:testvar"))
+ end)
+
+ it('works with Lua function', function()
+ exec_lua([[
+ function clicky_func(minwid, clicks, button, mods)
+ vim.g.testvar = string.format("%d %d %s", minwid, clicks, button)
+ end
+ ]])
+ meths.set_option('statusline', 'Not clicky stuff %0@v:lua.clicky_func@Clicky stuff%T')
+ meths.input_mouse('left', 'press', '', 0, 6, 17)
+ eq('0 1 l', eval("g:testvar"))
+ end)
+
+ it('ignores unsupported click items', function()
+ command('tabnew | tabprevious')
+ meths.set_option('statusline', '%2TNot clicky stuff%T')
+ meths.input_mouse('left', 'press', '', 0, 6, 0)
+ eq(1, meths.get_current_tabpage().id)
+ meths.set_option('statusline', '%2XNot clicky stuff%X')
+ meths.input_mouse('left', 'press', '', 0, 6, 0)
+ eq(2, #meths.list_tabpages())
+ end)
+
+ it("right click works when statusline isn't focused #18994", function()
+ meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
+ meths.input_mouse('right', 'press', '', 0, 6, 17)
+ eq('0 1 r', eval("g:testvar"))
+ meths.input_mouse('right', 'press', '', 0, 6, 17)
+ eq('0 2 r', eval("g:testvar"))
+ end)
+
+ it("works with modifiers #18994", function()
+ meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
+ -- Note: alternate between left and right mouse buttons to avoid triggering multiclicks
+ meths.input_mouse('left', 'press', 'S', 0, 6, 17)
+ eq('0 1 l(s )', eval("g:testvar"))
+ meths.input_mouse('right', 'press', 'S', 0, 6, 17)
+ eq('0 1 r(s )', eval("g:testvar"))
+ meths.input_mouse('left', 'press', 'A', 0, 6, 17)
+ eq('0 1 l( a )', eval("g:testvar"))
+ meths.input_mouse('right', 'press', 'A', 0, 6, 17)
+ eq('0 1 r( a )', eval("g:testvar"))
+ meths.input_mouse('left', 'press', 'AS', 0, 6, 17)
+ eq('0 1 l(s a )', eval("g:testvar"))
+ meths.input_mouse('right', 'press', 'AS', 0, 6, 17)
+ eq('0 1 r(s a )', eval("g:testvar"))
+ meths.input_mouse('left', 'press', 'T', 0, 6, 17)
+ eq('0 1 l( m)', eval("g:testvar"))
+ meths.input_mouse('right', 'press', 'T', 0, 6, 17)
+ eq('0 1 r( m)', eval("g:testvar"))
+ meths.input_mouse('left', 'press', 'TS', 0, 6, 17)
+ eq('0 1 l(s m)', eval("g:testvar"))
+ meths.input_mouse('right', 'press', 'TS', 0, 6, 17)
+ eq('0 1 r(s m)', eval("g:testvar"))
+ meths.input_mouse('left', 'press', 'C', 0, 6, 17)
+ eq('0 1 l( c )', eval("g:testvar"))
+ -- <C-RightMouse> is for tag jump
+ end)
+
+ it("works for global statusline with vertical splits #19186", function()
+ command('set laststatus=3')
+ meths.set_option('statusline', '%0@MyClickFunc@Clicky stuff%T %= %0@MyClickFunc@Clicky stuff%T')
+ command('vsplit')
+ screen:expect([[
+ ^ │ |
+ ~ │~ |
+ ~ │~ |
+ ~ │~ |
+ ~ │~ |
+ ~ │~ |
+ Clicky stuff Clicky stuff|
+ |
+ ]])
+
+ -- clickable area on the right
+ meths.input_mouse('left', 'press', '', 0, 6, 35)
+ eq('0 1 l', eval("g:testvar"))
+ meths.input_mouse('right', 'press', '', 0, 6, 35)
+ eq('0 1 r', eval("g:testvar"))
+
+ -- clickable area on the left
+ meths.input_mouse('left', 'press', '', 0, 6, 5)
+ eq('0 1 l', eval("g:testvar"))
+ meths.input_mouse('right', 'press', '', 0, 6, 5)
+ eq('0 1 r', eval("g:testvar"))
+ end)
+
+ it('no memory leak with zero-width click labels', function()
+ command([[
+ let &stl = '%@Test@%T%@MyClickFunc@%=%T%@Test@'
+ ]])
+ meths.input_mouse('left', 'press', '', 0, 6, 0)
+ eq('0 1 l', eval("g:testvar"))
+ meths.input_mouse('right', 'press', '', 0, 6, 39)
+ eq('0 1 r', eval("g:testvar"))
+ end)
+
+ it('no memory leak with truncated click labels', function()
+ command([[
+ let &stl = '%@MyClickFunc@foo%X' .. repeat('a', 40) .. '%<t%@Test@bar%X%@Test@baz'
+ ]])
+ meths.input_mouse('left', 'press', '', 0, 6, 2)
+ eq('0 1 l', eval("g:testvar"))
+ end)
+ end)
+end
describe('global statusline', function()
local screen