mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
fix(wininfo): when freeing windows, free the lowest priority wininfo
On master (and also before #31539) closing a window could cause the used wininfo for a buffer to change. This is due to always removing the previous NULL wininfo when deleting a window, even if that wininfo had higher priority than the the deleted window's own wininfo. Instead delete the wininfo with lowest priority. This retains the memory saving efect while not affecting the effective value of window options and so on.
This commit is contained in:
parent
2d6f57b289
commit
59da82abd9
@ -5242,11 +5242,13 @@ void win_free(win_T *wp, tabpage_T *tp)
|
|||||||
// freed memory is re-used for another window.
|
// freed memory is re-used for another window.
|
||||||
FOR_ALL_BUFFERS(buf) {
|
FOR_ALL_BUFFERS(buf) {
|
||||||
WinInfo *wip_wp = NULL;
|
WinInfo *wip_wp = NULL;
|
||||||
|
size_t pos_wip = kv_size(buf->b_wininfo);
|
||||||
size_t pos_null = kv_size(buf->b_wininfo);
|
size_t pos_null = kv_size(buf->b_wininfo);
|
||||||
for (size_t i = 0; i < kv_size(buf->b_wininfo); i++) {
|
for (size_t i = 0; i < kv_size(buf->b_wininfo); i++) {
|
||||||
WinInfo *wip = kv_A(buf->b_wininfo, i);
|
WinInfo *wip = kv_A(buf->b_wininfo, i);
|
||||||
if (wip->wi_win == wp) {
|
if (wip->wi_win == wp) {
|
||||||
wip_wp = wip;
|
wip_wp = wip;
|
||||||
|
pos_wip = i;
|
||||||
} else if (wip->wi_win == NULL) {
|
} else if (wip->wi_win == NULL) {
|
||||||
pos_null = i;
|
pos_null = i;
|
||||||
}
|
}
|
||||||
@ -5254,11 +5256,12 @@ void win_free(win_T *wp, tabpage_T *tp)
|
|||||||
|
|
||||||
if (wip_wp) {
|
if (wip_wp) {
|
||||||
wip_wp->wi_win = NULL;
|
wip_wp->wi_win = NULL;
|
||||||
// If there already is an entry with "wi_win" set to NULL it
|
// If there already is an entry with "wi_win" set to NULL, only
|
||||||
// must be removed, it would never be used.
|
// the first entry with NULL will ever be used, delete the other one.
|
||||||
if (pos_null < kv_size(buf->b_wininfo)) {
|
if (pos_null < kv_size(buf->b_wininfo)) {
|
||||||
free_wininfo(kv_A(buf->b_wininfo, pos_null), buf);
|
size_t pos_delete = MAX(pos_null, pos_wip);
|
||||||
kv_shift(buf->b_wininfo, pos_null, 1);
|
free_wininfo(kv_A(buf->b_wininfo, pos_delete), buf);
|
||||||
|
kv_shift(buf->b_wininfo, pos_delete, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -488,6 +488,48 @@ describe('API/win', function()
|
|||||||
assert_alive()
|
assert_alive()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
describe('after closing', function()
|
||||||
|
local buf, win0, win1, win2
|
||||||
|
|
||||||
|
before_each(function()
|
||||||
|
win0 = api.nvim_get_current_win()
|
||||||
|
command('new')
|
||||||
|
buf = api.nvim_get_current_buf()
|
||||||
|
win1 = api.nvim_get_current_win()
|
||||||
|
command('set numberwidth=10')
|
||||||
|
command('split')
|
||||||
|
win2 = api.nvim_get_current_win()
|
||||||
|
command('set numberwidth=15')
|
||||||
|
command('enew')
|
||||||
|
api.nvim_set_current_win(win1)
|
||||||
|
command('normal ix')
|
||||||
|
command('enew')
|
||||||
|
api.nvim_set_current_win(win0)
|
||||||
|
eq(4, api.nvim_get_option_value('numberwidth', {}))
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- at this point buffer `buf` is current in no windows. Closing shouldn't affect its defaults
|
||||||
|
it('0 windows', function()
|
||||||
|
api.nvim_set_current_buf(buf)
|
||||||
|
eq(10, api.nvim_get_option_value('numberwidth', {}))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('1 window', function()
|
||||||
|
api.nvim_win_close(win1, false)
|
||||||
|
|
||||||
|
api.nvim_set_current_buf(buf)
|
||||||
|
eq(10, api.nvim_get_option_value('numberwidth', {}))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('2 windows', function()
|
||||||
|
api.nvim_win_close(win1, false)
|
||||||
|
api.nvim_win_close(win2, false)
|
||||||
|
|
||||||
|
api.nvim_set_current_buf(buf)
|
||||||
|
eq(10, api.nvim_get_option_value('numberwidth', {}))
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
it('returns values for unset local options', function()
|
it('returns values for unset local options', function()
|
||||||
eq(-1, api.nvim_get_option_value('scrolloff', { win = 0, scope = 'local' }))
|
eq(-1, api.nvim_get_option_value('scrolloff', { win = 0, scope = 'local' }))
|
||||||
end)
|
end)
|
||||||
|
Loading…
Reference in New Issue
Block a user