fix: right-click in clickable statusline #19252

Problem:
1. Right-click does not work in statusline unless you left-click first (to focus
   the statusline).
2. Modifier (e.g. shift+rightclick) does not work in statusline.

Solution:
Make clickable statusline sections receive right-clicks regardless of whether
the statusline is focused.

Closes #18994
This commit is contained in:
Famiu Haque
2022-07-15 22:15:02 +06:00
committed by GitHub
parent 5c49129c5e
commit 6645f59832
2 changed files with 92 additions and 37 deletions

View File

@@ -128,8 +128,10 @@ bool is_mouse_key(int c)
/// @param which_button MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MIDDLE
int jump_to_mouse(int flags, bool *inclusive, int which_button)
{
static int on_status_line = 0; // #lines below bottom of window
static int on_sep_line = 0; // on separator right of window
static int status_line_offset = 0; // #lines offset from status line
static int sep_line_offset = 0; // #cols offset from sep line
static bool on_status_line = false;
static bool on_sep_line = false;
static bool on_winbar = false;
static int prev_row = -1;
static int prev_col = -1;
@@ -144,6 +146,7 @@ int jump_to_mouse(int flags, bool *inclusive, int which_button)
int col = mouse_col;
int grid = mouse_grid;
int fdc = 0;
bool keep_focus = flags & MOUSE_FOCUS;
mouse_past_bottom = false;
mouse_past_eol = false;
@@ -164,10 +167,10 @@ int jump_to_mouse(int flags, bool *inclusive, int which_button)
retnomove:
// before moving the cursor for a left click which is NOT in a status
// line, stop Visual mode
if (on_status_line) {
if (status_line_offset) {
return IN_STATUS_LINE;
}
if (on_sep_line) {
if (sep_line_offset) {
return IN_SEP_LINE;
}
if (on_winbar) {
@@ -189,49 +192,78 @@ retnomove:
old_curwin = curwin;
old_cursor = curwin->w_cursor;
if (!(flags & MOUSE_FOCUS)) {
if (row < 0 || col < 0) { // check if it makes sense
return IN_UNKNOWN;
if (row < 0 || col < 0) { // check if it makes sense
return IN_UNKNOWN;
}
// find the window where the row is in
wp = mouse_find_win(&grid, &row, &col);
if (wp == NULL) {
return IN_UNKNOWN;
}
on_status_line = (grid == DEFAULT_GRID_HANDLE && row + wp->w_winbar_height >= wp->w_height)
? row + wp->w_winbar_height - wp->w_height + 1 == 1
: false;
on_winbar = (row == -1)
? wp->w_winbar_height != 0
: false;
on_sep_line = grid == DEFAULT_GRID_HANDLE && col >= wp->w_width
? col - wp->w_width + 1 == 1
: false;
// The rightmost character of the status line might be a vertical
// separator character if there is no connecting window to the right.
if (on_status_line && on_sep_line) {
if (stl_connected(wp)) {
on_sep_line = false;
} else {
on_status_line = false;
}
}
if (keep_focus) {
// If we can't change focus, set the value of row, col and grid back to absolute values
// since the values relative to the window are only used when keep_focus is false
row = mouse_row;
col = mouse_col;
grid = mouse_grid;
}
if (!keep_focus) {
if (on_winbar) {
return IN_OTHER_WIN | MOUSE_WINBAR;
}
// find the window where the row is in
wp = mouse_find_win(&grid, &row, &col);
if (wp == NULL) {
return IN_UNKNOWN;
}
fdc = win_fdccol_count(wp);
dragwin = NULL;
if (row == -1) {
on_winbar = wp->w_winbar_height != 0;
return IN_OTHER_WIN | (on_winbar ? MOUSE_WINBAR : 0);
}
on_winbar = false;
// winpos and height may change in win_enter()!
if (grid == DEFAULT_GRID_HANDLE && row + wp->w_winbar_height >= wp->w_height) {
// In (or below) status line
on_status_line = row + wp->w_winbar_height - wp->w_height + 1;
status_line_offset = row + wp->w_winbar_height - wp->w_height + 1;
dragwin = wp;
} else {
on_status_line = 0;
status_line_offset = 0;
}
if (grid == DEFAULT_GRID_HANDLE && col >= wp->w_width) {
// In separator line
on_sep_line = col - wp->w_width + 1;
sep_line_offset = col - wp->w_width + 1;
dragwin = wp;
} else {
on_sep_line = 0;
sep_line_offset = 0;
}
// The rightmost character of the status line might be a vertical
// separator character if there is no connecting window to the right.
if (on_status_line && on_sep_line) {
if (status_line_offset && sep_line_offset) {
if (stl_connected(wp)) {
on_sep_line = 0;
sep_line_offset = 0;
} else {
on_status_line = 0;
status_line_offset = 0;
}
}
@@ -239,8 +271,8 @@ retnomove:
// click, stop Visual mode.
if (VIsual_active
&& (wp->w_buffer != curwin->w_buffer
|| (!on_status_line
&& !on_sep_line
|| (!status_line_offset
&& !sep_line_offset
&& (wp->w_p_rl
? col < wp->w_width_inner - fdc
: col >= fdc + (cmdwin_type == 0 && wp == curwin ? 0 : 1))
@@ -251,7 +283,7 @@ retnomove:
if (cmdwin_type != 0 && wp != curwin) {
// A click outside the command-line window: Use modeless
// selection if possible. Allow dragging the status lines.
on_sep_line = 0;
sep_line_offset = 0;
row = 0;
col += wp->w_wincol;
wp = curwin;
@@ -266,7 +298,7 @@ retnomove:
if (curwin != old_curwin) {
set_mouse_topline(curwin);
}
if (on_status_line) { // In (or below) status line
if (status_line_offset) { // In (or below) status line
// Don't use start_arrow() if we're in the same window
if (curwin == old_curwin) {
return IN_STATUS_LINE;
@@ -274,7 +306,7 @@ retnomove:
return IN_STATUS_LINE | CURSOR_MOVED;
}
}
if (on_sep_line) { // In (or below) status line
if (sep_line_offset) { // In (or below) status line
// Don't use start_arrow() if we're in the same window
if (curwin == old_curwin) {
return IN_SEP_LINE;
@@ -284,25 +316,27 @@ retnomove:
}
curwin->w_cursor.lnum = curwin->w_topline;
} else if (on_status_line) {
} else if (status_line_offset) {
if (which_button == MOUSE_LEFT && dragwin != NULL) {
// Drag the status line
count = row - dragwin->w_winrow - dragwin->w_height + 1
- on_status_line;
- status_line_offset;
win_drag_status_line(dragwin, count);
did_drag |= count;
}
return IN_STATUS_LINE; // Cursor didn't move
} else if (on_sep_line && which_button == MOUSE_LEFT) {
} else if (sep_line_offset && which_button == MOUSE_LEFT) {
if (dragwin != NULL) {
// Drag the separator column
count = col - dragwin->w_wincol - dragwin->w_width + 1
- on_sep_line;
- sep_line_offset;
win_drag_vsep_line(dragwin, count);
did_drag |= count;
}
return IN_SEP_LINE; // Cursor didn't move
} else if (on_winbar) {
} else if (on_status_line && which_button == MOUSE_RIGHT) {
return IN_STATUS_LINE;
} else if (on_winbar && which_button == MOUSE_RIGHT) {
// After a click on the window bar don't start Visual mode.
return IN_OTHER_WIN | MOUSE_WINBAR;
} else {

View File

@@ -20,7 +20,12 @@ describe('statusline clicks', function()
command('set laststatus=2')
exec([=[
function! MyClickFunc(minwid, clicks, button, mods)
let g:testvar = printf("%d %d %s", a:minwid, a:clicks, a:button)
let mods = trim(a:mods)
if mods ==# ''
let g:testvar = printf("%d %d %s", a:minwid, a:clicks, a:button)
else
let g:testvar = printf("%d %d %s %s", a:minwid, a:clicks, a:button, mods)
endif
endfunction
]=])
end)
@@ -37,7 +42,7 @@ describe('statusline clicks', function()
meths.set_option('winbar', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
meths.input_mouse('left', 'press', '', 0, 0, 17)
eq('0 1 l', eval("g:testvar"))
meths.input_mouse('right', 'press', '', 0, 6, 17)
meths.input_mouse('right', 'press', '', 0, 0, 17)
eq('0 1 r', eval("g:testvar"))
end)
@@ -84,6 +89,22 @@ describe('statusline clicks', function()
meths.input_mouse('left', 'press', '', 0, 6, 0)
eq(2, #meths.list_tabpages())
end)
it("right click works when statusline isn't focused #18994", function()
meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
meths.input_mouse('right', 'press', '', 0, 6, 17)
eq('0 1 r', eval("g:testvar"))
meths.input_mouse('right', 'press', '', 0, 6, 17)
eq('0 2 r', eval("g:testvar"))
end)
it("click works with modifiers #18994", function()
meths.set_option('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T')
meths.input_mouse('right', 'press', 's', 0, 6, 17)
eq('0 1 r s', eval("g:testvar"))
meths.input_mouse('left', 'press', 's', 0, 6, 17)
eq('0 1 l s', eval("g:testvar"))
end)
end)
describe('global statusline', function()