1
0
forked from aniani/vim

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

@@ -2535,6 +2535,7 @@ or({expr}, {expr}) Number bitwise OR
pathshorten({expr}) String shorten directory names in a path
perleval({expr}) any evaluate |Perl| expression
popup_atcursor({what}, {options}) Number create popup window near the cursor
popup_beval({what}, {options}) Number create popup window for 'ballooneval'
popup_clear() none close all popup windows
popup_close({id} [, {result}]) none close popup window {id}
popup_create({what}, {options}) Number create a popup window
@@ -2613,6 +2614,7 @@ screenattr({row}, {col}) Number attribute at screen position
screenchar({row}, {col}) Number character at screen position
screenchars({row}, {col}) List List of characters at screen position
screencol() Number current cursor column
screenpos({winid}, {lnum}, {col}) Dict screen row and col of a text character
screenrow() Number current cursor row
screenstring({row}, {col}) String characters at screen position
search({pattern} [, {flags} [, {stopline} [, {timeout}]]])
@@ -7907,6 +7909,23 @@ screencol() *screencol()*
nnoremap <expr> GG ":echom ".screencol()."\n"
nnoremap <silent> GG :echom screencol()<CR>
<
screenpos({winid}, {lnum}, {col}) *screenpos()*
The result is a Dict with the screen position of the text
character in window {winid} at buffer line {lnum} and column
{col}. {col} is a one-based byte index.
The Dict has these members:
row screen row
col first screen column
endcol last screen column
curscol cursor screen column
If the specified position is not visible, all values are zero.
The "endcol" value differs from "col" when the character
occupies more than one screen cell. E.g. for a Tab "col" can
be 1 and "endcol" can be 8.
The "curscol" value is where the cursor would be placed. For
a Tab it would be the same as "endcol", while for a double
width character it would be the same as "col".
screenrow() *screenrow()*
The result is a Number, which is the current screen row of the
cursor. The top line has number one.

View File

