patch 9.2.0422: popup: leave stray char when scrollbar changes
Commit:
https://github.com/vim/vim/commit/ba85f88fe95db2daf3ea2542042af9e65308e2b8
Author: Yasuhiro Matsumoto <
matt...@gmail.com>
Date: Fri May 1 13:12:11 2026 +0000
patch 9.2.0422: popup: leave stray char when scrollbar changes
Problem: popup: leave stray char when scrollbar changes
(Maxim Kim, after v9.2.0112)
Solution: refresh popup mask when scrollbar visibility changes
(Yasuhiro Matsumoto)
popup_adjust_position() set popup_mask_refresh only on geometry
changes, missing the case where w_has_scrollbar flips. After
popup_settext() shrinks the buffer enough that the scrollbar
disappears, the cell that held the old border / scrollbar was
never repainted, leaving stray characters.
fixes: #20092
closes: #20098
Signed-off-by: Yasuhiro Matsumoto <
matt...@gmail.com>
Signed-off-by: Christian Brabandt <
c...@256bit.org>
diff --git a/src/popupwin.c b/src/popupwin.c
index f92081633..103daccd2 100644
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -1288,6 +1288,7 @@ popup_adjust_position(win_T *wp)
int org_height = wp->w_height;
int org_leftcol = wp->w_leftcol;
int org_leftoff = wp->w_popup_leftoff;
+ int org_has_scrollbar = wp->w_has_scrollbar;
int minwidth, minheight;
int maxheight = Rows;
int wantline = wp->w_wantline; // adjusted for textprop
@@ -1830,7 +1831,8 @@ popup_adjust_position(win_T *wp)
|| org_leftcol != wp->w_leftcol
|| org_leftoff != wp->w_popup_leftoff
|| org_width != wp->w_width
- || org_height != wp->w_height)
+ || org_height != wp->w_height
+ || org_has_scrollbar != wp->w_has_scrollbar)
{
redraw_win_later(wp, UPD_NOT_VALID);
if (wp->w_popup_flags & POPF_ON_CMDLINE)
diff --git a/src/testdir/dumps/Test_popup_settext_scrollbar_disappear_1.dump b/src/testdir/dumps/Test_popup_settext_scrollbar_disappear_1.dump
new file mode 100644
index 000000000..d11662fe7
--- /dev/null
+++ b/src/testdir/dumps/Test_popup_settext_scrollbar_disappear_1.dump
@@ -0,0 +1,15 @@
+> +0&#ffffff0@49
+|~+0#4040ff13&| @48
+|~| @2|╔+0#0000001#ffd7ff255|═@30|╗| +0#4040ff13#ffffff0@12
+|~| @2|║+0#0000001#ffd7ff255|h|e|l@1|o| |w|o|r|l|d| @18| +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@12
+|~| @2|║+0#0000001#ffd7ff255|h|e|l@1|o| |w|o|r|l|d| @18| +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@12
+|~| @2|║+0#0000001#ffd7ff255|h|e|l@1|o| |w|o|r|l|d| @18| +0#0000000#0000001|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@12
+|~| @2|║+0#0000001#ffd7ff255|h|e|l@1|o| |w|o|r|l|d| @18| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@12
+|~| @2|║+0#0000001#ffd7ff255|h|e|l@1|o| |w|o|r|l|d| @18| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@12
+|~| @2|║+0#0000001#ffd7ff255|h|e|l@1|o| |w|o|r|l|d| @18| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@12
+|~| @2|║+0#0000001#ffd7ff255|h|e|l@1|o| |w|o|r|l|d| @18| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@12
+|~| @2|║+0#0000001#ffd7ff255|h|e|l@1|o| |w|o|r|l|d| @18| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@12
+|~| @2|║+0#0000001#ffd7ff255|h|e|l@1|o| |w|o|r|l|d| @18| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@12
+|~| @2|║+0#0000001#ffd7ff255|h|e|l@1|o| |w|o|r|l|d| @18| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255| +0#4040ff13#ffffff0@12
+|~| @2|╚+0#0000001#ffd7ff255|═@30|╝| +0#4040ff13#ffffff0@12
+| +0#0000000&@31|0|,|0|-|1| @8|A|l@1|
diff --git a/src/testdir/dumps/Test_popup_settext_scrollbar_disappear_2.dump b/src/testdir/dumps/Test_popup_settext_scrollbar_disappear_2.dump
new file mode 100644
index 000000000..52dc32b8d
--- /dev/null
+++ b/src/testdir/dumps/Test_popup_settext_scrollbar_disappear_2.dump
@@ -0,0 +1,15 @@
+> +0&#ffffff0@49
+|~+0#4040ff13&| @48
+|~| @2|╔+0#0000001#ffd7ff255|═@29|╗| +0#4040ff13#ffffff0@13
+|~| @2|║+0#0000001#ffd7ff255|s|h|o|r|t| @24|║| +0#4040ff13#ffffff0@13
+|~| @2|║+0#0000001#ffd7ff255| +0#4040ff13&@29|║+0#0000001&| +0#4040ff13#ffffff0@13
+|~| @2|║+0#0000001#ffd7ff255| +0#4040ff13&@29|║+0#0000001&| +0#4040ff13#ffffff0@13
+|~| @2|║+0#0000001#ffd7ff255| +0#4040ff13&@29|║+0#0000001&| +0#4040ff13#ffffff0@13
+|~| @2|║+0#0000001#ffd7ff255| +0#4040ff13&@29|║+0#0000001&| +0#4040ff13#ffffff0@13
+|~| @2|║+0#0000001#ffd7ff255| +0#4040ff13&@29|║+0#0000001&| +0#4040ff13#ffffff0@13
+|~| @2|║+0#0000001#ffd7ff255| +0#4040ff13&@29|║+0#0000001&| +0#4040ff13#ffffff0@13
+|~| @2|║+0#0000001#ffd7ff255| +0#4040ff13&@29|║+0#0000001&| +0#4040ff13#ffffff0@13
+|~| @2|║+0#0000001#ffd7ff255| +0#4040ff13&@29|║+0#0000001&| +0#4040ff13#ffffff0@13
+|~| @2|║+0#0000001#ffd7ff255| +0#4040ff13&@29|║+0#0000001&| +0#4040ff13#ffffff0@13
+|~| @2|╚+0#0000001#ffd7ff255|═@29|╝| +0#4040ff13#ffffff0@13
+|:+0#0000000&|c|a|l@1| |p|o|p|u|p|_|s|e|t@1|e|x|t|(|g|:|p|,| |[|'|s|h|o|r|t|0|,|0|-|1| @8|A|l@1|
diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim
index 4ce6a7158..1bc9344df 100644
--- a/src/testdir/test_popupwin.vim
+++ b/src/testdir/test_popupwin.vim
@@ -2563,6 +2563,32 @@ func Test_popup_settext()
call StopVimInTerminal(buf)
endfunc
+func Test_popup_settext_scrollbar_disappear()
+ CheckScreendump
+
+ let lines =<< trim END
+ let g:p = popup_create(repeat(['hello world'], 30), #{
+ \ line: 3,
+ \ col: 5,
+ \ pos: 'topleft',
+ \ minheight: 10,
+ \ maxheight: 10,
+ \ minwidth: 30,
+ \ border: [1, 1, 1, 1],
+ \ })
+ END
+ call writefile(lines, 'XtestPopupScrollDisappear', 'D')
+ let buf = RunVimInTerminal('-S XtestPopupScrollDisappear', #{rows: 15, cols: 50})
+ call VerifyScreenDump(buf, 'Test_popup_settext_scrollbar_disappear_1', {})
+
+ " Shrinking the buffer makes the scrollbar disappear. The right border
+ " column must not leave stray characters where the scrollbar used to be.
+ call term_sendkeys(buf, ":call popup_settext(g:p, ['short'])\<CR>")
+ call VerifyScreenDump(buf, 'Test_popup_settext_scrollbar_disappear_2', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
func Test_popup_settext_getline()
let id = popup_create('', #{ tabpage: 0 })
call popup_settext(id, ['a','b'])
diff --git a/src/version.c b/src/version.c
index 11ae9897a..9a28bf20e 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 422,
/**/
421,
/**/