mirror of
https://github.com/neovim/neovim.git
synced 2025-09-24 20:18:32 +00:00
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:
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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.
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user