diff src/popupwin.c @ 17219:5169811b3044 v8.1.1609

patch 8.1.1609: the user cannot easily close a popup window commit https://github.com/vim/vim/commit/2e62b568e91c36adb16dbcc609665170f09f3845 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jun 30 18:07:00 2019 +0200 patch 8.1.1609: the user cannot easily close a popup window Problem: The user cannot easily close a popup window. Solution: Add the "close" property. (mostly by Masato Nishihata, closes #4601)
author Bram Moolenaar <Bram@vim.org>
date Sun, 30 Jun 2019 18:15:04 +0200
parents 11f3cf51d43b
children 09fa437d33d8
line wrap: on
line diff
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -180,6 +180,17 @@ popup_on_border(win_T *wp, int row, int 
 	    || (col == popup_width(wp) - 1 && wp->w_popup_border[1] > 0);
 }
 
+/*
+ * Return TRUE if "row"/"col" is on the "X" button of the popup.
+ * The values are relative to the top-left corner.
+ * Caller should check w_popup_close is POPCLOSE_BUTTON.
+ */
+    int
+popup_on_X_button(win_T *wp, int row, int col)
+{
+    return row == 0 && col == popup_width(wp) - 1;
+}
+
 // Values set when dragging a popup window starts.
 static int drag_start_row;
 static int drag_start_col;
@@ -384,6 +395,30 @@ apply_general_options(win_T *wp, dict_T 
     if (di != NULL)
 	wp->w_popup_drag = dict_get_number(dict, (char_u *)"drag");
 
+    di = dict_find(dict, (char_u *)"close", -1);
+    if (di != NULL)
+    {
+	int ok = TRUE;
+
+	if (di->di_tv.v_type == VAR_STRING && di->di_tv.vval.v_string != NULL)
+	{
+	    char_u  *s = di->di_tv.vval.v_string;
+
+	    if (STRCMP(s, "none") == 0)
+		wp->w_popup_close = POPCLOSE_NONE;
+	    else if (STRCMP(s, "button") == 0)
+		wp->w_popup_close = POPCLOSE_BUTTON;
+	    else if (STRCMP(s, "click") == 0)
+		wp->w_popup_close = POPCLOSE_CLICK;
+	    else
+		ok = FALSE;
+	}
+	else
+	    ok = FALSE;
+	if (!ok)
+	    semsg(_(e_invargNval), "close", tv_get_string(&di->di_tv));
+    }
+
     str = dict_get_string(dict, (char_u *)"highlight", FALSE);
     if (str != NULL)
 	set_string_option_direct_in_win(wp, (char_u *)"wincolor", -1,
@@ -1072,6 +1107,7 @@ popup_create(typval_T *argvars, typval_T
 
     // set default values
     wp->w_zindex = POPUPWIN_DEFAULT_ZINDEX;
+    wp->w_popup_close = POPCLOSE_NONE;
 
     if (type == TYPE_NOTIFICATION)
     {
@@ -1106,6 +1142,7 @@ popup_create(typval_T *argvars, typval_T
 	wp->w_zindex = POPUPWIN_NOTIFICATION_ZINDEX;
 	wp->w_minwidth = 20;
 	wp->w_popup_drag = 1;
+	wp->w_popup_close = POPCLOSE_CLICK;
 	for (i = 0; i < 4; ++i)
 	    wp->w_popup_border[i] = 1;
 	wp->w_popup_padding[1] = 1;
@@ -1242,6 +1279,19 @@ popup_close_and_callback(win_T *wp, typv
 }
 
 /*
+ * Close popup "wp" because of a mouse click.
+ */
+    void
+popup_close_for_mouse_click(win_T *wp)
+{
+    typval_T res;
+
+    res.v_type = VAR_NUMBER;
+    res.vval.v_number = -2;
+    popup_close_and_callback(wp, &res);
+}
+
+/*
  * In a filter: check if the typed key is a mouse event that is used for
  * dragging the popup.
  */
@@ -1816,6 +1866,10 @@ f_popup_getoptions(typval_T *argvars, ty
 		break;
 	    }
 
+	dict_add_string(dict, "close", (char_u *)(
+		    wp->w_popup_close == POPCLOSE_BUTTON ? "button"
+		    : wp->w_popup_close == POPCLOSE_CLICK ? "click" : "none"));
+
 # if defined(FEAT_TIMERS)
 	dict_add_number(dict, "time", wp->w_popup_timer != NULL
 				 ?  (long)wp->w_popup_timer->tr_interval : 0L);
@@ -2434,6 +2488,14 @@ update_popups(void (*win_update)(win_T *
 	    }
 	}
 
+	if (wp->w_popup_close == POPCLOSE_BUTTON)
+	{
+	    // close button goes on top of anything at the top-right corner
+	    buf[mb_char2bytes('X', buf)] = NUL;
+	    screen_puts(buf, wp->w_winrow, wp->w_wincol + total_width - 1,
+		      wp->w_popup_border[0] > 0 ? border_attr[0] : popup_attr);
+	}
+
 	update_popup_transparent(wp, 0);
 
 	// Back to the normal zindex.