Patch 8.1.2304

15 views
Skip to first unread message

Bram Moolenaar

unread,
Nov 16, 2019, 12:23:45 PM11/16/19
to vim...@googlegroups.com

Patch 8.1.2304
Problem: Cannot get the mouse position when getting a mouse click.
Solution: Add getmousepos().
Files: runtime/doc/eval.txt, runtime/doc/popup.txt, src/mouse.c
src/proto/mouse.pro, src/evalfunc.c, src/popupwin.c,
src/popupwin.pro, src/testdir/test_popupwin.vim,
src/testdir/test_functions.vim


*** ../vim-8.1.2303/runtime/doc/eval.txt 2019-10-29 04:12:38.620582834 +0100
--- runtime/doc/eval.txt 2019-11-16 18:20:29.431251620 +0100
***************
*** 2480,2485 ****
--- 2480,2486 ----
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
***************
*** 4912,4919 ****

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: >
let c = getchar()
if c == "\<LeftMouse>" && v:mouse_win > 0
exe v:mouse_win . "wincmd w"
--- 4919,4927 ----

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|.
! |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"
***************
*** 5323,5328 ****
--- 5331,5365 ----
'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
*** ../vim-8.1.2303/runtime/doc/popup.txt 2019-11-11 21:45:01.925407125 +0100
--- runtime/doc/popup.txt 2019-11-16 15:57:02.558631367 +0100
***************
*** 862,871 ****
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).

Vim provides standard filters |popup_filter_menu()| and
|popup_filter_yesno()|.
--- 862,869 ----
cursor keys select another entry
Tab accept current suggestion

! A mouse click arrives as <LeftMouse>. The coordinates can be obtained with
! |mousegetpos()|.

Vim provides standard filters |popup_filter_menu()| and
|popup_filter_yesno()|.
*** ../vim-8.1.2303/src/mouse.c 2019-11-13 22:35:15.759521804 +0100
--- src/mouse.c 2019-11-16 18:12:11.385526875 +0100
***************
*** 2822,2827 ****
--- 2822,2828 ----
int retval = FALSE;
int off;
int count;
+ char_u *p;

#ifdef FEAT_RIGHTLEFT
if (win->w_p_rl)
***************
*** 2881,2886 ****
--- 2882,2892 ----
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,3003 ****
--- 3007,3067 ----
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
*** ../vim-8.1.2303/src/proto/mouse.pro 2019-09-23 21:16:51.387544361 +0200
--- src/proto/mouse.pro 2019-11-16 16:20:57.037027736 +0100
***************
*** 17,20 ****
--- 17,21 ----
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 : */
*** ../vim-8.1.2303/src/evalfunc.c 2019-11-10 00:13:46.434916175 +0100
--- src/evalfunc.c 2019-11-16 16:08:14.380168924 +0100
***************
*** 465,470 ****
--- 465,471 ----
{"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},
*** ../vim-8.1.2303/src/popupwin.c 2019-11-13 22:35:15.755521778 +0100
--- src/popupwin.c 2019-11-16 16:52:16.180901037 +0100
***************
*** 1047,1052 ****
--- 1047,1061 ----
}

/*
+ * 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.
*/
int
***************
*** 2908,2940 ****

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;
--- 2917,2928 ----
*** ../vim-8.1.2303/src/testdir/test_popupwin.vim 2019-11-13 22:35:15.759521804 +0100
--- src/testdir/test_popupwin.vim 2019-11-16 18:12:59.365307098 +0100
***************
*** 2205,2246 ****

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
return 0
endfunc

! let winid = popup_create(['short', 'long line that will wrap', 'short'], #{
! \ line: 4,
! \ col: 8,
\ maxwidth: 12,
\ 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)
!
! 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)
!
! 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)
!
! call test_setmouse(7, 20)
! 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 popup_close(winid)
delfunc MyPopupFilter
endfunc

--- 2205,2310 ----

func Test_popupwin_filter_mouse()
func MyPopupFilter(winid, c)
! let g:got_mousepos = getmousepos()
return 0
endfunc

! 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
! " 123456789012345678901
! " 1 .....................
! " 2 ...+--------------+..
! " 3 ...| |..
! " 4 ...| short |..
! " 5 ...| long line th |..
! " 6 ...| at will wrap |..
! " 7 ...| other |..
! " 8 ...| |..
! " 9 ...+--------------+..
! " 10 .....................
! let tests = []
!
! 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
!
! " 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)
!
! for item in tests
! call test_setmouse(item.clickrow, item.clickcol)
! call feedkeys("\<LeftMouse>", 'xt')
! call assert_equal(item.result, g:got_mousepos)
! endfor

call popup_close(winid)
+ enew!
delfunc MyPopupFilter
endfunc

*** ../vim-8.1.2303/src/testdir/test_functions.vim 2019-09-28 22:11:49.654184756 +0200
--- src/testdir/test_functions.vim 2019-11-16 18:18:14.083868933 +0100
***************
*** 1331,1336 ****
--- 1331,1337 ----
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,1347 ****
--- 1343,1349 ----
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()
*** ../vim-8.1.2303/src/version.c 2019-11-16 14:19:29.715739224 +0100
--- src/version.c 2019-11-16 18:08:02.754668833 +0100
***************
*** 743,744 ****
--- 743,746 ----
{ /* Add new patch number below this line */
+ /**/
+ 2304,
/**/

--
From "know your smileys":
|-P Reaction to unusually ugly C code

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///

John Marriott

unread,
Nov 16, 2019, 2:06:40 PM11/16/19
to vim...@googlegroups.com

On 17-Nov-2019 04:23, Bram Moolenaar wrote:
> Patch 8.1.2304
> Problem: Cannot get the mouse position when getting a mouse click.
> Solution: Add getmousepos().
> Files: runtime/doc/eval.txt, runtime/doc/popup.txt, src/mouse.c
> src/proto/mouse.pro, src/evalfunc.c, src/popupwin.c,
> src/popupwin.pro, src/testdir/test_popupwin.vim,
> src/testdir/test_functions.vim
>
After this patch, mingw64 (gcc 9.2.1) throws this warning:
gcc -c -I. -Iproto -DWIN32 -DWINVER=0x0603 -D_WIN32_WINNT=0x0603
-DHAVE_PATHDEF -DFEAT_NORMAL -DHAVE_STDINT_H -DFEAT_GUI_MSWIN
-DFEAT_CLIPBOARD -pipe -march=native -Wall -O3 -fomit-frame-pointer
-freg-struct-return mouse.c -o gobjnative/mouse.o
mouse.c: In function 'f_getmousepos':
mouse.c:3056:34: warning: passing argument 4 of 'mouse_comp_pos' from
incompatible pointer type [-Wincompatible-pointer-types]
 3056 |   mouse_comp_pos(wp, &row, &col, &line, NULL);
      |                                  ^~~~~
      |                                  |
      |                                  varnumber_T * {aka long long
int *}
mouse.c:2816:15: note: expected 'linenr_T *' {aka 'long int *'} but
argument is of type 'varnumber_T *' {aka 'long long int *'}
 2816 |     linenr_T *lnump,
      |     ~~~~~~~~~~^~~~~

Please check the attached patch which tries to fix it.

Cheers
John
mouse.c.8.1.2304.patch

Bram Moolenaar

unread,
Nov 16, 2019, 2:49:53 PM11/16/19
to vim...@googlegroups.com, John Marriott
Looks good, thanks.

--
From "know your smileys":
*<|:-) Santa Claus (Ho Ho Ho)
Reply all
Reply to author
Forward
0 new messages