patch 8.1.1525: cannot move a popup window with the mouse

Problem:    Cannot move a popup window with the mouse.
Solution:   Add the "drag" property and make it possible to drag a popup
            window by its border.
diff --git a/src/popupwin.c b/src/popupwin.c
index 5e444ae..f773958 100644
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -164,6 +164,68 @@
     }
 }
 
+/*
+ * Return TRUE if "row"/"col" is on the border of the popup.
+ * The values are relative to the top-left corner.
+ */
+    int
+popup_on_border(win_T *wp, int row, int col)
+{
+    return (row == 0 && wp->w_popup_border[0] > 0)
+	    || (row == popup_height(wp) - 1 && wp->w_popup_border[2] > 0)
+	    || (col == 0 && wp->w_popup_border[3] > 0)
+	    || (col == popup_width(wp) - 1 && wp->w_popup_border[1] > 0);
+}
+
+// Values set when dragging a popup window starts.
+static int drag_start_row;
+static int drag_start_col;
+static int drag_start_wantline;
+static int drag_start_wantcol;
+
+/*
+ * Mouse down on border of popup window: start dragging it.
+ * Uses mouse_col and mouse_row.
+ */
+    void
+popup_start_drag(win_T *wp)
+{
+    drag_start_row = mouse_row;
+    drag_start_col = mouse_col;
+    // TODO: handle using different corner
+    if (wp->w_wantline == 0)
+	drag_start_wantline = wp->w_winrow + 1;
+    else
+	drag_start_wantline = wp->w_wantline;
+    if (wp->w_wantcol == 0)
+	drag_start_wantcol = wp->w_wincol + 1;
+    else
+	drag_start_wantcol = wp->w_wantcol;
+}
+
+/*
+ * Mouse moved while dragging a popup window: adjust the window popup position.
+ */
+    void
+popup_drag(win_T *wp)
+{
+    // The popup may be closed before dragging stops.
+    if (!win_valid_popup(wp))
+	return;
+
+    wp->w_wantline = drag_start_wantline + (mouse_row - drag_start_row);
+    if (wp->w_wantline < 1)
+	wp->w_wantline = 1;
+    if (wp->w_wantline > Rows)
+	wp->w_wantline = Rows;
+    wp->w_wantcol = drag_start_wantcol + (mouse_col - drag_start_col);
+    if (wp->w_wantcol < 1)
+	wp->w_wantcol = 1;
+    if (wp->w_wantcol > Columns)
+	wp->w_wantcol = Columns;
+
+    popup_adjust_position(wp);
+}
 
 #if defined(FEAT_TIMERS)
     static void
@@ -237,6 +299,8 @@
 	wp->w_p_wrap = nr != 0;
     }
 
+    wp->w_popup_drag = dict_get_number(dict, (char_u *)"drag");
+
     di = dict_find(dict, (char_u *)"callback", -1);
     if (di != NULL)
     {
@@ -798,6 +862,7 @@
 	wp->w_popup_padding[3] = 1;
 	set_string_option_direct_in_win(wp, (char_u *)"wincolor", -1,
 				(char_u *)"WarningMsg", OPT_FREE|OPT_LOCAL, 0);
+	wp->w_popup_drag = 1;
     }
 
     // Deal with options.
diff --git a/src/proto/popupwin.pro b/src/proto/popupwin.pro
index 03d3729..eeabafa 100644
--- a/src/proto/popupwin.pro
+++ b/src/proto/popupwin.pro
@@ -1,4 +1,7 @@
 /* popupwin.c */
+int popup_on_border(win_T *wp, int row, int col);
+void popup_start_drag(win_T *wp);
+void popup_drag(win_T *wp);
 int popup_height(win_T *wp);
 int popup_width(win_T *wp);
 void popup_adjust_position(win_T *wp);
diff --git a/src/proto/window.pro b/src/proto/window.pro
index 1424c3d..94b9f08 100644
--- a/src/proto/window.pro
+++ b/src/proto/window.pro
@@ -3,6 +3,7 @@
 void get_wincmd_addr_type(char_u *arg, exarg_T *eap);
 int win_split(int size, int flags);
 int win_split_ins(int size, int flags, win_T *new_wp, int dir);
+int win_valid_popup(win_T *win);
 int win_valid(win_T *win);
 int win_valid_any_tab(win_T *win);
 int win_count(void);
diff --git a/src/structs.h b/src/structs.h
index da5ed2e..04e21a1 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -2909,6 +2909,7 @@
     linenr_T	w_popup_lnum;	    // close popup if cursor not on this line
     colnr_T	w_popup_mincol;	    // close popup if cursor before this col
     colnr_T	w_popup_maxcol;	    // close popup if cursor after this col
