mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 19:38:20 +00:00
perf(mouse): only generate <MouseMove> for a new cell positon (#31103)
Problem: Can receive dozens of <MouseMove> events for same cell position. #30965 Solution: Leverage check_multiclick() to detect if cell position is unchanged.
This commit is contained in:
@@ -290,8 +290,9 @@ size_t input_enqueue(String keys)
|
|||||||
= trans_special(&ptr, (size_t)(end - ptr), (char *)buf, FSK_KEYCODE, true, NULL);
|
= trans_special(&ptr, (size_t)(end - ptr), (char *)buf, FSK_KEYCODE, true, NULL);
|
||||||
|
|
||||||
if (new_size) {
|
if (new_size) {
|
||||||
new_size = handle_mouse_event(&ptr, buf, new_size);
|
if ((new_size = handle_mouse_event(&ptr, buf, new_size))) {
|
||||||
input_enqueue_raw((char *)buf, new_size);
|
input_enqueue_raw((char *)buf, new_size);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,7 +327,7 @@ size_t input_enqueue(String keys)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t check_multiclick(int code, int grid, int row, int col)
|
static uint8_t check_multiclick(int code, int grid, int row, int col, bool *skip_event)
|
||||||
{
|
{
|
||||||
static int orig_num_clicks = 0;
|
static int orig_num_clicks = 0;
|
||||||
static int orig_mouse_code = 0;
|
static int orig_mouse_code = 0;
|
||||||
@@ -335,24 +336,29 @@ static uint8_t check_multiclick(int code, int grid, int row, int col)
|
|||||||
static int orig_mouse_row = 0;
|
static int orig_mouse_row = 0;
|
||||||
static uint64_t orig_mouse_time = 0; // time of previous mouse click
|
static uint64_t orig_mouse_time = 0; // time of previous mouse click
|
||||||
|
|
||||||
if ((code >= KE_MOUSEDOWN && code <= KE_MOUSERIGHT) || code == KE_MOUSEMOVE) {
|
if (code >= KE_MOUSEDOWN && code <= KE_MOUSERIGHT) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For click events the number of clicks is updated.
|
bool no_move = orig_mouse_grid == grid && orig_mouse_col == col && orig_mouse_row == row;
|
||||||
if (code == KE_LEFTMOUSE || code == KE_RIGHTMOUSE || code == KE_MIDDLEMOUSE
|
|
||||||
|
if (code == KE_MOUSEMOVE) {
|
||||||
|
if (no_move) {
|
||||||
|
*skip_event = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if (code == KE_LEFTMOUSE || code == KE_RIGHTMOUSE || code == KE_MIDDLEMOUSE
|
||||||
|| code == KE_X1MOUSE || code == KE_X2MOUSE) {
|
|| code == KE_X1MOUSE || code == KE_X2MOUSE) {
|
||||||
|
// For click events the number of clicks is updated.
|
||||||
uint64_t mouse_time = os_hrtime(); // time of current mouse click (ns)
|
uint64_t mouse_time = os_hrtime(); // time of current mouse click (ns)
|
||||||
// compute the time elapsed since the previous mouse click and
|
// compute the time elapsed since the previous mouse click and
|
||||||
// convert p_mouse from ms to ns
|
// convert p_mouse from ms to ns
|
||||||
uint64_t timediff = mouse_time - orig_mouse_time;
|
uint64_t timediff = mouse_time - orig_mouse_time;
|
||||||
uint64_t mouset = (uint64_t)p_mouset * 1000000;
|
uint64_t mouset = (uint64_t)p_mouset * 1000000;
|
||||||
if (code == orig_mouse_code
|
if (code == orig_mouse_code
|
||||||
|
&& no_move
|
||||||
&& timediff < mouset
|
&& timediff < mouset
|
||||||
&& orig_num_clicks != 4
|
&& orig_num_clicks != 4) {
|
||||||
&& orig_mouse_grid == grid
|
|
||||||
&& orig_mouse_col == col
|
|
||||||
&& orig_mouse_row == row) {
|
|
||||||
orig_num_clicks++;
|
orig_num_clicks++;
|
||||||
} else {
|
} else {
|
||||||
orig_num_clicks = 1;
|
orig_num_clicks = 1;
|
||||||
@@ -367,6 +373,7 @@ static uint8_t check_multiclick(int code, int grid, int row, int col)
|
|||||||
orig_mouse_row = row;
|
orig_mouse_row = row;
|
||||||
|
|
||||||
uint8_t modifiers = 0;
|
uint8_t modifiers = 0;
|
||||||
|
if (code != KE_MOUSEMOVE) {
|
||||||
if (orig_num_clicks == 2) {
|
if (orig_num_clicks == 2) {
|
||||||
modifiers |= MOD_MASK_2CLICK;
|
modifiers |= MOD_MASK_2CLICK;
|
||||||
} else if (orig_num_clicks == 3) {
|
} else if (orig_num_clicks == 3) {
|
||||||
@@ -374,6 +381,7 @@ static uint8_t check_multiclick(int code, int grid, int row, int col)
|
|||||||
} else if (orig_num_clicks == 4) {
|
} else if (orig_num_clicks == 4) {
|
||||||
modifiers |= MOD_MASK_4CLICK;
|
modifiers |= MOD_MASK_4CLICK;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return modifiers;
|
return modifiers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,8 +429,12 @@ static unsigned handle_mouse_event(const char **ptr, uint8_t *buf, unsigned bufs
|
|||||||
*ptr += advance;
|
*ptr += advance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool skip_event = false;
|
||||||
uint8_t modifiers = check_multiclick(mouse_code, mouse_grid,
|
uint8_t modifiers = check_multiclick(mouse_code, mouse_grid,
|
||||||
mouse_row, mouse_col);
|
mouse_row, mouse_col, &skip_event);
|
||||||
|
if (skip_event) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (modifiers) {
|
if (modifiers) {
|
||||||
if (buf[1] != KS_MODIFIER) {
|
if (buf[1] != KS_MODIFIER) {
|
||||||
@@ -443,7 +455,11 @@ static unsigned handle_mouse_event(const char **ptr, uint8_t *buf, unsigned bufs
|
|||||||
|
|
||||||
void input_enqueue_mouse(int code, uint8_t modifier, int grid, int row, int col)
|
void input_enqueue_mouse(int code, uint8_t modifier, int grid, int row, int col)
|
||||||
{
|
{
|
||||||
modifier |= check_multiclick(code, grid, row, col);
|
bool skip_event = false;
|
||||||
|
modifier |= check_multiclick(code, grid, row, col, &skip_event);
|
||||||
|
if (skip_event) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
uint8_t buf[7];
|
uint8_t buf[7];
|
||||||
uint8_t *p = buf;
|
uint8_t *p = buf;
|
||||||
if (modifier) {
|
if (modifier) {
|
||||||
|
@@ -1908,19 +1908,33 @@ describe('ui/mouse/input', function()
|
|||||||
eq(0, api.nvim_get_var('mouse_up2'))
|
eq(0, api.nvim_get_var('mouse_up2'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('<MouseMove> is not translated into multiclicks and can be mapped', function()
|
it('<MouseMove> to different locations can be mapped', function()
|
||||||
api.nvim_set_var('mouse_move', 0)
|
api.nvim_set_var('mouse_move', 0)
|
||||||
api.nvim_set_var('mouse_move2', 0)
|
api.nvim_set_var('mouse_move2', 0)
|
||||||
command('nnoremap <MouseMove> <Cmd>let g:mouse_move += 1<CR>')
|
command('nnoremap <MouseMove> <Cmd>let g:mouse_move += 1<CR>')
|
||||||
command('nnoremap <2-MouseMove> <Cmd>let g:mouse_move2 += 1<CR>')
|
command('nnoremap <2-MouseMove> <Cmd>let g:mouse_move2 += 1<CR>')
|
||||||
feed('<MouseMove><0,0>')
|
feed('<MouseMove><1,0>')
|
||||||
feed('<MouseMove><0,0>')
|
feed('<MouseMove><2,0>')
|
||||||
api.nvim_input_mouse('move', '', '', 0, 0, 0)
|
api.nvim_input_mouse('move', '', '', 0, 0, 3)
|
||||||
api.nvim_input_mouse('move', '', '', 0, 0, 0)
|
api.nvim_input_mouse('move', '', '', 0, 0, 4)
|
||||||
eq(4, api.nvim_get_var('mouse_move'))
|
eq(4, api.nvim_get_var('mouse_move'))
|
||||||
eq(0, api.nvim_get_var('mouse_move2'))
|
eq(0, api.nvim_get_var('mouse_move2'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('<MouseMove> to same location does not generate events #31103', function()
|
||||||
|
api.nvim_input_mouse('move', '', '', 0, 0, 3)
|
||||||
|
api.nvim_set_var('mouse_move', 0)
|
||||||
|
api.nvim_set_var('mouse_move2', 0)
|
||||||
|
command('nnoremap <MouseMove> <Cmd>let g:mouse_move += 1<CR>')
|
||||||
|
command('nnoremap <2-MouseMove> <Cmd>let g:mouse_move2 += 1<CR>')
|
||||||
|
feed('<MouseMove><3,0>')
|
||||||
|
feed('<MouseMove><3,0>')
|
||||||
|
api.nvim_input_mouse('move', '', '', 0, 0, 3)
|
||||||
|
api.nvim_input_mouse('move', '', '', 0, 0, 3)
|
||||||
|
eq(0, api.nvim_get_var('mouse_move'))
|
||||||
|
eq(0, api.nvim_get_var('mouse_move2'))
|
||||||
|
end)
|
||||||
|
|
||||||
it('feeding <MouseMove> in Normal mode does not use uninitialized memory #19480', function()
|
it('feeding <MouseMove> in Normal mode does not use uninitialized memory #19480', function()
|
||||||
feed('<MouseMove>')
|
feed('<MouseMove>')
|
||||||
n.poke_eventloop()
|
n.poke_eventloop()
|
||||||
|
Reference in New Issue
Block a user