@@ -146,6 +146,8 @@ Creating a popup window:
|popup_create()| centered in the screen
|popup_atcursor()| just above the cursor position, closes when
the cursor moves away
|popup_beval()| at the position indicated by v:beval_
variables, closes when the mouse moves away
|popup_notification()| show a notification for three seconds
|popup_dialog()| centered with padding and border
|popup_menu()| prompt for selecting an item from a list
@@ -184,6 +186,20 @@ popup_atcursor({what}, {options}) *popup_atcursor()*
< Use {options} to change the properties.
popup_beval({what}, {options}) *popup_beval()*
Show the {what} above the position from 'ballooneval' and
close it when the mouse moves. This works like: >
let pos = screenpos(v:beval_winnr, v:beval_lnum, v:beval_col)
call popup_create({what}, {
\ 'pos': 'botleft',
\ 'line': pos.lnum - 1,
\ 'col': pos.col,
\ 'mousemoved': 'WORD',
\ })
< Use {options} to change the properties.
See |popup_beval_example| for an example use.
*popup_clear()*
popup_clear() Emergency solution to a misbehaving plugin: close all popup
windows for the current tab and global popups.
@@ -276,8 +292,11 @@ popup_getoptions({id}) *popup_getoptions()*
A zero value means the option was not set. For "zindex" the
default value is returned, not zero.
The "moved" entry is a list with minimum and maximum column,
[0, 0] when not set.
The "moved" entry is a list with line number, minimum and
maximum column, [0, 0, 0] when not set.
The "mousemoved" entry is a list with screen row, minimum and
maximum screen column, [0, 0, 0] when not set.
"border" and "padding" are not included when all values are
zero. When all values are one then an empty list is included.
@@ -566,6 +585,7 @@ The second argument of |popup_create()| is a dictionary with options:
- "any": if the cursor moved at all
- "word": if the cursor moved outside |<cword>|
- "WORD": if the cursor moved outside |<cWORD>|
- "expr": if the cursor moved outside |<cexpr>|
- [{start}, {end}]: if the cursor moved before column
{start} or after {end}
The popup also closes if the cursor moves to another
@@ -736,5 +756,45 @@ Extend popup_filter_menu() with shortcut keys: >
return popup_filter_menu(a:id, a:key)
endfunc
<
*popup_beval_example*
Example for using a popup window for 'ballooneval': >
set ballooneval balloonevalterm
set balloonexpr=BalloonExpr()
let s:winid = 0
func BalloonExpr()
if s:winid
call popup_close(s:winid)
let s:winid = 0
endif
let s:winid = popup_beval([bufname(v:beval_bufnr), v:beval_text], {})
return ''
endfunc
<
If the text has to be obtained asynchronously return an empty string from the
expression function and call popup_beval() once the text is available. In
this example similated with a timer callback: >
set ballooneval balloonevalterm
set balloonexpr=BalloonExpr()
let s:winid = 0
func BalloonExpr()
if s:winid
call popup_close(s:winid)
let s:winid = 0
endif
" simulate an asynchronous loopup for the text to display
let s:balloonFile = bufname(v:beval_bufnr)
let s:balloonWord = v:beval_text
call timer_start(100, 'ShowPopup')
return ''
endfunc
func ShowPopup(id)
let s:winid = popup_beval([s:balloonFile, s:balloonWord], {})
endfunc
<
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@@ -720,6 +720,7 @@ Cursor and mark position: *cursor-functions* *mark-functions*
cursor() position the cursor at a line/column
screencol() get screen column of the cursor
screenrow() get screen row of the cursor
screenpos() screen row and col of a text character
getcurpos() get position of the cursor
getpos() get position of cursor, mark, etc.
setpos() set position of cursor, mark, etc.
@@ -1046,6 +1047,8 @@ Popup window: *popup-window-functions*
popup_create() create popup centered in the screen
popup_atcursor() create popup just above the cursor position,
closes when the cursor moves away
popup_beval() at the position indicated by v:beval_
variables, closes when the mouse moves away
popup_notification() show a notification for three seconds
popup_dialog() create popup centered with padding and border
popup_menu() prompt for selecting an item from a list

View File

