0
0
mirror of https://github.com/vim/vim.git synced 2025-08-27 20:13:38 -04:00

patch 8.2.4674: cannot force getting MouseMove events

Problem:    Cannot force getting MouseMove events.
Solution:   Add the 'mousemoveevent' option with implementaiton for the GUI.
            (Ernie Rael, closes #10044)
This commit is contained in:
Ernie Rael 2022-04-03 15:47:28 +01:00 committed by Bram Moolenaar
parent 8ef6997e2d
commit c4cb544cd5
9 changed files with 166 additions and 16 deletions

View File

@ -261,6 +261,7 @@ Other options that are relevant:
'mousefocus' window focus follows mouse pointer |gui-mouse-focus| 'mousefocus' window focus follows mouse pointer |gui-mouse-focus|
'mousemodel' what mouse button does which action 'mousemodel' what mouse button does which action
'mousehide' hide mouse pointer while typing text 'mousehide' hide mouse pointer while typing text
'mousemoveevent' enable mouse move events so that <MouseMove> can be mapped
'selectmode' whether to start Select mode or Visual mode 'selectmode' whether to start Select mode or Visual mode
A quick way to set these is with the ":behave" command. A quick way to set these is with the ":behave" command.
@ -406,6 +407,9 @@ These mappings make selection work the way it probably should in a Motif
application, with shift-left mouse allowing for extending the visual area application, with shift-left mouse allowing for extending the visual area
rather than the right mouse button. rather than the right mouse button.
<MouseMove> may be mapped, but 'mousemoveevent' must be enabled to use the
mapping.
Mouse mapping with modifiers does not work for modeless selection. Mouse mapping with modifiers does not work for modeless selection.

View File

@ -5517,6 +5517,18 @@ A jump table for the options with a short description can be found at |Q_op|.
The 'mousemodel' option is set by the |:behave| command. The 'mousemodel' option is set by the |:behave| command.
*'mousemoveevent'* *'mousemev'*
'mousemoveevent' 'mousemev' boolean (default off)
global
{only works in the GUI}
When on, mouse move events are delivered to the input queue and are
available for mapping. The default, off, avoids the mouse movement
overhead except when needed. See |gui-mouse-mapping|.
Warning: Setting this option can make pending mappings to be aborted
when the mouse is moved.
Currently only works in the GUI, may be made to work in a terminal
later.
*'mouseshape'* *'mouses'* *E547* *'mouseshape'* *'mouses'* *E547*
'mouseshape' 'mouses' string (default "i-r:beam,s:updown,sd:udsizing, 'mouseshape' 'mouses' string (default "i-r:beam,s:updown,sd:udsizing,
vs:leftright,vd:lrsizing,m:no, vs:leftright,vd:lrsizing,m:no,

View File

@ -131,8 +131,8 @@ test_gui_event({event}, {args})
forward: set to 1 for forward search. forward: set to 1 for forward search.
"mouse": "mouse":
Inject a mouse button click event. The supported items in Inject either a mouse button click, or a mouse move, event.
{args} are: The supported items in {args} are:
button: mouse button. The supported values are: button: mouse button. The supported values are:
0 right mouse button 0 right mouse button
1 middle mouse button 1 middle mouse button
@ -151,6 +151,28 @@ test_gui_event({event}, {args})
4 shift is pressed 4 shift is pressed
8 alt is pressed 8 alt is pressed
16 ctrl is pressed 16 ctrl is pressed
move: Optional; if used and TRUE then a mouse move
event can be generated.
Only {args} row: and col: are used and
required; they are interpreted as pixels.
Only results in an event when 'mousemoveevent'
is set or a popup uses mouse move events.
"scrollbar":
Set or drag the left, right or horizontal scrollbar. Only
works when the scrollbar actually exists. The supported
items in {args} are:
which: scrollbar. The supported values are:
left Left scrollbar of the current window
right Right scrollbar of the current window
hor Horizontal scrollbar
value: amount to scroll. For the vertical scrollbars
the value can be 1 to the line-count of the
buffer. For the horizontal scrollbar the
value can be between 1 and the maximum line
length, assuming 'wrap' is not set.
dragging: 1 to drag the scrollbar and 0 to click in the
scrollbar.
"scrollbar": "scrollbar":
Set or drag the left, right or horizontal scrollbar. Only Set or drag the left, right or horizontal scrollbar. Only

View File

@ -3142,13 +3142,26 @@ button_set:
if (hold_gui_events) if (hold_gui_events)
return; return;
row = gui_xy2colrow(x, y, &col);
// Don't report a mouse move unless moved to a
// different character position.
if (button == MOUSE_MOVE)
{
if (row == prev_row && col == prev_col)
return;
else
{
prev_row = row >= 0 ? row : 0;
prev_col = col;
}
}
string[3] = CSI; string[3] = CSI;
string[4] = KS_EXTRA; string[4] = KS_EXTRA;
string[5] = (int)button_char; string[5] = (int)button_char;
// Pass the pointer coordinates of the scroll event so that we // Pass the pointer coordinates of the scroll event so that we
// know which window to scroll. // know which window to scroll.
row = gui_xy2colrow(x, y, &col);
string[6] = (char_u)(col / 128 + ' ' + 1); string[6] = (char_u)(col / 128 + ' ' + 1);
string[7] = (char_u)(col % 128 + ' ' + 1); string[7] = (char_u)(col % 128 + ' ' + 1);
string[8] = (char_u)(row / 128 + ' ' + 1); string[8] = (char_u)(row / 128 + ' ' + 1);
@ -4967,12 +4980,14 @@ gui_mouse_moved(int x, int y)
// apply 'mousefocus' and pointer shape // apply 'mousefocus' and pointer shape
gui_mouse_focus(x, y); gui_mouse_focus(x, y);
if (p_mousemev
#ifdef FEAT_PROP_POPUP #ifdef FEAT_PROP_POPUP
if (popup_uses_mouse_move) || popup_uses_mouse_move
// Generate a mouse-moved event, so that the popup can perhaps be
// closed, just like in the terminal.
gui_send_mouse_event(MOUSE_MOVE, x, y, FALSE, 0);
#endif #endif
)
// Generate a mouse-moved event. For a <MouseMove> mapping. Or so the
// popup can perhaps be closed, just like in the terminal.
gui_send_mouse_event(MOUSE_MOVE, x, y, FALSE, 0);
} }
/* /*

View File

@ -760,6 +760,9 @@ EXTERN int p_mousef; // 'mousefocus'
EXTERN int p_mh; // 'mousehide' EXTERN int p_mh; // 'mousehide'
#endif #endif
EXTERN char_u *p_mousem; // 'mousemodel' EXTERN char_u *p_mousem; // 'mousemodel'
#ifdef FEAT_GUI
EXTERN int p_mousemev; // 'mousemoveevent'
#endif
EXTERN long p_mouset; // 'mousetime' EXTERN long p_mouset; // 'mousetime'
EXTERN int p_more; // 'more' EXTERN int p_more; // 'more'
#ifdef FEAT_MZSCHEME #ifdef FEAT_MZSCHEME

View File

@ -1746,6 +1746,13 @@ static struct vimoption options[] =
# endif # endif
#endif #endif
(char_u *)0L} SCTX_INIT}, (char_u *)0L} SCTX_INIT},
{"mousemoveevent", "mousemev", P_BOOL|P_VI_DEF,
#ifdef FEAT_GUI
(char_u *)&p_mousemev, PV_NONE,
#else
(char_u *)NULL, PV_NONE,
#endif
{(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
{"mouseshape", "mouses", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP, {"mouseshape", "mouses", P_STRING|P_VI_DEF|P_ONECOMMA|P_NODUP,
#ifdef FEAT_MOUSESHAPE #ifdef FEAT_MOUSESHAPE
(char_u *)&p_mouseshape, PV_NONE, (char_u *)&p_mouseshape, PV_NONE,

View File

@ -1194,6 +1194,78 @@ func Test_gui_mouse_event()
set mousemodel& set mousemodel&
endfunc endfunc
func Test_gui_mouse_move_event()
let args = #{move: 1, button: 0, multiclick: 0, modifiers: 0}
" default, do not generate mouse move events
set mousemev&
call assert_false(&mousemev)
let n_event = 0
nnoremap <special> <MouseMove> :let n_event += 1<CR>
" start at mouse pos (1,1), clear counter
call extend(args, #{row: 1, col:1})
call test_gui_event('mouse', args)
call feedkeys('', 'Lx!')
let n_event = 0
call extend(args, #{row: 30, col:300})
call test_gui_event('mouse', args)
call feedkeys('', 'Lx!')
call extend(args, #{row: 100, col:300})
call test_gui_event('mouse', args)
call feedkeys('', 'Lx!')
" no events since mousemev off
call assert_equal(0, n_event)
" turn on mouse events and try the same thing
set mousemev
call extend(args, #{row: 1, col:1})
call test_gui_event('mouse', args)
call feedkeys('', 'Lx!')
let n_event = 0
call extend(args, #{row: 30, col:300})
call test_gui_event('mouse', args)
call feedkeys('', 'Lx!')
call extend(args, #{row: 100, col:300})
call test_gui_event('mouse', args)
call feedkeys('', 'Lx!')
call assert_equal(2, n_event)
" wiggle the mouse around, shouldn't get events
call extend(args, #{row: 1, col:1})
call test_gui_event('mouse', args)
call feedkeys('', 'Lx!')
let n_event = 0
call extend(args, #{row: 1, col:2})
call test_gui_event('mouse', args)
call feedkeys('', 'Lx!')
call extend(args, #{row: 2, col:2})
call test_gui_event('mouse', args)
call feedkeys('', 'Lx!')
call extend(args, #{row: 2, col:1})
call test_gui_event('mouse', args)
call feedkeys('', 'Lx!')
call extend(args, #{row: 1, col:1})
call test_gui_event('mouse', args)
call feedkeys('', 'Lx!')
call assert_equal(0, n_event)
unmap <MouseMove>
set mousemev&
endfunc
" Test for 'guitablabel' and 'guitabtooltip' options " Test for 'guitablabel' and 'guitabtooltip' options
func TestGuiTabLabel() func TestGuiTabLabel()
call add(g:TabLabels, v:lnum + 100) call add(g:TabLabels, v:lnum + 100)

View File

@ -1368,22 +1368,35 @@ test_gui_mouse_event(dict_T *args)
int col; int col;
int repeated_click; int repeated_click;
int_u mods; int_u mods;
int move;
if (dict_find(args, (char_u *)"button", -1) == NULL if (dict_find(args, (char_u *)"row", -1) == NULL
|| dict_find(args, (char_u *)"row", -1) == NULL || dict_find(args, (char_u *)"col", -1) == NULL)
|| dict_find(args, (char_u *)"col", -1) == NULL return FALSE;
|| dict_find(args, (char_u *)"multiclick", -1) == NULL
|| dict_find(args, (char_u *)"modifiers", -1) == NULL) // Note: "move" is optional, requires fewer arguments
move = (int)dict_get_bool(args, (char_u *)"move", FALSE);
if (!move && (dict_find(args, (char_u *)"button", -1) == NULL
|| dict_find(args, (char_u *)"multiclick", -1) == NULL
|| dict_find(args, (char_u *)"modifiers", -1) == NULL))
return FALSE; return FALSE;
button = (int)dict_get_number(args, (char_u *)"button");
row = (int)dict_get_number(args, (char_u *)"row"); row = (int)dict_get_number(args, (char_u *)"row");
col = (int)dict_get_number(args, (char_u *)"col"); col = (int)dict_get_number(args, (char_u *)"col");
repeated_click = (int)dict_get_number(args, (char_u *)"multiclick");
mods = (int)dict_get_number(args, (char_u *)"modifiers");
gui_send_mouse_event(button, TEXT_X(col - 1), TEXT_Y(row - 1), if (move)
gui_mouse_moved(col, row);
else
{
button = (int)dict_get_number(args, (char_u *)"button");
repeated_click = (int)dict_get_number(args, (char_u *)"multiclick");
mods = (int)dict_get_number(args, (char_u *)"modifiers");
gui_send_mouse_event(button, TEXT_X(col - 1), TEXT_Y(row - 1),
repeated_click, mods); repeated_click, mods);
}
return TRUE; return TRUE;
} }

View File

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