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:
Sean Dewar
2023-07-24 11:56:26 +01:00
parent 472271199e
commit a47be0b2d9
3 changed files with 49 additions and 8 deletions

View File

@@ -5712,8 +5712,9 @@ void win_size_save(garray_T *gap)
{
ga_init(gap, (int)sizeof(int), 1);
ga_grow(gap, win_count() * 2 + 1);
// first entry is value of 'lines'
((int *)gap->ga_data)[gap->ga_len++] = Rows;
// first entry is the total lines available for windows
((int *)gap->ga_data)[gap->ga_len++] =
(int)ROWS_AVAIL + global_stl_height() - last_stl_height(false);
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
((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
// and 'lines' didn't change.
// and total lines available for windows didn't change.
// Does not free the growarray.
void win_size_restore(garray_T *gap)
FUNC_ATTR_NONNULL_ALL
{
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
// difficult to get right. The easy way out is to do it twice.
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)
{
// Don't make a difference between horizontal or vertical split.
last_status_rec(topframe, (p_ls == 2 || (p_ls == 1 && (morewin || !one_nonfloat()))),
global_stl_height() > 0);
last_status_rec(topframe, last_stl_height(morewin) > 0, global_stl_height() > 0);
}
// 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 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
/// the current number of windows.
int min_rows(void)