@@ -14,7 +14,7 @@
/*
* Get the text and position to be evaluated for "beval".
* If "getword" is true the returned text is not the whole line but the
* If "getword" is TRUE the returned text is not the whole line but the
* relevant word in allocated memory.
* Returns OK or FAIL.
*/
@@ -27,12 +27,8 @@ get_beval_info(
char_u **textp,
int *colp)
{
win_T *wp;
int row, col;
char_u *lbuf;
linenr_T lnum;
*textp = NULL;
# ifdef FEAT_BEVAL_TERM
# ifdef FEAT_GUI
if (!gui.in_use)
@@ -49,22 +45,68 @@ get_beval_info(
col = X_2_COL(beval->x);
}
#endif
if (find_word_under_cursor(row, col, getword,
FIND_IDENT + FIND_STRING + FIND_EVAL,
winp, lnump, textp, colp) == OK)
{
#ifdef FEAT_VARTABS
vim_free(beval->vts);
beval->vts = tabstop_copy((*winp)->w_buffer->b_p_vts_array);
if ((*winp)->w_buffer->b_p_vts_array != NULL && beval->vts == NULL)
{
if (getword)
vim_free(*textp);
return FAIL;
}
#endif
beval->ts = (*winp)->w_buffer->b_p_ts;
return OK;
}
return FAIL;
}
/*
* Find text under the mouse position "row" / "col".
* If "getword" is TRUE the returned text in "*textp" is not the whole line but
* the relevant word in allocated memory.
* Return OK if found.
* Return FAIL if not found, no text at the mouse position.
*/
int
find_word_under_cursor(
int mouserow,
int mousecol,
int getword,
int flags, // flags for find_ident_at_pos()
win_T **winp, // can be NULL
linenr_T *lnump, // can be NULL
char_u **textp,
int *colp)
{
int row = mouserow;
int col = mousecol;
win_T *wp;
char_u *lbuf;
linenr_T lnum;
*textp = NULL;
wp = mouse_find_win(&row, &col, FAIL_POPUP);
if (wp != NULL && row >= 0 && row < wp->w_height && col < wp->w_width)
{
/* Found a window and the cursor is in the text. Now find the line
* number. */
// Found a window and the cursor is in the text. Now find the line
// number.
if (!mouse_comp_pos(wp, &row, &col, &lnum))
{
/* Not past end of the file. */
// Not past end of the file.
lbuf = ml_get_buf(wp->w_buffer, lnum, FALSE);
if (col <= win_linetabsize(wp, lbuf, (colnr_T)MAXCOL))
{
/* Not past end of line. */
// Not past end of line.
if (getword)
{
/* For Netbeans we get the relevant part of the line
* instead of the whole line. */
// For Netbeans we get the relevant part of the line
// instead of the whole line.
int len;
pos_T *spos = NULL, *epos = NULL;
@@ -93,9 +135,9 @@ get_beval_info(
? col <= (int)epos->col
: lnum < epos->lnum))
{
/* Visual mode and pointing to the line with the
* Visual selection: return selected text, with a
* maximum of one line. */
// Visual mode and pointing to the line with the
// Visual selection: return selected text, with a
// maximum of one line.
if (spos->lnum != epos->lnum || spos->col == epos->col)
return FAIL;
@@ -109,10 +151,10 @@ get_beval_info(
}
else
{
/* Find the word under the cursor. */
// Find the word under the cursor.
++emsg_off;
len = find_ident_at_pos(wp, lnum, (colnr_T)col, &lbuf,
FIND_IDENT + FIND_STRING + FIND_EVAL);
flags);
--emsg_off;
if (len == 0)
return FAIL;
@@ -120,22 +162,16 @@ get_beval_info(
}
}
*winp = wp;
*lnump = lnum;
if (winp != NULL)
*winp = wp;
if (lnump != NULL)
*lnump = lnum;
*textp = lbuf;
*colp = col;
#ifdef FEAT_VARTABS
vim_free(beval->vts);
beval->vts = tabstop_copy(wp->w_buffer->b_p_vts_array);
if (wp->w_buffer->b_p_vts_array != NULL && beval->vts == NULL)
return FAIL;
#endif
beval->ts = wp->w_buffer->b_p_ts;
return OK;
}
}
}
return FAIL;
}

View File

@@ -771,6 +771,7 @@ static struct fst
#endif
#ifdef FEAT_TEXT_PROP
{"popup_atcursor", 2, 2, f_popup_atcursor},
{"popup_beval", 2, 2, f_popup_beval},
{"popup_clear", 0, 0, f_popup_clear},
{"popup_close", 1, 2, f_popup_close},
{"popup_create", 2, 2, f_popup_create},
@@ -849,6 +850,7 @@ static struct fst
{"screenchar", 2, 2, f_screenchar},
{"screenchars", 2, 2, f_screenchars},
{"screencol", 0, 0, f_screencol},
{"screenpos", 3, 3, f_screenpos},
{"screenrow", 0, 0, f_screenrow},
{"screenstring", 2, 2, f_screenstring},
{"search", 1, 4, f_search},

View File

