patch 8.1.2240: popup window width changes when scrolling

Problem:    Popup window width changes when scrolling.
Solution:   Also adjust maxwidth when applying minwidth and there is a
            scrollbar.  Fix off-by-one error. (closes #5162)
diff --git a/src/popupwin.c b/src/popupwin.c
index 212076b..d6e6207 100644
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -1201,6 +1201,7 @@
 	allow_adjust_left = FALSE;
 	maxwidth = wp->w_maxwidth;
     }
+    minwidth = wp->w_minwidth;
 
     // start at the desired first line
     if (wp->w_firstline > 0)
@@ -1270,18 +1271,19 @@
 	    if (wp->w_maxwidth > 0 && wp->w_width > wp->w_maxwidth)
 		wp->w_width = wp->w_maxwidth;
 	}
-	// do not use the width of lines we're not going to show
-	if (wp->w_maxheight > 0
-		   && (wp->w_firstline >= 0
-			       ? lnum - wp->w_topline
-			       : wp->w_buffer->b_ml.ml_line_count - lnum)
-		       + 1 + wrapped > wp->w_maxheight)
-	    break;
 
 	if (wp->w_firstline < 0)
 	    --lnum;
 	else
 	    ++lnum;
+
+	// do not use the width of lines we're not going to show
+	if (wp->w_maxheight > 0
+		   && (wp->w_firstline >= 0
+			       ? lnum - wp->w_topline
+			       : wp->w_buffer->b_ml.ml_line_count - lnum)
+		       + wrapped >= wp->w_maxheight)
+	    break;
     }
 
     if (wp->w_firstline < 0)
@@ -1293,11 +1295,13 @@
     {
 	++right_extra;
 	++extra_width;
-	if (used_maxwidth)
-	    maxwidth -= 2;  // try to show the scrollbar
+	// make space for the scrollbar if needed, when lines wrap and when
+	// applying minwidth
+	if (maxwidth + right_extra >= maxspace
+		&& (used_maxwidth || (minwidth > 0 && wp->w_width < minwidth)))
+	    maxwidth -= wp->w_popup_padding[1] + 1;
     }
 
