Mercurial > vim
comparison src/window.c @ 34548:db67c09ccd53 v9.1.0175
patch 9.1.0175: wrong window positions with 'winfix{width,height}'
Commit: https://github.com/vim/vim/commit/5866bc3a0f54115d5982fdc09bdbe4c45069265a
Author: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Date: Wed Mar 13 20:17:24 2024 +0100
patch 9.1.0175: wrong window positions with 'winfix{width,height}'
Problem: winframe functions incorrectly recompute window positions if
the altframe wasn't adjacent to the closed frame, which is
possible if adjacent windows had 'winfix{width,height}' set.
Solution: recompute for windows within the parent of the altframe and
closed frame. Skip this (as before) if the altframe was
top/left, but only if adjacent to the closed frame, as
positions won't change in that case. Also correct the return
value documentation for win_screenpos. (Sean Dewar)
The issue revealed itself after removing the win_comp_pos call below
winframe_restore in win_splitmove. Similarly, wrong positions could result from
windows closed in other tabpages, as win_free_mem uses winframe_remove (at least
until it is entered later, where enter_tabpage calls win_comp_pos).
NOTE: As win_comp_pos handles only curtab, it's possible via other means for
positions in non-current tabpages to be wrong (e.g: after changing 'laststatus',
'showtabline', etc.). Given enter_tabpage recomputes it, maybe it's intentional
as an optimization? Should probably be documented in win_screenpos then, but I
won't address that here.
closes: #14191
Signed-off-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Wed, 13 Mar 2024 20:30:03 +0100 |
parents | c865c2f93a04 |
children | f9b510d3ed32 |
comparison
equal
deleted
inserted
replaced
34547:5ddbf662a64a | 34548:db67c09ccd53 |
---|---|
3491 // the space, and it is not flattened | 3491 // the space, and it is not flattened |
3492 { | 3492 { |
3493 frame_T *frp, *frp2, *frp3; | 3493 frame_T *frp, *frp2, *frp3; |
3494 frame_T *frp_close = win->w_frame; | 3494 frame_T *frp_close = win->w_frame; |
3495 win_T *wp; | 3495 win_T *wp; |
3496 int row, col; | |
3496 | 3497 |
3497 /* | 3498 /* |
3498 * If there is only one window there is nothing to remove. | 3499 * If there is only one window there is nothing to remove. |
3499 */ | 3500 */ |
3500 if (tp == NULL ? ONE_WINDOW : tp->tp_firstwin == tp->tp_lastwin) | 3501 if (tp == NULL ? ONE_WINDOW : tp->tp_firstwin == tp->tp_lastwin) |
3501 return NULL; | 3502 return NULL; |
3503 | |
3504 // Save the position of the containing frame (which will also contain the | |
3505 // altframe) before we remove anything, to recompute window positions later. | |
3506 wp = frame2win(frp_close->fr_parent); | |
3507 row = wp->w_winrow; | |
3508 col = wp->w_wincol; | |
3502 | 3509 |
3503 /* | 3510 /* |
3504 * Remove the window from its frame. | 3511 * Remove the window from its frame. |
3505 */ | 3512 */ |
3506 frp2 = win_altframe(win, tp); | 3513 frp2 = win_altframe(win, tp); |
3582 frame_new_width(frp2, frp2->fr_width + frp_close->fr_width, | 3589 frame_new_width(frp2, frp2->fr_width + frp_close->fr_width, |
3583 frp2 == frp_close->fr_next, FALSE); | 3590 frp2 == frp_close->fr_next, FALSE); |
3584 *dirp = 'h'; | 3591 *dirp = 'h'; |
3585 } | 3592 } |
3586 | 3593 |
3587 // If rows/columns go to a window below/right its positions need to be | 3594 // If the altframe wasn't adjacent and left/above, resizing it will have |
3588 // updated. Can only be done after the sizes have been updated. | 3595 // changed window positions within the parent frame. Recompute them. |
3589 if (frp2 == frp_close->fr_next) | 3596 if (frp2 != frp_close->fr_prev) |
3590 { | 3597 frame_comp_pos(frp_close->fr_parent, &row, &col); |
3591 int row = win->w_winrow; | |
3592 int col = win->w_wincol; | |
3593 | |
3594 frame_comp_pos(frp2, &row, &col); | |
3595 } | |
3596 | 3598 |
3597 if (unflat_altfr == NULL) | 3599 if (unflat_altfr == NULL) |
3598 frame_flatten(frp2); | 3600 frame_flatten(frp2); |
3599 else | 3601 else |
3600 *unflat_altfr = frp2; | 3602 *unflat_altfr = frp2; |
3664 */ | 3666 */ |
3665 static void | 3667 static void |
3666 winframe_restore(win_T *wp, int dir, frame_T *unflat_altfr) | 3668 winframe_restore(win_T *wp, int dir, frame_T *unflat_altfr) |
3667 { | 3669 { |
3668 frame_T *frp = wp->w_frame; | 3670 frame_T *frp = wp->w_frame; |
3669 int row = wp->w_winrow; | |
3670 int col = wp->w_wincol; | |
3671 | 3671 |
3672 // Put "wp"'s frame back where it was. | 3672 // Put "wp"'s frame back where it was. |
3673 if (frp->fr_prev != NULL) | 3673 if (frp->fr_prev != NULL) |
3674 frame_append(frp->fr_prev, frp); | 3674 frame_append(frp->fr_prev, frp); |
3675 else | 3675 else |
3689 // adjusts window sizes to fit restored statuslines/separators, if needed. | 3689 // adjusts window sizes to fit restored statuslines/separators, if needed. |
3690 if (dir == 'v') | 3690 if (dir == 'v') |
3691 { | 3691 { |
3692 frame_new_height(unflat_altfr, unflat_altfr->fr_height - frp->fr_height, | 3692 frame_new_height(unflat_altfr, unflat_altfr->fr_height - frp->fr_height, |
3693 unflat_altfr == frp->fr_next, FALSE); | 3693 unflat_altfr == frp->fr_next, FALSE); |
3694 row += frp->fr_height; | |
3695 } | 3694 } |
3696 else if (dir == 'h') | 3695 else if (dir == 'h') |
3697 { | 3696 { |
3698 frame_new_width(unflat_altfr, unflat_altfr->fr_width - frp->fr_width, | 3697 frame_new_width(unflat_altfr, unflat_altfr->fr_width - frp->fr_width, |
3699 unflat_altfr == frp->fr_next, FALSE); | 3698 unflat_altfr == frp->fr_next, FALSE); |
3700 col += frp->fr_width; | 3699 } |
3701 } | 3700 |
3702 | 3701 // Recompute window positions within the parent frame to restore them. |
3703 // If rows/columns went to a window below/right, its positions need to be | 3702 // Positions were unchanged if the altframe was adjacent and left/above. |
3704 // restored. Can only be done after the sizes have been updated. | 3703 if (unflat_altfr != frp->fr_prev) |
3705 if (unflat_altfr == frp->fr_next) | 3704 { |
3706 frame_comp_pos(unflat_altfr, &row, &col); | 3705 win_T *topleft = frame2win(frp->fr_parent); |
3706 int row = topleft->w_winrow; | |
3707 int col = topleft->w_wincol; | |
3708 | |
3709 frame_comp_pos(frp->fr_parent, &row, &col); | |
3710 } | |
3707 } | 3711 } |
3708 | 3712 |
3709 /* | 3713 /* |
3710 * Return a pointer to the frame that will receive the empty screen space that | 3714 * Return a pointer to the frame that will receive the empty screen space that |
3711 * is left over after "win" is closed. | 3715 * is left over after "win" is closed. |