patch 8.1.1303: not possible to hide a balloon

Problem:    Not possible to hide a balloon.
Solution:   Hide the balloon when balloon_show() is called with an empty
            string or list.  Add balloon_gettext().
diff --git a/src/beval.h b/src/beval.h
index 090c5fb..60cf1ab 100644
--- a/src/beval.h
+++ b/src/beval.h
@@ -75,7 +75,7 @@
 #ifdef FEAT_VARTABS
     int			*vts;		// vartabstop setting for this buffer
 #endif
-    char_u		*msg;
+    char_u		*msg;		// allocated: current text
 #ifdef FEAT_GUI_MSWIN
     void		*tofree;
 #endif
diff --git a/src/evalfunc.c b/src/evalfunc.c
index ca412f7..eaefccf 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -63,6 +63,7 @@
 static void f_atan2(typval_T *argvars, typval_T *rettv);
 #endif
 #ifdef FEAT_BEVAL
+static void f_balloon_gettext(typval_T *argvars, typval_T *rettv);
 static void f_balloon_show(typval_T *argvars, typval_T *rettv);
 # if defined(FEAT_BEVAL_TERM)
 static void f_balloon_split(typval_T *argvars, typval_T *rettv);
@@ -552,6 +553,7 @@
     {"atan2",		2, 2, f_atan2},
 #endif
 #ifdef FEAT_BEVAL
+    {"balloon_gettext",	0, 0, f_balloon_gettext},
     {"balloon_show",	1, 1, f_balloon_show},
 # if defined(FEAT_BEVAL_TERM)
     {"balloon_split",	1, 1, f_balloon_split},
@@ -1764,6 +1766,19 @@
  */
 #ifdef FEAT_BEVAL
     static void
+f_balloon_gettext(typval_T *argvars UNUSED, typval_T *rettv)
+{
+    rettv->v_type = VAR_STRING;
+    if (balloonEval != NULL)
+    {
+	if (balloonEval->msg == NULL)
+	    rettv->vval.v_string = NULL;
+	else
+	    rettv->vval.v_string = vim_strsave(balloonEval->msg);
+    }
+}
+
+    static void
 f_balloon_show(typval_T *argvars, typval_T *rettv UNUSED)
 {
     if (balloonEval != NULL)
@@ -1773,9 +1788,21 @@
 		&& !gui.in_use
 # endif
 	   )
-	    post_balloon(balloonEval, NULL, argvars[0].vval.v_list);
+	{
+	    list_T *l = argvars[0].vval.v_list;
+
+	    // empty list removes the balloon
+	    post_balloon(balloonEval, NULL,
+				       l == NULL || l->lv_len == 0 ? NULL : l);
+	}
 	else
-	    post_balloon(balloonEval, tv_get_string_chk(&argvars[0]), NULL);
+	{
+	    char_u *mesg = tv_get_string_chk(&argvars[0]);
+
+	    if (mesg != NULL)
+		// empty string removes the balloon
+		post_balloon(balloonEval, *mesg == NUL ? NULL : mesg, NULL);
+	}
     }
 }
 
diff --git a/src/gui_beval.c b/src/gui_beval.c
index e1e093f..f4309b8 100644
--- a/src/gui_beval.c
+++ b/src/gui_beval.c
@@ -117,7 +117,8 @@
 	beval->appContext = XtWidgetToApplicationContext((Widget)target);
 #endif
 	beval->showState = ShS_NEUTRAL;
-	beval->msg = mesg;
+	vim_free(beval->msg);
+	beval->msg = mesg == NULL ? NULL : vim_strsave(mesg);
 	beval->msgCB = mesgCB;
 	beval->clientData = clientData;
 
@@ -208,8 +209,9 @@
     void
 gui_mch_post_balloon(BalloonEval *beval, char_u *mesg)
 {
-    beval->msg = mesg;
-    if (mesg != NULL)
+    vim_free(beval->msg);
+    beval->msg = mesg == NULL ? NULL : vim_strsave(mesg);
+    if (beval->msg != NULL)
 	drawBalloon(beval);
     else
 	undrawBalloon(beval);
@@ -225,6 +227,7 @@
     void
 gui_mch_unpost_balloon(BalloonEval *beval)
 {
+    VIM_CLEAR(beval->msg);
     undrawBalloon(beval);
 }
 #endif
@@ -975,6 +978,7 @@
 	gtk_widget_show(beval->balloonShell);
 
 	beval->showState = ShS_SHOWING;
+	gui_mch_update();
     }
 }
 
diff --git a/src/gui_w32.c b/src/gui_w32.c
index 69212eb..8d28148 100644
--- a/src/gui_w32.c
+++ b/src/gui_w32.c
@@ -8506,6 +8506,15 @@
 {
     POINT   pt;
 
+    vim_free(beval->msg);
+    beval->msg = mesg == NULL ? NULL : vim_strsave(mesg);
+    if (beval->msg == NULL)
+    {
+	delete_tooltip(beval);
+	beval->showState = ShS_NEUTRAL;
+	return;
+    }
+
     // TRACE0("gui_mch_post_balloon {{{");
     if (beval->showState == ShS_SHOWING)
 	return;
diff --git a/src/popupmnu.c b/src/popupmnu.c
index 2639d97..0b002f5 100644
--- a/src/popupmnu.c
+++ b/src/popupmnu.c
@@ -1154,7 +1154,10 @@
     ui_remove_balloon();
 
     if (mesg == NULL && list == NULL)
+    {
+	pum_undisplay();
 	return;
+    }
     if (list != NULL)
     {
 	listitem_T  *li;
diff --git a/src/testdir/test_balloon.vim b/src/testdir/test_balloon.vim
index 966587c..57d8dcc 100644
--- a/src/testdir/test_balloon.vim
+++ b/src/testdir/test_balloon.vim
@@ -1,8 +1,7 @@
 " Tests for 'balloonevalterm'.
 
-if !has('balloon_eval_term') || has('gui_running')
-  finish
-endif
+" Tests that only work in the terminal.
+if has('balloon_eval_term') && !has('gui_running')
 
 source screendump.vim
 if !CanRunVimInTerminal()
@@ -53,3 +52,24 @@
   call StopVimInTerminal(buf)
   call delete('XTest_beval_visual')
 endfunc
+
+endif
+
+" Tests that only work in the GUI
+if has('gui_running')
+
+func Test_balloon_show_gui()
+  let msg = 'this this this this'
+  call balloon_show(msg)
+  call assert_equal(msg, balloon_gettext())
+  sleep 10m
+  call balloon_show('')
+
+  let msg = 'that that'
+  call balloon_show(msg)
+  call assert_equal(msg, balloon_gettext())
+  sleep 10m
+  call balloon_show('')
+endfunc
+
+endif
diff --git a/src/version.c b/src/version.c
index 96c72fa..8aef9dd 100644
--- a/src/version.c
+++ b/src/version.c
@@ -768,6 +768,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1303,
+/**/
     1302,
 /**/
     1301,