-    minwidth = wp->w_minwidth;
     if (wp->w_popup_title != NULL && *wp->w_popup_title != NUL)
     {
 	int title_len = vim_strsize(wp->w_popup_title) + 2 - extra_width;
diff --git a/src/testdir/dumps/Test_popupwin_previewpopup_4.dump b/src/testdir/dumps/Test_popupwin_previewpopup_4.dump
index bfaf9a5..b453c17 100644
--- a/src/testdir/dumps/Test_popupwin_previewpopup_4.dump
+++ b/src/testdir/dumps/Test_popupwin_previewpopup_4.dump
@@ -2,12 +2,12 @@
 |#|i|n|c|l|u|d|e| |"|X|h|e|a|d|e|r|.|h|"| @54
 |t|h|r|e@1| @69
 |f|o|u|r| @70
-|f|i|v|e| @27|╔+0#0000001#ffd7ff255| |X|t|a|g|f|i|l|e| |═@30|X
-|s+0#0000000#ffffff0|i|x| @28|║+0#0000001#ffd7ff255|2|7| @37| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
-|s+0#0000000#ffffff0|e|v|e|n| @26|║+0#0000001#ffd7ff255|t|h|i|s| |i|s| |a|n|o|t|h|e|r| |p|l|a|c|e| @18| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
-|f+0#0000000#ffffff0|i|n|d| |t|h|e|w|o|r|d| |s|o|m|e|w|h|e|r|e| @9|║+0#0000001#ffd7ff255|2|9| @37| +0#0000000#0000001|║+0#0000001#ffd7ff255
-|n+0#0000000#ffffff0|i|n|e| @27|║+0#0000001#ffd7ff255|3|0| @37| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
-|t+0#0000000#ffffff0|h|i|s| |i|s| |a|n|o|t|h|e|r| |w|o|r|d| @11|╚+0#0000001#ffd7ff255|═@40|⇲
+|f|i|v|e| @28|╔+0#0000001#ffd7ff255| |X|t|a|g|f|i|l|e| |═@29|X
+|s+0#0000000#ffffff0|i|x| @29|║+0#0000001#ffd7ff255|2|7| @36| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
+|s+0#0000000#ffffff0|e|v|e|n| @27|║+0#0000001#ffd7ff255|t|h|i|s| |i|s| |a|n|o|t|h|e|r| |p|l|a|c|e| @17| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
+|f+0#0000000#ffffff0|i|n|d| |t|h|e|w|o|r|d| |s|o|m|e|w|h|e|r|e| @10|║+0#0000001#ffd7ff255|2|9| @36| +0#0000000#0000001|║+0#0000001#ffd7ff255
+|n+0#0000000#ffffff0|i|n|e| @28|║+0#0000001#ffd7ff255|3|0| @36| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
+|t+0#0000000#ffffff0|h|i|s| |i|s| |a|n|o|t|h|e|r| |w|o|r|d| @12|╚+0#0000001#ffd7ff255|═@39|⇲
 |v+0#0000000#ffffff0|e|r|y| |l|o|n|g| |l|i|n|e| |w|h|e|r|e| |t|h|e| |w|o|r|d| |i|s| |a|l|s|o| >a|n|o|t|h|e|r| @29
 |~+0#4040ff13&| @73
 |~| @73
diff --git a/src/testdir/dumps/Test_popupwin_previewpopup_5.dump b/src/testdir/dumps/Test_popupwin_previewpopup_5.dump
index b167c69..2a3b972 100644
--- a/src/testdir/dumps/Test_popupwin_previewpopup_5.dump
+++ b/src/testdir/dumps/Test_popupwin_previewpopup_5.dump
@@ -2,12 +2,12 @@
 |#|i|n|c|l|u|d|e| |"|X|h|e|a|d|e|r|.|h|"| @54
 |t|h|r|e@1| @69
 |f|o|u|r| @70
-|f|i|v|e| @27|╔+0#0000001#ffd7ff255| |t|e|s|t|d|i|r|/|X|t|a|g|f|i|l|e| |═@22|X
-|s+0#0000000#ffffff0|i|x| @28|║+0#0000001#ffd7ff255|2|7| @37| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
-|s+0#0000000#ffffff0|e|v|e|n| @26|║+0#0000001#ffd7ff255|t|h|i|s| |i|s| |a|n|o|t|h|e|r| |p|l|a|c|e| @18| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
-|f+0#0000000#ffffff0|i|n|d| |t|h|e|w|o|r|d| |s|o|m|e|w|h|e|r|e| @9|║+0#0000001#ffd7ff255|2|9| @37| +0#0000000#0000001|║+0#0000001#ffd7ff255
-|n+0#0000000#ffffff0|i|n|e| @27|║+0#0000001#ffd7ff255|3|0| @37| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
-|t+0#0000000#ffffff0|h|i|s| |i|s| |a|n|o|t|h|e|r| |w|o|r|d| @11|╚+0#0000001#ffd7ff255|═@40|⇲
+|f|i|v|e| @28|╔+0#0000001#ffd7ff255| |t|e|s|t|d|i|r|/|X|t|a|g|f|i|l|e| |═@21|X
+|s+0#0000000#ffffff0|i|x| @29|║+0#0000001#ffd7ff255|2|7| @36| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
+|s+0#0000000#ffffff0|e|v|e|n| @27|║+0#0000001#ffd7ff255|t|h|i|s| |i|s| |a|n|o|t|h|e|r| |p|l|a|c|e| @17| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
+|f+0#0000000#ffffff0|i|n|d| |t|h|e|w|o|r|d| |s|o|m|e|w|h|e|r|e| @10|║+0#0000001#ffd7ff255|2|9| @36| +0#0000000#0000001|║+0#0000001#ffd7ff255
+|n+0#0000000#ffffff0|i|n|e| @28|║+0#0000001#ffd7ff255|3|0| @36| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
+|t+0#0000000#ffffff0|h|i|s| |i|s| |a|n|o|t|h|e|r| |w|o|r|d| @12|╚+0#0000001#ffd7ff255|═@39|⇲
 |v+0#0000000#ffffff0|e|r|y| |l|o|n|g| |l|i|n|e| |w|h|e|r|e| |t|h|e| |w|o|r|d| |i|s| |a|l|s|o| >a|n|o|t|h|e|r| @29
 |~+0#4040ff13&| @73
 |~| @73
diff --git a/src/testdir/dumps/Test_popupwin_previewpopup_7.dump b/src/testdir/dumps/Test_popupwin_previewpopup_7.dump
index f510b8b..add98bf 100644
--- a/src/testdir/dumps/Test_popupwin_previewpopup_7.dump
+++ b/src/testdir/dumps/Test_popupwin_previewpopup_7.dump
@@ -2,12 +2,12 @@
 |#|i|n|c|l|u|d|e| |"|X|h|e|a|d|e|r|.|h|"| @54
 |t|h|r|e@1| @69
 |f|o|u|r| @70
-|f|i|v|e| @27|╔+0#0000001#ffd7ff255| |X|t|a|g|f|i|l|e| |═@30|X
-|s+0#0000000#ffffff0|i|x| @28|║+0#0000001#ffd7ff255|2|0| @37| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
-|s+0#0000000#ffffff0|e|v|e|n| @26|║+0#0000001#ffd7ff255|t|h|e|w|o|r|d| |i|s| |h|e|r|e| @24| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
-|f+0#0000000#ffffff0|i|n|d| |t|h|e|w|o|r|d| |s|o|m|e|w|h|e|r|e| @9|║+0#0000001#ffd7ff255|2@1| @37| +0#0000000#0000001|║+0#0000001#ffd7ff255
-|n+0#0000000#ffffff0|i|n|e| @27|║+0#0000001#ffd7ff255|2|3| @37| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
-|t+0#0000000#ffffff0|h|i|s| |i|s| |a|n|o|t|h|e|r| |w|o|r|d| @11|╚+0#0000001#ffd7ff255|═@40|⇲
+|f|i|v|e| @28|╔+0#0000001#ffd7ff255| |X|t|a|g|f|i|l|e| |═@29|X
+|s+0#0000000#ffffff0|i|x| @29|║+0#0000001#ffd7ff255|2|0| @36| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
+|s+0#0000000#ffffff0|e|v|e|n| @27|║+0#0000001#ffd7ff255|t|h|e|w|o|r|d| |i|s| |h|e|r|e| @23| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
+|f+0#0000000#ffffff0|i|n|d| |t|h|e|w|o|r|d| |s|o|m|e|w|h|e|r|e| @10|║+0#0000001#ffd7ff255|2@1| @36| +0#0000000#0000001|║+0#0000001#ffd7ff255
+|n+0#0000000#ffffff0|i|n|e| @28|║+0#0000001#ffd7ff255|2|3| @36| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
+|t+0#0000000#ffffff0|h|i|s| |i|s| |a|n|o|t|h|e|r| |w|o|r|d| @12|╚+0#0000001#ffd7ff255|═@39|⇲
 |v+0#0000000#ffffff0|e|r|y| |l|o|n|g| |l|i|n|e| |w|h|e|r|e| |t|h|e| |w|o|r|d| |i|s| |a|l|s|o| >a|n|o|t|h|e|r| @29
 |~+0#4040ff13&| @73
 |~| @73
diff --git a/src/testdir/dumps/Test_popupwin_previewpopup_8.dump b/src/testdir/dumps/Test_popupwin_previewpopup_8.dump
index 6e88fff..c5e75e1 100644
--- a/src/testdir/dumps/Test_popupwin_previewpopup_8.dump
+++ b/src/testdir/dumps/Test_popupwin_previewpopup_8.dump
@@ -2,12 +2,12 @@
 |#|i|n|c|l|u|d|e| |"|X|h|e|a|d|e|r|.|h|"| @54
 |t|h|r|e@1| @69
 |f|o|u|r| @70
-|f|i|v|e| @27|╔+0#0000001#ffd7ff255| |X|h|e|a|d|e|r|.|h| |═@29|X
-|s+0#0000000#ffffff0|i|x| @28|║+0#0000001#ffd7ff255|1+0#e000002&|0| +0#0000001&@37| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
-|s+0#0000000#ffffff0|e|v|e|n| @26|║+0#0000001#ffd7ff255|s|e|a|r|c|h|e|d| |w|o|r|d| |i|s| |h|e|r|e| @18| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
-|f+0#0000000#ffffff0|i|n|d| |t|h|e|w|o|r|d| |s|o|m|e|w|h|e|r|e| @9|║+0#0000001#ffd7ff255|1+0#e000002&|2| +0#0000001&@37| +0#0000000#0000001|║+0#0000001#ffd7ff255
-|n+0#0000000#ffffff0|i|n|e| @27|║+0#0000001#ffd7ff255|1+0#e000002&|3| +0#0000001&@37| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
-|t+0#0000000#ffffff0|h|i|s| |i|s| |a|n|o|t|h|e|r| |w|o|r|d| @11|╚+0#0000001#ffd7ff255|═@40|⇲
+|f|i|v|e| @28|╔+0#0000001#ffd7ff255| |X|h|e|a|d|e|r|.|h| |═@28|X
+|s+0#0000000#ffffff0|i|x| @29|║+0#0000001#ffd7ff255|1+0#e000002&|0| +0#0000001&@36| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
+|s+0#0000000#ffffff0|e|v|e|n| @27|║+0#0000001#ffd7ff255|s|e|a|r|c|h|e|d| |w|o|r|d| |i|s| |h|e|r|e| @17| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
+|f+0#0000000#ffffff0|i|n|d| |t|h|e|w|o|r|d| |s|o|m|e|w|h|e|r|e| @10|║+0#0000001#ffd7ff255|1+0#e000002&|2| +0#0000001&@36| +0#0000000#0000001|║+0#0000001#ffd7ff255
+|n+0#0000000#ffffff0|i|n|e| @28|║+0#0000001#ffd7ff255|1+0#e000002&|3| +0#0000001&@36| +0#0000000#a8a8a8255|║+0#0000001#ffd7ff255
+|t+0#0000000#ffffff0|h|i|s| |i|s| |a|n|o|t|h|e|r| |w|o|r|d| @12|╚+0#0000001#ffd7ff255|═@39|⇲
 |v+0#0000000#ffffff0|e|r|y| |l|o|n|g| |l|i|n|e| |w|h|e|r|e| |t|h|e| |w|o|r|d| |i|s| |a|l|s|o| >a|n|o|t|h|e|r| @29
 |~+0#4040ff13&| @73
 |~| @73
diff --git a/src/testdir/dumps/Test_popupwin_scroll_11.dump b/src/testdir/dumps/Test_popupwin_scroll_11.dump
new file mode 100644
index 0000000..938f86a
--- /dev/null
+++ b/src/testdir/dumps/Test_popupwin_scroll_11.dump
@@ -0,0 +1,10 @@
+>1+0&#ffffff0| @73
+|2| @73
+|3| @73
+|4| @20|1+0#0000001#ffd7ff255| @28| +0#0000000#0000001| +0&#ffffff0@21
+|5| @20|2+0#0000001#ffd7ff255| @28| +0#0000000#0000001| +0&#ffffff0@21
+|6| @20|3+0#0000001#ffd7ff255| @28| +0#0000000#a8a8a8255| +0&#ffffff0@21
+|7| @20|4+0#0000001#ffd7ff255| @28| +0#0000000#a8a8a8255| +0&#ffffff0@21
+|8| @73
+|9| @73
+|:|c|a|l@1| |P|o|p|u|p|S|c|r|o|l@1|(|)| @37|1|,|1| @10|T|o|p| 
diff --git a/src/testdir/dumps/Test_popupwin_scroll_12.dump b/src/testdir/dumps/Test_popupwin_scroll_12.dump
new file mode 100644
index 0000000..9fa71c7
--- /dev/null
+++ b/src/testdir/dumps/Test_popupwin_scroll_12.dump
@@ -0,0 +1,10 @@
+>1+0&#ffffff0| @73
+|2| @73
+|3| @73
+|4| @20|2+0#0000001#ffd7ff255| @28| +0#0000000#a8a8a8255| +0&#ffffff0@21
+|5| @20|3+0#0000001#ffd7ff255| @28| +0#0000000#0000001| +0&#ffffff0@21
+|6| @20|4+0#0000001#ffd7ff255| @28| +0#0000000#0000001| +0&#ffffff0@21
+|7| @20|l+0#0000001#ffd7ff255|o|n|g| |l|i|n|e| |l|o|n|g| |l|i|n|e| |l|o|n|g| |l|i|n|e| | +0#0000000#a8a8a8255| +0&#ffffff0@21
+|8| @73
+|9| @73
+|:|c|a|l@1| |P|o|p|u|p|S|c|r|o|l@1|(|)| @37|1|,|1| @10|T|o|p| 
diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim
index 1c5bcb2..2dcd14d 100644
--- a/src/testdir/test_popupwin.vim
+++ b/src/testdir/test_popupwin.vim
@@ -1764,6 +1764,42 @@
       call popup_setoptions(g:winid, #{border: [], close: 'button'})
       call feedkeys("\<F5>\<LeftMouse>", "xt")
     endfunc
+    func Popup_filter(winid, key)
+      if a:key == 'j'
+	let line = popup_getoptions(a:winid).firstline
+	let nlines = line('$', a:winid)
+	let newline = line < nlines ? (line + 1) : nlines
+	call popup_setoptions(a:winid, #{firstline: newline})
+	return v:true
+      elseif a:key == 'x'
+	call popup_close(a:winid)
+	return v:true
+      endif
+    endfunc
+
+    func PopupScroll()
+      call popup_clear()
+      let text =<< trim END
+	  1
+	  2
+	  3
+	  4
+	  long line long line long line long line long line long line
+	  long line long line long line long line long line long line
+	  long line long line long line long line long line long line
+      END
+      call popup_create(text, #{
+	    \ minwidth: 30,
+	    \ maxwidth: 30,
+	    \ minheight: 4,
+	    \ maxheight: 4,
+	    \ firstline: 1,
+	    \ wrap: v:true,
+	    \ scrollbar: v:true,
+	    \ mapping: v:false,
+	    \ filter: funcref('Popup_filter')
+	    \ })
+    endfunc
     map <silent> <F3> :call test_setmouse(5, 36)<CR>
     map <silent> <F4> :call test_setmouse(4, 42)<CR>
     map <silent> <F5> :call test_setmouse(7, 42)<CR>
@@ -1811,6 +1847,15 @@
   call term_sendkeys(buf, ":\<CR>")
   call VerifyScreenDump(buf, 'Test_popupwin_scroll_10', {})
 
+  " check size with non-wrapping lines
+  call term_sendkeys(buf, ":call PopupScroll()\<CR>")
+  call VerifyScreenDump(buf, 'Test_popupwin_scroll_11', {})
+
+  " check size with wrapping lines
+  call term_sendkeys(buf, "j")
+  call VerifyScreenDump(buf, 'Test_popupwin_scroll_12', {})
+  call term_sendkeys(buf, "x")
+
   " clean up
   call StopVimInTerminal(buf)
   call delete('XtestPopupScroll')
diff --git a/src/version.c b/src/version.c
index d0f62e9..bd0390a 100644
--- a/src/version.c
+++ b/src/version.c
@@ -742,6 +742,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2240,
+/**/
     2239,
 /**/
     2238,