patch 8.1.1645: cannot use a popup window for a balloon
Problem: Cannot use a popup window for a balloon.
Solution: Add popup_beval(). Add the "mousemoved" property. Add the
screenpos() function.
diff --git a/src/popupwin.c b/src/popupwin.c
index 02aa83e..401f1fb 100644
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -168,6 +168,35 @@
}
/*
+ * Used when popup options contain "mousemoved": set default moved values.
+ */
+ static void
+set_mousemoved_values(win_T *wp)
+{
+ wp->w_popup_mouse_row = mouse_row;
+ wp->w_popup_mouse_mincol = mouse_col;
+ wp->w_popup_mouse_maxcol = mouse_col;
+}
+
+/*
+ * Used when popup options contain "moved" with "word" or "WORD".
+ */
+ static void
+set_mousemoved_columns(win_T *wp, int flags)
+{
+ char_u *text;
+ int col;
+
+ if (find_word_under_cursor(mouse_row, mouse_col, TRUE, flags,
+ NULL, NULL, &text, &col) == OK)
+ {
+ wp->w_popup_mouse_mincol = col;
+ wp->w_popup_mouse_maxcol = col + STRLEN(text) - 1;
+ vim_free(text);
+ }
+}
+
+/*
* Return TRUE if "row"/"col" is on the border of the popup.
* The values are relative to the top-left corner.
*/
@@ -336,6 +365,53 @@
}
static void
+handle_moved_argument(win_T *wp, dictitem_T *di, int mousemoved)
+{
+ if (di->di_tv.v_type == VAR_STRING && di->di_tv.vval.v_string != NULL)
+ {
+ char_u *s = di->di_tv.vval.v_string;
+ int flags = 0;
+
+ if (STRCMP(s, "word") == 0)
+ flags = FIND_IDENT | FIND_STRING;
+ else if (STRCMP(s, "WORD") == 0)
+ flags = FIND_STRING;
+ else if (STRCMP(s, "expr") == 0)
+ flags = FIND_IDENT | FIND_STRING | FIND_EVAL;
+ else if (STRCMP(s, "any") != 0)
+ semsg(_(e_invarg2), s);
+ if (flags != 0)
+ {
+ if (mousemoved)
+ set_mousemoved_columns(wp, flags);
+ else
+ set_moved_columns(wp, flags);
+ }
+ }
+ else if (di->di_tv.v_type == VAR_LIST
+ && di->di_tv.vval.v_list != NULL
+ && di->di_tv.vval.v_list->lv_len == 2)
+ {
+ list_T *l = di->di_tv.vval.v_list;
+ int mincol = tv_get_number(&l->lv_first->li_tv);
+ int maxcol = tv_get_number(&l->lv_first->li_next->li_tv);
+
+ if (mousemoved)
+ {
+ wp->w_popup_mouse_mincol = mincol;
+ wp->w_popup_mouse_maxcol = maxcol;
+ }
+ else
+ {
+ wp->w_popup_mincol = mincol;
+ wp->w_popup_maxcol = maxcol;
+ }
+ }
+ else
+ semsg(_(e_invarg2), tv_get_string(&di->di_tv));
+}
+
+ static void
check_highlight(dict_T *dict, char *name, char_u **pval)
{
dictitem_T *di;
@@ -541,31 +617,14 @@
if (di != NULL)
{
set_moved_values(wp);
- if (di->di_tv.v_type == VAR_STRING && di->di_tv.vval.v_string != NULL)
- {
- char_u *s = di->di_tv.vval.v_string;
- int flags = 0;
+ handle_moved_argument(wp, di, FALSE);
+ }
- if (STRCMP(s, "word") == 0)
- flags = FIND_IDENT | FIND_STRING;
- else if (STRCMP(s, "WORD") == 0)
- flags = FIND_STRING;
- else if (STRCMP(s, "any") != 0)
- semsg(_(e_invarg2), s);
- if (flags != 0)
- set_moved_columns(wp, flags);
- }
- else if (di->di_tv.v_type == VAR_LIST
- && di->di_tv.vval.v_list != NULL
- && di->di_tv.vval.v_list->lv_len == 2)
- {
- list_T *l = di->di_tv.vval.v_list;
-
- wp->w_popup_mincol = tv_get_number(&l->lv_first->li_tv);
- wp->w_popup_maxcol = tv_get_number(&l->lv_first->li_next->li_tv);
- }
- else
- semsg(_(e_invarg2), tv_get_string(&di->di_tv));
+ di = dict_find(dict, (char_u *)"mousemoved", -1);
+ if (di != NULL)
+ {
+ set_mousemoved_values(wp);
+ handle_moved_argument(wp, di, TRUE);
}
di = dict_find(dict, (char_u *)"filter", -1);
@@ -956,6 +1015,7 @@
{
TYPE_NORMAL,
TYPE_ATCURSOR,
+ TYPE_BEVAL,
TYPE_NOTIFICATION,
TYPE_DIALOG,
TYPE_MENU
@@ -1137,17 +1197,33 @@
{
wp->w_popup_pos = POPPOS_BOTLEFT;
setcursor_mayforce(TRUE);
- wp->w_wantline = screen_screenrow();
+ wp->w_wantline = curwin->w_winrow + curwin->w_wrow;
if (wp->w_wantline == 0) // cursor in first line
{
wp->w_wantline = 2;
wp->w_popup_pos = POPPOS_TOPLEFT;
}
- wp->w_wantcol = screen_screencol() + 1;
+ wp->w_wantcol = curwin->w_wincol + curwin->w_wcol + 1;
set_moved_values(wp);
set_moved_columns(wp, FIND_STRING);
}
+ if (type == TYPE_BEVAL)
+ {
+ wp->w_popup_pos = POPPOS_BOTLEFT;
+
+ // by default use the mouse position
+ wp->w_wantline = mouse_row;
+ if (wp->w_wantline <= 0) // mouse on first line
+ {
+ wp->w_wantline = 2;
+ wp->w_popup_pos = POPPOS_TOPLEFT;
+ }
+ wp->w_wantcol = mouse_col + 1;
+ set_mousemoved_values(wp);
+ set_mousemoved_columns(wp, FIND_IDENT + FIND_STRING + FIND_EVAL);
+ }
+
// set default values
wp->w_zindex = POPUPWIN_DEFAULT_ZINDEX;
wp->w_popup_close = POPCLOSE_NONE;
@@ -1276,6 +1352,15 @@
}
/*
+ * popup_beval({text}, {options})
+ */
+ void
+f_popup_beval(typval_T *argvars, typval_T *rettv)
+{
+ popup_create(argvars, rettv, TYPE_BEVAL);
+}
+
+/*
* Invoke the close callback for window "wp" with value "result".
* Careful: The callback may make "wp" invalid!
*/
@@ -1334,6 +1419,48 @@
popup_close_and_callback(wp, &res);
}
+ static void
+check_mouse_moved(win_T *wp, win_T *mouse_wp)
+{
+ // Close the popup when all if these are true:
+ // - the mouse is not on this popup
+ // - "mousemoved" was used
+ // - the mouse is no longer on the same screen row or the mouse column is
+ // outside of the relevant text
+ if (wp != mouse_wp
+ && wp->w_popup_mouse_row != 0
+ && (wp->w_popup_mouse_row != mouse_row
+ || mouse_col < wp->w_popup_mouse_mincol
+ || mouse_col > wp->w_popup_mouse_maxcol))
+ {
+ typval_T res;
+
+ res.v_type = VAR_NUMBER;
+ res.vval.v_number = -2;
+ popup_close_and_callback(wp, &res);
+ }
+}
+
+/*
+ * Called when the mouse moved: may close a popup with "mousemoved".
+ */
+ void
+popup_handle_mouse_moved(void)
+{
+ win_T *wp;
+ win_T *mouse_wp;
+ int row = mouse_row;
+ int col = mouse_col;
+
+ // find the window where the mouse is in
+ mouse_wp = mouse_find_win(&row, &col, FIND_POPUP);
+
+ for (wp = first_popupwin; wp != NULL; wp = wp->w_next)
+ check_mouse_moved(wp, mouse_wp);
+ for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next)
+ check_mouse_moved(wp, mouse_wp);
+}
+
/*
* In a filter: check if the typed key is a mouse event that is used for
* dragging the popup.
@@ -1821,7 +1948,7 @@
}
/*
- * For popup_getoptions(): add a "moved" entry to "dict".
+ * For popup_getoptions(): add a "moved" and "mousemoved" entry to "dict".
*/
static void
get_moved_list(dict_T *dict, win_T *wp)
@@ -1832,9 +1959,18 @@
if (list != NULL)
{
dict_add_list(dict, "moved", list);
+ list_append_number(list, wp->w_popup_lnum);
list_append_number(list, wp->w_popup_mincol);
list_append_number(list, wp->w_popup_maxcol);
}
+ list = list_alloc();
+ if (list != NULL)
+ {
+ dict_add_list(dict, "mousemoved", list);
+ list_append_number(list, wp->w_popup_mouse_row);
+ list_append_number(list, wp->w_popup_mouse_mincol);
+ list_append_number(list, wp->w_popup_mouse_maxcol);
+ }
}
/*