diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-09-28 10:21:06 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-28 10:21:06 +0800 |
commit | 4f9311b759fff0371433fb5b5355fccb001d54e7 (patch) | |
tree | 616920f079d5be9b7ac0c2e07fda93eb8913654c | |
parent | 0f067cd34d09b38f9aaf2e1732d825e89b573077 (diff) | |
download | rneovim-4f9311b759fff0371433fb5b5355fccb001d54e7.tar.gz rneovim-4f9311b759fff0371433fb5b5355fccb001d54e7.tar.bz2 rneovim-4f9311b759fff0371433fb5b5355fccb001d54e7.zip |
fix(window): making float with title/footer non-float leaks memory (#30551)
-rw-r--r-- | src/nvim/api/win_config.c | 9 | ||||
-rw-r--r-- | src/nvim/window.c | 15 | ||||
-rw-r--r-- | src/nvim/winfloat.c | 8 | ||||
-rw-r--r-- | test/functional/api/window_spec.lua | 24 | ||||
-rw-r--r-- | test/functional/ui/float_spec.lua | 31 |
5 files changed, 60 insertions, 27 deletions
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c index b006f86a76..f63fdc5381 100644 --- a/src/nvim/api/win_config.c +++ b/src/nvim/api/win_config.c @@ -448,7 +448,7 @@ void nvim_win_set_config(Window window, Dict(win_config) *config, Error *err) } } } - win->w_config = fconfig; + merge_win_config(&win->w_config, fconfig); // If there's no "vertical" or "split" set, or if "split" is unchanged, // then we can just change the size of the window. @@ -1312,12 +1312,7 @@ static bool parse_win_config(win_T *wp, Dict(win_config) *config, WinConfig *fco return true; fail: - if (wp == NULL || fconfig->title_chunks.items != wp->w_config.title_chunks.items) { - clear_virttext(&fconfig->title_chunks); - } - if (wp == NULL || fconfig->footer_chunks.items != wp->w_config.footer_chunks.items) { - clear_virttext(&fconfig->footer_chunks); - } + merge_win_config(fconfig, wp != NULL ? wp->w_config : WIN_CONFIG_INIT); return false; #undef HAS_KEY_X } diff --git a/src/nvim/window.c b/src/nvim/window.c index f7d5ee92cd..d3280a3478 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -798,6 +798,19 @@ int win_fdccol_count(win_T *wp) return fdc[0] - '0'; } +/// Merges two window configs, freeing replaced fields if necessary. +void merge_win_config(WinConfig *dst, const WinConfig src) + FUNC_ATTR_NONNULL_ALL +{ + if (dst->title_chunks.items != src.title_chunks.items) { + clear_virttext(&dst->title_chunks); + } + if (dst->footer_chunks.items != src.footer_chunks.items) { + clear_virttext(&dst->footer_chunks); + } + *dst = src; +} + void ui_ext_win_position(win_T *wp, bool validate) { wp->w_pos_changed = false; @@ -1288,7 +1301,7 @@ win_T *win_split_ins(int size, int flags, win_T *new_wp, int dir, frame_T *to_fl new_frame(wp); // non-floating window doesn't store float config or have a border. - wp->w_config = WIN_CONFIG_INIT; + merge_win_config(&wp->w_config, WIN_CONFIG_INIT); CLEAR_FIELD(wp->w_border_adj); } diff --git a/src/nvim/winfloat.c b/src/nvim/winfloat.c index 0a90f638f3..f7e9128599 100644 --- a/src/nvim/winfloat.c +++ b/src/nvim/winfloat.c @@ -203,13 +203,7 @@ void win_config_float(win_T *wp, WinConfig fconfig) wp->w_config.border_hl_ids, sizeof fconfig.border_hl_ids) != 0); - if (fconfig.title_chunks.items != wp->w_config.title_chunks.items) { - clear_virttext(&wp->w_config.title_chunks); - } - if (fconfig.footer_chunks.items != wp->w_config.footer_chunks.items) { - clear_virttext(&wp->w_config.footer_chunks); - } - wp->w_config = fconfig; + merge_win_config(&wp->w_config, fconfig); bool has_border = wp->w_floating && wp->w_config.border; for (int i = 0; i < 4; i++) { diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua index 135b24fa5f..5ce93f9e04 100644 --- a/test/functional/api/window_spec.lua +++ b/test/functional/api/window_spec.lua @@ -1815,10 +1815,10 @@ describe('API/win', function() 'title/footer must be string or array', pcall_err(api.nvim_open_win, 0, false, { relative = 'editor', - row = 5, - col = 5, - height = 5, - width = 5, + row = 10, + col = 10, + height = 10, + width = 10, border = 'single', title = { { 'TITLE' } }, footer = 0, @@ -1831,10 +1831,10 @@ describe('API/win', function() 'title/footer must be string or array', pcall_err(api.nvim_open_win, 0, false, { relative = 'editor', - row = 5, - col = 5, - height = 5, - width = 5, + row = 10, + col = 10, + height = 10, + width = 10, border = 'single', title = 0, footer = { { 'FOOTER' } }, @@ -2840,10 +2840,10 @@ describe('API/win', function() before_each(function() win = api.nvim_open_win(0, false, { relative = 'editor', - row = 5, - col = 5, - height = 5, - width = 5, + row = 10, + col = 10, + height = 10, + width = 10, border = 'single', title = { { 'OLD_TITLE' } }, footer = { { 'OLD_FOOTER' } }, diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 52b46d0ecb..b2ed5f5a5f 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -2562,6 +2562,37 @@ describe('float window', function() end eq({{"🦄", ""}, {"BB", {"B0", "B1", ""}}}, api.nvim_win_get_config(win).title) eq({{"🦄", ""}, {"BB", {"B0", "B1", ""}}}, api.nvim_win_get_config(win).footer) + + -- making it a split should not leak memory + api.nvim_win_set_config(win, { vertical = true }) + if multigrid then + screen:expect{grid=[[ + ## grid 1 + [4:--------------------]{5:│}[2:-------------------]|*5 + {5:[No Name] [+] }{4:[No Name] }| + [3:----------------------------------------]| + ## grid 2 + ^ | + {0:~ }|*4 + ## grid 3 + | + ## grid 4 + halloj! | + BORDAA | + {0:~ }|*3 + ]], win_viewport={ + [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}; + [4] = {win = 1001, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0}; + }} + else + screen:expect{grid=[[ + halloj! {5:│}^ | + BORDAA {5:│}{0:~ }| + {0:~ }{5:│}{0:~ }|*3 + {5:[No Name] [+] }{4:[No Name] }| + | + ]]} + end end) it('terminates border on edge of viewport when window extends past viewport', function() |