0
0
mirror of https://github.com/vim/vim.git synced 2025-09-27 04:14:06 -04:00

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.
This commit is contained in:
Bram Moolenaar
2019-07-07 18:28:14 +02:00
parent 5b19e5b919
commit b3d17a20d2
18 changed files with 522 additions and 63 deletions

View File

@@ -167,6 +167,35 @@ set_moved_columns(win_T *wp, int flags)
}
}
/*
* 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.
@@ -335,6 +364,53 @@ apply_move_options(win_T *wp, dict_T *d)
get_pos_options(wp, d);
}
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)
{
@@ -541,31 +617,14 @@ apply_general_options(win_T *wp, dict_T *dict)
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 @@ typedef enum
{
TYPE_NORMAL,
TYPE_ATCURSOR,
TYPE_BEVAL,
TYPE_NOTIFICATION,
TYPE_DIALOG,
TYPE_MENU
@@ -1137,17 +1197,33 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
{
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;
@@ -1275,6 +1351,15 @@ f_popup_atcursor(typval_T *argvars, typval_T *rettv)
popup_create(argvars, rettv, TYPE_ATCURSOR);
}
/*
* 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_for_mouse_click(win_T *wp)
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 @@ get_borderchars(dict_T *dict, win_T *wp)
}
/*
* 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 @@ get_moved_list(dict_T *dict, win_T *wp)
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);
}
}
/*