From a8a93e517f9eb988ee86170d9a77382637dd24a3 Mon Sep 17 00:00:00 2001 From: luukvbaal Date: Fri, 24 Nov 2023 02:15:50 +0100 Subject: [PATCH] fix(mouse): avoid dragging after click label popupmenu callback (#26187) --- src/nvim/mouse.c | 26 ++++++++++++++--------- src/nvim/popupmenu.c | 2 ++ test/functional/ui/statuscolumn_spec.lua | 27 ++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 10 deletions(-) diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index 8a48a8928e..368153cad6 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -241,6 +241,14 @@ static int get_fpos_of_mouse(pos_T *mpos) 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. /// Not used for Command-line mode. /// @@ -282,8 +290,6 @@ static int get_fpos_of_mouse(pos_T *mpos) /// @return true if start_arrow() should be called for edit mode. bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent) { - static bool got_click = false; // got a click some time back - int which_button; // MOUSE_LEFT, _MIDDLE or _RIGHT bool is_click; // If false it's a drag or release event bool is_drag; // If true it's a drag event @@ -341,13 +347,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. if (is_click) { - got_click = true; + mouse_got_click = true; } else { - if (!got_click) { // didn't get click, ignore + if (!mouse_got_click) { // didn't get click, ignore return false; } if (!is_drag) { // release, reset got_click - got_click = false; + mouse_got_click = false; if (in_tab_line) { in_tab_line = false; return false; @@ -364,7 +370,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent) stuffnumReadbuff(count); } stuffcharReadbuff(Ctrl_T); - got_click = false; // ignore drag&release now + mouse_got_click = false; // ignore drag&release now return false; } @@ -588,7 +594,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent) ui_flush(); // Update before showing popup menu } show_popupmenu(); - got_click = false; // ignore release events + mouse_got_click = false; // ignore release events return (jump_flags & CURSOR_MOVED) != 0; } if (which_button == MOUSE_LEFT @@ -628,7 +634,7 @@ popupexit: // 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) { - got_click = false; + mouse_got_click = false; oap->motion_type = kMTCharWise; } @@ -838,7 +844,7 @@ popupexit: } else { // location list window do_cmdline_cmd(".ll"); } - got_click = false; // ignore drag&release now + mouse_got_click = false; // ignore drag&release now } else if ((mod_mask & MOD_MASK_CTRL) || (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 @@ -847,7 +853,7 @@ popupexit: stuffcharReadbuff(Ctrl_O); } stuffcharReadbuff(Ctrl_RSB); - got_click = false; // ignore drag&release now + mouse_got_click = false; // ignore drag&release now } else if ((mod_mask & MOD_MASK_SHIFT)) { // Shift-Mouse click searches for the next occurrence of the word under // the mouse pointer diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c index a6eb32ecb1..e04d0c7acd 100644 --- a/src/nvim/popupmenu.c +++ b/src/nvim/popupmenu.c @@ -26,6 +26,7 @@ #include "nvim/memory.h" #include "nvim/menu.h" #include "nvim/message.h" +#include "nvim/mouse.h" #include "nvim/move.h" #include "nvim/option.h" #include "nvim/option_vars.h" @@ -1147,6 +1148,7 @@ void pum_show_popupmenu(vimmenu_T *menu) // right mouse release: select clicked item, close if any pum_select_mouse_pos(); if (pum_selected >= 0) { + reset_mouse_got_click(); pum_execute_menu(menu, mode); break; } diff --git a/test/functional/ui/statuscolumn_spec.lua b/test/functional/ui/statuscolumn_spec.lua index dd11fa7c15..73039701cd 100644 --- a/test/functional/ui/statuscolumn_spec.lua +++ b/test/functional/ui/statuscolumn_spec.lua @@ -589,6 +589,33 @@ describe('statuscolumn', function() meths.input_mouse('left', 'press', '', 0, 7, 7) eq('0 1 l 11', eval("g:testvar")) end) + + it('selecting popupmenu does not drag mouse', function() + screen:try_resize(screen._width, 2) + screen:set_default_attr_ids({ + [0] = {foreground = Screen.colors.Brown}, + [1] = {background = Screen.colors.Plum1}, + }) + meths.set_option_value('statuscolumn', '%0@MyClickFunc@%l%T', {}) + exec([[ + function! MyClickFunc(minwid, clicks, button, mods) + let g:testvar = printf("%d %d %s %d", a:minwid, a:clicks, a:button, getmousepos().line) + menu PopupStc.Echo echo g:testvar + popup PopupStc + endfunction + ]]) + meths.input_mouse('left', 'press', '', 0, 0, 0) + screen:expect([[ + {0:8 }^aaaaa | + {1: Echo } | + ]]) + meths.input_mouse('left', 'press', '', 0, 1, 5) + meths.input_mouse('left', 'release', '', 0, 1, 5) + screen:expect([[ + {0:8 }^aaaaa | + 0 1 l 8 | + ]]) + end) end) end