@@ -1189,6 +1189,96 @@ curs_columns(
curwin->w_valid |= VALID_WCOL|VALID_WROW|VALID_VIRTCOL;
}
#if defined(FEAT_EVAL) || defined(PROTO)
/*
* Compute the screen position of text character at "pos" in window "wp"
* The resulting values are one-based, zero when character is not visible.
*/
static void
textpos2screenpos(
win_T *wp,
pos_T *pos,
int *rowp, // screen row
int *scolp, // start screen column
int *ccolp, // cursor screen column
int *ecolp) // end screen column
{
colnr_T scol = 0, ccol = 0, ecol = 0;
int row = 0;
int rowoff = 0;
colnr_T coloff = 0;
if (pos->lnum >= wp->w_topline && pos->lnum < wp->w_botline)
{
colnr_T off;
colnr_T col;
int width;
row = plines_m_win(wp, wp->w_topline, pos->lnum - 1) + 1;
getvcol(wp, pos, &scol, &ccol, &ecol);
// similar to what is done in validate_cursor_col()
col = scol;
off = win_col_off(wp);
col += off;
width = wp->w_width - off + win_col_off2(wp);
/* long line wrapping, adjust row */
if (wp->w_p_wrap
&& col >= (colnr_T)wp->w_width
&& width > 0)
{
/* use same formula as what is used in curs_columns() */
rowoff = ((col - wp->w_width) / width + 1);
col -= rowoff * width;
}
col -= wp->w_leftcol;
if (col >= width)
col = -1;
if (col >= 0)
coloff = col - scol + wp->w_wincol + 1;
else
// character is left or right of the window
row = scol = ccol = ecol = 0;
}
*rowp = wp->w_winrow + row + rowoff;
*scolp = scol + coloff;
*ccolp = ccol + coloff;
*ecolp = ecol + coloff;
}
/*
* "screenpos({winid}, {lnum}, {col})" function
*/
void
f_screenpos(typval_T *argvars UNUSED, typval_T *rettv)
{
dict_T *dict;
win_T *wp;
pos_T pos;
int row = 0;
int scol = 0, ccol = 0, ecol = 0;
if (rettv_dict_alloc(rettv) != OK)
return;
dict = rettv->vval.v_dict;
wp = find_win_by_nr_or_id(&argvars[0]);
if (wp == NULL)
return;
pos.lnum = tv_get_number(&argvars[1]);
pos.col = tv_get_number(&argvars[2]) - 1;
pos.coladd = 0;
textpos2screenpos(wp, &pos, &row, &scol, &ccol, &ecol);
dict_add_number(dict, "row", row);
dict_add_number(dict, "col", scol);
dict_add_number(dict, "curscol", ccol);
dict_add_number(dict, "endcol", ecol);
}
#endif
/*
* Scroll the current window down by "line_count" logical lines. "CTRL-Y"
*/

View File

@@ -2328,6 +2328,9 @@ do_mouse(
profile_setlimit(p_bdlay, &bevalexpr_due);
bevalexpr_due_set = TRUE;
}
#endif
#ifdef FEAT_TEXT_PROP
popup_handle_mouse_moved();
#endif
return FALSE;
}

View File

@@ -992,8 +992,6 @@ pum_position_at_mouse(int min_width)
# if defined(FEAT_BEVAL_TERM) || defined(PROTO)
static pumitem_T *balloon_array = NULL;
static int balloon_arraysize;
static int balloon_mouse_row = 0;
static int balloon_mouse_col = 0;
#define BALLOON_MIN_WIDTH 50
#define BALLOON_MIN_HEIGHT 10
@@ -1209,8 +1207,9 @@ ui_post_balloon(char_u *mesg, list_T *list)
void
ui_may_remove_balloon(void)
{
if (mouse_row != balloon_mouse_row || mouse_col != balloon_mouse_col)
ui_remove_balloon();
// For now: remove the balloon whenever the mouse moves to another screen
// cell.
ui_remove_balloon();
}
# endif

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);
}
}
/*

View File

@@ -1,5 +1,6 @@
/* beval.c */
int get_beval_info(BalloonEval *beval, int getword, win_T **winp, linenr_T *lnump, char_u **textp, int *colp);
int find_word_under_cursor(int mouserow, int mousecol, int getword, int flags, win_T **winp, linenr_T *lnump, char_u **textp, int *colp);
void post_balloon(BalloonEval *beval, char_u *mesg, list_T *list);
int can_use_beval(void);
void general_beval_cb(BalloonEval *beval, int state);

