commit d131d67e67a8406fff2c3dc2f9a4aceb8ef36716
parent 249f305bbcddf10264835c5845035a42030d9184
Author: luukvbaal <luukvbaal@gmail.com>
Date: Mon, 16 Feb 2026 15:33:32 +0100
fix(float): clamp floating window above cmdline #37899
Problem: A float whose zindex is below the cmdline can be enlarged and
end up behind the cmdline.
Solution: Clamp height of such windows to not extend beyond 'cmdheight'.
Diffstat:
2 files changed, 92 insertions(+), 7 deletions(-)
diff --git a/src/nvim/winfloat.c b/src/nvim/winfloat.c
@@ -239,7 +239,8 @@ void win_config_float(win_T *wp, WinConfig fconfig)
}
if (!ui_has(kUIMultigrid)) {
- wp->w_height = MIN(wp->w_height, Rows - win_border_height(wp));
+ int above_ch = wp->w_config.zindex < kZIndexMessages ? (int)p_ch : 0;
+ wp->w_height = MIN(wp->w_height, Rows - win_border_height(wp) - above_ch);
wp->w_width = MIN(wp->w_width, Columns - win_border_width(wp));
}
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
@@ -5028,9 +5028,9 @@ describe('float window', function()
}
else
screen:expect([[
- {1:such } |
- {0:~ }{1:very }{0: }|
- ^ |
+ {1:very } |
+ {0:~ }{1:^float }{0: }|
+ |
]])
end
@@ -10924,7 +10924,7 @@ describe('float window', function()
{0:~ }{5:│}{2:~}{5:│}{2:~}{5:│┌──┐│}{2: }{5:││}{0: }|
{0:~ }{5:│}{2:~}{5:│}{2:~}{5:││}{1: }{5:││}{2: }{5:││}{0: }|
{0:~ }{5:│}{2:~}{5:│}{2:~}{5:││}{2:~ }{5:││}{2: }{5:││}{0: }|
- {0:~ }{5:│}{2:~}{5:│}{2:~}{5:└└──┘┘}{2: }{5:││}{0: }|
+ {0:~ }{5:└─└─└└──┘┘─┘┘}{0: }|
|
]])
end
@@ -10966,7 +10966,7 @@ describe('float window', function()
^ {5:┌─┌─┌────┐─┐┐} |
{0:~ }{5:│}{1: }{5:│}{1: }{5:│}{1: }{5:│}{1: }{5:││}{0: }|
{0:~ }{5:│}{2:~}{5:│}{2:~}{5:│}{2:~ }{5:│}{2: }{5:││}{0: }|*3
- {0:~ }{5:│}{2:~}{5:│}{2:~}{5:└────┘}{2: }{5:││}{0: }|
+ {0:~ }{5:└─└─└────┘─┘┘}{0: }|
|
]])
end
@@ -11002,7 +11002,8 @@ describe('float window', function()
screen:expect([[
^ {5:┌─┌────────┐┐} |
{0:~ }{5:│}{1: }{5:│}{1: }{5:││}{0: }|
- {0:~ }{5:│}{2:~}{5:│}{2:~ }{5:││}{0: }|*4
+ {0:~ }{5:│}{2:~}{5:│}{2:~ }{5:││}{0: }|*3
+ {0:~ }{5:└─└────────┘┘}{0: }|
|
]])
end
@@ -11730,6 +11731,89 @@ describe('float window', function()
screen:expect { mode = 'cmdline_normal' }
end
end)
+
+ it("window is not enlarged behind 'cmdheight'", function()
+ local opts = { relative = 'editor', width = 10, height = 4, row = 0, col = 0, zindex = 199 }
+ opts.border = 'single'
+ api.nvim_open_win(0, true, opts)
+ opts.zindex, opts.col = 200, 12
+ local above = api.nvim_open_win(0, false, opts)
+ command('echo "cmdline" | wincmd +')
+ if multigrid then
+ screen:expect({
+ grid = [[
+ ## grid 1
+ [2:----------------------------------------]|*6
+ [3:----------------------------------------]|
+ ## grid 2
+ |
+ {0:~ }|*5
+ ## grid 3
+ cmdline |
+ ## grid 4
+ {5:┌──────────┐}|
+ {5:│}{1:^ }{5:│}|
+ {5:│}{2:~ }{5:│}|*4
+ {5:└──────────┘}|
+ ## grid 5
+ {5:┌──────────┐}|
+ {5:│}{1: }{5:│}|
+ {5:│}{2:~ }{5:│}|*3
+ {5:└──────────┘}|
+ ]],
+ float_pos = {
+ [5] = { 1002, 'NW', 1, 0, 12, true, 200, 3, 0, 12 },
+ [4] = { 1001, 'NW', 1, 0, 0, true, 199, 1, 0, 0 },
+ },
+ })
+ else
+ screen:expect([[
+ {5:┌──────────┐┌──────────┐} |
+ {5:│}{1:^ }{5:││}{1: }{5:│}{0: }|
+ {5:│}{2:~ }{5:││}{2:~ }{5:│}{0: }|*3
+ {5:└──────────┘└──────────┘}{0: }|
+ cmdline |
+ ]])
+ end
+ api.nvim_set_current_win(above)
+ command('wincmd +')
+ if multigrid then
+ screen:expect({
+ grid = [[
+ ## grid 1
+ [2:----------------------------------------]|*6
+ [3:----------------------------------------]|
+ ## grid 2
+ |
+ {0:~ }|*5
+ ## grid 3
+ cmdline |
+ ## grid 4
+ {5:┌──────────┐}|
+ {5:│}{1: }{5:│}|
+ {5:│}{2:~ }{5:│}|*4
+ {5:└──────────┘}|
+ ## grid 5
+ {5:┌──────────┐}|
+ {5:│}{1:^ }{5:│}|
+ {5:│}{2:~ }{5:│}|*4
+ {5:└──────────┘}|
+ ]],
+ float_pos = {
+ [5] = { 1002, 'NW', 1, 0, 12, true, 200, 3, 0, 12 },
+ [4] = { 1001, 'NW', 1, 0, 0, true, 199, 1, 0, 0 },
+ },
+ })
+ else
+ screen:expect([[
+ {5:┌──────────┐┌──────────┐} |
+ {5:│}{1: }{5:││}{1:^ }{5:│}{0: }|
+ {5:│}{2:~ }{5:││}{2:~ }{5:│}{0: }|*3
+ {5:└──────────┘│}{2:~ }{5:│}{0: }|
+ cmdline {5:└──────────┘} |
+ ]])
+ end
+ end)
end
describe('with ext_multigrid and actual mouse grid', function()