feat(ui): support grid=0 in nvim_input_mouse #32535

Problem:
Multigrid UIs have to find out which window to send the input by using
the Nvim focus rules, which are not fully documented.

Furthermore,`getmousepos()` has several problems when multigrid is
enabled, with the main one being that screenrow and screencol are window
relative instead of screen relative, due to the fact that the UI don't
send any absolute coordinates.

Solution:
Allow passing 0 as grid to `nvim_input_mouse`, with absolute
coordinates, which lets nvim determine the actual window to send the
mouse input to. This works as long as nvim is in charge of the window
positioning. If the UI repositions or resizes the windows, it can still
pass the grid it determines like before.
This commit is contained in:
fredizzimo
2025-09-14 00:57:04 +03:00
committed by GitHub
parent c1648cf820
commit 8ae9a44d38
15 changed files with 2388 additions and 2162 deletions

View File

@@ -1147,8 +1147,9 @@ nvim_input_mouse({button}, {action}, {modifier}, {grid}, {row}, {col})
press, except that the "-" separator is optional, so
"C-A-", "c-a" and "CA" can all be used to specify
Ctrl+Alt+click.
• {grid} (`integer`) Grid number if the client uses |ui-multigrid|,
else 0.
• {grid} (`integer`) Grid number (used by |ui-multigrid| client),
or 0 to let Nvim decide positioning of windows. For more
information, see |dev-ui-multigrid|
• {row} (`integer`) Mouse row-position (zero-based, like redraw
events)
• {col} (`integer`) Mouse column-position (zero-based, like redraw

View File

@@ -685,5 +685,23 @@ External UIs are expected to implement these common features:
- Handle the "restart" UI event so that |:restart| works.
- Detect capslock and show an indicator if capslock is active.
Multigrid UI ~
*dev-ui-multigrid*
- A multigrid UI should display floating windows using one of the following
methods, using the `win_float_pos` |ui-multigrid| event. Different methods
can be selected for each window as needed.
1. Let Nvim determine the position and z-order of the windows. This can be
achieved by using the `compindex`, `screen_row`, and `screen_col` information from
the `win_float_pos` UI event. To allow Nvim to automatically determine the grid,
the UI should call `nvim_input_mouse` with 0 as the `grid` parameter.
2. Use the `anchor`, `anchor_grid`, `anchor_row`, `anchor_col`, and `zindex` as
references for positioning the windows. If windows are outside the screen,
it is the UI's responsibility to reposition and/or resize them. Since Nvim
lacks information about actual window placement in this case, the UI must
call `nvim_input_mouse` with the actual grid id, factoring in `mouse_enabled`.
Note: Some API functions may return unexpected results for these windows due
to the missing information.
- For external windows, the grid id should also be passed to `nvim_input_mouse`.
vim:tw=78:ts=8:sw=4:et:ft=help:norl:

View File

@@ -339,6 +339,7 @@ UI
• "Error executing Lua:" changed to "Lua:".
• 'busy' status is shown in default statusline with symbol ◐
• Improved LSP signature help rendering.
• Multigrid UIs can call nvim_input_mouse with grid 0 to let Nvim decide the grid.
VIMSCRIPT

View File

@@ -1606,7 +1606,8 @@ function vim.api.nvim_input(keys) end
--- The same specifiers are used as for a key press, except
--- that the "-" separator is optional, so "C-A-", "c-a"
--- and "CA" can all be used to specify Ctrl+Alt+click.
--- @param grid integer Grid number if the client uses `ui-multigrid`, else 0.
--- @param grid integer Grid number (used by `ui-multigrid` client), or 0 to let Nvim decide positioning of
--- windows. For more information, see [dev-ui-multigrid]
--- @param row integer Mouse row-position (zero-based, like redraw events)
--- @param col integer Mouse column-position (zero-based, like redraw events)
function vim.api.nvim_input_mouse(button, action, modifier, grid, row, col) end

View File

@@ -382,7 +382,8 @@ Integer nvim_input(uint64_t channel_id, String keys)
/// The same specifiers are used as for a key press, except
/// that the "-" separator is optional, so "C-A-", "c-a"
/// and "CA" can all be used to specify Ctrl+Alt+click.
/// @param grid Grid number if the client uses |ui-multigrid|, else 0.
/// @param grid Grid number (used by |ui-multigrid| client), or 0 to let Nvim decide positioning of
/// windows. For more information, see [dev-ui-multigrid]
/// @param row Mouse row-position (zero-based, like redraw events)
/// @param col Mouse column-position (zero-based, like redraw events)
/// @param[out] err Error details, if any

View File

@@ -2013,7 +2013,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv, bool allow_number
int winnr = 1;
// Find the window at the mouse coordinates and compute the
// text position.
win_T *const win = mouse_find_win(&grid, &row, &col);
win_T *const win = mouse_find_win_inner(&grid, &row, &col);
if (win == NULL) {
return;
}

View File

@@ -235,7 +235,7 @@ static int get_fpos_of_mouse(pos_T *mpos)
}
// find the window where the row is in
win_T *wp = mouse_find_win(&grid, &row, &col);
win_T *wp = mouse_find_win_inner(&grid, &row, &col);
if (wp == NULL) {
return IN_UNKNOWN;
}
@@ -663,7 +663,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
int click_grid = mouse_grid;
int click_row = mouse_row;
int click_col = mouse_col;
win_T *wp = mouse_find_win(&click_grid, &click_row, &click_col);
win_T *wp = mouse_find_win_inner(&click_grid, &click_row, &click_col);
if (wp == NULL) {
return false;
}
@@ -1093,7 +1093,7 @@ void ins_mousescroll(int dir)
int grid = mouse_grid;
int row = mouse_row;
int col = mouse_col;
curwin = mouse_find_win(&grid, &row, &col);
curwin = mouse_find_win_inner(&grid, &row, &col);
if (curwin == NULL) {
curwin = old_curwin;
return;
@@ -1263,8 +1263,8 @@ retnomove:
}
// find the window where the row is in and adjust "row" and "col" to be
// relative to top-left of the window
win_T *wp = mouse_find_win(&grid, &row, &col);
// relative to top-left of the window inner area
win_T *wp = mouse_find_win_inner(&grid, &row, &col);
if (wp == NULL) {
return IN_UNKNOWN;
}
@@ -1581,7 +1581,7 @@ void nv_mousescroll(cmdarg_T *cap)
int grid = mouse_grid;
int row = mouse_row;
int col = mouse_col;
curwin = mouse_find_win(&grid, &row, &col);
curwin = mouse_find_win_inner(&grid, &row, &col);
if (curwin == NULL) {
curwin = old_curwin;
return;
@@ -1695,10 +1695,10 @@ bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump)
}
/// Find the window at "grid" position "*rowp" and "*colp". The positions are
/// updated to become relative to the top-left of the window.
/// updated to become relative to the top-left of the window inner area.
///
/// @return NULL when something is wrong.
win_T *mouse_find_win(int *gridp, int *rowp, int *colp)
win_T *mouse_find_win_inner(int *gridp, int *rowp, int *colp)
{
win_T *wp_grid = mouse_find_grid_win(gridp, rowp, colp);
if (wp_grid) {
@@ -1740,6 +1740,20 @@ win_T *mouse_find_win(int *gridp, int *rowp, int *colp)
return NULL;
}
/// Find the window at "grid" position "*rowp" and "*colp". The positions are
/// updated to become relative to the top-left of the window.
///
/// @return NULL when something is wrong.
win_T *mouse_find_win_outer(int *gridp, int *rowp, int *colp)
{
win_T *wp = mouse_find_win_inner(gridp, rowp, colp);
if (wp) {
*rowp += wp->w_winrow_off;
*colp += wp->w_wincol_off;
}
return wp;
}
static win_T *mouse_find_grid_win(int *gridp, int *rowp, int *colp)
{
if (*gridp == msg_grid.handle) {
@@ -1755,18 +1769,26 @@ static win_T *mouse_find_grid_win(int *gridp, int *rowp, int *colp)
}
} else if (*gridp == 0) {
ScreenGrid *grid = ui_comp_mouse_focus(*rowp, *colp);
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (&wp->w_grid_alloc != grid) {
continue;
}
if (grid == &pum_grid) {
*gridp = grid->handle;
*rowp -= grid->comp_row + wp->w_grid.row_offset;
*colp -= grid->comp_col + wp->w_grid.col_offset;
return wp;
*rowp -= grid->comp_row;
*colp -= grid->comp_col;
// The popup menu doesn't have a window, so return NULL
return NULL;
} else {
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (&wp->w_grid_alloc != grid) {
continue;
}
*gridp = grid->handle;
*rowp -= wp->w_winrow + wp->w_grid.row_offset;
*colp -= wp->w_wincol + wp->w_grid.col_offset;
return wp;
}
}
// no float found, click on the default grid
// TODO(bfredl): grid can be &pum_grid, allow select pum items by mouse?
// No grid found, return the default grid. With multigrid this happens for split separators for
// example.
*gridp = DEFAULT_GRID_HANDLE;
}
return NULL;
@@ -1877,7 +1899,7 @@ static void mouse_check_grid(colnr_T *vcolp, int *flagsp)
int click_col = mouse_col;
// XXX: this doesn't change click_grid if it is 1, even with multigrid
if (mouse_find_win(&click_grid, &click_row, &click_col) != curwin
if (mouse_find_win_inner(&click_grid, &click_row, &click_col) != curwin
// Only use vcols[] after the window was redrawn. Mainly matters
// for tests, a user would not click before redrawing.
|| curwin->w_redr_type != 0) {
@@ -1931,7 +1953,7 @@ void f_getmousepos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
tv_dict_add_nr(d, S_LEN("screenrow"), (varnumber_T)mouse_row + 1);
tv_dict_add_nr(d, S_LEN("screencol"), (varnumber_T)mouse_col + 1);
win_T *wp = mouse_find_win(&grid, &row, &col);
win_T *wp = mouse_find_win_inner(&grid, &row, &col);
if (wp != NULL) {
int height = wp->w_height + wp->w_hsep_height + wp->w_status_height;
// The height is adjusted by 1 when there is a bottom border. This is not

View File

@@ -37,6 +37,7 @@
#include "nvim/memory_defs.h"
#include "nvim/menu.h"
#include "nvim/message.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/option_defs.h"
@@ -1325,6 +1326,10 @@ static void pum_position_at_mouse(int min_width)
int col = mouse_col;
pum_win_row_offset = 0;
pum_win_col_offset = 0;
if (ui_has(kUIMultigrid) && grid == 0) {
mouse_find_win_outer(&grid, &row, &col);
}
if (grid > 1) {
win_T *wp = get_win_by_grid_handle(grid);
if (wp != NULL) {
@@ -1395,17 +1400,27 @@ static void pum_position_at_mouse(int min_width)
/// Select the pum entry at the mouse position.
static void pum_select_mouse_pos(void)
{
if (mouse_grid == pum_grid.handle) {
pum_selected = mouse_row;
int grid = mouse_grid;
int row = mouse_row;
int col = mouse_col;
if (grid == 0) {
mouse_find_win_outer(&grid, &row, &col);
}
if (grid == pum_grid.handle) {
pum_selected = row;
return;
} else if (mouse_grid != pum_anchor_grid
|| mouse_col < pum_left_col - pum_win_col_offset
|| mouse_col >= pum_right_col - pum_win_col_offset) {
}
if (grid != pum_anchor_grid
|| col < pum_left_col - pum_win_col_offset
|| col >= pum_right_col - pum_win_col_offset) {
pum_selected = -1;
return;
}
int idx = mouse_row - (pum_row - pum_win_row_offset);
int idx = row - (pum_row - pum_win_row_offset);
if (idx < 0 || idx >= pum_height) {
pum_selected = -1;

View File

@@ -1907,7 +1907,7 @@ static bool send_mouse_event(Terminal *term, int c)
int row = mouse_row;
int col = mouse_col;
int grid = mouse_grid;
win_T *mouse_win = mouse_find_win(&grid, &row, &col);
win_T *mouse_win = mouse_find_win_inner(&grid, &row, &col);
if (mouse_win == NULL) {
goto end;
}

View File

@@ -318,6 +318,15 @@ ScreenGrid *ui_comp_mouse_focus(int row, int col)
return grid;
}
}
if (ui_has(kUIMultigrid)) {
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
ScreenGrid *grid = &wp->w_grid_alloc;
if (grid->mouse_enabled && row >= wp->w_winrow && row < wp->w_winrow + grid->rows
&& col >= wp->w_wincol && col < wp->w_wincol + grid->cols) {
return grid;
}
}
}
return NULL;
}

View File

@@ -5187,6 +5187,8 @@ win_T *win_alloc(win_T *after, bool hidden)
new_wp->handle = ++last_win_id;
pmap_put(int)(&window_handles, new_wp->handle, new_wp);
new_wp->w_grid_alloc.mouse_enabled = true;
grid_assign_handle(&new_wp->w_grid_alloc);
// Init w: variables.

View File

@@ -192,7 +192,7 @@ void win_config_float(win_T *wp, WinConfig fconfig)
int row = mouse_row;
int col = mouse_col;
int grid = mouse_grid;
win_T *mouse_win = mouse_find_win(&grid, &row, &col);
win_T *mouse_win = mouse_find_win_inner(&grid, &row, &col);
if (mouse_win != NULL) {
fconfig.relative = kFloatRelativeWindow;
fconfig.row += row;

View File

@@ -971,7 +971,7 @@ describe('float window', function()
api.nvim_win_set_config(win, api.nvim_win_get_config(win))
end)
local function with_ext_multigrid(multigrid)
local function with_ext_multigrid(multigrid, send_mouse_grid)
local screen, attrs
before_each(function()
screen = Screen.new(40, 7, { ext_multigrid = multigrid })
@@ -6164,8 +6164,12 @@ describe('float window', function()
end)
local function test_float_mouse_focus()
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 0, 0)
else
api.nvim_input_mouse('left', 'press', '', 0, 2, 5)
end
if multigrid then
screen:expect {
grid = [[
## grid 1
@@ -6183,7 +6187,6 @@ describe('float window', function()
float_pos = expected_pos,
}
else
api.nvim_input_mouse('left', 'press', '', 0, 2, 5)
screen:expect([[
x |
{0:~ }|
@@ -6194,8 +6197,12 @@ describe('float window', function()
]])
end
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 2, 0, 0)
else
api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
end
if multigrid then
screen:expect {
grid = [[
## grid 1
@@ -6213,7 +6220,6 @@ describe('float window', function()
float_pos = expected_pos,
}
else
api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
screen:expect([[
^x |
{0:~ }|
@@ -6237,27 +6243,53 @@ describe('float window', function()
local function test_float_mouse_no_focus()
api.nvim_buf_set_lines(0, -1, -1, true, { 'a' })
expected_pos[4][6] = false
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 0, 0)
screen:expect {
grid = [[
## grid 1
[2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^x |
a |
{0:~ }|*4
## grid 3
|
## grid 4
{1:y }|
{2:~ }|
]],
float_pos = expected_pos,
}
else
api.nvim_input_mouse('left', 'press', '', 0, 2, 5)
end
if multigrid then
if send_mouse_grid then
-- Sending input to grid 4 is a user error, you are not supposed to pass a grid
-- that isn't focusable. In this case, nothing happens and the input is not passed
-- through to grid 4, like normally happens when you pass grid 0.
screen:expect {
grid = [[
## grid 1
[2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^x |
a |
{0:~ }|*4
## grid 3
|
## grid 4
{1:y }|
{2:~ }|
]],
float_pos = expected_pos,
}
else
screen:expect {
grid = [[
## grid 1
[2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
x |
^a |
{0:~ }|*4
## grid 3
|
## grid 4
{1:y }|
{2:~ }|
]],
float_pos = expected_pos,
}
end
else
screen:expect([[
x |
^a |
@@ -6268,8 +6300,12 @@ describe('float window', function()
]])
end
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 2, 0, 0)
else
api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
end
if multigrid then
screen:expect {
grid = [[
## grid 1
@@ -6289,7 +6325,6 @@ describe('float window', function()
unchanged = true,
}
else
api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
screen:expect([[
^x |
a |
@@ -7959,7 +7994,11 @@ describe('float window', function()
},
}
api.nvim_input_mouse('left', 'press', '', 4, 0, 0)
if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 0, 0)
else
api.nvim_input_mouse('left', 'press', '', 0, 2, 5)
end
screen:expect {
grid = [[
## grid 1
@@ -7982,7 +8021,11 @@ describe('float window', function()
},
}
api.nvim_input_mouse('left', 'drag', '', 4, 1, 2)
if send_mouse_grid then
api.nvim_input_mouse('left', 'drag', '', 4, 1, 2)
else
api.nvim_input_mouse('left', 'drag', '', 0, 3, 7)
end
screen:expect {
grid = [[
## grid 1
@@ -8074,7 +8117,11 @@ describe('float window', function()
},
}
api.nvim_input_mouse('left', 'press', '', 4, 1, 1)
if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 1, 1)
else
api.nvim_input_mouse('left', 'press', '', 0, 1, 6)
end
screen:expect {
grid = [[
## grid 1
@@ -8099,7 +8146,11 @@ describe('float window', function()
},
}
api.nvim_input_mouse('left', 'drag', '', 4, 2, 3)
if send_mouse_grid then
api.nvim_input_mouse('left', 'drag', '', 4, 2, 3)
else
api.nvim_input_mouse('left', 'drag', '', 0, 2, 8)
end
screen:expect {
grid = [[
## grid 1
@@ -8193,7 +8244,11 @@ describe('float window', function()
},
}
api.nvim_input_mouse('left', 'press', '', 4, 1, 0)
if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 1, 0)
else
api.nvim_input_mouse('left', 'press', '', 0, 2, 5)
end
screen:expect {
grid = [[
## grid 1
@@ -8217,7 +8272,11 @@ describe('float window', function()
},
}
api.nvim_input_mouse('left', 'drag', '', 4, 2, 2)
if send_mouse_grid then
api.nvim_input_mouse('left', 'drag', '', 4, 2, 2)
else
api.nvim_input_mouse('left', 'drag', '', 0, 3, 7)
end
screen:expect {
grid = [[
## grid 1
@@ -8304,7 +8363,11 @@ describe('float window', function()
{0:~ }|*2
]])
api.nvim_input_mouse('left', 'press', '', 4, 2, 2)
if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 2, 2)
else
api.nvim_input_mouse('left', 'press', '', 0, 2, 22)
end
screen:expect([[
## grid 1
[2:-------------------]{5:│}[4:--------------------]|*5
@@ -8322,7 +8385,11 @@ describe('float window', function()
{0:~ }|*2
]])
api.nvim_input_mouse('left', 'drag', '', 4, 1, 1)
if send_mouse_grid then
api.nvim_input_mouse('left', 'drag', '', 4, 1, 1)
else
api.nvim_input_mouse('left', 'drag', '', 0, 1, 21)
end
screen:expect([[
## grid 1
[2:-------------------]{5:│}[4:--------------------]|*5
@@ -8409,21 +8476,21 @@ describe('float window', function()
}
end
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 3, 1)
else
api.nvim_input_mouse('left', 'press', '', 0, 3, 6)
end
eq({ 0, 3, 1, 0, 1 }, fn.getcurpos())
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 3, 2)
else
api.nvim_input_mouse('left', 'press', '', 0, 3, 7)
end
eq({ 0, 3, 1, 0, 2 }, fn.getcurpos())
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 3, 10)
else
api.nvim_input_mouse('left', 'press', '', 0, 3, 15)
@@ -8470,8 +8537,12 @@ describe('float window', function()
}
end
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 2, 1)
else
api.nvim_input_mouse('left', 'press', '', 0, 2, 6)
end
if multigrid then
screen:expect {
grid = [[
## grid 1
@@ -8496,7 +8567,6 @@ describe('float window', function()
},
}
else
api.nvim_input_mouse('left', 'press', '', 0, 2, 6)
screen:expect {
grid = [[
{5:┌────────────────────┐} |
@@ -8510,21 +8580,21 @@ describe('float window', function()
}
end
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 2, 2)
else
api.nvim_input_mouse('left', 'press', '', 0, 2, 7)
end
eq({ 0, 2, 1, 0, 1 }, fn.getcurpos())
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 2, 3)
else
api.nvim_input_mouse('left', 'press', '', 0, 2, 8)
end
eq({ 0, 2, 1, 0, 2 }, fn.getcurpos())
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 2, 11)
else
api.nvim_input_mouse('left', 'press', '', 0, 2, 16)
@@ -8840,8 +8910,12 @@ describe('float window', function()
end
-- Test scrolling by mouse
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('wheel', 'down', '', 4, 2, 2)
else
api.nvim_input_mouse('wheel', 'down', '', 0, 4, 7)
end
if multigrid then
screen:expect {
grid = [[
## grid 1
@@ -8865,7 +8939,6 @@ describe('float window', function()
float_pos = { [4] = { 1001, 'NW', 1, 2, 5, true, 50, 1, 2, 5 } },
}
else
api.nvim_input_mouse('wheel', 'down', '', 0, 4, 7)
screen:expect([[
Ut enim ad minim veniam, quis nostrud |
exercitation ullamco laboris nisi ut aliquip ex |
@@ -11047,10 +11120,15 @@ describe('float window', function()
end)
end
describe('with ext_multigrid', function()
with_ext_multigrid(true)
describe('with ext_multigrid and actual mouse grid', function()
with_ext_multigrid(true, true)
end)
describe('with ext_multigrid and mouse grid 0', function()
with_ext_multigrid(true, false)
end)
describe('without ext_multigrid', function()
with_ext_multigrid(false)
with_ext_multigrid(false, false)
end)
end)

File diff suppressed because it is too large Load Diff

View File

@@ -1018,7 +1018,7 @@ end)
describe('builtin popupmenu', function()
before_each(clear)
local function with_ext_multigrid(multigrid)
local function with_ext_multigrid(multigrid, send_mouse_grid)
local screen
before_each(function()
screen = Screen.new(32, 20, { ext_multigrid = multigrid })
@@ -2553,8 +2553,12 @@ describe('builtin popupmenu', function()
]])
end
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('wheel', 'down', '', 2, 9, 33)
else
api.nvim_input_mouse('wheel', 'down', '', 0, 9, 40)
end
if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -2595,7 +2599,6 @@ describe('builtin popupmenu', function()
float_pos = { [5] = { -1, 'NW', 4, 1, 3, false, 100, 1, 1, 3 } },
})
else
api.nvim_input_mouse('wheel', 'down', '', 0, 9, 40)
screen:expect([[
Est ^ |
L{n: sunt }{12: }sit amet, consectetur |
@@ -2672,8 +2675,12 @@ describe('builtin popupmenu', function()
]])
end
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('wheel', 'up', '', 2, 9, 33)
else
api.nvim_input_mouse('wheel', 'up', '', 0, 9, 40)
end
if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -2712,7 +2719,6 @@ describe('builtin popupmenu', function()
float_pos = { [5] = { -1, 'NW', 4, 1, 3, false, 100, 1, 1, 3 } },
})
else
api.nvim_input_mouse('wheel', 'up', '', 0, 9, 40)
screen:expect([[
Est e^ |
L{n: elit } sit amet, consectetur |
@@ -2781,8 +2787,12 @@ describe('builtin popupmenu', function()
]])
end
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('wheel', 'down', '', 2, 9, 33)
else
api.nvim_input_mouse('wheel', 'down', '', 0, 9, 40)
end
if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -2813,7 +2823,6 @@ describe('builtin popupmenu', function()
float_pos = { [5] = { -1, 'NW', 4, 1, 3, false, 100, 1, 1, 3 } },
})
else
api.nvim_input_mouse('wheel', 'down', '', 0, 9, 40)
screen:expect([[
Est es^ |
L{n: esse } sit amet, consectetur |
@@ -2948,8 +2957,12 @@ describe('builtin popupmenu', function()
]])
end
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('wheel', 'down', '', 2, 9, 33)
else
api.nvim_input_mouse('wheel', 'down', '', 0, 9, 40)
end
if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -2988,7 +3001,6 @@ describe('builtin popupmenu', function()
float_pos = { [5] = { -1, 'NW', 4, 1, 3, false, 100, 1, 1, 3 } },
})
else
api.nvim_input_mouse('wheel', 'down', '', 0, 9, 40)
screen:expect([[
Est eu^ |
L{n: elit } sit amet, consectetur |
@@ -6614,9 +6626,13 @@ describe('builtin popupmenu', function()
return new_state
end
local no_sel_screen ---@type string|test.functional.ui.screen.Expect
if multigrid then
local no_sel_screen ---@type string|test.function.ui.screen.Expect
if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 2, 0, 4)
else
feed('<RightMouse><4,0>')
end
if multigrid then
no_sel_screen = {
grid = [[
## grid 1
@@ -6635,7 +6651,6 @@ describe('builtin popupmenu', function()
float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250, 2, 1, 3 } },
}
else
feed('<RightMouse><4,0>')
no_sel_screen = [[
^popup menu test |
{1:~ }{n: foo }{1: }|
@@ -6673,8 +6688,12 @@ describe('builtin popupmenu', function()
screen:expect(no_menu_screen)
eq('bar', api.nvim_get_var('menustr'))
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 2, 2, 20)
else
feed('<RightMouse><20,2>')
end
if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -6693,7 +6712,6 @@ describe('builtin popupmenu', function()
float_pos = { [4] = { -1, 'NW', 2, 3, 19, false, 250, 2, 3, 19 } },
})
else
feed('<RightMouse><20,2>')
screen:expect([[
^popup menu test |
{1:~ }|*2
@@ -6702,8 +6720,12 @@ describe('builtin popupmenu', function()
:let g:menustr = 'b{n: baz } |
]])
end
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 2, 0, 18)
else
feed('<RightMouse><18,0>')
end
if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -6722,7 +6744,6 @@ describe('builtin popupmenu', function()
float_pos = { [4] = { -1, 'NW', 2, 1, 17, false, 250, 2, 1, 17 } },
})
else
feed('<RightMouse><18,0>')
screen:expect([[
^popup menu test |
{1:~ }{n: foo }{1: }|
@@ -6732,8 +6753,12 @@ describe('builtin popupmenu', function()
:let g:menustr = 'bar' |
]])
end
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 4, 1, 3)
else
feed('<RightMouse><20,2>')
end
if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -6752,7 +6777,6 @@ describe('builtin popupmenu', function()
float_pos = { [4] = { -1, 'NW', 2, 3, 19, false, 250, 2, 3, 19 } },
})
else
feed('<RightMouse><20,2>')
screen:expect([[
^popup menu test |
{1:~ }|*2
@@ -6761,7 +6785,7 @@ describe('builtin popupmenu', function()
:let g:menustr = 'b{n: baz } |
]])
end
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 2, 2)
else
feed('<LeftMouse><21,5>')
@@ -6770,8 +6794,12 @@ describe('builtin popupmenu', function()
screen:expect(no_menu_screen)
eq('baz', api.nvim_get_var('menustr'))
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 2, 0, 4)
else
feed('<RightMouse><4,0>')
end
if multigrid then
no_sel_screen = {
grid = [[
## grid 1
@@ -6790,7 +6818,6 @@ describe('builtin popupmenu', function()
float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250, 2, 1, 3 } },
}
else
feed('<RightMouse><4,0>')
no_sel_screen = [[
^popup menu test |
{1:~ }{n: foo }{1: }|
@@ -6801,13 +6828,13 @@ describe('builtin popupmenu', function()
]]
end
screen:expect(no_sel_screen)
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('right', 'drag', '', 2, 3, 6)
else
feed('<RightDrag><6,3>')
end
screen:expect(screen_replace(no_sel_screen, '{n: baz }', '{12: baz }'))
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('right', 'release', '', 2, 1, 6)
else
feed('<RightRelease><6,1>')
@@ -6818,35 +6845,36 @@ describe('builtin popupmenu', function()
no_sel_screen = screen_replace(no_sel_screen, [['baz']], [['foo']])
eq(false, screen.options.mousemoveevent)
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 2, 0, 4)
else
feed('<RightMouse><4,0>')
end
screen:expect(no_sel_screen)
eq(true, screen.options.mousemoveevent)
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('wheel', 'up', '', 2, 0, 4)
else
feed('<ScrollWheelUp><4,0>')
end
screen:expect(screen_replace(no_sel_screen, '{n: foo }', '{12: foo }'))
eq(true, screen.options.mousemoveevent)
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('move', '', '', 4, 2, 3)
else
feed('<MouseMove><6,3>')
end
screen:expect(screen_replace(no_sel_screen, '{n: baz }', '{12: baz }'))
eq(true, screen.options.mousemoveevent)
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('wheel', 'down', '', 4, 2, 3)
else
feed('<ScrollWheelDown><6,3>')
end
screen:expect(screen_replace(no_sel_screen, '{n: bar }', '{12: bar }'))
eq(true, screen.options.mousemoveevent)
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 1, 3)
else
feed('<LeftMouse><6,2>')
@@ -6857,8 +6885,12 @@ describe('builtin popupmenu', function()
eq('bar', api.nvim_get_var('menustr'))
command('set laststatus=0 | botright split')
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 5, 1, 20)
else
feed('<RightMouse><20,4>')
end
if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -6882,7 +6914,6 @@ describe('builtin popupmenu', function()
float_pos = { [4] = { -1, 'SW', 5, 1, 19, false, 250, 2, 1, 19 } },
})
else
feed('<RightMouse><20,4>')
screen:expect([[
popup menu test |
{1:~ }{n: foo }{1: }|
@@ -6892,8 +6923,12 @@ describe('builtin popupmenu', function()
:let g:menustr = 'bar' |
]])
end
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 2, 2)
else
feed('<LeftMouse><21,3>')
end
if multigrid then
screen:expect([[
## grid 1
[2:--------------------------------]|*2
@@ -6910,7 +6945,6 @@ describe('builtin popupmenu', function()
{1:~ }|
]])
else
feed('<LeftMouse><21,3>')
screen:expect([[
popup menu test |
{1:~ }|
@@ -6923,8 +6957,12 @@ describe('builtin popupmenu', function()
eq('baz', api.nvim_get_var('menustr'))
command('set winwidth=1 | rightbelow vsplit')
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 6, 1, 14)
else
feed('<RightMouse><30,4>')
end
if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -6951,7 +6989,6 @@ describe('builtin popupmenu', function()
float_pos = { [4] = { -1, 'SW', 6, 1, 12, false, 250, 2, 1, 28 } },
})
else
feed('<RightMouse><30,4>')
screen:expect([[
popup menu test |
{1:~ }{n: foo}|
@@ -6961,8 +6998,12 @@ describe('builtin popupmenu', function()
:let g:menustr = 'baz' |
]])
end
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 0, 2)
else
feed('<LeftMouse><31,1>')
end
if multigrid then
screen:expect([[
## grid 1
[2:--------------------------------]|*2
@@ -6982,7 +7023,6 @@ describe('builtin popupmenu', function()
{1:~ }|
]])
else
feed('<LeftMouse><31,1>')
screen:expect([[
popup menu test |
{1:~ }|
@@ -6995,8 +7035,12 @@ describe('builtin popupmenu', function()
eq('foo', api.nvim_get_var('menustr'))
command('setlocal winbar=WINBAR')
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 6, 1, 14)
else
feed('<RightMouse><30,4>')
end
if multigrid then
no_sel_screen = {
grid = [[
## grid 1
@@ -7023,7 +7067,6 @@ describe('builtin popupmenu', function()
float_pos = { [4] = { -1, 'SW', 6, 1, 12, false, 250, 2, 1, 28 } },
}
else
feed('<RightMouse><30,4>')
no_sel_screen = [[
popup menu test |
{1:~ }{n: foo}|
@@ -7034,20 +7077,24 @@ describe('builtin popupmenu', function()
]]
end
screen:expect(no_sel_screen)
if multigrid then
if send_mouse_grid 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}', '{12: baz}'))
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('right', 'release', '', 6, 1, 15)
else
feed('<RightRelease><31,4>')
end
screen:expect(no_sel_screen)
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 1, 2)
else
feed('<LeftMouse><31,2>')
end
if multigrid then
screen:expect([[
## grid 1
[2:--------------------------------]|*2
@@ -7067,7 +7114,6 @@ describe('builtin popupmenu', function()
^popup menu test |
]])
else
feed('<LeftMouse><31,2>')
screen:expect([[
popup menu test |
{1:~ }|
@@ -7181,7 +7227,7 @@ describe('builtin popupmenu', function()
{ 0, 5, 19 },
{ 0, 5, 18 },
}
if multigrid then
if send_mouse_grid then
for i = 1, 7 do
local _, row, col = unpack(pos[i])
pos[i] = { 2, row - 2, col - 5 }
@@ -7206,7 +7252,7 @@ describe('builtin popupmenu', function()
screen:expect(no_menu_screen)
eq('', api.nvim_get_var('menustr'))
if multigrid then
if send_mouse_grid then
for i = 2, 6, 2 do
local _, row, col = unpack(pos[i])
pos[i] = { 4, row - 1, col - 14 }
@@ -7329,7 +7375,7 @@ describe('builtin popupmenu', function()
{ 0, 5, 21 },
{ 0, 5, 22 },
}
if multigrid then
if send_mouse_grid then
for i = 1, 7 do
local _, row, col = unpack(pos[i])
pos[i] = { 2, row - 2, col - 5 }
@@ -7352,7 +7398,7 @@ describe('builtin popupmenu', function()
screen:expect(no_menu_screen)
eq('', api.nvim_get_var('menustr'))
if multigrid then
if send_mouse_grid then
for i = 2, 6, 2 do
local _, row, col = unpack(pos[i])
pos[i] = { 4, row - 1, col - 12 }
@@ -7551,8 +7597,12 @@ describe('builtin popupmenu', function()
call setline(1, join(range(20)))
]])
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 2, 0, 45 - 1)
else
api.nvim_input_mouse('right', 'press', '', 0, 0, 45 - 1)
end
if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -7578,7 +7628,6 @@ describe('builtin popupmenu', function()
float_pos = { [4] = { -1, 'NW', 2, 1, 33, false, 250, 2, 1, 33 } },
})
else
api.nvim_input_mouse('right', 'press', '', 0, 0, 45 - 1)
screen:expect([[
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ^18 19 |
{1:~ }{n: Undo }|
@@ -7598,8 +7647,12 @@ describe('builtin popupmenu', function()
feed('<Esc>')
command('set rightleft')
if multigrid then
if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 2, 0, 50 - 45)
else
api.nvim_input_mouse('right', 'press', '', 0, 0, 50 - 45)
end
if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -7625,7 +7678,6 @@ describe('builtin popupmenu', function()
float_pos = { [4] = { -1, 'NW', 2, 1, 0, false, 250, 2, 1, 0 } },
})
else
api.nvim_input_mouse('right', 'press', '', 0, 0, 50 - 45)
screen:expect([[
91 8^1 71 61 51 41 31 21 11 01 9 8 7 6 5 4 3 2 1 0|
{n: odnU }{1: ~}|
@@ -8678,11 +8730,15 @@ describe('builtin popupmenu', function()
end
end
describe('with ext_multigrid', function()
with_ext_multigrid(true)
describe('with ext_multigrid and actual mouse grid', function()
with_ext_multigrid(true, true)
end)
describe('with ext_multigrid and mouse grid 0', function()
with_ext_multigrid(true, false)
end)
describe('without ext_multigrid', function()
with_ext_multigrid(false)
with_ext_multigrid(false, false)
end)
end)