From d4f2b9050dc6028871eb4dbfb6500cd7b5c07890 Mon Sep 17 00:00:00 2001 From: glepnir Date: Wed, 23 Apr 2025 20:22:43 +0800 Subject: [PATCH] fix(float): cursor visible in "hidden" floating window #30866 Problem: Cursor is visible in "hidden" floating window. Solution: Hide cursor when curwin is a hidden floating window. Show cursor after returning to a normal (non-hidden) window. --- runtime/doc/api.txt | 3 +- runtime/lua/vim/_meta/api.lua | 3 +- src/nvim/api/win_config.c | 3 +- src/nvim/ui.c | 14 ++ test/functional/ui/float_spec.lua | 205 ++++++++++++++++++++++++++++++ 5 files changed, 225 insertions(+), 3 deletions(-) diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 9dbeaed310..07be740dd5 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -3554,7 +3554,8 @@ nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()* the duration of the call. • fixed: If true when anchor is NW or SW, the float window would be kept fixed even if the window would be truncated. - • hide: If true the floating window will be hidden. + • hide: If true the floating window will be hidden and the + cursor will be invisible when focused on it. • vertical: Split vertically |:vertical|. • split: Split direction: "left", "right", "above", "below". diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua index a205e9a446..8123ad4ceb 100644 --- a/runtime/lua/vim/_meta/api.lua +++ b/runtime/lua/vim/_meta/api.lua @@ -1848,7 +1848,8 @@ function vim.api.nvim_open_term(buffer, opts) end --- the call. --- - fixed: If true when anchor is NW or SW, the float window --- would be kept fixed even if the window would be truncated. ---- - hide: If true the floating window will be hidden. +--- - hide: If true the floating window will be hidden and the cursor will be invisible when +--- focused on it. --- - vertical: Split vertically `:vertical`. --- - split: Split direction: "left", "right", "above", "below". --- @return integer # |window-ID|, or 0 on error diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c index dcbadad799..6075ffca4f 100644 --- a/src/nvim/api/win_config.c +++ b/src/nvim/api/win_config.c @@ -201,7 +201,8 @@ /// the call. /// - fixed: If true when anchor is NW or SW, the float window /// would be kept fixed even if the window would be truncated. -/// - hide: If true the floating window will be hidden. +/// - hide: If true the floating window will be hidden and the cursor will be invisible when +/// focused on it. /// - vertical: Split vertically |:vertical|. /// - split: Split direction: "left", "right", "above", "below". /// diff --git a/src/nvim/ui.c b/src/nvim/ui.c index c2983430a0..64c952bd28 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -539,7 +539,21 @@ void ui_flush(void) if (!ui_active()) { return; } + + static bool was_busy = false; + cmdline_ui_flush(); + + if (State != MODE_CMDLINE && curwin->w_floating && curwin->w_config.hide) { + if (!was_busy) { + ui_call_busy_start(); + was_busy = true; + } + } else if (was_busy) { + ui_call_busy_stop(); + was_busy = false; + } + win_ui_flush(false); msg_ext_ui_flush(); msg_scroll_flush(); diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index fc0849b450..0e45dab94c 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -9585,6 +9585,211 @@ describe('float window', function() | ]]) end + + -- + -- Cursor visibility: + -- + -- Cursor is not visible in a hide=true floating window. + api.nvim_set_current_win(win) + if multigrid then + screen:expect({ + grid = [[ + ## grid 1 + [2:----------------------------------------]|*6 + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }|*5 + ## grid 3 + | + ## grid 4 (hidden) + {1: }| + {2:~ }| + ]], win_viewport={ + [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + }, win_viewport_margins={ + [2] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1000 + }, + [4] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1001 + } + } + }) + else + screen:expect({ + grid = [[ + | + {0:~ }|*5 + | + ]] + }) + end + + -- Show cursor if cmdline is entered while curwin is a hide=true floating window. + feed(':') + if multigrid then + screen:expect({ + grid = [[ + ## grid 1 + [2:----------------------------------------]|*6 + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }|*5 + ## grid 3 + :^ | + ## grid 4 (hidden) + {1: }| + {2:~ }| + ]], win_viewport={ + [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + }, win_viewport_margins={ + [2] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1000 + }, + [4] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1001 + } + } + }) + else + screen:expect({ + grid = [[ + | + {0:~ }|*5 + :^ | + ]] + }) + end + feed('') + + -- Show cursor after switching to a normal window (hide=false). + api.nvim_set_current_win(cwin) + if multigrid then + screen:expect({ + grid = [[ + ## grid 1 + [2:----------------------------------------]|*6 + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }|*5 + ## grid 3 + | + ## grid 4 (hidden) + {1: }| + {2:~ }| + ]], win_viewport={ + [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + }, win_viewport_margins={ + [2] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1000 + }, + [4] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1001 + } + } + }) + else + screen:expect({ + grid = [[ + ^ | + {0:~ }|*5 + | + ]] + }) + end + api.nvim_set_current_win(win) + local win1 = api.nvim_open_win(buf, false, {relative='editor', width=4, height=4, row=1, col=2}) + api.nvim_set_current_win(win1) + if multigrid then + screen:expect({ + grid = [[ + ## grid 1 + [2:----------------------------------------]|*6 + [3:----------------------------------------]| + ## grid 2 + | + {0:~ }|*5 + ## grid 3 + | + ## grid 4 (hidden) + {1: }| + {2:~ }| + ## grid 5 + {1:^ }| + {2:~ }|*3 + ]], float_pos={ + [5] = {1002, "NW", 1, 1, 2, true, 50, 1, 1, 2}; + }, win_viewport={ + [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [5] = {win = 1002, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + }, win_viewport_margins={ + [2] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1000 + }, + [4] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1001 + }, + [5] = { + bottom = 0, + left = 0, + right = 0, + top = 0, + win = 1002 + } + } + }) + else + screen:expect({ + grid = [[ + | + {0:~ }{1:^ }{0: }| + {0:~ }{2:~ }{0: }|*3 + {0:~ }| + | + ]] + }) + end + api.nvim_win_close(win1, true) + -- check window jump with hide feed('') -- should keep on current window