fix(pum): don't select item when clicking to the left/right (#30967)

Problem:  Selecting an item in the right-click menu when clicking to the
          left/right of it is confusing, especially in a UI that doesn't
          support 'mousemoveevent'.
Solution: Don't select an item when clicking to the left/right of the
          right-click menu.
This commit is contained in:
zeertzjq 2024-10-28 14:29:59 +08:00 committed by GitHub
parent 7a20f93a92
commit d24fb72c33
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 78 additions and 7 deletions

View File

@ -1358,14 +1358,15 @@ 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) { } else if (mouse_grid != pum_anchor_grid || mouse_col < pum_grid.comp_col
|| mouse_col >= pum_grid.comp_col + pum_grid.comp_width) {
pum_selected = -1; pum_selected = -1;
return; return;
} }
int idx = mouse_row - pum_row; int idx = mouse_row - pum_grid.comp_row;
if (idx < 0 || idx >= pum_height) { if (idx < 0 || idx >= pum_grid.comp_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

@ -4506,9 +4506,10 @@ describe('builtin popupmenu', function()
:let g:menustr = 'foo' | :let g:menustr = 'foo' |
]]) ]])
end end
local no_menu_screen ---@type string|test.function.ui.screen.Expect
if multigrid then if multigrid then
api.nvim_input_mouse('left', 'press', '', 4, 1, 2) api.nvim_input_mouse('left', 'press', '', 4, 1, 2)
screen:expect({ no_menu_screen = {
grid = [[ grid = [[
## grid 1 ## grid 1
[2:--------------------------------]|*2 [2:--------------------------------]|*2
@ -4527,19 +4528,88 @@ describe('builtin popupmenu', function()
{2:WINBAR }| {2:WINBAR }|
^popup menu test | ^popup menu test |
]], ]],
}) }
else else
feed('<LeftMouse><31,2>') feed('<LeftMouse><31,2>')
screen:expect([[ no_menu_screen = {
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
if multigrid then
no_sel_screen = {
grid = [[
## grid 1
[2:--------------------------------]|*2
{3:[No Name] [+] }|
[5:---------------]│[6:----------------]|*2
[3:--------------------------------]|
## grid 2
popup menu test |
{1:~ }|
## grid 3
:let g:menustr = 'bar' |
## grid 4
{n: foo }|
{n: bar }|
{n: baz }|
## grid 5
popup menu test|
{1:~ }|
## grid 6
{2:WINBAR }|
^popup menu test |
]],
float_pos = { [4] = { -1, 'NW', 1, 1, 19, false, 250 } },
}
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'))
end) end)
if not multigrid then if not multigrid then