commit 31c814a0ed0eca1822ecb0409b06bab24d1c4792
parent 4daa8eb5abcad2e3cf4501f0e4fcaae90ec85b72
Author: glepnir <glephunter@gmail.com>
Date: Fri, 28 Nov 2025 02:23:46 +0800
fix(float): respect statusline=3, don't inherit local 'statusline' #36716
Problem: When creating floating window from existing window, the
window-local 'statusline' option is inherited, causing unwanted
statusline display. Additionally, with laststatus=3 (global statusline),
the early return skipped clearing wp->w_redr_status flag.
Solution: Clear inherited window-local 'statusline' in win_new_float
for style="minimal". Restructure win_redr_status to always clear the
flag before any early returns, and only render floating window statusline
when window-local 'statusline' is explicitly set. And respect 'laststatus'
option.
Diffstat:
4 files changed, 86 insertions(+), 16 deletions(-)
diff --git a/src/nvim/option.c b/src/nvim/option.c
@@ -2117,6 +2117,7 @@ static const char *did_set_laststatus(optset_T *args)
status_redraw_curbuf();
last_status(false); // (re)set last window status line.
+ win_float_update_statusline();
return NULL;
}
diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c
@@ -76,14 +76,8 @@ void win_redr_status(win_T *wp)
|| (wild_menu_showing != 0 && !ui_has(kUIWildmenu))) {
return;
}
- wp->w_redr_status = false;
-
- if (wp->w_floating && is_stl_global) {
- return;
- }
-
busy = true;
-
+ wp->w_redr_status = false;
if (wp->w_status_height == 0 && !(is_stl_global && wp == curwin)) {
// no status line, either global statusline is enabled or the window is a last window
redraw_cmdline = true;
@@ -91,7 +85,8 @@ void win_redr_status(win_T *wp)
// Don't redraw right now, do it later. Don't update status line when
// popup menu is visible and may be drawn over it
wp->w_redr_status = true;
- } else if (*p_stl != NUL || *wp->w_p_stl != NUL) {
+ } else if (*wp->w_p_stl != NUL
+ || (*p_stl != NUL && (!wp->w_floating || (is_stl_global && wp == curwin)))) {
// redraw custom status line
redraw_custom_statusline(wp);
}
@@ -234,7 +229,7 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler, bool u
StlClickRecord *tabtab;
bool is_stl_global = global_stl_height() > 0;
- ScreenGrid *grid = wp && wp->w_floating ? &wp->w_grid_alloc : &default_grid;
+ ScreenGrid *grid = wp && wp->w_floating && !is_stl_global ? &wp->w_grid_alloc : &default_grid;
// There is a tiny chance that this gets called recursively: When
// redrawing a status line triggers redrawing the ruler or tabline.
@@ -275,7 +270,7 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler, bool u
&wp->w_winbar_click_defs_size);
} else {
const bool in_status_line = wp->w_status_height != 0 || is_stl_global;
- if (wp->w_floating && !draw_ruler) {
+ if (wp->w_floating && !is_stl_global && !draw_ruler) {
row = wp->w_winrow_off + wp->w_view_height;
col = wp->w_wincol_off;
maxwidth = wp->w_view_width;
diff --git a/src/nvim/winfloat.c b/src/nvim/winfloat.c
@@ -70,6 +70,10 @@ win_T *win_new_float(win_T *wp, bool last, WinConfig fconfig, Error *err)
}
wp->w_p_wbr = empty_string_option;
}
+ if (wp->w_p_stl && wp->w_p_stl != empty_string_option) {
+ free_string_option(wp->w_p_stl);
+ wp->w_p_stl = empty_string_option;
+ }
} else {
assert(!last);
assert(!wp->w_floating);
@@ -104,7 +108,7 @@ win_T *win_new_float(win_T *wp, bool last, WinConfig fconfig, Error *err)
win_append(lastwin_nofloating(), wp, NULL);
}
wp->w_floating = true;
- wp->w_status_height = *wp->w_p_stl != NUL ? STATUS_HEIGHT : 0;
+ wp->w_status_height = *wp->w_p_stl != NUL && (p_ls == 1 || p_ls == 2) ? STATUS_HEIGHT : 0;
wp->w_winbar_height = 0;
wp->w_hsep_height = 0;
wp->w_vsep_width = 0;
@@ -164,13 +168,13 @@ void win_set_minimal_style(win_T *wp)
// statuscolumn: cleared
if (wp->w_p_stc != NULL && *wp->w_p_stc != NUL) {
free_string_option(wp->w_p_stc);
- wp->w_p_stc = xstrdup("");
+ wp->w_p_stc = empty_string_option;
}
// statusline: cleared (for floating windows)
if (wp->w_floating && wp->w_p_stl != NULL && *wp->w_p_stl != NUL) {
free_string_option(wp->w_p_stl);
- wp->w_p_stl = xstrdup("");
+ wp->w_p_stl = empty_string_option;
if (wp->w_status_height > 0) {
win_config_float(wp, wp->w_config);
}
@@ -190,7 +194,7 @@ int win_border_width(win_T *wp)
void win_config_float(win_T *wp, WinConfig fconfig)
{
// Process statusline changes before applying new height from config
- bool show_stl = *wp->w_p_stl != NUL;
+ bool show_stl = *wp->w_p_stl != NUL && (p_ls == 1 || p_ls == 2);
if (wp->w_status_height && !show_stl) {
win_remove_status_line(wp, false);
} else if (wp->w_status_height == 0 && show_stl) {
@@ -329,7 +333,7 @@ void win_float_update_statusline(void)
{
for (win_T *wp = lastwin; wp && wp->w_floating; wp = wp->w_prev) {
bool has_status = wp->w_status_height > 0;
- bool should_show = *wp->w_p_stl != NUL;
+ bool should_show = *wp->w_p_stl != NUL && (p_ls == 1 || p_ls == 2);
if (should_show != has_status) {
win_config_float(wp, wp->w_config);
}
diff --git a/test/functional/ui/statusline_spec.lua b/test/functional/ui/statusline_spec.lua
@@ -909,7 +909,7 @@ describe("'statusline' in floatwin", function()
})
end)
- it('controlled by ":setlocal statusline" and "style"', function()
+ it('controlled by ":setlocal statusline" and "style" and "laststatus"', function()
local buf = api.nvim_create_buf(false, false)
api.nvim_buf_set_lines(buf, 0, -1, false, { '1', '2', '3', '4' })
local cfg = {
@@ -996,5 +996,75 @@ describe("'statusline' in floatwin", function()
{3:[No Name] }|
|
]])
+ -- clear statusline when laststatus is 3
+ command('tabclose | set laststatus=2')
+ screen:expect([[
+ |
+ {1:~}┌──────────┐{1: }|
+ {1:~}│{4:^1 }│{1: }|
+ {1:~}│{4:2 }│{1: }|
+ {1:~}│{4:3 }│{1: }|
+ {1:~}│{4:4 }│{1: }|
+ {1:~}│{3:<Name] [+]}│{1: }|
+ {1:~}└──────────┘{1: }|
+ {1:~ }|*10
+ {2:[No Name] }|
+ |
+ ]])
+ command('set laststatus=0')
+ screen:expect([[
+ |
+ {1:~}┌──────────┐{1: }|
+ {1:~}│{4:^1 }│{1: }|
+ {1:~}│{4:2 }│{1: }|
+ {1:~}│{4:3 }│{1: }|
+ {1:~}│{4:4 }│{1: }|
+ {1:~}└──────────┘{1: }|
+ {1:~ }|*12
+ |
+ ]])
+
+ command('set laststatus=3')
+ screen:expect([[
+ |
+ {1:~}┌──────────┐{1: }|
+ {1:~}│{4:^1 }│{1: }|
+ {1:~}│{4:2 }│{1: }|
+ {1:~}│{4:3 }│{1: }|
+ {1:~}│{4:4 }│{1: }|
+ {1:~}└──────────┘{1: }|
+ {1:~ }|*11
+ {3:[No Name] [+] }|
+ |
+ ]])
+ api.nvim_buf_set_name(buf, 'stl_test')
+ screen:expect([[
+ |
+ {1:~}┌──────────┐{1: }|
+ {1:~}│{4:^1 }│{1: }|
+ {1:~}│{4:2 }│{1: }|
+ {1:~}│{4:3 }│{1: }|
+ {1:~}│{4:4 }│{1: }|
+ {1:~}└──────────┘{1: }|
+ {1:~ }|*11
+ {3:stl_test [+] }|
+ |
+ ]])
+ end)
+
+ it("clears inherited window-local 'statusline' on creation", function()
+ command('set laststatus=2')
+ api.nvim_set_option_value('statusline', 'global', {})
+ local curwin = api.nvim_get_current_win()
+ api.nvim_set_option_value('statusline', 'split-local', { win = curwin })
+ api.nvim_open_win(0, true, { relative = 'editor', row = 1, col = 1, height = 2, width = 4 })
+ screen:expect([[
+ |
+ {1:~}{4:^ }{1: }|
+ {1:~}{11:~ }{1: }|
+ {1:~ }|*15
+ {2:split-local }|
+ |
+ ]])
end)
end)