From 31c814a0ed0eca1822ecb0409b06bab24d1c4792 Mon Sep 17 00:00:00 2001 From: glepnir Date: Fri, 28 Nov 2025 02:23:46 +0800 Subject: [PATCH] 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. --- src/nvim/option.c | 1 + src/nvim/statusline.c | 15 ++---- src/nvim/winfloat.c | 14 +++-- test/functional/ui/statusline_spec.lua | 72 +++++++++++++++++++++++++- 4 files changed, 86 insertions(+), 16 deletions(-) diff --git a/src/nvim/option.c b/src/nvim/option.c index 531fc5758a..196077c047 100644 --- 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 index f14a9bf2ce..5b98954875 100644 --- 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 index 43ec966aed..0d253f1328 100644 --- 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 index 422e7b68f2..0273bfe2a9 100644 --- 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: