patch 9.1.1650: popup: window may not properly resize

Problem:  After scrolling a popup and then using popup_settext() with
          fewer lines, the popup fails to resize properly because
          firstline points beyond the new buffer content (lifepillar)
Solution: In popup_adjust_position(), validate that firstline doesn't
          exceed buffer line count and reset to 0 (auto-position) if it
          does (glepnir)

fixes: #14745
closes: #18031

Signed-off-by: glepnir <glephunter@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
glepnir
2025-08-18 21:14:48 +02:00
committed by Christian Brabandt
parent c7c10f8c11
commit 31170af24a
4 changed files with 68 additions and 1 deletions

View File

@ -1403,7 +1403,15 @@ popup_adjust_position(win_T *wp)
// start at the desired first line
if (wp->w_firstline > 0)
wp->w_topline = wp->w_firstline;
{
// If firstline is beyond the buffer content, reset it to auto-position.
// This can happen when the popup was scrolled and then the buffer
// content was changed to have fewer lines.
if (wp->w_firstline > wp->w_buffer->b_ml.ml_line_count)
wp->w_firstline = 0;
else
wp->w_topline = wp->w_firstline;
}
if (wp->w_topline < 1)
wp->w_topline = 1;
else if (wp->w_topline > wp->w_buffer->b_ml.ml_line_count)

View File

@ -0,0 +1,20 @@
> +0&#ffffff0@74
|~+0#4040ff13&| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~|╔+0#0000001#ffd7ff255|═@69|╗| +0#4040ff13#ffffff0@1
|~|║+0#0000001#ffd7ff255|a| @68|║| +0#4040ff13#ffffff0@1
|~|║+0#0000001#ffd7ff255|b| @68|║| +0#4040ff13#ffffff0@1
|~|║+0#0000001#ffd7ff255|c| @68|║| +0#4040ff13#ffffff0@1
|~|╚+0#0000001#ffd7ff255|═@69|╝| +0#4040ff13#ffffff0@1
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|:+0#0000000&|c|a|l@1| |p|o|p|u|p|_|s|e|t@1|e|x|t|(|1|0@1|1|,| |[|'|a|'|,| |'|b|'|,| |'|c|'|]|)| @14|0|,|0|-|1| @8|A|l@1|

View File

@ -4533,4 +4533,41 @@ func Test_popupwin_closing_buffer()
%bd!
endfunc
func Test_popupwin_firstline_after_scroll()
CheckScreendump
let lines =<< trim END
vim9script
def Popup(): number
return popup_create([], {
border: [1, 1, 1, 1],
close: 'click',
minheight: 1,
maxheight: 10,
scrollbar: true,
minwidth: &columns - 5,
maxwidth: &columns - 5,
})
enddef
var id = Popup()
g:popup_id = id
popup_settext(id, repeat(['abcd'], 20))
END
call writefile(lines, 'XtestPopupScroll_win', 'D')
let buf = RunVimInTerminal('-S XtestPopupScroll_win', {})
call TermWait(buf, 50)
call term_sendkeys(buf, ":call popup_setoptions(g:popup_id, {'firstline': 6})\<CR>")
call TermWait(buf, 50)
call term_sendkeys(buf, ":call popup_settext(g:popup_id, [])\<CR>")
call TermWait(buf, 50)
call term_sendkeys(buf, ":call popup_settext(1001, ['a', 'b', 'c'])\<CR>")
call TermWait(buf, 50)
call VerifyScreenDump(buf, 'Test_popupwin_first_after_scroll', {})
call StopVimInTerminal(buf)
endfunc
" vim: shiftwidth=2 sts=2

View File

@ -719,6 +719,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1650,
/**/
1649,
/**/