commit d4f2b9050dc6028871eb4dbfb6500cd7b5c07890
parent 70d79794395659c7738ec07cb8d3727d21cc2aa5
Author: glepnir <glephunter@gmail.com>
Date: Wed, 23 Apr 2025 20:22:43 +0800
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.
Diffstat:
5 files changed, 225 insertions(+), 3 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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
@@ -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('<ESC>')
+
+ -- 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('<C-W><C-W>')
-- should keep on current window