diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-10-20 22:18:26 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-20 22:18:26 +0800 |
commit | 9b8907d90508d7b66f025bbd1f5a48a78c5ce035 (patch) | |
tree | 28ba9bba6705cf19f8f3279c6b0b3ade41c81f4c | |
parent | dff684fdb3d2e787ac6d6fd49ec52ede604fd0ce (diff) | |
download | rneovim-9b8907d90508d7b66f025bbd1f5a48a78c5ce035.tar.gz rneovim-9b8907d90508d7b66f025bbd1f5a48a78c5ce035.tar.bz2 rneovim-9b8907d90508d7b66f025bbd1f5a48a78c5ce035.zip |
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.
-rw-r--r-- | runtime/doc/api.txt | 8 | ||||
-rw-r--r-- | runtime/doc/news.txt | 2 | ||||
-rw-r--r-- | runtime/doc/ui.txt | 7 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/api.lua | 7 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/api_keysets.lua | 1 | ||||
-rw-r--r-- | src/nvim/api/keysets_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/api/ui_events.in.h | 2 | ||||
-rw-r--r-- | src/nvim/api/win_config.c | 13 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 2 | ||||
-rw-r--r-- | src/nvim/grid_defs.h | 4 | ||||
-rw-r--r-- | src/nvim/message.c | 2 | ||||
-rw-r--r-- | src/nvim/mouse.c | 2 | ||||
-rw-r--r-- | src/nvim/ui_compositor.c | 2 | ||||
-rw-r--r-- | src/nvim/window.c | 5 | ||||
-rw-r--r-- | src/nvim/winfloat.c | 1 | ||||
-rw-r--r-- | test/functional/ui/float_spec.lua | 32 |
16 files changed, 70 insertions, 21 deletions
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index dee0324a5b..c77f38a693 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -3195,7 +3195,13 @@ nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()* be fractional. • focusable: Enable focus by user actions (wincmds, mouse 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 top-level window. Currently accepts no other positioning configuration together with this. diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index def66a0773..56104d9fdb 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -40,6 +40,8 @@ API 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 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 `nvim__id_dict`. diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt index d37cdfb9df..cb057a8fd2 100644 --- a/runtime/doc/ui.txt +++ b/runtime/doc/ui.txt @@ -610,11 +610,12 @@ tabs. size). If the window was previously hidden, it should now be shown 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 displayed above another grid `anchor_grid` at the specified position - `anchor_row` and `anchor_col`. For the meaning of `anchor` and more - details of positioning, see |nvim_open_win()|. + `anchor_row` and `anchor_col`. For the meaning of `anchor` and more details + of positioning, see |nvim_open_win()|. `mouse_enabled` is true if the + window can receive mouse events. ["win_external_pos", grid, win] ~ Display or reconfigure external window `win`. The window should be diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index c66b295d3a..8236cc7cf0 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -1767,7 +1767,12 @@ function vim.api.nvim_open_term(buffer, opts) end --- fractional. --- - focusable: Enable focus by user actions (wincmds, mouse events). --- 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 --- top-level window. Currently accepts no other positioning --- configuration together with this. diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua index 2fe5c32faf..bf184dee2d 100644 --- a/runtime/lua/vim/_meta/api_keysets.lua +++ b/runtime/lua/vim/_meta/api_keysets.lua @@ -295,6 +295,7 @@ error('Cannot require a meta file') --- @field bufpos? any[] --- @field external? boolean --- @field focusable? boolean +--- @field mouse? boolean --- @field vertical? boolean --- @field zindex? integer --- @field border? any diff --git a/src/nvim/api/keysets_defs.h b/src/nvim/api/keysets_defs.h index 552612dd13..96aabb851f 100644 --- a/src/nvim/api/keysets_defs.h +++ b/src/nvim/api/keysets_defs.h @@ -119,6 +119,7 @@ typedef struct { Array bufpos; Boolean external; Boolean focusable; + Boolean mouse; Boolean vertical; Integer zindex; Object border; diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h index 2bd8792d71..865e84ab91 100644 --- a/src/nvim/api/ui_events.in.h +++ b/src/nvim/api/ui_events.in.h @@ -102,7 +102,7 @@ void win_pos(Integer grid, Window win, Integer startrow, Integer startcol, Integ Integer height) FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY; 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; void win_external_pos(Integer grid, Window win) FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY; diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c index f63fdc5381..16811e0cd9 100644 --- a/src/nvim/api/win_config.c +++ b/src/nvim/api/win_config.c @@ -129,7 +129,12 @@ /// fractional. /// - focusable: Enable focus by user actions (wincmds, mouse events). /// 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 /// top-level window. Currently accepts no other positioning /// 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, external, config->external); PUT_KEY_X(rv, hide, config->hide); + PUT_KEY_X(rv, mouse, config->mouse); if (wp->w_floating) { 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)) { fconfig->focusable = config->focusable; + fconfig->mouse = config->focusable; + } + + if (HAS_KEY_X(config, mouse)) { + fconfig->mouse = config->mouse; } if (HAS_KEY_X(config, zindex)) { diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 6f059fc376..1fe5512708 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -938,6 +938,7 @@ typedef struct { FloatRelative relative; bool external; bool focusable; + bool mouse; WinSplit split; int zindex; WinStyle style; @@ -964,6 +965,7 @@ typedef struct { .row = 0, .col = 0, .anchor = 0, \ .relative = 0, .external = false, \ .focusable = true, \ + .mouse = true, \ .split = 0, \ .zindex = kZIndexFloatDefault, \ .style = kWinStyleUnused, \ diff --git a/src/nvim/grid_defs.h b/src/nvim/grid_defs.h index ac67f42fe0..19a79ff810 100644 --- a/src/nvim/grid_defs.h +++ b/src/nvim/grid_defs.h @@ -80,8 +80,8 @@ struct ScreenGrid { // whether the compositor should blend the grid with the background grid bool blending; - // whether the grid can be focused with mouse clicks. - bool focusable; + // whether the grid interacts with mouse events. + bool mouse_enabled; // z-index: the order in the stack of grids. int zindex; diff --git a/src/nvim/message.c b/src/nvim/message.c index 79e6bc8be7..151fb3d903 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -199,7 +199,7 @@ void msg_grid_validate(void) ui_call_grid_resize(msg_grid.handle, msg_grid.cols, msg_grid.rows); msg_scrolled_at_flush = msg_scrolled; - msg_grid.focusable = false; + msg_grid.mouse_enabled = false; msg_grid_adj.target = &msg_grid; } else if (!should_alloc && msg_grid.chars) { ui_comp_remove_grid(&msg_grid); diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index 884bc88d73..1289adfabb 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -1740,7 +1740,7 @@ static win_T *mouse_find_grid_win(int *gridp, int *rowp, int *colp) } else if (*gridp > 1) { win_T *wp = get_win_by_grid_handle(*gridp); 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); *colp = MIN(*colp - wp->w_grid.col_offset, wp->w_grid.cols - 1); return wp; diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c index 6e89894e0b..e28e8d4da7 100644 --- a/src/nvim/ui_compositor.c +++ b/src/nvim/ui_compositor.c @@ -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--) { ScreenGrid *grid = kv_A(layers, i); - if (grid->focusable + if (grid->mouse_enabled && row >= grid->comp_row && row < grid->comp_row + grid->rows && col >= grid->comp_col && col < grid->comp_col + grid->cols) { return grid; diff --git a/src/nvim/window.c b/src/nvim/window.c index d3280a3478..91a69c3ec4 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -857,7 +857,7 @@ void ui_ext_win_position(win_T *wp, bool validate) String anchor = cstr_as_string(float_anchor_str[c.anchor]); if (!c.hide) { 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); } else { 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, wp->w_height_outer, wp->w_width_outer, valid, false); 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) { wp->w_grid_alloc.valid = false; redraw_later(wp, UPD_NOT_VALID); @@ -4044,6 +4044,7 @@ void win_alloc_aucmd_win(int idx) fconfig.width = Columns; fconfig.height = 5; fconfig.focusable = false; + fconfig.mouse = false; aucmd_win[idx].auc_win = win_new_float(NULL, true, fconfig, &err); aucmd_win[idx].auc_win->w_buffer->b_nwindows--; RESET_BINDING(aucmd_win[idx].auc_win); diff --git a/src/nvim/winfloat.c b/src/nvim/winfloat.c index fdb65ad614..054ef07fc5 100644 --- a/src/nvim/winfloat.c +++ b/src/nvim/winfloat.c @@ -389,6 +389,7 @@ win_T *win_float_create(bool enter, bool new_buf) config.row = curwin->w_wrow; config.relative = kFloatRelativeEditor; config.focusable = false; + config.mouse = false; config.anchor = 0; // NW config.noautocmd = true; config.hide = true; diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 9b77cb4014..b76474fd58 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -1278,7 +1278,7 @@ describe('float window', function() it('return their configuration', function() 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 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(true, exec_lua([[ local expected, win = ... @@ -1290,11 +1290,11 @@ describe('float window', function() end 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 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) @@ -3988,7 +3988,7 @@ describe('float window', function() ]]} end 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>') if multigrid then @@ -5606,7 +5606,7 @@ describe('float window', function() end end) - it("focus by mouse", function() + local function test_float_mouse_focus() if multigrid then api.nvim_input_mouse('left', 'press', '', 4, 0, 0) screen:expect{grid=[[ @@ -5660,10 +5660,18 @@ describe('float window', function() | ]]) end + end + + it("focus by mouse (focusable=true)", function() + test_float_mouse_focus() end) - it("focus by mouse (focusable=false)", function() - api.nvim_win_set_config(win, {focusable=false}) + it("focus by mouse (focusable=false, mouse=true)", function() + 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"}) expected_pos[4][6] = false if multigrid then @@ -5721,6 +5729,16 @@ describe('float window', function() | ]]) 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) it("j", function() |