mirror of
https://github.com/neovim/neovim.git
synced 2024-12-24 13:15:09 -07:00
fix(window): prevent win_size_restore from changing cmdheight
Currently it only skips if `Rows` changed, but it's possible for the height of the usable area for windows to change (e.g: via `&ch`, `&stal` or `&ls`), which can cause the value of `&cmdheight` to change when the sizes are restored. This is a Vim bug, so I've submitted a PR there too. No telling when it'll be merged though, given the current lack of activity there. `ROWS_AVAIL` is convenient here, but also subtracts the `global_stl_height()`. Not ideal, as we also care about the height of the last statusline for other values of `&ls`. Meh. Introduce `last_stl_height` for getting the height of the last statusline and use it in `win_size_save/restore` and `last_status` (means `last_status_rec`'s `statusline` argument will now be true if `&ls` is 3, but that does not change the behaviour). Also corrects the logic in `comp_col` to not assume there's a last statusline if `&ls` is 1 and the last window is floating.
This commit is contained in:
parent
472271199e
commit
a47be0b2d9
@ -1137,7 +1137,7 @@ static void recording_mode(int attr)
|
|||||||
/// of 'ru_col'.
|
/// of 'ru_col'.
|
||||||
void comp_col(void)
|
void comp_col(void)
|
||||||
{
|
{
|
||||||
int last_has_status = (p_ls > 1 || (p_ls == 1 && !ONE_WINDOW));
|
bool last_has_status = last_stl_height(false) > 0;
|
||||||
|
|
||||||
sc_col = 0;
|
sc_col = 0;
|
||||||
ru_col = 0;
|
ru_col = 0;
|
||||||
|
@ -5712,8 +5712,9 @@ void win_size_save(garray_T *gap)
|
|||||||
{
|
{
|
||||||
ga_init(gap, (int)sizeof(int), 1);
|
ga_init(gap, (int)sizeof(int), 1);
|
||||||
ga_grow(gap, win_count() * 2 + 1);
|
ga_grow(gap, win_count() * 2 + 1);
|
||||||
// first entry is value of 'lines'
|
// first entry is the total lines available for windows
|
||||||
((int *)gap->ga_data)[gap->ga_len++] = Rows;
|
((int *)gap->ga_data)[gap->ga_len++] =
|
||||||
|
(int)ROWS_AVAIL + global_stl_height() - last_stl_height(false);
|
||||||
|
|
||||||
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
||||||
((int *)gap->ga_data)[gap->ga_len++] =
|
((int *)gap->ga_data)[gap->ga_len++] =
|
||||||
@ -5723,13 +5724,14 @@ void win_size_save(garray_T *gap)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Restore window sizes, but only if the number of windows is still the same
|
// Restore window sizes, but only if the number of windows is still the same
|
||||||
// and 'lines' didn't change.
|
// and total lines available for windows didn't change.
|
||||||
// Does not free the growarray.
|
// Does not free the growarray.
|
||||||
void win_size_restore(garray_T *gap)
|
void win_size_restore(garray_T *gap)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
if (win_count() * 2 + 1 == gap->ga_len
|
if (win_count() * 2 + 1 == gap->ga_len
|
||||||
&& ((int *)gap->ga_data)[0] == Rows) {
|
&& ((int *)gap->ga_data)[0] ==
|
||||||
|
(int)ROWS_AVAIL + global_stl_height() - last_stl_height(false)) {
|
||||||
// The order matters, because frames contain other frames, but it's
|
// The order matters, because frames contain other frames, but it's
|
||||||
// difficult to get right. The easy way out is to do it twice.
|
// difficult to get right. The easy way out is to do it twice.
|
||||||
for (int j = 0; j < 2; j++) {
|
for (int j = 0; j < 2; j++) {
|
||||||
@ -6993,8 +6995,7 @@ char *file_name_in_line(char *line, int col, int options, int count, char *rel_f
|
|||||||
void last_status(bool morewin)
|
void last_status(bool morewin)
|
||||||
{
|
{
|
||||||
// Don't make a difference between horizontal or vertical split.
|
// Don't make a difference between horizontal or vertical split.
|
||||||
last_status_rec(topframe, (p_ls == 2 || (p_ls == 1 && (morewin || !one_nonfloat()))),
|
last_status_rec(topframe, last_stl_height(morewin) > 0, global_stl_height() > 0);
|
||||||
global_stl_height() > 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove status line from window, replacing it with a horizontal separator if needed.
|
// Remove status line from window, replacing it with a horizontal separator if needed.
|
||||||
@ -7193,6 +7194,14 @@ int global_stl_height(void)
|
|||||||
return (p_ls == 3) ? STATUS_HEIGHT : 0;
|
return (p_ls == 3) ? STATUS_HEIGHT : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the height of the last window's statusline, or the global statusline if set.
|
||||||
|
///
|
||||||
|
/// @param morewin pretend there are two or more windows if true.
|
||||||
|
int last_stl_height(bool morewin)
|
||||||
|
{
|
||||||
|
return (p_ls > 1 || (p_ls == 1 && (!one_nonfloat() || morewin))) ? STATUS_HEIGHT : 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the minimal number of rows that is needed on the screen to display
|
/// Return the minimal number of rows that is needed on the screen to display
|
||||||
/// the current number of windows.
|
/// the current number of windows.
|
||||||
int min_rows(void)
|
int min_rows(void)
|
||||||
|
@ -984,14 +984,46 @@ it('tabline is not redrawn in Ex mode #24122', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
describe("cmdline height", function()
|
describe("cmdline height", function()
|
||||||
|
before_each(clear)
|
||||||
|
|
||||||
it("does not crash resized screen #14263", function()
|
it("does not crash resized screen #14263", function()
|
||||||
clear()
|
|
||||||
local screen = Screen.new(25, 10)
|
local screen = Screen.new(25, 10)
|
||||||
screen:attach()
|
screen:attach()
|
||||||
command('set cmdheight=9999')
|
command('set cmdheight=9999')
|
||||||
screen:try_resize(25, 5)
|
screen:try_resize(25, 5)
|
||||||
assert_alive()
|
assert_alive()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('unchanged when trying to restore window sizes', function()
|
||||||
|
command('set showtabline=0 cmdheight=2 laststatus=0')
|
||||||
|
feed('q:') -- Closing cmdwin tries to restore sizes
|
||||||
|
command('set cmdheight=1 | quit')
|
||||||
|
eq(1, eval('&cmdheight'))
|
||||||
|
|
||||||
|
command('set showtabline=2 cmdheight=3')
|
||||||
|
feed('q:')
|
||||||
|
command('set showtabline=0 | quit')
|
||||||
|
eq(3, eval('&cmdheight'))
|
||||||
|
|
||||||
|
command('set cmdheight=1 laststatus=2')
|
||||||
|
feed('q:')
|
||||||
|
command('set laststatus=0 | quit')
|
||||||
|
eq(1, eval('&cmdheight'))
|
||||||
|
|
||||||
|
command('set laststatus=2')
|
||||||
|
feed('q:')
|
||||||
|
command('set laststatus=1 | quit')
|
||||||
|
eq(1, eval('&cmdheight'))
|
||||||
|
|
||||||
|
command('set laststatus=2 | belowright vsplit | wincmd _')
|
||||||
|
local restcmds = eval('winrestcmd()')
|
||||||
|
feed('q:')
|
||||||
|
command('set laststatus=1 | quit')
|
||||||
|
-- As we have 2 windows, &ls = 1 should still have a statusline on the last
|
||||||
|
-- window. As such, the number of available rows hasn't changed and the window
|
||||||
|
-- sizes should be restored.
|
||||||
|
eq(restcmds, eval('winrestcmd()'))
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('cmdheight=0', function()
|
describe('cmdheight=0', function()
|
||||||
|
Loading…
Reference in New Issue
Block a user