fix(mouse): avoid dragging when clicking next to popupmenu

This commit is contained in:
Luuk van Baal 2023-11-24 17:57:50 +01:00
parent 53cc835b51
commit bce65ee429
3 changed files with 27 additions and 19 deletions

View File

@ -132,6 +132,8 @@ static void move_tab_to_mouse(void)
} }
} }
static bool got_click = false; // got a click some time back
/// Call click definition function for column "col" in the "click_defs" array for button /// Call click definition function for column "col" in the "click_defs" array for button
/// "which_button". /// "which_button".
static void call_click_def_func(StlClickDefinition *click_defs, int col, int which_button) static void call_click_def_func(StlClickDefinition *click_defs, int col, int which_button)
@ -187,6 +189,8 @@ static void call_click_def_func(StlClickDefinition *click_defs, int col, int whi
typval_T rettv; typval_T rettv;
(void)call_vim_function(click_defs[col].func, ARRAY_SIZE(argv), argv, &rettv); (void)call_vim_function(click_defs[col].func, ARRAY_SIZE(argv), argv, &rettv);
tv_clear(&rettv); tv_clear(&rettv);
// Make sure next click does not register as drag when callback absorbs the release event.
got_click = false;
} }
/// Translate window coordinates to buffer position without any side effects. /// Translate window coordinates to buffer position without any side effects.
@ -241,14 +245,6 @@ static int get_fpos_of_mouse(pos_T *mpos)
return IN_BUFFER; return IN_BUFFER;
} }
static bool mouse_got_click = false; ///< got a click some time back
/// Reset the flag that a mouse click was seen.
void reset_mouse_got_click(void)
{
mouse_got_click = false;
}
/// Do the appropriate action for the current mouse click in the current mode. /// Do the appropriate action for the current mouse click in the current mode.
/// Not used for Command-line mode. /// Not used for Command-line mode.
/// ///
@ -347,13 +343,13 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
// Ignore drag and release events if we didn't get a click. // Ignore drag and release events if we didn't get a click.
if (is_click) { if (is_click) {
mouse_got_click = true; got_click = true;
} else { } else {
if (!mouse_got_click) { // didn't get click, ignore if (!got_click) { // didn't get click, ignore
return false; return false;
} }
if (!is_drag) { // release, reset got_click if (!is_drag) { // release, reset got_click
mouse_got_click = false; got_click = false;
if (in_tab_line) { if (in_tab_line) {
in_tab_line = false; in_tab_line = false;
return false; return false;
@ -370,7 +366,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
stuffnumReadbuff(count); stuffnumReadbuff(count);
} }
stuffcharReadbuff(Ctrl_T); stuffcharReadbuff(Ctrl_T);
mouse_got_click = false; // ignore drag&release now got_click = false; // ignore drag&release now
return false; return false;
} }
@ -594,7 +590,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
ui_flush(); // Update before showing popup menu ui_flush(); // Update before showing popup menu
} }
show_popupmenu(); show_popupmenu();
mouse_got_click = false; // ignore release events got_click = false; // ignore release events
return (jump_flags & CURSOR_MOVED) != 0; return (jump_flags & CURSOR_MOVED) != 0;
} }
if (which_button == MOUSE_LEFT if (which_button == MOUSE_LEFT
@ -634,7 +630,7 @@ popupexit:
// If an operator is pending, ignore all drags and releases until the next mouse click. // If an operator is pending, ignore all drags and releases until the next mouse click.
if (!is_drag && oap != NULL && oap->op_type != OP_NOP) { if (!is_drag && oap != NULL && oap->op_type != OP_NOP) {
mouse_got_click = false; got_click = false;
oap->motion_type = kMTCharWise; oap->motion_type = kMTCharWise;
} }
@ -844,7 +840,7 @@ popupexit:
} else { // location list window } else { // location list window
do_cmdline_cmd(".ll"); do_cmdline_cmd(".ll");
} }
mouse_got_click = false; // ignore drag&release now got_click = false; // ignore drag&release now
} else if ((mod_mask & MOD_MASK_CTRL) } else if ((mod_mask & MOD_MASK_CTRL)
|| (curbuf->b_help && (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)) { || (curbuf->b_help && (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)) {
// Ctrl-Mouse click (or double click in a help window) jumps to the tag // Ctrl-Mouse click (or double click in a help window) jumps to the tag
@ -853,7 +849,7 @@ popupexit:
stuffcharReadbuff(Ctrl_O); stuffcharReadbuff(Ctrl_O);
} }
stuffcharReadbuff(Ctrl_RSB); stuffcharReadbuff(Ctrl_RSB);
mouse_got_click = false; // ignore drag&release now got_click = false; // ignore drag&release now
} else if ((mod_mask & MOD_MASK_SHIFT)) { } else if ((mod_mask & MOD_MASK_SHIFT)) {
// Shift-Mouse click searches for the next occurrence of the word under // Shift-Mouse click searches for the next occurrence of the word under
// the mouse pointer // the mouse pointer

View File

@ -26,7 +26,6 @@
#include "nvim/memory.h" #include "nvim/memory.h"
#include "nvim/menu.h" #include "nvim/menu.h"
#include "nvim/message.h" #include "nvim/message.h"
#include "nvim/mouse.h"
#include "nvim/move.h" #include "nvim/move.h"
#include "nvim/option.h" #include "nvim/option.h"
#include "nvim/option_vars.h" #include "nvim/option_vars.h"
@ -1148,7 +1147,6 @@ void pum_show_popupmenu(vimmenu_T *menu)
// right mouse release: select clicked item, close if any // right mouse release: select clicked item, close if any
pum_select_mouse_pos(); pum_select_mouse_pos();
if (pum_selected >= 0) { if (pum_selected >= 0) {
reset_mouse_got_click();
pum_execute_menu(menu, mode); pum_execute_menu(menu, mode);
break; break;
} }

View File

@ -590,7 +590,7 @@ describe('statuscolumn', function()
eq('0 1 l 11', eval("g:testvar")) eq('0 1 l 11', eval("g:testvar"))
end) end)
it('selecting popupmenu does not drag mouse', function() it('popupmenu callback does not drag mouse on close', function()
screen:try_resize(screen._width, 2) screen:try_resize(screen._width, 2)
screen:set_default_attr_ids({ screen:set_default_attr_ids({
[0] = {foreground = Screen.colors.Brown}, [0] = {foreground = Screen.colors.Brown},
@ -604,6 +604,7 @@ describe('statuscolumn', function()
popup PopupStc popup PopupStc
endfunction endfunction
]]) ]])
-- clicking an item does not drag mouse
meths.input_mouse('left', 'press', '', 0, 0, 0) meths.input_mouse('left', 'press', '', 0, 0, 0)
screen:expect([[ screen:expect([[
{0:8 }^aaaaa | {0:8 }^aaaaa |
@ -615,6 +616,19 @@ describe('statuscolumn', function()
{0:8 }^aaaaa | {0:8 }^aaaaa |
0 1 l 8 | 0 1 l 8 |
]]) ]])
command('echo')
-- clicking outside to close the menu does not drag mouse
meths.input_mouse('left', 'press', '', 0, 0, 0)
screen:expect([[
{0:8 }^aaaaa |
{1: Echo } |
]])
meths.input_mouse('left', 'press', '', 0, 0, 10)
meths.input_mouse('left', 'release', '', 0, 0, 10)
screen:expect([[
{0:8 }^aaaaa |
|
]])
end) end)
end) end)
end end