fix(pum): handle RightDrag on parent grid properly (#33626)

This commit is contained in:
zeertzjq
2025-04-25 14:37:42 +08:00
committed by GitHub
parent 1670fbee0f
commit 7d569abb20
2 changed files with 311 additions and 346 deletions

View File

@@ -78,6 +78,7 @@ static int pum_col; // left column of pum, right column if 'righ
static int pum_win_row_offset; // The row offset needed to convert to window relative coordinates static int pum_win_row_offset; // The row offset needed to convert to window relative coordinates
static int pum_win_col_offset; // The column offset needed to convert to window relative coordinates static int pum_win_col_offset; // The column offset needed to convert to window relative coordinates
static int pum_left_col; // left column of pum, before padding or scrollbar static int pum_left_col; // left column of pum, before padding or scrollbar
static int pum_right_col; // right column of pum, after padding or scrollbar
static bool pum_above; // pum is drawn above cursor line static bool pum_above; // pum is drawn above cursor line
static bool pum_is_visible = false; static bool pum_is_visible = false;
@@ -613,6 +614,7 @@ void pum_redraw(void)
grid_assign_handle(&pum_grid); grid_assign_handle(&pum_grid);
pum_left_col = pum_col - col_off; pum_left_col = pum_col - col_off;
pum_right_col = pum_left_col + grid_width;
bool moved = ui_comp_put_grid(&pum_grid, pum_row, pum_left_col, bool moved = ui_comp_put_grid(&pum_grid, pum_row, pum_left_col,
pum_height, grid_width, false, true); pum_height, grid_width, false, true);
bool invalid_grid = moved || pum_invalid; bool invalid_grid = moved || pum_invalid;
@@ -1392,15 +1394,16 @@ static void pum_select_mouse_pos(void)
if (mouse_grid == pum_grid.handle) { if (mouse_grid == pum_grid.handle) {
pum_selected = mouse_row; pum_selected = mouse_row;
return; return;
} else if (mouse_grid != pum_anchor_grid || mouse_col < pum_grid.comp_col } else if (mouse_grid != pum_anchor_grid
|| mouse_col >= pum_grid.comp_col + pum_grid.comp_width) { || mouse_col < pum_left_col - pum_win_col_offset
|| mouse_col >= pum_right_col - pum_win_col_offset) {
pum_selected = -1; pum_selected = -1;
return; return;
} }
int idx = mouse_row - pum_grid.comp_row; int idx = mouse_row - (pum_row - pum_win_row_offset);
if (idx < 0 || idx >= pum_grid.comp_height) { if (idx < 0 || idx >= pum_height) {
pum_selected = -1; pum_selected = -1;
} else if (*pum_array[idx].pum_text != NUL) { } else if (*pum_array[idx].pum_text != NUL) {
pum_selected = idx; pum_selected = idx;

View File

@@ -692,7 +692,7 @@ describe('ui/ext_popupmenu', function()
end) end)
end) end)
it('<PageUP>, <PageDown> works without ui_pum_set_height', function() it('<PageUp>, <PageDown> works without ui_pum_set_height', function()
source_complete_month() source_complete_month()
local month_expected = { local month_expected = {
{ 'January', '', '', '' }, { 'January', '', '', '' },
@@ -6687,9 +6687,26 @@ describe('builtin popupmenu', function()
menu PopUp.baz :let g:menustr = 'baz'<CR> menu PopUp.baz :let g:menustr = 'baz'<CR>
]]) ]])
--- @param state string|test.function.ui.screen.Expect
--- @param str string
--- @param repl string
--- @return string|test.function.ui.screen.Expect
local function screen_replace(state, str, repl)
if type(state) == 'string' then
local new_state = state:gsub(vim.pesc(str), vim.pesc(repl))
return new_state
end
local new_state = vim.deepcopy(state)
local grid = assert(new_state.grid)
grid = grid:gsub(vim.pesc(str), vim.pesc(repl))
new_state.grid = grid
return new_state
end
local no_sel_screen ---@type string|test.function.ui.screen.Expect
if multigrid then if multigrid then
api.nvim_input_mouse('right', 'press', '', 2, 0, 4) api.nvim_input_mouse('right', 'press', '', 2, 0, 4)
screen:expect({ no_sel_screen = {
grid = [[ grid = [[
## grid 1 ## grid 1
[2:--------------------------------]|*5 [2:--------------------------------]|*5
@@ -6705,80 +6722,27 @@ describe('builtin popupmenu', function()
{n: baz }| {n: baz }|
]], ]],
float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250, 2, 1, 3 } }, float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250, 2, 1, 3 } },
}) }
else else
feed('<RightMouse><4,0>') feed('<RightMouse><4,0>')
screen:expect([[ no_sel_screen = [[
^popup menu test | ^popup menu test |
{1:~ }{n: foo }{1: }| {1:~ }{n: foo }{1: }|
{1:~ }{n: bar }{1: }| {1:~ }{n: bar }{1: }|
{1:~ }{n: baz }{1: }| {1:~ }{n: baz }{1: }|
{1:~ }| {1:~ }|
| |
]]) ]]
end end
screen:expect(no_sel_screen)
feed('<Down>') feed('<Down>')
if multigrid then screen:expect(screen_replace(no_sel_screen, '{n: foo }', '{s: foo }'))
screen:expect({
grid = [[
## grid 1
[2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
{1:~ }|*4
## grid 3
|
## grid 4
{s: foo }|
{n: bar }|
{n: baz }|
]],
float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250, 2, 1, 3 } },
})
else
screen:expect([[
^popup menu test |
{1:~ }{s: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{n: baz }{1: }|
{1:~ }|
|
]])
end
feed('<Down>') feed('<Down>')
if multigrid then screen:expect(screen_replace(no_sel_screen, '{n: bar }', '{s: bar }'))
screen:expect({
grid = [[
## grid 1
[2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
{1:~ }|*4
## grid 3
|
## grid 4
{n: foo }|
{s: bar }|
{n: baz }|
]],
float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250, 2, 1, 3 } },
})
else
screen:expect([[
^popup menu test |
{1:~ }{n: foo }{1: }|
{1:~ }{s: bar }{1: }|
{1:~ }{n: baz }{1: }|
{1:~ }|
|
]])
end
feed('<CR>') feed('<CR>')
local no_menu_screen ---@type string
if multigrid then if multigrid then
screen:expect({ no_menu_screen = [[
grid = [[
## grid 1 ## grid 1
[2:--------------------------------]|*5 [2:--------------------------------]|*5
[3:--------------------------------]| [3:--------------------------------]|
@@ -6787,15 +6751,15 @@ describe('builtin popupmenu', function()
{1:~ }|*4 {1:~ }|*4
## grid 3 ## grid 3
:let g:menustr = 'bar' | :let g:menustr = 'bar' |
]], ]]
})
else else
screen:expect([[ no_menu_screen = [[
^popup menu test | ^popup menu test |
{1:~ }|*4 {1:~ }|*4
:let g:menustr = 'bar' | :let g:menustr = 'bar' |
]]) ]]
end end
screen:expect(no_menu_screen)
eq('bar', api.nvim_get_var('menustr')) eq('bar', api.nvim_get_var('menustr'))
if multigrid then if multigrid then
@@ -6888,31 +6852,16 @@ describe('builtin popupmenu', function()
end end
if multigrid then if multigrid then
api.nvim_input_mouse('left', 'press', '', 4, 2, 2) api.nvim_input_mouse('left', 'press', '', 4, 2, 2)
screen:expect({
grid = [[
## grid 1
[2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
{1:~ }|*4
## grid 3
:let g:menustr = 'baz' |
]],
})
else else
feed('<LeftMouse><21,5>') feed('<LeftMouse><21,5>')
screen:expect([[
^popup menu test |
{1:~ }|*4
:let g:menustr = 'baz' |
]])
end end
no_menu_screen = no_menu_screen:gsub([['bar']], [['baz']])
screen:expect(no_menu_screen)
eq('baz', api.nvim_get_var('menustr')) eq('baz', api.nvim_get_var('menustr'))
if multigrid then if multigrid then
api.nvim_input_mouse('right', 'press', '', 2, 0, 4) api.nvim_input_mouse('right', 'press', '', 2, 0, 4)
screen:expect({ no_sel_screen = {
grid = [[ grid = [[
## grid 1 ## grid 1
[2:--------------------------------]|*5 [2:--------------------------------]|*5
@@ -6928,76 +6877,38 @@ describe('builtin popupmenu', function()
{n: baz }| {n: baz }|
]], ]],
float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250, 2, 1, 3 } }, float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250, 2, 1, 3 } },
}) }
else else
feed('<RightMouse><4,0>') feed('<RightMouse><4,0>')
screen:expect([[ no_sel_screen = [[
^popup menu test | ^popup menu test |
{1:~ }{n: foo }{1: }| {1:~ }{n: foo }{1: }|
{1:~ }{n: bar }{1: }| {1:~ }{n: bar }{1: }|
{1:~ }{n: baz }{1: }| {1:~ }{n: baz }{1: }|
{1:~ }| {1:~ }|
:let g:menustr = 'baz' | :let g:menustr = 'baz' |
]]) ]]
end end
screen:expect(no_sel_screen)
if multigrid then if multigrid then
api.nvim_input_mouse('right', 'drag', '', 2, 3, 6) api.nvim_input_mouse('right', 'drag', '', 2, 3, 6)
screen:expect({
grid = [[
## grid 1
[2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
{1:~ }|*4
## grid 3
:let g:menustr = 'baz' |
## grid 4
{n: foo }|
{n: bar }|
{s: baz }|
]],
float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250, 2, 1, 3 } },
})
else else
feed('<RightDrag><6,3>') feed('<RightDrag><6,3>')
screen:expect([[
^popup menu test |
{1:~ }{n: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{s: baz }{1: }|
{1:~ }|
:let g:menustr = 'baz' |
]])
end end
screen:expect(screen_replace(no_sel_screen, '{n: baz }', '{s: baz }'))
if multigrid then if multigrid then
api.nvim_input_mouse('right', 'release', '', 2, 1, 6) api.nvim_input_mouse('right', 'release', '', 2, 1, 6)
screen:expect({
grid = [[
## grid 1
[2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
{1:~ }|*4
## grid 3
:let g:menustr = 'foo' |
]],
})
else else
feed('<RightRelease><6,1>') feed('<RightRelease><6,1>')
screen:expect([[
^popup menu test |
{1:~ }|*4
:let g:menustr = 'foo' |
]])
end end
no_menu_screen = no_menu_screen:gsub([['baz']], [['foo']])
screen:expect(no_menu_screen)
eq('foo', api.nvim_get_var('menustr')) eq('foo', api.nvim_get_var('menustr'))
eq(false, screen.options.mousemoveevent) eq(false, screen.options.mousemoveevent)
if multigrid then if multigrid then
api.nvim_input_mouse('right', 'press', '', 2, 0, 4) api.nvim_input_mouse('right', 'press', '', 2, 0, 4)
screen:expect({ no_sel_screen = {
grid = [[ grid = [[
## grid 1 ## grid 1
[2:--------------------------------]|*5 [2:--------------------------------]|*5
@@ -7013,134 +6924,48 @@ describe('builtin popupmenu', function()
{n: baz }| {n: baz }|
]], ]],
float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250, 2, 1, 3 } }, float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250, 2, 1, 3 } },
}) }
else else
feed('<RightMouse><4,0>') feed('<RightMouse><4,0>')
screen:expect([[ no_sel_screen = [[
^popup menu test | ^popup menu test |
{1:~ }{n: foo }{1: }| {1:~ }{n: foo }{1: }|
{1:~ }{n: bar }{1: }| {1:~ }{n: bar }{1: }|
{1:~ }{n: baz }{1: }| {1:~ }{n: baz }{1: }|
{1:~ }| {1:~ }|
:let g:menustr = 'foo' | :let g:menustr = 'foo' |
]]) ]]
end end
screen:expect(no_sel_screen)
eq(true, screen.options.mousemoveevent) eq(true, screen.options.mousemoveevent)
if multigrid then if multigrid then
api.nvim_input_mouse('wheel', 'up', '', 2, 0, 4) api.nvim_input_mouse('wheel', 'up', '', 2, 0, 4)
screen:expect({
grid = [[
## grid 1
[2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
{1:~ }|*4
## grid 3
:let g:menustr = 'foo' |
## grid 4
{s: foo }|
{n: bar }|
{n: baz }|
]],
float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250, 2, 1, 3 } },
})
else else
feed('<ScrollWheelUp><4,0>') feed('<ScrollWheelUp><4,0>')
screen:expect([[
^popup menu test |
{1:~ }{s: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{n: baz }{1: }|
{1:~ }|
:let g:menustr = 'foo' |
]])
end end
screen:expect(screen_replace(no_sel_screen, '{n: foo }', '{s: foo }'))
eq(true, screen.options.mousemoveevent) eq(true, screen.options.mousemoveevent)
if multigrid then if multigrid then
api.nvim_input_mouse('move', '', '', 4, 2, 3) api.nvim_input_mouse('move', '', '', 4, 2, 3)
screen:expect({
grid = [[
## grid 1
[2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
{1:~ }|*4
## grid 3
:let g:menustr = 'foo' |
## grid 4
{n: foo }|
{n: bar }|
{s: baz }|
]],
float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250, 2, 1, 3 } },
})
else else
feed('<MouseMove><6,3>') feed('<MouseMove><6,3>')
screen:expect([[
^popup menu test |
{1:~ }{n: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{s: baz }{1: }|
{1:~ }|
:let g:menustr = 'foo' |
]])
end end
screen:expect(screen_replace(no_sel_screen, '{n: baz }', '{s: baz }'))
eq(true, screen.options.mousemoveevent) eq(true, screen.options.mousemoveevent)
if multigrid then if multigrid then
api.nvim_input_mouse('wheel', 'down', '', 4, 2, 3) api.nvim_input_mouse('wheel', 'down', '', 4, 2, 3)
screen:expect({
grid = [[
## grid 1
[2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
{1:~ }|*4
## grid 3
:let g:menustr = 'foo' |
## grid 4
{n: foo }|
{s: bar }|
{n: baz }|
]],
float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250, 2, 1, 3 } },
})
else else
feed('<ScrollWheelDown><6,3>') feed('<ScrollWheelDown><6,3>')
screen:expect([[
^popup menu test |
{1:~ }{n: foo }{1: }|
{1:~ }{s: bar }{1: }|
{1:~ }{n: baz }{1: }|
{1:~ }|
:let g:menustr = 'foo' |
]])
end end
screen:expect(screen_replace(no_sel_screen, '{n: bar }', '{s: bar }'))
eq(true, screen.options.mousemoveevent) eq(true, screen.options.mousemoveevent)
if multigrid then if multigrid then
api.nvim_input_mouse('left', 'press', '', 4, 1, 3) api.nvim_input_mouse('left', 'press', '', 4, 1, 3)
screen:expect({
grid = [[
## grid 1
[2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
{1:~ }|*4
## grid 3
:let g:menustr = 'bar' |
]],
})
else else
feed('<LeftMouse><6,2>') feed('<LeftMouse><6,2>')
screen:expect([[
^popup menu test |
{1:~ }|*4
:let g:menustr = 'bar' |
]])
end end
no_menu_screen = no_menu_screen:gsub([['foo']], [['bar']])
screen:expect(no_menu_screen)
eq(false, screen.options.mousemoveevent) eq(false, screen.options.mousemoveevent)
eq('bar', api.nvim_get_var('menustr')) eq('bar', api.nvim_get_var('menustr'))
@@ -7289,7 +7114,7 @@ describe('builtin popupmenu', function()
command('setlocal winbar=WINBAR') command('setlocal winbar=WINBAR')
if multigrid then if multigrid then
api.nvim_input_mouse('right', 'press', '', 6, 1, 14) api.nvim_input_mouse('right', 'press', '', 6, 1, 14)
screen:expect({ no_sel_screen = {
grid = [[ grid = [[
## grid 1 ## grid 1
[2:--------------------------------]|*2 [2:--------------------------------]|*2
@@ -7313,23 +7138,28 @@ describe('builtin popupmenu', function()
^popup menu test | ^popup menu test |
]], ]],
float_pos = { [4] = { -1, 'SW', 6, 1, 12, false, 250, 2, 1, 28 } }, float_pos = { [4] = { -1, 'SW', 6, 1, 12, false, 250, 2, 1, 28 } },
}) }
else else
feed('<RightMouse><30,4>') feed('<RightMouse><30,4>')
screen:expect([[ no_sel_screen = [[
popup menu test | popup menu test |
{1:~ }{n: foo}| {1:~ }{n: foo}|
{3:[No Name] [+] }{n: bar}| {3:[No Name] [+] }{n: bar}|
popup menu test│{2:WINBAR }{n: baz}| popup menu test│{2:WINBAR }{n: baz}|
{1:~ }│^popup menu test | {1:~ }│^popup menu test |
:let g:menustr = 'foo' | :let g:menustr = 'foo' |
]]) ]]
end end
local no_menu_screen ---@type string|test.function.ui.screen.Expect screen:expect(no_sel_screen)
if multigrid then
api.nvim_input_mouse('right', 'drag', '', 6, 0, 15)
else
feed('<RightDrag><31,3>')
end
screen:expect(screen_replace(no_sel_screen, '{n: baz}', '{s: baz}'))
if multigrid then if multigrid then
api.nvim_input_mouse('left', 'press', '', 4, 1, 2) api.nvim_input_mouse('left', 'press', '', 4, 1, 2)
no_menu_screen = { screen:expect([[
grid = [[
## grid 1 ## grid 1
[2:--------------------------------]|*2 [2:--------------------------------]|*2
{3:[No Name] [+] }| {3:[No Name] [+] }|
@@ -7346,189 +7176,321 @@ describe('builtin popupmenu', function()
## grid 6 ## grid 6
{2:WINBAR }| {2:WINBAR }|
^popup menu test | ^popup menu test |
]], ]])
}
else else
feed('<LeftMouse><31,2>') feed('<LeftMouse><31,2>')
no_menu_screen = { screen:expect([[
grid = [[
popup menu test | popup menu test |
{1:~ }| {1:~ }|
{3:[No Name] [+] }| {3:[No Name] [+] }|
popup menu test│{2:WINBAR }| popup menu test│{2:WINBAR }|
{1:~ }│^popup menu test | {1:~ }│^popup menu test |
:let g:menustr = 'bar' | :let g:menustr = 'bar' |
]], ]])
}
end end
screen:expect(no_menu_screen)
eq('bar', api.nvim_get_var('menustr')) eq('bar', api.nvim_get_var('menustr'))
local no_sel_screen ---@type string|test.function.ui.screen.Expect command([[let g:menustr = '']])
screen:try_resize(32, 9)
command('wincmd t | 4vsplit | wincmd l | topleft 1split')
if multigrid then
no_menu_screen = [[
## grid 1
[8:--------------------------------]|
{4:[No Name] [+] }|
[7:----]│[2:---------------------------]|*2
{3:<+] [No Name] [+] }|
[5:---------------]│[6:----------------]|*3
[3:--------------------------------]|
## grid 2
popup menu test |
{1:~ }|
## grid 3
|
## grid 5
popup menu test|
{1:~ }|*2
## grid 6
{2:WINBAR }|
popup menu test |
{1:~ }|
## grid 7
popu|
p me|
## grid 8
^popup menu test |
]]
else
no_menu_screen = [[
^popup menu test |
{4:[No Name] [+] }|
popu│popup menu test |
p me│{1:~ }|
{3:<+] [No Name] [+] }|
popup menu test│{2:WINBAR }|
{1:~ }│popup menu test |
{1:~ }│{1:~ }|
|
]]
end
screen:expect(no_menu_screen)
if multigrid then if multigrid then
no_sel_screen = { no_sel_screen = {
grid = [[ grid = [[
## grid 1 ## grid 1
[2:--------------------------------]|*2 [8:--------------------------------]|
{3:[No Name] [+] }| {4:[No Name] [+] }|
[5:---------------]│[6:----------------]|*2 [7:----]│[2:---------------------------]|*2
{3:<+] [No Name] [+] }|
[5:---------------]│[6:----------------]|*3
[3:--------------------------------]| [3:--------------------------------]|
## grid 2 ## grid 2
popup menu test | popup menu test |
{1:~ }| {1:~ }|
## grid 3 ## grid 3
:let g:menustr = 'bar' | |
## grid 4 ## grid 4
{n: foo }| {n: foo }|
{n: bar }| {n: bar }|
{n: baz }| {n: baz }|
## grid 5 ## grid 5
popup menu test| popup menu test|
{1:~ }| {1:~ }|*2
## grid 6
{2:WINBAR }|
^popup menu test |
]],
float_pos = { [4] = { -1, 'NW', 1, 1, 19, false, 250, 2, 1, 19 } },
}
else
no_sel_screen = {
grid = [[
popup menu test |
{1:~ }{n: foo }{1: }|
{3:[No Name] [+] }{n: bar }{3: }|
popup menu test│{2:WIN}{n: baz }{2: }|
{1:~ }│^popup menu test |
:let g:menustr = 'bar' |
]],
}
end
local sel_screens = {} ---@type (string|test.function.ui.screen.Expect)[]
for i, s in ipairs({ 'foo', 'bar', 'baz' }) do
local sel_screen = vim.deepcopy(no_sel_screen)
local grid = assert(sel_screen.grid)
grid = grid:gsub(vim.pesc(('{n: %s }'):format(s)), ('{s: %s }'):format(s))
sel_screen.grid = grid
sel_screens[i] = sel_screen
end
command([[let g:menustr = '']])
local g = multigrid and 1 or 0
api.nvim_input_mouse('right', 'press', '', g, 0, 20)
screen:expect(no_sel_screen)
api.nvim_input_mouse('move', '', '', g, 1, 19)
screen:expect(sel_screens[1])
api.nvim_input_mouse('move', '', '', g, 1, 18)
screen:expect(no_sel_screen)
api.nvim_input_mouse('move', '', '', g, 2, 23)
screen:expect(sel_screens[2])
api.nvim_input_mouse('move', '', '', g, 2, 24)
screen:expect(no_sel_screen)
api.nvim_input_mouse('move', '', '', g, 3, 19)
screen:expect(sel_screens[3])
api.nvim_input_mouse('left', 'press', '', g, 3, 18)
screen:expect(no_menu_screen)
eq('', api.nvim_get_var('menustr'))
command('wincmd t | set rightleft')
if multigrid then
no_menu_screen = {
grid = [[
## grid 1
[2:--------------------------------]|*2
{4:[No Name] [+] }|
[5:---------------]│[6:----------------]|*2
[3:--------------------------------]|
## grid 2
tset unem pupo^p|
{1: ~}|
## grid 3
:let g:menustr = 'bar' |
## grid 5
popup menu test|
{1:~ }|
## grid 6 ## grid 6
{2:WINBAR }| {2:WINBAR }|
popup menu test | popup menu test |
{1:~ }|
## grid 7
popu|
p me|
## grid 8
^popup menu test |
]], ]],
float_pos = { [4] = { -1, 'NW', 1, 1, 14, false, 250, 2, 1, 14 } },
} }
else else
no_menu_screen = { no_sel_screen = {
grid = [[ grid = [[
tset unem pupo^p| ^popup menu test |
{1: ~}|
{4:[No Name] [+] }| {4:[No Name] [+] }|
popup menu test│{2:WINBAR }| popu│popup menu test |
p me│{1:~ }{n: foo }{1: }|
{3:<+] [No Name] [+] }{n: bar }{3: }|
popup menu test│{2:WIN}{n: baz }{2: }|
{1:~ }│popup menu test | {1:~ }│popup menu test |
:let g:menustr = 'bar' | {1:~ }│{1:~ }|
|
]], ]],
} }
end end
local pos = {
{ 0, 2, 20 },
{ 0, 3, 19 },
{ 0, 3, 18 },
{ 0, 4, 23 },
{ 0, 4, 24 },
{ 0, 5, 19 },
{ 0, 5, 18 },
}
if multigrid then
for i = 1, 7 do
local _, row, col = unpack(pos[i])
pos[i] = { 1, row - 2, col - 5 }
end
end
api.nvim_input_mouse('right', 'press', '', unpack(pos[1]))
screen:expect(no_sel_screen)
api.nvim_input_mouse('right', 'drag', '', unpack(pos[2]))
screen:expect(screen_replace(no_sel_screen, '{n: foo }', '{s: foo }'))
api.nvim_input_mouse('right', 'drag', '', unpack(pos[3]))
screen:expect(no_sel_screen)
api.nvim_input_mouse('right', 'drag', '', unpack(pos[4]))
screen:expect(screen_replace(no_sel_screen, '{n: bar }', '{s: bar }'))
api.nvim_input_mouse('right', 'drag', '', unpack(pos[5]))
screen:expect(no_sel_screen)
api.nvim_input_mouse('right', 'drag', '', unpack(pos[6]))
screen:expect(screen_replace(no_sel_screen, '{n: baz }', '{s: baz }'))
api.nvim_input_mouse('right', 'release', '', unpack(pos[7]))
screen:expect(no_sel_screen)
api.nvim_input_mouse('left', 'press', '', unpack(pos[7]))
screen:expect(no_menu_screen)
eq('', api.nvim_get_var('menustr'))
if multigrid then
for i = 2, 6, 2 do
local _, row, col = unpack(pos[i])
pos[i] = { 4, row - 1, col - 14 }
end
end
api.nvim_input_mouse('right', 'press', '', unpack(pos[1]))
screen:expect(no_sel_screen)
api.nvim_input_mouse('move', '', '', unpack(pos[2]))
screen:expect(screen_replace(no_sel_screen, '{n: foo }', '{s: foo }'))
api.nvim_input_mouse('move', '', '', unpack(pos[3]))
screen:expect(no_sel_screen)
api.nvim_input_mouse('move', '', '', unpack(pos[4]))
screen:expect(screen_replace(no_sel_screen, '{n: bar }', '{s: bar }'))
api.nvim_input_mouse('move', '', '', unpack(pos[5]))
screen:expect(no_sel_screen)
api.nvim_input_mouse('move', '', '', unpack(pos[6]))
screen:expect(screen_replace(no_sel_screen, '{n: baz }', '{s: baz }'))
api.nvim_input_mouse('left', 'press', '', unpack(pos[7]))
screen:expect(no_menu_screen)
eq('', api.nvim_get_var('menustr'))
command('set rightleft | wincmd p | set rightleft | wincmd p')
if multigrid then
no_menu_screen = [[
## grid 1
[8:--------------------------------]|
{4:[No Name] [+] }|
[7:----]│[2:---------------------------]|*2
{3:<+] [No Name] [+] }|
[5:---------------]│[6:----------------]|*3
[3:--------------------------------]|
## grid 2
tset unem pupop|
{1: ~}|
## grid 3
|
## grid 5
popup menu test|
{1:~ }|*2
## grid 6
{2:WINBAR }|
popup menu test |
{1:~ }|
## grid 7
popu|
p me|
## grid 8
tset unem pupo^p|
]]
else
no_menu_screen = [[
tset unem pupo^p|
{4:[No Name] [+] }|
popu│ tset unem pupop|
p me│{1: ~}|
{3:<+] [No Name] [+] }|
popup menu test│{2:WINBAR }|
{1:~ }│popup menu test |
{1:~ }│{1:~ }|
|
]]
end
screen:expect(no_menu_screen) screen:expect(no_menu_screen)
if multigrid then if multigrid then
no_sel_screen = { no_sel_screen = {
grid = [[ grid = [[
## grid 1 ## grid 1
[2:--------------------------------]|*2 [8:--------------------------------]|
{4:[No Name] [+] }| {4:[No Name] [+] }|
[5:---------------]│[6:----------------]|*2 [7:----]│[2:---------------------------]|*2
{3:<+] [No Name] [+] }|
[5:---------------]│[6:----------------]|*3
[3:--------------------------------]| [3:--------------------------------]|
## grid 2 ## grid 2
tset unem pupo^p| tset unem pupop|
{1: ~}| {1: ~}|
## grid 3 ## grid 3
:let g:menustr = 'bar' | |
## grid 4 ## grid 4
{n: oof }| {n: oof }|
{n: rab }| {n: rab }|
{n: zab }| {n: zab }|
## grid 5 ## grid 5
popup menu test| popup menu test|
{1:~ }| {1:~ }|*2
## grid 6 ## grid 6
{2:WINBAR }| {2:WINBAR }|
popup menu test | popup menu test |
{1:~ }|
## grid 7
popu|
p me|
## grid 8
tset unem pupo^p|
]], ]],
float_pos = { [4] = { -1, 'NW', 1, 1, 17, false, 250, 2, 1, 17 } }, float_pos = { [4] = { -1, 'NW', 1, 1, 12, false, 250, 2, 1, 12 } },
} }
else else
no_sel_screen = { no_sel_screen = {
grid = [[ grid = [[
tset unem pupo^p| tset unem pupo^p|
{1: }{n: oof }{1: ~}| {4:[No Name] [+] }|
{4:[No Name] [+] }{n: rab }{4: }| popu│ tset unem pupop|
p me│{1: }{n: oof }{1: ~}|
{3:<+] [No Name] [+}{n: rab }{3: }|
popup menu test│{2:W}{n: zab }{2: }| popup menu test│{2:W}{n: zab }{2: }|
{1:~ }│popup menu test | {1:~ }│popup menu test |
:let g:menustr = 'bar' | {1:~ }│{1:~ }|
|
]], ]],
} }
end end
for i, s in ipairs({ 'oof', 'rab', 'zab' }) do
local sel_screen = vim.deepcopy(no_sel_screen) pos = {
local grid = assert(sel_screen.grid) { 0, 2, 20 },
grid = grid:gsub(vim.pesc(('{n: %s }'):format(s)), ('{s: %s }'):format(s)) { 0, 3, 21 },
sel_screen.grid = grid { 0, 3, 22 },
sel_screens[i] = sel_screen { 0, 4, 17 },
{ 0, 4, 16 },
{ 0, 5, 21 },
{ 0, 5, 22 },
}
if multigrid then
for i = 1, 7 do
local _, row, col = unpack(pos[i])
pos[i] = { 1, row - 2, col - 5 }
end
end end
api.nvim_input_mouse('right', 'press', '', g, 0, 20) api.nvim_input_mouse('right', 'press', '', unpack(pos[1]))
screen:expect(no_sel_screen) screen:expect(no_sel_screen)
api.nvim_input_mouse('move', '', '', g, 1, 21) api.nvim_input_mouse('move', '', '', unpack(pos[2]))
screen:expect(sel_screens[1]) screen:expect(screen_replace(no_sel_screen, '{n: oof }', '{s: oof }'))
api.nvim_input_mouse('move', '', '', g, 1, 22) api.nvim_input_mouse('move', '', '', unpack(pos[3]))
screen:expect(no_sel_screen) screen:expect(no_sel_screen)
api.nvim_input_mouse('move', '', '', g, 2, 17) api.nvim_input_mouse('move', '', '', unpack(pos[4]))
screen:expect(sel_screens[2]) screen:expect(screen_replace(no_sel_screen, '{n: rab }', '{s: rab }'))
api.nvim_input_mouse('move', '', '', g, 2, 16) api.nvim_input_mouse('move', '', '', unpack(pos[5]))
screen:expect(no_sel_screen) screen:expect(no_sel_screen)
api.nvim_input_mouse('move', '', '', g, 3, 21) api.nvim_input_mouse('move', '', '', unpack(pos[6]))
screen:expect(sel_screens[3]) screen:expect(screen_replace(no_sel_screen, '{n: zab }', '{s: zab }'))
api.nvim_input_mouse('left', 'press', '', g, 3, 22) api.nvim_input_mouse('left', 'press', '', unpack(pos[7]))
screen:expect(no_menu_screen) screen:expect(no_menu_screen)
eq('', api.nvim_get_var('menustr')) eq('', api.nvim_get_var('menustr'))
if multigrid then
for i = 2, 6, 2 do
local _, row, col = unpack(pos[i])
pos[i] = { 4, row - 1, col - 12 }
end
end
api.nvim_input_mouse('right', 'press', '', unpack(pos[1]))
screen:expect(no_sel_screen)
api.nvim_input_mouse('right', 'drag', '', unpack(pos[2]))
screen:expect(screen_replace(no_sel_screen, '{n: oof }', '{s: oof }'))
api.nvim_input_mouse('right', 'drag', '', unpack(pos[3]))
screen:expect(no_sel_screen)
api.nvim_input_mouse('right', 'drag', '', unpack(pos[4]))
screen:expect(screen_replace(no_sel_screen, '{n: rab }', '{s: rab }'))
api.nvim_input_mouse('right', 'drag', '', unpack(pos[5]))
screen:expect(no_sel_screen)
api.nvim_input_mouse('right', 'drag', '', unpack(pos[6]))
screen:expect(screen_replace(no_sel_screen, '{n: zab }', '{s: zab }'))
api.nvim_input_mouse('right', 'release', '', unpack(pos[7]))
screen:expect(no_sel_screen)
api.nvim_input_mouse('left', 'press', '', unpack(pos[7]))
eq('', api.nvim_get_var('menustr'))
command('set norightleft') command('set norightleft')
end) end)