mirror of
https://github.com/neovim/neovim
synced 2025-07-18 02:01:46 +00:00
feat(float): allow enabling mouse for non-focusable window (#30844)
Problem: Cannot allow mouse interaction for non-focusable float window. Solution: Add a "mouse" field to float window config.
This commit is contained in:
@ -3195,7 +3195,13 @@ nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()*
|
|||||||
be fractional.
|
be fractional.
|
||||||
• focusable: Enable focus by user actions (wincmds, mouse
|
• focusable: Enable focus by user actions (wincmds, mouse
|
||||||
events). Defaults to true. Non-focusable windows can be
|
events). Defaults to true. Non-focusable windows can be
|
||||||
entered by |nvim_set_current_win()|.
|
entered by |nvim_set_current_win()|, or, when the `mouse`
|
||||||
|
field is set to true, by mouse events.
|
||||||
|
• mouse: Specify how this window interacts with mouse
|
||||||
|
events. Defaults to `focusable` value.
|
||||||
|
• If false, mouse events pass through this window.
|
||||||
|
• If true, mouse events interact with this window
|
||||||
|
normally.
|
||||||
• external: GUI should display the window as an external
|
• external: GUI should display the window as an external
|
||||||
top-level window. Currently accepts no other positioning
|
top-level window. Currently accepts no other positioning
|
||||||
configuration together with this.
|
configuration together with this.
|
||||||
|
@ -40,6 +40,8 @@ API
|
|||||||
This is not expected to break clients because there are no known clients
|
This is not expected to break clients because there are no known clients
|
||||||
that actually use the `return_type` field or the parameter type names
|
that actually use the `return_type` field or the parameter type names
|
||||||
reported by |--api-info| or |nvim_get_api_info()|.
|
reported by |--api-info| or |nvim_get_api_info()|.
|
||||||
|
• |nvim_open_win()| supports a `mouse` field that allows configuring mouse
|
||||||
|
interaction with the window separately from `focusable` field.
|
||||||
• Renamed `nvim__id_dictionary` (unsupported/experimental API) to
|
• Renamed `nvim__id_dictionary` (unsupported/experimental API) to
|
||||||
`nvim__id_dict`.
|
`nvim__id_dict`.
|
||||||
|
|
||||||
|
@ -610,11 +610,12 @@ tabs.
|
|||||||
size). If the window was previously hidden, it should now be shown
|
size). If the window was previously hidden, it should now be shown
|
||||||
again.
|
again.
|
||||||
|
|
||||||
["win_float_pos", grid, win, anchor, anchor_grid, anchor_row, anchor_col, focusable, zindex] ~
|
["win_float_pos", grid, win, anchor, anchor_grid, anchor_row, anchor_col, mouse_enabled, zindex] ~
|
||||||
Display or reconfigure floating window `win`. The window should be
|
Display or reconfigure floating window `win`. The window should be
|
||||||
displayed above another grid `anchor_grid` at the specified position
|
displayed above another grid `anchor_grid` at the specified position
|
||||||
`anchor_row` and `anchor_col`. For the meaning of `anchor` and more
|
`anchor_row` and `anchor_col`. For the meaning of `anchor` and more details
|
||||||
details of positioning, see |nvim_open_win()|.
|
of positioning, see |nvim_open_win()|. `mouse_enabled` is true if the
|
||||||
|
window can receive mouse events.
|
||||||
|
|
||||||
["win_external_pos", grid, win] ~
|
["win_external_pos", grid, win] ~
|
||||||
Display or reconfigure external window `win`. The window should be
|
Display or reconfigure external window `win`. The window should be
|
||||||
|
7
runtime/lua/vim/_meta/api.lua
generated
7
runtime/lua/vim/_meta/api.lua
generated
@ -1767,7 +1767,12 @@ function vim.api.nvim_open_term(buffer, opts) end
|
|||||||
--- fractional.
|
--- fractional.
|
||||||
--- - focusable: Enable focus by user actions (wincmds, mouse events).
|
--- - focusable: Enable focus by user actions (wincmds, mouse events).
|
||||||
--- Defaults to true. Non-focusable windows can be entered by
|
--- Defaults to true. Non-focusable windows can be entered by
|
||||||
--- `nvim_set_current_win()`.
|
--- `nvim_set_current_win()`, or, when the `mouse` field is set to true,
|
||||||
|
--- by mouse events.
|
||||||
|
--- - mouse: Specify how this window interacts with mouse events.
|
||||||
|
--- Defaults to `focusable` value.
|
||||||
|
--- - If false, mouse events pass through this window.
|
||||||
|
--- - If true, mouse events interact with this window normally.
|
||||||
--- - external: GUI should display the window as an external
|
--- - external: GUI should display the window as an external
|
||||||
--- top-level window. Currently accepts no other positioning
|
--- top-level window. Currently accepts no other positioning
|
||||||
--- configuration together with this.
|
--- configuration together with this.
|
||||||
|
1
runtime/lua/vim/_meta/api_keysets.lua
generated
1
runtime/lua/vim/_meta/api_keysets.lua
generated
@ -295,6 +295,7 @@ error('Cannot require a meta file')
|
|||||||
--- @field bufpos? any[]
|
--- @field bufpos? any[]
|
||||||
--- @field external? boolean
|
--- @field external? boolean
|
||||||
--- @field focusable? boolean
|
--- @field focusable? boolean
|
||||||
|
--- @field mouse? boolean
|
||||||
--- @field vertical? boolean
|
--- @field vertical? boolean
|
||||||
--- @field zindex? integer
|
--- @field zindex? integer
|
||||||
--- @field border? any
|
--- @field border? any
|
||||||
|
@ -119,6 +119,7 @@ typedef struct {
|
|||||||
Array bufpos;
|
Array bufpos;
|
||||||
Boolean external;
|
Boolean external;
|
||||||
Boolean focusable;
|
Boolean focusable;
|
||||||
|
Boolean mouse;
|
||||||
Boolean vertical;
|
Boolean vertical;
|
||||||
Integer zindex;
|
Integer zindex;
|
||||||
Object border;
|
Object border;
|
||||||
|
@ -102,7 +102,7 @@ void win_pos(Integer grid, Window win, Integer startrow, Integer startcol, Integ
|
|||||||
Integer height)
|
Integer height)
|
||||||
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
|
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
|
||||||
void win_float_pos(Integer grid, Window win, String anchor, Integer anchor_grid, Float anchor_row,
|
void win_float_pos(Integer grid, Window win, String anchor, Integer anchor_grid, Float anchor_row,
|
||||||
Float anchor_col, Boolean focusable, Integer zindex)
|
Float anchor_col, Boolean mouse_enabled, Integer zindex)
|
||||||
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
|
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
|
||||||
void win_external_pos(Integer grid, Window win)
|
void win_external_pos(Integer grid, Window win)
|
||||||
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
|
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
|
||||||
|
@ -129,7 +129,12 @@
|
|||||||
/// fractional.
|
/// fractional.
|
||||||
/// - focusable: Enable focus by user actions (wincmds, mouse events).
|
/// - focusable: Enable focus by user actions (wincmds, mouse events).
|
||||||
/// Defaults to true. Non-focusable windows can be entered by
|
/// Defaults to true. Non-focusable windows can be entered by
|
||||||
/// |nvim_set_current_win()|.
|
/// |nvim_set_current_win()|, or, when the `mouse` field is set to true,
|
||||||
|
/// by mouse events.
|
||||||
|
/// - mouse: Specify how this window interacts with mouse events.
|
||||||
|
/// Defaults to `focusable` value.
|
||||||
|
/// - If false, mouse events pass through this window.
|
||||||
|
/// - If true, mouse events interact with this window normally.
|
||||||
/// - external: GUI should display the window as an external
|
/// - external: GUI should display the window as an external
|
||||||
/// top-level window. Currently accepts no other positioning
|
/// top-level window. Currently accepts no other positioning
|
||||||
/// configuration together with this.
|
/// configuration together with this.
|
||||||
@ -714,6 +719,7 @@ Dict(win_config) nvim_win_get_config(Window window, Arena *arena, Error *err)
|
|||||||
PUT_KEY_X(rv, focusable, config->focusable);
|
PUT_KEY_X(rv, focusable, config->focusable);
|
||||||
PUT_KEY_X(rv, external, config->external);
|
PUT_KEY_X(rv, external, config->external);
|
||||||
PUT_KEY_X(rv, hide, config->hide);
|
PUT_KEY_X(rv, hide, config->hide);
|
||||||
|
PUT_KEY_X(rv, mouse, config->mouse);
|
||||||
|
|
||||||
if (wp->w_floating) {
|
if (wp->w_floating) {
|
||||||
PUT_KEY_X(rv, width, config->width);
|
PUT_KEY_X(rv, width, config->width);
|
||||||
@ -1202,6 +1208,11 @@ static bool parse_win_config(win_T *wp, Dict(win_config) *config, WinConfig *fco
|
|||||||
|
|
||||||
if (HAS_KEY_X(config, focusable)) {
|
if (HAS_KEY_X(config, focusable)) {
|
||||||
fconfig->focusable = config->focusable;
|
fconfig->focusable = config->focusable;
|
||||||
|
fconfig->mouse = config->focusable;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HAS_KEY_X(config, mouse)) {
|
||||||
|
fconfig->mouse = config->mouse;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HAS_KEY_X(config, zindex)) {
|
if (HAS_KEY_X(config, zindex)) {
|
||||||
|
@ -938,6 +938,7 @@ typedef struct {
|
|||||||
FloatRelative relative;
|
FloatRelative relative;
|
||||||
bool external;
|
bool external;
|
||||||
bool focusable;
|
bool focusable;
|
||||||
|
bool mouse;
|
||||||
WinSplit split;
|
WinSplit split;
|
||||||
int zindex;
|
int zindex;
|
||||||
WinStyle style;
|
WinStyle style;
|
||||||
@ -964,6 +965,7 @@ typedef struct {
|
|||||||
.row = 0, .col = 0, .anchor = 0, \
|
.row = 0, .col = 0, .anchor = 0, \
|
||||||
.relative = 0, .external = false, \
|
.relative = 0, .external = false, \
|
||||||
.focusable = true, \
|
.focusable = true, \
|
||||||
|
.mouse = true, \
|
||||||
.split = 0, \
|
.split = 0, \
|
||||||
.zindex = kZIndexFloatDefault, \
|
.zindex = kZIndexFloatDefault, \
|
||||||
.style = kWinStyleUnused, \
|
.style = kWinStyleUnused, \
|
||||||
|
@ -80,8 +80,8 @@ struct ScreenGrid {
|
|||||||
// whether the compositor should blend the grid with the background grid
|
// whether the compositor should blend the grid with the background grid
|
||||||
bool blending;
|
bool blending;
|
||||||
|
|
||||||
// whether the grid can be focused with mouse clicks.
|
// whether the grid interacts with mouse events.
|
||||||
bool focusable;
|
bool mouse_enabled;
|
||||||
|
|
||||||
// z-index: the order in the stack of grids.
|
// z-index: the order in the stack of grids.
|
||||||
int zindex;
|
int zindex;
|
||||||
|
@ -199,7 +199,7 @@ void msg_grid_validate(void)
|
|||||||
ui_call_grid_resize(msg_grid.handle, msg_grid.cols, msg_grid.rows);
|
ui_call_grid_resize(msg_grid.handle, msg_grid.cols, msg_grid.rows);
|
||||||
|
|
||||||
msg_scrolled_at_flush = msg_scrolled;
|
msg_scrolled_at_flush = msg_scrolled;
|
||||||
msg_grid.focusable = false;
|
msg_grid.mouse_enabled = false;
|
||||||
msg_grid_adj.target = &msg_grid;
|
msg_grid_adj.target = &msg_grid;
|
||||||
} else if (!should_alloc && msg_grid.chars) {
|
} else if (!should_alloc && msg_grid.chars) {
|
||||||
ui_comp_remove_grid(&msg_grid);
|
ui_comp_remove_grid(&msg_grid);
|
||||||
|
@ -1740,7 +1740,7 @@ static win_T *mouse_find_grid_win(int *gridp, int *rowp, int *colp)
|
|||||||
} else if (*gridp > 1) {
|
} else if (*gridp > 1) {
|
||||||
win_T *wp = get_win_by_grid_handle(*gridp);
|
win_T *wp = get_win_by_grid_handle(*gridp);
|
||||||
if (wp && wp->w_grid_alloc.chars
|
if (wp && wp->w_grid_alloc.chars
|
||||||
&& !(wp->w_floating && !wp->w_config.focusable)) {
|
&& !(wp->w_floating && !wp->w_config.mouse)) {
|
||||||
*rowp = MIN(*rowp - wp->w_grid.row_offset, wp->w_grid.rows - 1);
|
*rowp = MIN(*rowp - wp->w_grid.row_offset, wp->w_grid.rows - 1);
|
||||||
*colp = MIN(*colp - wp->w_grid.col_offset, wp->w_grid.cols - 1);
|
*colp = MIN(*colp - wp->w_grid.col_offset, wp->w_grid.cols - 1);
|
||||||
return wp;
|
return wp;
|
||||||
|
@ -275,7 +275,7 @@ ScreenGrid *ui_comp_mouse_focus(int row, int col)
|
|||||||
{
|
{
|
||||||
for (ssize_t i = (ssize_t)kv_size(layers) - 1; i > 0; i--) {
|
for (ssize_t i = (ssize_t)kv_size(layers) - 1; i > 0; i--) {
|
||||||
ScreenGrid *grid = kv_A(layers, i);
|
ScreenGrid *grid = kv_A(layers, i);
|
||||||
if (grid->focusable
|
if (grid->mouse_enabled
|
||||||
&& row >= grid->comp_row && row < grid->comp_row + grid->rows
|
&& row >= grid->comp_row && row < grid->comp_row + grid->rows
|
||||||
&& col >= grid->comp_col && col < grid->comp_col + grid->cols) {
|
&& col >= grid->comp_col && col < grid->comp_col + grid->cols) {
|
||||||
return grid;
|
return grid;
|
||||||
|
@ -857,7 +857,7 @@ void ui_ext_win_position(win_T *wp, bool validate)
|
|||||||
String anchor = cstr_as_string(float_anchor_str[c.anchor]);
|
String anchor = cstr_as_string(float_anchor_str[c.anchor]);
|
||||||
if (!c.hide) {
|
if (!c.hide) {
|
||||||
ui_call_win_float_pos(wp->w_grid_alloc.handle, wp->handle, anchor,
|
ui_call_win_float_pos(wp->w_grid_alloc.handle, wp->handle, anchor,
|
||||||
grid->handle, row, col, c.focusable,
|
grid->handle, row, col, c.mouse,
|
||||||
wp->w_grid_alloc.zindex);
|
wp->w_grid_alloc.zindex);
|
||||||
} else {
|
} else {
|
||||||
ui_call_win_hide(wp->w_grid_alloc.handle);
|
ui_call_win_hide(wp->w_grid_alloc.handle);
|
||||||
@ -889,7 +889,7 @@ void ui_ext_win_position(win_T *wp, bool validate)
|
|||||||
ui_comp_put_grid(&wp->w_grid_alloc, comp_row, comp_col,
|
ui_comp_put_grid(&wp->w_grid_alloc, comp_row, comp_col,
|
||||||
wp->w_height_outer, wp->w_width_outer, valid, false);
|
wp->w_height_outer, wp->w_width_outer, valid, false);
|
||||||
ui_check_cursor_grid(wp->w_grid_alloc.handle);
|
ui_check_cursor_grid(wp->w_grid_alloc.handle);
|
||||||
wp->w_grid_alloc.focusable = wp->w_config.focusable;
|
wp->w_grid_alloc.mouse_enabled = wp->w_config.mouse;
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
wp->w_grid_alloc.valid = false;
|
wp->w_grid_alloc.valid = false;
|
||||||
redraw_later(wp, UPD_NOT_VALID);
|
redraw_later(wp, UPD_NOT_VALID);
|
||||||
@ -4044,6 +4044,7 @@ void win_alloc_aucmd_win(int idx)
|
|||||||
fconfig.width = Columns;
|
fconfig.width = Columns;
|
||||||
fconfig.height = 5;
|
fconfig.height = 5;
|
||||||
fconfig.focusable = false;
|
fconfig.focusable = false;
|
||||||
|
fconfig.mouse = false;
|
||||||
aucmd_win[idx].auc_win = win_new_float(NULL, true, fconfig, &err);
|
aucmd_win[idx].auc_win = win_new_float(NULL, true, fconfig, &err);
|
||||||
aucmd_win[idx].auc_win->w_buffer->b_nwindows--;
|
aucmd_win[idx].auc_win->w_buffer->b_nwindows--;
|
||||||
RESET_BINDING(aucmd_win[idx].auc_win);
|
RESET_BINDING(aucmd_win[idx].auc_win);
|
||||||
|
@ -389,6 +389,7 @@ win_T *win_float_create(bool enter, bool new_buf)
|
|||||||
config.row = curwin->w_wrow;
|
config.row = curwin->w_wrow;
|
||||||
config.relative = kFloatRelativeEditor;
|
config.relative = kFloatRelativeEditor;
|
||||||
config.focusable = false;
|
config.focusable = false;
|
||||||
|
config.mouse = false;
|
||||||
config.anchor = 0; // NW
|
config.anchor = 0; // NW
|
||||||
config.noautocmd = true;
|
config.noautocmd = true;
|
||||||
config.hide = true;
|
config.hide = true;
|
||||||
|
@ -1278,7 +1278,7 @@ describe('float window', function()
|
|||||||
it('return their configuration', function()
|
it('return their configuration', function()
|
||||||
local buf = api.nvim_create_buf(false, false)
|
local buf = api.nvim_create_buf(false, false)
|
||||||
local win = api.nvim_open_win(buf, false, {relative='editor', width=20, height=2, row=3, col=5, zindex=60})
|
local win = api.nvim_open_win(buf, false, {relative='editor', width=20, height=2, row=3, col=5, zindex=60})
|
||||||
local expected = {anchor='NW', col=5, external=false, focusable=true, height=2, relative='editor', row=3, width=20, zindex=60, hide=false}
|
local expected = {anchor='NW', col=5, external=false, focusable=true, mouse=true, height=2, relative='editor', row=3, width=20, zindex=60, hide=false}
|
||||||
eq(expected, api.nvim_win_get_config(win))
|
eq(expected, api.nvim_win_get_config(win))
|
||||||
eq(true, exec_lua([[
|
eq(true, exec_lua([[
|
||||||
local expected, win = ...
|
local expected, win = ...
|
||||||
@ -1290,11 +1290,11 @@ describe('float window', function()
|
|||||||
end
|
end
|
||||||
return true]], expected, win))
|
return true]], expected, win))
|
||||||
|
|
||||||
eq({external=false, focusable=true, hide=false, relative='',split="left",width=40,height=6}, api.nvim_win_get_config(0))
|
eq({external=false, focusable=true, mouse=true, hide=false, relative='',split="left",width=40,height=6}, api.nvim_win_get_config(0))
|
||||||
|
|
||||||
if multigrid then
|
if multigrid then
|
||||||
api.nvim_win_set_config(win, {external=true, width=10, height=1})
|
api.nvim_win_set_config(win, {external=true, width=10, height=1})
|
||||||
eq({external=true,focusable=true,width=10,height=1,relative='',hide=false}, api.nvim_win_get_config(win))
|
eq({external=true,focusable=true,mouse=true,width=10,height=1,relative='',hide=false}, api.nvim_win_get_config(win))
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -3988,7 +3988,7 @@ describe('float window', function()
|
|||||||
]]}
|
]]}
|
||||||
end
|
end
|
||||||
eq({relative='win', width=12, height=1, bufpos={1,32}, anchor='NW', hide=false,
|
eq({relative='win', width=12, height=1, bufpos={1,32}, anchor='NW', hide=false,
|
||||||
external=false, col=0, row=1, win=firstwin, focusable=true, zindex=50}, api.nvim_win_get_config(win))
|
external=false, col=0, row=1, win=firstwin, focusable=true, mouse=true, zindex=50}, api.nvim_win_get_config(win))
|
||||||
|
|
||||||
feed('<c-e>')
|
feed('<c-e>')
|
||||||
if multigrid then
|
if multigrid then
|
||||||
@ -5606,7 +5606,7 @@ describe('float window', function()
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("focus by mouse", function()
|
local function test_float_mouse_focus()
|
||||||
if multigrid then
|
if multigrid then
|
||||||
api.nvim_input_mouse('left', 'press', '', 4, 0, 0)
|
api.nvim_input_mouse('left', 'press', '', 4, 0, 0)
|
||||||
screen:expect{grid=[[
|
screen:expect{grid=[[
|
||||||
@ -5660,10 +5660,18 @@ describe('float window', function()
|
|||||||
|
|
|
|
||||||
]])
|
]])
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it("focus by mouse (focusable=true)", function()
|
||||||
|
test_float_mouse_focus()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("focus by mouse (focusable=false)", function()
|
it("focus by mouse (focusable=false, mouse=true)", function()
|
||||||
api.nvim_win_set_config(win, {focusable=false})
|
api.nvim_win_set_config(win, {focusable=false, mouse=true})
|
||||||
|
test_float_mouse_focus()
|
||||||
|
end)
|
||||||
|
|
||||||
|
local function test_float_mouse_no_focus()
|
||||||
api.nvim_buf_set_lines(0, -1, -1, true, {"a"})
|
api.nvim_buf_set_lines(0, -1, -1, true, {"a"})
|
||||||
expected_pos[4][6] = false
|
expected_pos[4][6] = false
|
||||||
if multigrid then
|
if multigrid then
|
||||||
@ -5721,6 +5729,16 @@ describe('float window', function()
|
|||||||
|
|
|
|
||||||
]])
|
]])
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it("focus by mouse (focusable=false)", function()
|
||||||
|
api.nvim_win_set_config(win, {focusable=false})
|
||||||
|
test_float_mouse_no_focus()
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("focus by mouse (focusable=true, mouse=false)", function()
|
||||||
|
api.nvim_win_set_config(win, {mouse=false})
|
||||||
|
test_float_mouse_no_focus()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("j", function()
|
it("j", function()
|
||||||
|
Reference in New Issue
Block a user