mirror of
https://github.com/neovim/neovim.git
synced 2026-05-25 06:18:32 +00:00
Merge pull request #39429 from ollien/mouse-n-visual
fix(mouse): mouse=n should not adjust visual selection
This commit is contained in:
@@ -609,9 +609,10 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
|
||||
|
||||
pos_T end_visual = { 0 };
|
||||
pos_T start_visual = { 0 };
|
||||
bool mouse_can_visual = ui_mouse_has(MOUSE_VISUAL);
|
||||
if ((State & (MODE_NORMAL | MODE_INSERT))
|
||||
&& !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))) {
|
||||
if (which_button == MOUSE_LEFT) {
|
||||
if (which_button == MOUSE_LEFT && mouse_can_visual) {
|
||||
if (is_click) {
|
||||
// stop Visual mode for a left click in a window, but not when on a status line
|
||||
if (VIsual_active) {
|
||||
@@ -620,7 +621,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
|
||||
} else {
|
||||
jump_flags |= MOUSE_MAY_VIS;
|
||||
}
|
||||
} else if (which_button == MOUSE_RIGHT) {
|
||||
} else if (which_button == MOUSE_RIGHT && mouse_can_visual) {
|
||||
if (is_click && VIsual_active) {
|
||||
// Remember the start and end of visual before moving the cursor.
|
||||
if (lt(curwin->w_cursor, VIsual)) {
|
||||
@@ -631,8 +632,10 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
|
||||
end_visual = curwin->w_cursor;
|
||||
}
|
||||
}
|
||||
jump_flags |= MOUSE_FOCUS;
|
||||
jump_flags |= MOUSE_MAY_VIS;
|
||||
jump_flags |= MOUSE_FOCUS;
|
||||
} else if (which_button == MOUSE_RIGHT) {
|
||||
jump_flags |= MOUSE_FOCUS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -650,7 +653,12 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
|
||||
// JUMP!
|
||||
int old_active = VIsual_active;
|
||||
pos_T save_cursor = curwin->w_cursor;
|
||||
jump_flags = jump_to_mouse(jump_flags, oap == NULL ? NULL : &(oap->inclusive), which_button);
|
||||
|
||||
// Even though we gate *_VIS flags above, we want to make sure the cursor doesn't move
|
||||
// in visual mode unless it is set as a mouse option
|
||||
if (!VIsual_active || mouse_can_visual) {
|
||||
jump_flags = jump_to_mouse(jump_flags, oap == NULL ? NULL : &(oap->inclusive), which_button);
|
||||
}
|
||||
|
||||
bool moved = (jump_flags & CURSOR_MOVED);
|
||||
bool in_winbar = (jump_flags & MOUSE_WINBAR);
|
||||
@@ -891,7 +899,8 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
|
||||
} else if (in_status_line || in_sep_line) {
|
||||
// Do nothing if on status line or vertical separator
|
||||
// Handle double clicks otherwise
|
||||
} else if ((mod_mask & MOD_MASK_MULTI_CLICK) && (State & (MODE_NORMAL | MODE_INSERT))) {
|
||||
} else if ((mod_mask & MOD_MASK_MULTI_CLICK) && (State & (MODE_NORMAL | MODE_INSERT))
|
||||
&& mouse_can_visual) {
|
||||
if (is_click || !VIsual_active) {
|
||||
if (VIsual_active) {
|
||||
orig_cursor = VIsual;
|
||||
|
||||
@@ -630,32 +630,44 @@ void ui_check_mouse(void)
|
||||
checkfor = ' '; // don't use mouse for ":!cmd"
|
||||
}
|
||||
|
||||
// mouse should be active if at least one of the following is true:
|
||||
// - "c" is in 'mouse', or
|
||||
// - 'a' is in 'mouse' and "c" is in MOUSE_A, or
|
||||
// - the current buffer is a help file and 'h' is in 'mouse' and we are in a
|
||||
// normal editing mode (not at hit-return message).
|
||||
if (ui_mouse_has(checkfor)) {
|
||||
has_mouse = true;
|
||||
}
|
||||
}
|
||||
|
||||
// check if 'mouse' is active for the given mode
|
||||
//
|
||||
// mouse should be active if at least one of the following is true:
|
||||
// - "mode" is in 'mouse', or
|
||||
// - 'a' is in 'mouse' and "mode" is in MOUSE_A, or
|
||||
// - the current buffer is a help file and 'h' is in 'mouse' and we are in a
|
||||
// normal editing mode (not at hit-return message).
|
||||
bool ui_mouse_has(int mode)
|
||||
{
|
||||
for (char *p = p_mouse; *p; p++) {
|
||||
switch (*p) {
|
||||
case 'a':
|
||||
if (vim_strchr(MOUSE_A, checkfor) != NULL) {
|
||||
has_mouse = true;
|
||||
return;
|
||||
if (vim_strchr(MOUSE_A, mode) != NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
case MOUSE_HELP:
|
||||
if (checkfor != MOUSE_RETURN && curbuf->b_help) {
|
||||
has_mouse = true;
|
||||
return;
|
||||
if (mode != MOUSE_RETURN && curbuf->b_help) {
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
if (checkfor == *p) {
|
||||
has_mouse = true;
|
||||
return;
|
||||
if (mode == *p) {
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Check if current mode has changed.
|
||||
|
||||
@@ -111,6 +111,63 @@ describe('ui/mouse/input', function()
|
||||
})
|
||||
end)
|
||||
|
||||
it('double left click stays in normal mode if mouse does not contain v', function()
|
||||
api.nvim_set_option_value('mouse', 'n', {})
|
||||
|
||||
feed('<LeftMouse><0,0>')
|
||||
feed('<LeftRelease><0,0>')
|
||||
feed('<LeftMouse><0,0>')
|
||||
feed('<LeftRelease><0,0>')
|
||||
screen:expect({
|
||||
any = {
|
||||
'%^testing',
|
||||
'mouse',
|
||||
'support and selection',
|
||||
},
|
||||
mode = 'normal',
|
||||
})
|
||||
end)
|
||||
|
||||
it('triple left click stays in normal mode if mouse does not contain v', function()
|
||||
api.nvim_set_option_value('mouse', 'n', {})
|
||||
|
||||
feed('<LeftMouse><0,0>')
|
||||
feed('<LeftRelease><0,0>')
|
||||
feed('<LeftMouse><0,0>')
|
||||
feed('<LeftRelease><0,0>')
|
||||
feed('<LeftMouse><0,0>')
|
||||
feed('<LeftRelease><0,0>')
|
||||
screen:expect({
|
||||
any = {
|
||||
'%^testing',
|
||||
'mouse',
|
||||
'support and selection',
|
||||
},
|
||||
mode = 'normal',
|
||||
})
|
||||
end)
|
||||
|
||||
it('quadruple left click stays in normal mode if mouse does not contain v', function()
|
||||
api.nvim_set_option_value('mouse', 'n', {})
|
||||
|
||||
feed('<LeftMouse><0,0>')
|
||||
feed('<LeftRelease><0,0>')
|
||||
feed('<LeftMouse><0,0>')
|
||||
feed('<LeftRelease><0,0>')
|
||||
feed('<LeftMouse><0,0>')
|
||||
feed('<LeftRelease><0,0>')
|
||||
feed('<LeftMouse><0,0>')
|
||||
feed('<LeftRelease><0,0>')
|
||||
screen:expect({
|
||||
any = {
|
||||
'%^testing',
|
||||
'mouse',
|
||||
'support and selection',
|
||||
},
|
||||
mode = 'normal',
|
||||
})
|
||||
end)
|
||||
|
||||
describe('tab drag', function()
|
||||
it('in tabline on filler space moves tab to the end', function()
|
||||
feed_command('%delete')
|
||||
@@ -579,6 +636,104 @@ describe('ui/mouse/input', function()
|
||||
})
|
||||
end)
|
||||
|
||||
it('left drag moves cursor if mouse does not contain v', function()
|
||||
api.nvim_set_option_value('mouse', 'n', {})
|
||||
|
||||
-- drag events must be preceded by a click
|
||||
feed('<LeftMouse><2,1>')
|
||||
screen:expect({
|
||||
any = {
|
||||
'testing',
|
||||
'mo%^use',
|
||||
'support and selection',
|
||||
},
|
||||
mode = 'normal',
|
||||
})
|
||||
feed('<LeftDrag><4,1>')
|
||||
screen:expect({
|
||||
any = {
|
||||
'testing',
|
||||
'mous%^e',
|
||||
'support and selection',
|
||||
},
|
||||
mode = 'normal',
|
||||
})
|
||||
feed('<LeftDrag><2,2>')
|
||||
screen:expect({
|
||||
any = {
|
||||
'testing',
|
||||
'mouse',
|
||||
'su%^pport and selection',
|
||||
},
|
||||
mode = 'normal',
|
||||
})
|
||||
feed('<LeftDrag><0,0>')
|
||||
screen:expect({
|
||||
any = {
|
||||
'%^testing',
|
||||
'mouse',
|
||||
'support and selection',
|
||||
},
|
||||
mode = 'normal',
|
||||
})
|
||||
end)
|
||||
|
||||
it('left drag does not adjust existing visual selection if mouse does not contain v', function()
|
||||
api.nvim_set_option_value('mouse', 'n', {})
|
||||
|
||||
feed('gg^vlj')
|
||||
screen:expect({
|
||||
any = {
|
||||
'{17:testing}',
|
||||
'{17:m}%^ouse',
|
||||
'support and selection',
|
||||
'VISUAL',
|
||||
},
|
||||
})
|
||||
|
||||
-- drag events must be preceded by a click
|
||||
feed('<LeftMouse><2,1>')
|
||||
screen:expect({
|
||||
any = {
|
||||
'{17:testing}',
|
||||
'{17:m}%^ouse',
|
||||
'support and selection',
|
||||
'VISUAL',
|
||||
},
|
||||
unchanged = true,
|
||||
})
|
||||
feed('<LeftDrag><4,1>')
|
||||
screen:expect({
|
||||
any = {
|
||||
'{17:testing}',
|
||||
'{17:m}%^ouse',
|
||||
'support and selection',
|
||||
'VISUAL',
|
||||
},
|
||||
unchanged = true,
|
||||
})
|
||||
feed('<LeftDrag><2,2>')
|
||||
screen:expect({
|
||||
any = {
|
||||
'{17:testing}',
|
||||
'{17:m}%^ouse',
|
||||
'support and selection',
|
||||
'VISUAL',
|
||||
},
|
||||
unchanged = true,
|
||||
})
|
||||
feed('<LeftRelease>')
|
||||
screen:expect({
|
||||
any = {
|
||||
'{17:testing}',
|
||||
'{17:m}%^ouse',
|
||||
'support and selection',
|
||||
'VISUAL',
|
||||
},
|
||||
unchanged = true,
|
||||
})
|
||||
end)
|
||||
|
||||
it('left drag changes visual selection after tab click', function()
|
||||
feed_command('silent file foo | tabnew | file bar')
|
||||
insert('this is bar')
|
||||
|
||||
Reference in New Issue
Block a user