aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/normal.c
diff options
context:
space:
mode:
authorFamiu Haque <famiuhaque@protonmail.com>2022-05-23 19:11:24 +0600
committerGitHub <noreply@github.com>2022-05-23 06:11:24 -0700
commit4c6626f03dc645a426c1e63ca372b96f1073581b (patch)
treee0ab7136f9b7c32a827ad59bbe1d0cc3f6b7dd65 /src/nvim/normal.c
parent9e1ee9fb1d747facb6fa97a32dc5e22c7dfcb346 (diff)
downloadrneovim-4c6626f03dc645a426c1e63ca372b96f1073581b.tar.gz
rneovim-4c6626f03dc645a426c1e63ca372b96f1073581b.tar.bz2
rneovim-4c6626f03dc645a426c1e63ca372b96f1073581b.zip
feat: click support for 'statusline', 'winbar' #18650
The mouseclick item "%@" is now supported by 'statusline' and 'winbar'. Previously it was only supported by 'tabline'.
Diffstat (limited to 'src/nvim/normal.c')
-rw-r--r--src/nvim/normal.c153
1 files changed, 90 insertions, 63 deletions
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 0c55c64b5c..7c7a042eac 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -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.