feat: click support for 'statusline', 'winbar' #18650

The mouseclick item "%@" is now supported by 'statusline' and 'winbar'.
Previously it was only supported by 'tabline'.
This commit is contained in:
Famiu Haque
2022-05-23 19:11:24 +06:00
committed by GitHub
parent 9e1ee9fb1d
commit 4c6626f03d
10 changed files with 529 additions and 386 deletions

View File

@@ -32,6 +32,7 @@
#include "nvim/fold.h"
#include "nvim/getchar.h"
#include "nvim/globals.h"
#include "nvim/grid_defs.h"
#include "nvim/indent.h"
#include "nvim/keycodes.h"
#include "nvim/log.h"
@@ -1432,6 +1433,63 @@ static void move_tab_to_mouse(void)
}
}
/// Call click definition function for column "col" in the "click_defs" array for button
/// "which_button".
static void call_click_def_func(StlClickDefinition *click_defs, int col, int which_button)
{
typval_T argv[] = {
{
.v_lock = VAR_FIXED,
.v_type = VAR_NUMBER,
.vval = {
.v_number = (varnumber_T)click_defs[col].tabnr
},
},
{
.v_lock = VAR_FIXED,
.v_type = VAR_NUMBER,
.vval = {
.v_number = ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_4CLICK
? 4
: ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_3CLICK
? 3
: ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK
? 2
: 1)))
},
},
{
.v_lock = VAR_FIXED,
.v_type = VAR_STRING,
.vval = {
.v_string = (which_button == MOUSE_LEFT
? "l"
: (which_button == MOUSE_RIGHT
? "r"
: (which_button == MOUSE_MIDDLE
? "m"
: "?")))
},
},
{
.v_lock = VAR_FIXED,
.v_type = VAR_STRING,
.vval = {
.v_string = (char[]) {
(char)(mod_mask & MOD_MASK_SHIFT ? 's' : ' '),
(char)(mod_mask & MOD_MASK_CTRL ? 'c' : ' '),
(char)(mod_mask & MOD_MASK_ALT ? 'a' : ' '),
(char)(mod_mask & MOD_MASK_META ? 'm' : ' '),
NUL
}
},
}
};
typval_T rettv;
(void)call_vim_function(click_defs[col].func, ARRAY_SIZE(argv), argv, &rettv);
tv_clear(&rettv);
}
/// Do the appropriate action for the current mouse click in the current mode.
/// Not used for Command-line mode.
///
@@ -1481,6 +1539,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
int jump_flags = 0; // flags for jump_to_mouse()
pos_T start_visual;
bool moved; // Has cursor moved?
bool in_winbar; // mouse in window bar
bool in_status_line; // mouse in status line
static bool in_tab_line = false; // mouse clicked in tab line
bool in_sep_line; // mouse in vertical separator line
@@ -1711,66 +1770,10 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
}
}
break;
case kStlClickFuncRun: {
typval_T argv[] = {
{
.v_lock = VAR_FIXED,
.v_type = VAR_NUMBER,
.vval = {
.v_number = (varnumber_T)tab_page_click_defs[mouse_col].tabnr
},
},
{
.v_lock = VAR_FIXED,
.v_type = VAR_NUMBER,
.vval = {
.v_number = ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_4CLICK
? 4
: ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_3CLICK
? 3
: ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK
? 2
: 1)))
},
},
{
.v_lock = VAR_FIXED,
.v_type = VAR_STRING,
.vval = {
.v_string = (which_button == MOUSE_LEFT
? "l"
: (which_button == MOUSE_RIGHT
? "r"
: (which_button == MOUSE_MIDDLE
? "m"
: "?")))
},
},
{
.v_lock = VAR_FIXED,
.v_type = VAR_STRING,
.vval = {
.v_string = (char[]) {
(char)(mod_mask & MOD_MASK_SHIFT ? 's' : ' '),
(char)(mod_mask & MOD_MASK_CTRL ? 'c' : ' '),
(char)(mod_mask & MOD_MASK_ALT ? 'a' : ' '),
(char)(mod_mask & MOD_MASK_META ? 'm' : ' '),
NUL
}
},
}
};
typval_T rettv;
funcexe_T funcexe = FUNCEXE_INIT;
funcexe.firstline = curwin->w_cursor.lnum;
funcexe.lastline = curwin->w_cursor.lnum;
funcexe.evaluate = true;
(void)call_func(tab_page_click_defs[mouse_col].func, -1,
&rettv, ARRAY_SIZE(argv), argv, &funcexe);
tv_clear(&rettv);
case kStlClickFuncRun:
call_click_def_func(tab_page_click_defs, mouse_col, which_button);
break;
}
}
}
return true;
} else if (is_drag && in_tab_line) {
@@ -1840,15 +1843,39 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
oap == NULL ? NULL : &(oap->inclusive),
which_button);
// A click in the window bar has no side effects.
if (jump_flags & MOUSE_WINBAR) {
return false;
}
moved = (jump_flags & CURSOR_MOVED);
in_winbar = (jump_flags & MOUSE_WINBAR);
in_status_line = (jump_flags & IN_STATUS_LINE);
in_sep_line = (jump_flags & IN_SEP_LINE);
if ((in_winbar || in_status_line) && is_click) {
// Handle click event on window bar or status lin
int click_grid = mouse_grid;
int click_row = mouse_row;
int click_col = mouse_col;
win_T *wp = mouse_find_win(&click_grid, &click_row, &click_col);
StlClickDefinition *click_defs = in_status_line ? wp->w_status_click_defs
: wp->w_winbar_click_defs;
if (click_defs != NULL) {
switch (click_defs[click_col].type) {
case kStlClickDisabled:
break;
case kStlClickFuncRun:
call_click_def_func(click_defs, click_col, which_button);
break;
default:
assert(false && "winbar and statusline only support %@ for clicks");
break;
}
}
return false;
} else if (in_winbar) {
// A drag or release event in the window bar has no side effects.
return false;
}
// When jumping to another window, clear a pending operator. That's a bit
// friendlier than beeping and not jumping to that window.