View File

@@ -27,6 +27,7 @@ int curwin_col_off(void);
int win_col_off2(win_T *wp);
int curwin_col_off2(void);
void curs_columns(int may_scroll);
void f_screenpos(typval_T *argvars, typval_T *rettv);
void scrolldown(long line_count, int byfold);
void scrollup(long line_count, int byfold);
void check_topfill(win_T *wp, int down);

View File

@@ -11,7 +11,9 @@ void popup_adjust_position(win_T *wp);
void f_popup_clear(typval_T *argvars, typval_T *rettv);
void f_popup_create(typval_T *argvars, typval_T *rettv);
void f_popup_atcursor(typval_T *argvars, typval_T *rettv);
void f_popup_beval(typval_T *argvars, typval_T *rettv);
void popup_close_for_mouse_click(win_T *wp);
void popup_handle_mouse_moved(void);
void f_popup_filter_menu(typval_T *argvars, typval_T *rettv);
void f_popup_filter_yesno(typval_T *argvars, typval_T *rettv);
void f_popup_dialog(typval_T *argvars, typval_T *rettv);

View File

@@ -0,0 +1,10 @@
|1+0&#ffffff0| @73
>2| @73
|3| @73
|4| @12|t+0#0000001#ffd7ff255|e|x|t| +0#0000000#ffffff0@56
|h|e|r|e| |i|s| |s|o|m|e| |t|e|x|t| |t|o| |h|o|v|e|r| |o|v|e|r| @43
|6| @73
|7| @73
|8| @73
|9| @73
|:|c|a|l@1| |H|o|v|e|r|(|)| @43|2|,|1| @10|T|o|p|

View File

@@ -0,0 +1,10 @@
|1+0&#ffffff0| @73
>2| @73
|3| @73
|4| @12|t+0#0000001#ffd7ff255|e|x|t| +0#0000000#ffffff0@56
|h|e|r|e| |i|s| |s|o|m|e| |t|e|x|t| |t|o| |h|o|v|e|r| |o|v|e|r| @43
|6| @73
|7| @73
|8| @73
|9| @73
|:|c|a|l@1| |M|o|v|e|O|n|t|o|P|o|p|u|p|(|)| @35|2|,|1| @10|T|o|p|

View File

@@ -0,0 +1,10 @@
|1+0&#ffffff0| @73
>2| @73
|3| @73
|4| @73
|h|e|r|e| |i|s| |s|o|m|e| |t|e|x|t| |t|o| |h|o|v|e|r| |o|v|e|r| @43
|6| @73
|7| @73
|8| @73
|9| @73
|:|c|a|l@1| |M|o|v|e|A|w|a|y|(|)| @40|2|,|1| @10|T|o|p|

View File

@@ -72,3 +72,31 @@ func Test_curswant_with_cursorline()
call assert_equal(6, winsaveview().curswant)
quit!
endfunc
func Test_screenpos()
rightbelow new
rightbelow 20vsplit
call setline(1, ["\tsome text", "long wrapping line here", "next line"])
redraw
let winid = win_getid()
let [winrow, wincol] = win_screenpos(winid)
call assert_equal({'row': winrow,
\ 'col': wincol + 0,
\ 'curscol': wincol + 7,
\ 'endcol': wincol + 7}, screenpos(winid, 1, 1))
call assert_equal({'row': winrow,
\ 'col': wincol + 13,
\ 'curscol': wincol + 13,
\ 'endcol': wincol + 13}, screenpos(winid, 1, 7))
call assert_equal({'row': winrow + 2,
\ 'col': wincol + 1,
\ 'curscol': wincol + 1,
\ 'endcol': wincol + 1}, screenpos(winid, 2, 22))
setlocal number
call assert_equal({'row': winrow + 3,
\ 'col': wincol + 9,
\ 'curscol': wincol + 9,
\ 'endcol': wincol + 9}, screenpos(winid, 2, 22))
close
bwipe!
endfunc

