From 84d84e9b5befede3cdd2c14b5c11be19b442df0c Mon Sep 17 00:00:00 2001 From: glepnir Date: Tue, 3 Mar 2026 19:51:58 +0800 Subject: [PATCH] fix(window): style=minimal window loses local options when switching buffers #38138 Problem: 5943a81 skips saving window options in `buflist_altfpos` for style=minimal windows, which also prevents the window from restoring its own options when switching buffers. Solution: revert the change. In `get_winopts`, don't restore options from the `WinInfo` of style=minimal windows when reusing values for a different window. In `win_free`, clear `wi_optset` for minimal windows. --- src/nvim/buffer.c | 12 +++++++----- src/nvim/window.c | 5 +++++ test/functional/ui/float_spec.lua | 23 +++++++++++++++++++++++ 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index fed5b175b3..373cc6263b 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -599,7 +599,7 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i } buflist_setfpos(buf, win, win->w_cursor.lnum == 1 ? 0 : win->w_cursor.lnum, - win->w_cursor.col, win->w_config.style != kWinStyleMinimal); + win->w_cursor.col, true); } bufref_T bufref; @@ -2856,13 +2856,16 @@ void get_winopts(buf_T *buf) WinInfo *const wip = find_wininfo(buf, true, true); if (wip != NULL && wip->wi_win != curwin && wip->wi_win != NULL - && wip->wi_win->w_buffer == buf) { + && wip->wi_win->w_buffer == buf + && wip->wi_win->w_config.style != kWinStyleMinimal) { win_T *wp = wip->wi_win; copy_winopt(&wp->w_onebuf_opt, &curwin->w_onebuf_opt); curwin->w_fold_manual = wp->w_fold_manual; curwin->w_foldinvalid = true; cloneFoldGrowArray(&wp->w_folds, &curwin->w_folds); - } else if (wip != NULL && wip->wi_optset) { + } else if (wip != NULL && wip->wi_optset + && (wip->wi_win == NULL || wip->wi_win == curwin + || wip->wi_win->w_config.style != kWinStyleMinimal)) { copy_winopt(&wip->wi_opt, &curwin->w_onebuf_opt); curwin->w_fold_manual = wip->wi_fold_manual; curwin->w_foldinvalid = true; @@ -3215,8 +3218,7 @@ void buflist_slash_adjust(void) /// Also save the local window option values. void buflist_altfpos(win_T *win) { - buflist_setfpos(curbuf, win, win->w_cursor.lnum, win->w_cursor.col, - win->w_config.style != kWinStyleMinimal); + buflist_setfpos(curbuf, win, win->w_cursor.lnum, win->w_cursor.col, true); } /// Check that "ffname" is not the same file as current file. diff --git a/src/nvim/window.c b/src/nvim/window.c index b8284f3315..0b953feeb0 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -5549,6 +5549,11 @@ void win_free(win_T *wp, tabpage_T *tp) if (wip_wp) { wip_wp->wi_win = NULL; + // Discard saved options if the style is minimal. + if (wp->w_config.style == kWinStyleMinimal && wip_wp->wi_optset) { + clear_winopt(&wip_wp->wi_opt); + wip_wp->wi_optset = false; + } // If there already is an entry with "wi_win" set to NULL, only // the first entry with NULL will ever be used, delete the other one. if (pos_null < kv_size(buf->b_wininfo)) { diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 2cbaab2b85..09f5236d64 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -409,12 +409,18 @@ describe('float window', function() it("should re-apply 'style' when present and not leak to normal windows", function() local buf = api.nvim_create_buf(true, false) + local buf2 = api.nvim_create_buf(true, false) local float_opts = { style = 'minimal', relative = 'editor', row = 1, col = 1, width = 1, height = 1 } local float_win = api.nvim_open_win(buf, true, float_opts) api.nvim_set_option_value('number', true, { win = float_win }) float_opts.row = 2 api.nvim_win_set_config(float_win, float_opts) eq(false, api.nvim_get_option_value('number', { win = float_win })) + -- minimal float should preserve its own options when switching buffers + api.nvim_set_option_value('listchars', 'extends:…,precedes:…', { win = float_win, scope = 'local' }) + api.nvim_win_set_buf(float_win, buf2) + api.nvim_win_set_buf(float_win, buf) + eq('extends:…,precedes:…', api.nvim_get_option_value('listchars', { win = float_win, scope = 'local' })) -- closing the float should not leak minimal style options to normal windows api.nvim_win_close(float_win, true) api.nvim_set_option_value('number', true, { win = 0 }) @@ -422,6 +428,23 @@ describe('float window', function() eq(true, api.nvim_get_option_value('number', { win = 0 })) end) + it('style=minimal options should not leak to other windows via wininfo', function() + command('set noswapfile cursorline') + command('edit foo') + local foo_buf = api.nvim_get_current_buf() + fn.setline(1, 'foo') + command('edit bar') + local bar_buf = api.nvim_get_current_buf() + fn.setline(1, 'bar') + local float_opts = { style = 'minimal', relative = 'editor', row = 5, col = 5, width = 5, height = 5 } + local minimal_win = api.nvim_open_win(foo_buf, false, float_opts) + eq(false, api.nvim_get_option_value('cursorline', { win = minimal_win })) + api.nvim_win_set_buf(minimal_win, bar_buf) + eq('', api.nvim_win_get_config(0).relative) + command('split foo') + eq(true, api.nvim_get_option_value('cursorline', { win = 0 })) + end) + it("should not re-apply 'style' when missing", function() local float_opts = { style = 'minimal', relative = 'editor', row = 1, col = 1, width = 1, height = 1 } local float_win = api.nvim_open_win(0, true, float_opts)