+    int		w_popup_drag;	    // allow moving the popup with the mouse
 
 # if defined(FEAT_TIMERS)
     timer_T	*w_popup_timer;	    // timer for closing popup window
diff --git a/src/ui.c b/src/ui.c
index 62d8ae7..08b3011 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -1002,7 +1002,7 @@
 
 /*
  * Start, continue or end a modeless selection.  Used when editing the
- * command-line and in the cmdline window.
+ * command-line, in the cmdline window and when the mouse is in a popup window.
  */
     void
 clip_modeless(int button, int is_click, int is_drag)
@@ -2841,7 +2841,8 @@
     static int  in_winbar = FALSE;
 #endif
 #ifdef FEAT_TEXT_PROP
-    static int  in_popup_win = FALSE;
+    static int   in_popup_win = FALSE;
+    static win_T *popup_dragwin = NULL;
 #endif
     static int	prev_row = -1;
     static int	prev_col = -1;
@@ -2869,6 +2870,9 @@
 	    flags &= ~(MOUSE_FOCUS | MOUSE_DID_MOVE);
 	dragwin = NULL;
 	did_drag = FALSE;
+#ifdef FEAT_TEXT_PROP
+	popup_dragwin = NULL;
+#endif
     }
 
     if ((flags & MOUSE_DID_MOVE)
@@ -2910,7 +2914,15 @@
 #ifdef FEAT_TEXT_PROP
 	// Continue a modeless selection in a popup window.
 	if (in_popup_win)
+	{
+	    if (popup_dragwin != NULL)
+	    {
+		// dragging a popup window
+		popup_drag(popup_dragwin);
+		return IN_UNKNOWN;
+	    }
 	    return IN_OTHER_WIN;
+	}
 #endif
 	return IN_BUFFER;
     }
@@ -2936,29 +2948,36 @@
 
     if (!(flags & MOUSE_FOCUS))
     {
-	if (row < 0 || col < 0)			/* check if it makes sense */
+	if (row < 0 || col < 0)			// check if it makes sense
 	    return IN_UNKNOWN;
 
-	/* find the window where the row is in */
+	// find the window where the row is in
 	wp = mouse_find_win(&row, &col, FIND_POPUP);
 	if (wp == NULL)
 	    return IN_UNKNOWN;
 	dragwin = NULL;
 
 #ifdef FEAT_TEXT_PROP
-	// Click in a popup window may start modeless selection, but not much
-	// else.
+	// Click in a popup window may start dragging or modeless selection,
+	// but not much else.
 	if (bt_popup(wp->w_buffer))
 	{
 	    on_sep_line = 0;
 	    in_popup_win = TRUE;
+	    if (wp->w_popup_drag && popup_on_border(wp, row, col))
+	    {
+		popup_dragwin = wp;
+		popup_start_drag(wp);
+		return IN_UNKNOWN;
+	    }
 # ifdef FEAT_CLIPBOARD
 	    return IN_OTHER_WIN;
 # else
 	    return IN_UNKNOWN;
 # endif
 	}
-	    in_popup_win = FALSE;
+	in_popup_win = FALSE;
+	popup_dragwin = NULL;
 #endif
 #ifdef FEAT_MENU
 	if (row == -1)
@@ -3127,9 +3146,17 @@
 	    return IN_OTHER_WIN;
 #endif
 #ifdef FEAT_TEXT_PROP
-	// Continue a modeless selection in a popup window.
 	if (in_popup_win)
+	{
+	    if (popup_dragwin != NULL)
+	    {
+		// dragging a popup window
+		popup_drag(popup_dragwin);
+		return IN_UNKNOWN;
+	    }
+	    // continue a modeless selection in a popup window
 	    return IN_OTHER_WIN;
+	}
 #endif
 
 	row -= W_WINROW(curwin);
diff --git a/src/version.c b/src/version.c
index 9835fcc..058dbc7 100644
--- a/src/version.c
+++ b/src/version.c
@@ -778,6 +778,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1525,
+/**/
     1524,
 /**/
     1523,
diff --git a/src/window.c b/src/window.c
index c15a861..4369129 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1371,7 +1371,7 @@
 /*
  * Return TRUE if "win" is a global popup or a popup in the current tab page.
  */
-    static int
+    int
 win_valid_popup(win_T *win UNUSED)
 {
 #ifdef FEAT_TEXT_PROP