View File

@@ -1005,6 +1005,53 @@ func Test_popup_atcursor()
bwipe!
endfunc
func Test_popup_beval()
if !CanRunVimInTerminal()
throw 'Skipped: cannot make screendumps'
endif
let lines =<< trim END
call setline(1, range(1, 20))
call setline(5, 'here is some text to hover over')
set balloonevalterm
set balloonexpr=BalloonExpr()
set balloondelay=100
func BalloonExpr()
let s:winid = popup_beval([v:beval_text], {})
return ''
endfunc
func Hover()
call test_setmouse(5, 15)
call feedkeys("\<MouseMove>\<Ignore>", "xt")
sleep 100m
endfunc
func MoveOntoPopup()
call test_setmouse(4, 17)
call feedkeys("\<F4>\<MouseMove>\<Ignore>", "xt")
endfunc
func MoveAway()
call test_setmouse(5, 13)
call feedkeys("\<F5>\<MouseMove>\<Ignore>", "xt")
endfunc
END
call writefile(lines, 'XtestPopupBeval')
let buf = RunVimInTerminal('-S XtestPopupBeval', {'rows': 10})
call term_wait(buf, 100)
call term_sendkeys(buf, 'j')
call term_sendkeys(buf, ":call Hover()\<CR>")
call VerifyScreenDump(buf, 'Test_popupwin_beval_1', {})
call term_sendkeys(buf, ":call MoveOntoPopup()\<CR>")
call VerifyScreenDump(buf, 'Test_popupwin_beval_2', {})
call term_sendkeys(buf, ":call MoveAway()\<CR>")
call VerifyScreenDump(buf, 'Test_popupwin_beval_3', {})
" clean up
call StopVimInTerminal(buf)
call delete('XtestPopupBeval')
endfunc
func Test_popup_filter()
new
call setline(1, 'some text')
@@ -1413,7 +1460,7 @@ func Test_popup_moved()
let winid = popup_atcursor('text', {'moved': 'any'})
redraw
call assert_equal(1, popup_getpos(winid).visible)
call assert_equal([4, 4], popup_getoptions(winid).moved)
call assert_equal([1, 4, 4], popup_getoptions(winid).moved)
" trigger the check for last_cursormoved by going into insert mode
call feedkeys("li\<Esc>", 'xt')
call assert_equal({}, popup_getpos(winid))
@@ -1423,7 +1470,7 @@ func Test_popup_moved()
let winid = popup_atcursor('text', {'moved': 'word'})
redraw
call assert_equal(1, popup_getpos(winid).visible)
call assert_equal([4, 7], popup_getoptions(winid).moved)
call assert_equal([1, 4, 7], popup_getoptions(winid).moved)
call feedkeys("hi\<Esc>", 'xt')
call assert_equal({}, popup_getpos(winid))
call popup_clear()
@@ -1432,7 +1479,7 @@ func Test_popup_moved()
let winid = popup_atcursor('text', {'moved': 'word'})
redraw
call assert_equal(1, popup_getpos(winid).visible)
call assert_equal([4, 7], popup_getoptions(winid).moved)
call assert_equal([1, 4, 7], popup_getoptions(winid).moved)
call feedkeys("li\<Esc>", 'xt')
call assert_equal(1, popup_getpos(winid).visible)
call feedkeys("ei\<Esc>", 'xt')
@@ -1446,7 +1493,7 @@ func Test_popup_moved()
let winid = popup_atcursor('text', {})
redraw
call assert_equal(1, popup_getpos(winid).visible)
call assert_equal([2, 15], popup_getoptions(winid).moved)
call assert_equal([2, 2, 15], popup_getoptions(winid).moved)
call feedkeys("eli\<Esc>", 'xt')
call assert_equal(1, popup_getpos(winid).visible)
call feedkeys("wi\<Esc>", 'xt')

View File

@@ -777,6 +777,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1645,
/**/
1644,
/**/