mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
patch 8.1.2304: cannot get the mouse position when getting a mouse click
Problem: Cannot get the mouse position when getting a mouse click. Solution: Add getmousepos().
This commit is contained in:
@@ -1956,15 +1956,11 @@ v:mouse_winid Window ID for a mouse click obtained with |getchar()|.
|
||||
|
||||
*v:mouse_lnum* *mouse_lnum-variable*
|
||||
v:mouse_lnum Line number for a mouse click obtained with |getchar()|.
|
||||
Also used for a click in a popup window when the filter is
|
||||
invoked.
|
||||
This is the text line number, not the screen line number. The
|
||||
value is zero when there was no mouse button click.
|
||||
|
||||
*v:mouse_col* *mouse_col-variable*
|
||||
v:mouse_col Column number for a mouse click obtained with |getchar()|.
|
||||
Also used for a click in a popup window when the filter is
|
||||
invoked.
|
||||
This is the screen column number, like with |virtcol()|. The
|
||||
value is zero when there was no mouse button click.
|
||||
|
||||
@@ -2484,6 +2480,7 @@ getline({lnum}) String line {lnum} of current buffer
|
||||
getline({lnum}, {end}) List lines {lnum} to {end} of current buffer
|
||||
getloclist({nr} [, {what}]) List list of location list items
|
||||
getmatches([{win}]) List list of current matches
|
||||
getmousepos() Dict last known mouse position
|
||||
getpid() Number process ID of Vim
|
||||
getpos({expr}) List position of cursor, mark, etc.
|
||||
getqflist([{what}]) List list of quickfix items
|
||||
@@ -4922,8 +4919,9 @@ getchar([expr]) *getchar()*
|
||||
|
||||
When the user clicks a mouse button, the mouse event will be
|
||||
returned. The position can then be found in |v:mouse_col|,
|
||||
|v:mouse_lnum|, |v:mouse_winid| and |v:mouse_win|. This
|
||||
example positions the mouse as it would normally happen: >
|
||||
|v:mouse_lnum|, |v:mouse_winid| and |v:mouse_win|.
|
||||
|getmousepos()| can also be used. This example positions the
|
||||
mouse as it would normally happen: >
|
||||
let c = getchar()
|
||||
if c == "\<LeftMouse>" && v:mouse_win > 0
|
||||
exe v:mouse_win . "wincmd w"
|
||||
@@ -5333,6 +5331,35 @@ getmatches([{win}]) *getmatches()*
|
||||
'pattern': 'FIXME', 'priority': 10, 'id': 2}] >
|
||||
:unlet m
|
||||
<
|
||||
getmousepos() *getmousepos()*
|
||||
Returns a Dictionary with the last known position of the
|
||||
mouse. This can be used in a mapping for a mouse click or in
|
||||
a filter of a popup window. The items are:
|
||||
screenrow screen row
|
||||
screencol screen column
|
||||
winid Window ID of the click
|
||||
winrow row inside "winid"
|
||||
wincol column inside "winid"
|
||||
line text line inside "winid"
|
||||
column text column inside "winid"
|
||||
All numbers are 1-based.
|
||||
|
||||
If not over a window, e.g. when in the command line, then only
|
||||
"screenrow" and "screencol" are valid, the others are zero.
|
||||
|
||||
When on the status line below a window or the vertical
|
||||
separater right of a window, the "line" and "column" values
|
||||
are zero.
|
||||
|
||||
When the position is after the text then "column" is the
|
||||
length of the text in bytes.
|
||||
|
||||
If the mouse is over a popup window then that window is used.
|
||||
|
||||
|
||||
When using |getchar()| the Vim variables |v:mouse_lnum|,
|
||||
|v:mouse_col| and |v:mouse_winid| also provide these values.
|
||||
|
||||
*getpid()*
|
||||
getpid() Return a Number which is the process ID of the Vim process.
|
||||
On Unix and MS-Windows this is a unique number, until Vim
|
||||
|
@@ -862,10 +862,8 @@ Some recommended key actions:
|
||||
cursor keys select another entry
|
||||
Tab accept current suggestion
|
||||
|
||||
A mouse click arrives as <LeftMouse>. The coordinates are in |v:mouse_col|
|
||||
and |v:mouse_lnum|. |v:mouse_winid| holds the window ID, |v:mouse_win| is
|
||||
always zero. The top-left screen cell of the popup is col 1, row 1 (not
|
||||
counting the border).
|
||||
A mouse click arrives as <LeftMouse>. The coordinates can be obtained with
|
||||
|mousegetpos()|.
|
||||
|
||||
Vim provides standard filters |popup_filter_menu()| and
|
||||
|popup_filter_yesno()|.
|
||||
|
@@ -465,6 +465,7 @@ static funcentry_T global_functions[] =
|
||||
{"getline", 1, 2, FEARG_1, f_getline},
|
||||
{"getloclist", 1, 2, 0, f_getloclist},
|
||||
{"getmatches", 0, 1, 0, f_getmatches},
|
||||
{"getmousepos", 0, 0, 0, f_getmousepos},
|
||||
{"getpid", 0, 0, 0, f_getpid},
|
||||
{"getpos", 1, 1, FEARG_1, f_getpos},
|
||||
{"getqflist", 0, 1, 0, f_getqflist},
|
||||
|
64
src/mouse.c
64
src/mouse.c
@@ -2822,6 +2822,7 @@ mouse_comp_pos(
|
||||
int retval = FALSE;
|
||||
int off;
|
||||
int count;
|
||||
char_u *p;
|
||||
|
||||
#ifdef FEAT_RIGHTLEFT
|
||||
if (win->w_p_rl)
|
||||
@@ -2881,6 +2882,11 @@ mouse_comp_pos(
|
||||
col += row * (win->w_width - off);
|
||||
// add skip column (for long wrapping line)
|
||||
col += win->w_skipcol;
|
||||
// limit to text length plus one
|
||||
p = ml_get_buf(win->w_buffer, lnum, FALSE);
|
||||
count = STRLEN(p);
|
||||
if (col > count)
|
||||
col = count;
|
||||
}
|
||||
|
||||
if (!win->w_p_wrap)
|
||||
@@ -3001,3 +3007,61 @@ vcol2col(win_T *wp, linenr_T lnum, int vcol)
|
||||
return (int)(ptr - line);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FEAT_EVAL) || defined(PROTO)
|
||||
void
|
||||
f_getmousepos(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
{
|
||||
dict_T *d;
|
||||
win_T *wp;
|
||||
int row = mouse_row;
|
||||
int col = mouse_col;
|
||||
varnumber_T winid = 0;
|
||||
varnumber_T winrow = 0;
|
||||
varnumber_T wincol = 0;
|
||||
varnumber_T line = 0;
|
||||
varnumber_T column = 0;
|
||||
|
||||
if (rettv_dict_alloc(rettv) != OK)
|
||||
return;
|
||||
d = rettv->vval.v_dict;
|
||||
|
||||
dict_add_number(d, "screenrow", (varnumber_T)mouse_row + 1);
|
||||
dict_add_number(d, "screencol", (varnumber_T)mouse_col + 1);
|
||||
|
||||
wp = mouse_find_win(&row, &col, FIND_POPUP);
|
||||
if (wp != NULL)
|
||||
{
|
||||
int top_off = 0;
|
||||
int left_off = 0;
|
||||
int height = wp->w_height + wp->w_status_height;
|
||||
|
||||
#ifdef FEAT_TEXT_PROP
|
||||
if (WIN_IS_POPUP(wp))
|
||||
{
|
||||
top_off = popup_top_extra(wp);
|
||||
left_off = popup_left_extra(wp);
|
||||
height = popup_height(wp);
|
||||
}
|
||||
#endif
|
||||
if (row < height)
|
||||
{
|
||||
winid = wp->w_id;
|
||||
winrow = row + 1;
|
||||
wincol = col + 1;
|
||||
row -= top_off;
|
||||
col -= left_off;
|
||||
if (row >= 0 && row < wp->w_height && col >= 0 && col < wp->w_width)
|
||||
{
|
||||
mouse_comp_pos(wp, &row, &col, &line, NULL);
|
||||
column = col + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
dict_add_number(d, "winid", winid);
|
||||
dict_add_number(d, "winrow", winrow);
|
||||
dict_add_number(d, "wincol", wincol);
|
||||
dict_add_number(d, "line", line);
|
||||
dict_add_number(d, "column", column);
|
||||
}
|
||||
#endif
|
||||
|
@@ -1046,6 +1046,15 @@ popup_top_extra(win_T *wp)
|
||||
return extra;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the padding plus border at the left.
|
||||
*/
|
||||
int
|
||||
popup_left_extra(win_T *wp)
|
||||
{
|
||||
return wp->w_popup_border[3] + wp->w_popup_padding[3];
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the height of popup window "wp", including border and padding.
|
||||
*/
|
||||
@@ -2908,33 +2917,12 @@ invoke_popup_filter(win_T *wp, int c)
|
||||
|
||||
argv[2].v_type = VAR_UNKNOWN;
|
||||
|
||||
if (is_mouse_key(c))
|
||||
{
|
||||
int row = mouse_row - wp->w_winrow;
|
||||
int col = mouse_col - wp->w_wincol;
|
||||
linenr_T lnum;
|
||||
|
||||
if (row >= 0 && col >= 0)
|
||||
{
|
||||
(void)mouse_comp_pos(wp, &row, &col, &lnum, NULL);
|
||||
set_vim_var_nr(VV_MOUSE_LNUM, lnum);
|
||||
set_vim_var_nr(VV_MOUSE_COL, col + 1);
|
||||
set_vim_var_nr(VV_MOUSE_WINID, wp->w_id);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: The callback might close the popup and make "wp" invalid.
|
||||
call_callback(&wp->w_filter_cb, -1, &rettv, 2, argv);
|
||||
if (win_valid_popup(wp) && old_lnum != wp->w_cursor.lnum)
|
||||
popup_highlight_curline(wp);
|
||||
res = tv_get_number(&rettv);
|
||||
|
||||
if (is_mouse_key(c))
|
||||
{
|
||||
set_vim_var_nr(VV_MOUSE_LNUM, 0);
|
||||
set_vim_var_nr(VV_MOUSE_COL, 0);
|
||||
set_vim_var_nr(VV_MOUSE_WINID, wp->w_id);
|
||||
}
|
||||
vim_free(argv[1].vval.v_string);
|
||||
clear_tv(&rettv);
|
||||
return res;
|
||||
|
@@ -17,4 +17,5 @@ int check_termcode_mouse(char_u *tp, int *slen, char_u *key_name, char_u *modifi
|
||||
int mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump, int *plines_cache);
|
||||
win_T *mouse_find_win(int *rowp, int *colp, mouse_find_T popup);
|
||||
int vcol2col(win_T *wp, linenr_T lnum, int vcol);
|
||||
void f_getmousepos(typval_T *argvars, typval_T *rettv);
|
||||
/* vim: set ft=c : */
|
||||
|
@@ -1331,6 +1331,7 @@ func Test_getchar()
|
||||
call feedkeys('a', '')
|
||||
call assert_equal(char2nr('a'), getchar())
|
||||
|
||||
call setline(1, 'xxxx')
|
||||
call test_setmouse(1, 3)
|
||||
let v:mouse_win = 9
|
||||
let v:mouse_winid = 9
|
||||
@@ -1342,6 +1343,7 @@ func Test_getchar()
|
||||
call assert_equal(win_getid(1), v:mouse_winid)
|
||||
call assert_equal(1, v:mouse_lnum)
|
||||
call assert_equal(3, v:mouse_col)
|
||||
enew!
|
||||
endfunc
|
||||
|
||||
func Test_libcall_libcallnr()
|
||||
|
@@ -2205,42 +2205,106 @@ endfunc
|
||||
|
||||
func Test_popupwin_filter_mouse()
|
||||
func MyPopupFilter(winid, c)
|
||||
let g:got_mouse_col = v:mouse_col
|
||||
let g:got_mouse_lnum = v:mouse_lnum
|
||||
let g:got_mouse_winid = v:mouse_winid
|
||||
let g:got_mousepos = getmousepos()
|
||||
return 0
|
||||
endfunc
|
||||
|
||||
let winid = popup_create(['short', 'long line that will wrap', 'short'], #{
|
||||
\ line: 4,
|
||||
\ col: 8,
|
||||
call setline(1, ['.'->repeat(25)]->repeat(10))
|
||||
let winid = popup_create(['short', 'long line that will wrap', 'other'], #{
|
||||
\ line: 2,
|
||||
\ col: 4,
|
||||
\ maxwidth: 12,
|
||||
\ padding: [],
|
||||
\ border: [],
|
||||
\ filter: 'MyPopupFilter',
|
||||
\ })
|
||||
redraw
|
||||
call test_setmouse(4, 8)
|
||||
call feedkeys("\<LeftMouse>", 'xt')
|
||||
call assert_equal(1, g:got_mouse_col)
|
||||
call assert_equal(1, g:got_mouse_lnum)
|
||||
call assert_equal(winid, g:got_mouse_winid)
|
||||
" 123456789012345678901
|
||||
" 1 .....................
|
||||
" 2 ...+--------------+..
|
||||
" 3 ...| |..
|
||||
" 4 ...| short |..
|
||||
" 5 ...| long line th |..
|
||||
" 6 ...| at will wrap |..
|
||||
" 7 ...| other |..
|
||||
" 8 ...| |..
|
||||
" 9 ...+--------------+..
|
||||
" 10 .....................
|
||||
let tests = []
|
||||
|
||||
call test_setmouse(5, 8)
|
||||
call feedkeys("\<LeftMouse>", 'xt')
|
||||
call assert_equal(1, g:got_mouse_col)
|
||||
call assert_equal(2, g:got_mouse_lnum)
|
||||
func AddItemOutsidePopup(tests, row, col)
|
||||
eval a:tests->add(#{clickrow: a:row, clickcol: a:col, result: #{
|
||||
\ screenrow: a:row, screencol: a:col,
|
||||
\ winid: win_getid(), winrow: a:row, wincol: a:col,
|
||||
\ line: a:row, column: a:col,
|
||||
\ }})
|
||||
endfunc
|
||||
func AddItemInPopupBorder(tests, winid, row, col)
|
||||
eval a:tests->add(#{clickrow: a:row, clickcol: a:col, result: #{
|
||||
\ screenrow: a:row, screencol: a:col,
|
||||
\ winid: a:winid, winrow: a:row - 1, wincol: a:col - 3,
|
||||
\ line: 0, column: 0,
|
||||
\ }})
|
||||
endfunc
|
||||
func AddItemInPopupText(tests, winid, row, col, textline, textcol)
|
||||
eval a:tests->add(#{clickrow: a:row, clickcol: a:col, result: #{
|
||||
\ screenrow: a:row, screencol: a:col,
|
||||
\ winid: a:winid, winrow: a:row - 1, wincol: a:col - 3,
|
||||
\ line: a:textline, column: a:textcol,
|
||||
\ }})
|
||||
endfunc
|
||||
|
||||
call test_setmouse(6, 8)
|
||||
call feedkeys("\<LeftMouse>", 'xt')
|
||||
call assert_equal(13, g:got_mouse_col)
|
||||
call assert_equal(2, g:got_mouse_lnum)
|
||||
" above and below popup
|
||||
for c in range(1, 21)
|
||||
call AddItemOutsidePopup(tests, 1, c)
|
||||
call AddItemOutsidePopup(tests, 10, c)
|
||||
endfor
|
||||
" left and right of popup
|
||||
for r in range(1, 10)
|
||||
call AddItemOutsidePopup(tests, r, 3)
|
||||
call AddItemOutsidePopup(tests, r, 20)
|
||||
endfor
|
||||
" top and bottom in popup
|
||||
for c in range(4, 19)
|
||||
call AddItemInPopupBorder(tests, winid, 2, c)
|
||||
call AddItemInPopupBorder(tests, winid, 3, c)
|
||||
call AddItemInPopupBorder(tests, winid, 8, c)
|
||||
call AddItemInPopupBorder(tests, winid, 9, c)
|
||||
endfor
|
||||
" left and right margin in popup
|
||||
for r in range(2, 9)
|
||||
call AddItemInPopupBorder(tests, winid, r, 4)
|
||||
call AddItemInPopupBorder(tests, winid, r, 5)
|
||||
call AddItemInPopupBorder(tests, winid, r, 18)
|
||||
call AddItemInPopupBorder(tests, winid, r, 19)
|
||||
endfor
|
||||
" text "short"
|
||||
call AddItemInPopupText(tests, winid, 4, 6, 1, 1)
|
||||
call AddItemInPopupText(tests, winid, 4, 10, 1, 5)
|
||||
call AddItemInPopupText(tests, winid, 4, 11, 1, 6)
|
||||
call AddItemInPopupText(tests, winid, 4, 17, 1, 6)
|
||||
" text "long line th"
|
||||
call AddItemInPopupText(tests, winid, 5, 6, 2, 1)
|
||||
call AddItemInPopupText(tests, winid, 5, 10, 2, 5)
|
||||
call AddItemInPopupText(tests, winid, 5, 17, 2, 12)
|
||||
" text "at will wrap"
|
||||
call AddItemInPopupText(tests, winid, 6, 6, 2, 13)
|
||||
call AddItemInPopupText(tests, winid, 6, 10, 2, 17)
|
||||
call AddItemInPopupText(tests, winid, 6, 17, 2, 24)
|
||||
" text "other"
|
||||
call AddItemInPopupText(tests, winid, 7, 6, 3, 1)
|
||||
call AddItemInPopupText(tests, winid, 7, 10, 3, 5)
|
||||
call AddItemInPopupText(tests, winid, 7, 11, 3, 6)
|
||||
call AddItemInPopupText(tests, winid, 7, 17, 3, 6)
|
||||
|
||||
call test_setmouse(7, 20)
|
||||
for item in tests
|
||||
call test_setmouse(item.clickrow, item.clickcol)
|
||||
call feedkeys("\<LeftMouse>", 'xt')
|
||||
call assert_equal(13, g:got_mouse_col)
|
||||
call assert_equal(3, g:got_mouse_lnum)
|
||||
call assert_equal(winid, g:got_mouse_winid)
|
||||
call assert_equal(item.result, g:got_mousepos)
|
||||
endfor
|
||||
|
||||
call popup_close(winid)
|
||||
enew!
|
||||
delfunc MyPopupFilter
|
||||
endfunc
|
||||
|
||||
|
@@ -741,6 +741,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
2304,
|
||||
/**/
|
||||
2303,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user