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.
This commit is contained in:
glepnir
2025-11-28 02:23:46 +08:00
committed by GitHub
parent 4daa8eb5ab
commit 31c814a0ed
4 changed files with 86 additions and 16 deletions

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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)