mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
fix(mouse): 'statuscolumn' fold and popopmenu handling
Problem: A right-click on the 'statuscolumn' does not open the popupmenu, even if a cell without a clickdef is clicked. Clicking the %C fold item does not open/close the fold. Solution: Open the popupmenu when there is no clickdef like right-clicking the sign/numbercolumn does. Fill "linebuf_vcol" when drawing the 'statuscolumn' to handle foldcolumn item clicks.
This commit is contained in:
parent
a450fda4ed
commit
2cd72258f6
@ -368,14 +368,14 @@ static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode,
|
|||||||
|
|
||||||
// TODO(bfredl): integrate with grid.c linebuf code? madness?
|
// TODO(bfredl): integrate with grid.c linebuf code? madness?
|
||||||
static void draw_col_buf(win_T *wp, winlinevars_T *wlv, const char *text, size_t len, int attr,
|
static void draw_col_buf(win_T *wp, winlinevars_T *wlv, const char *text, size_t len, int attr,
|
||||||
bool vcol)
|
const colnr_T *fold_vcol, bool inc_vcol)
|
||||||
{
|
{
|
||||||
const char *ptr = text;
|
const char *ptr = text;
|
||||||
while (ptr < text + len && wlv->off < wp->w_grid.cols) {
|
while (ptr < text + len && wlv->off < wp->w_grid.cols) {
|
||||||
int cells = line_putchar(wp->w_buffer, &ptr, &linebuf_char[wlv->off],
|
int cells = line_putchar(wp->w_buffer, &ptr, &linebuf_char[wlv->off],
|
||||||
wp->w_grid.cols - wlv->off, wlv->off);
|
wp->w_grid.cols - wlv->off, wlv->off);
|
||||||
int myattr = attr;
|
int myattr = attr;
|
||||||
if (vcol) {
|
if (inc_vcol) {
|
||||||
advance_color_col(wlv, wlv->vcol);
|
advance_color_col(wlv, wlv->vcol);
|
||||||
if (wlv->color_cols && wlv->vcol == *wlv->color_cols) {
|
if (wlv->color_cols && wlv->vcol == *wlv->color_cols) {
|
||||||
myattr = hl_combine_attr(win_hl_attr(wp, HLF_MC), myattr);
|
myattr = hl_combine_attr(win_hl_attr(wp, HLF_MC), myattr);
|
||||||
@ -383,7 +383,7 @@ static void draw_col_buf(win_T *wp, winlinevars_T *wlv, const char *text, size_t
|
|||||||
}
|
}
|
||||||
for (int c = 0; c < cells; c++) {
|
for (int c = 0; c < cells; c++) {
|
||||||
linebuf_attr[wlv->off] = myattr;
|
linebuf_attr[wlv->off] = myattr;
|
||||||
linebuf_vcol[wlv->off] = vcol ? wlv->vcol++ : -1;
|
linebuf_vcol[wlv->off] = inc_vcol ? wlv->vcol++ : fold_vcol ? *(fold_vcol++) : -1;
|
||||||
wlv->off++;
|
wlv->off++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -412,7 +412,7 @@ static void draw_foldcolumn(win_T *wp, winlinevars_T *wlv)
|
|||||||
int fdc = compute_foldcolumn(wp, 0);
|
int fdc = compute_foldcolumn(wp, 0);
|
||||||
if (fdc > 0) {
|
if (fdc > 0) {
|
||||||
int attr = win_hl_attr(wp, use_cursor_line_highlight(wp, wlv->lnum) ? HLF_CLF : HLF_FC);
|
int attr = win_hl_attr(wp, use_cursor_line_highlight(wp, wlv->lnum) ? HLF_CLF : HLF_FC);
|
||||||
fill_foldcolumn(wp, wlv->foldinfo, wlv->lnum, attr, fdc, &wlv->off, NULL);
|
fill_foldcolumn(wp, wlv->foldinfo, wlv->lnum, attr, fdc, &wlv->off, NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -421,8 +421,9 @@ static void draw_foldcolumn(win_T *wp, winlinevars_T *wlv)
|
|||||||
/// @param fdc Current width of the foldcolumn
|
/// @param fdc Current width of the foldcolumn
|
||||||
/// @param[out] wlv_off Pointer to linebuf offset, incremented for default column
|
/// @param[out] wlv_off Pointer to linebuf offset, incremented for default column
|
||||||
/// @param[out] out_buffer Char array to fill, only used for 'statuscolumn'
|
/// @param[out] out_buffer Char array to fill, only used for 'statuscolumn'
|
||||||
|
/// @param[out] out_vcol vcol array to fill, only used for 'statuscolumn'
|
||||||
void fill_foldcolumn(win_T *wp, foldinfo_T foldinfo, linenr_T lnum, int attr, int fdc, int *wlv_off,
|
void fill_foldcolumn(win_T *wp, foldinfo_T foldinfo, linenr_T lnum, int attr, int fdc, int *wlv_off,
|
||||||
schar_T *out_buffer)
|
colnr_T *out_vcol, schar_T *out_buffer)
|
||||||
{
|
{
|
||||||
bool closed = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0;
|
bool closed = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0;
|
||||||
int level = foldinfo.fi_level;
|
int level = foldinfo.fi_level;
|
||||||
@ -448,10 +449,12 @@ void fill_foldcolumn(win_T *wp, foldinfo_T foldinfo, linenr_T lnum, int attr, in
|
|||||||
symbol = schar_from_ascii('>');
|
symbol = schar_from_ascii('>');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int vcol = i >= level ? -1 : (i == closedcol - 1 && closed) ? -2 : -3;
|
||||||
if (out_buffer) {
|
if (out_buffer) {
|
||||||
|
out_vcol[i] = vcol;
|
||||||
out_buffer[i] = symbol;
|
out_buffer[i] = symbol;
|
||||||
} else {
|
} else {
|
||||||
linebuf_vcol[*wlv_off] = i >= level ? -1 : (i == closedcol - 1 && closed) ? -2 : -3;
|
linebuf_vcol[*wlv_off] = vcol;
|
||||||
linebuf_attr[*wlv_off] = attr;
|
linebuf_attr[*wlv_off] = attr;
|
||||||
linebuf_char[(*wlv_off)++] = symbol;
|
linebuf_char[(*wlv_off)++] = symbol;
|
||||||
}
|
}
|
||||||
@ -577,7 +580,7 @@ static void draw_lnum_col(win_T *wp, winlinevars_T *wlv)
|
|||||||
char *num = skipwhite(buf);
|
char *num = skipwhite(buf);
|
||||||
rl_mirror_ascii(num, skiptowhite(num));
|
rl_mirror_ascii(num, skiptowhite(num));
|
||||||
}
|
}
|
||||||
draw_col_buf(wp, wlv, buf, (size_t)width, attr, false);
|
draw_col_buf(wp, wlv, buf, (size_t)width, attr, NULL, false);
|
||||||
} else {
|
} else {
|
||||||
draw_col_fill(wlv, schar_from_ascii(' '), width, attr);
|
draw_col_fill(wlv, schar_from_ascii(' '), width, attr);
|
||||||
}
|
}
|
||||||
@ -632,6 +635,7 @@ static void draw_statuscol(win_T *wp, winlinevars_T *wlv, linenr_T lnum, int vir
|
|||||||
|
|
||||||
char *p = buf;
|
char *p = buf;
|
||||||
char transbuf[MAXPATHL];
|
char transbuf[MAXPATHL];
|
||||||
|
colnr_T *fold_vcol = NULL;
|
||||||
size_t len = strlen(buf);
|
size_t len = strlen(buf);
|
||||||
int scl_attr = win_hl_attr(wp, use_cursor_line_highlight(wp, wlv->lnum) ? HLF_CLS : HLF_SC);
|
int scl_attr = win_hl_attr(wp, use_cursor_line_highlight(wp, wlv->lnum) ? HLF_CLS : HLF_SC);
|
||||||
int num_attr = hl_combine_attr(get_line_number_attr(wp, wlv),
|
int num_attr = hl_combine_attr(get_line_number_attr(wp, wlv),
|
||||||
@ -643,13 +647,14 @@ static void draw_statuscol(win_T *wp, winlinevars_T *wlv, linenr_T lnum, int vir
|
|||||||
ptrdiff_t textlen = sp->start - p;
|
ptrdiff_t textlen = sp->start - p;
|
||||||
// Make all characters printable.
|
// Make all characters printable.
|
||||||
size_t translen = transstr_buf(p, textlen, transbuf, MAXPATHL, true);
|
size_t translen = transstr_buf(p, textlen, transbuf, MAXPATHL, true);
|
||||||
draw_col_buf(wp, wlv, transbuf, translen, cur_attr, false);
|
draw_col_buf(wp, wlv, transbuf, translen, cur_attr, fold_vcol, false);
|
||||||
int attr = sp->item == STL_SIGNCOL ? scl_attr : sp->item == STL_FOLDCOL ? 0 : num_attr;
|
int attr = sp->item == STL_SIGNCOL ? scl_attr : sp->item == STL_FOLDCOL ? 0 : num_attr;
|
||||||
cur_attr = hl_combine_attr(attr, sp->userhl < 0 ? syn_id2attr(-sp->userhl) : 0);
|
cur_attr = hl_combine_attr(attr, sp->userhl < 0 ? syn_id2attr(-sp->userhl) : 0);
|
||||||
|
fold_vcol = sp->item == STL_FOLDCOL ? stcp->fold_vcol : NULL;
|
||||||
p = sp->start;
|
p = sp->start;
|
||||||
}
|
}
|
||||||
size_t translen = transstr_buf(p, buf + len - p, transbuf, MAXPATHL, true);
|
size_t translen = transstr_buf(p, buf + len - p, transbuf, MAXPATHL, true);
|
||||||
draw_col_buf(wp, wlv, transbuf, translen, num_attr, false);
|
draw_col_buf(wp, wlv, transbuf, translen, num_attr, fold_vcol, false);
|
||||||
draw_col_fill(wlv, schar_from_ascii(' '), stcp->width - width, num_attr);
|
draw_col_fill(wlv, schar_from_ascii(' '), stcp->width - width, num_attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -722,7 +727,7 @@ static void handle_showbreak_and_filler(win_T *wp, winlinevars_T *wlv)
|
|||||||
// Combine 'showbreak' with 'cursorline', prioritizing 'showbreak'.
|
// Combine 'showbreak' with 'cursorline', prioritizing 'showbreak'.
|
||||||
int attr = hl_combine_attr(wlv->cul_attr, win_hl_attr(wp, HLF_AT));
|
int attr = hl_combine_attr(wlv->cul_attr, win_hl_attr(wp, HLF_AT));
|
||||||
colnr_T vcol_before = wlv->vcol;
|
colnr_T vcol_before = wlv->vcol;
|
||||||
draw_col_buf(wp, wlv, sbr, strlen(sbr), attr, true);
|
draw_col_buf(wp, wlv, sbr, strlen(sbr), attr, NULL, true);
|
||||||
wlv->vcol_sbr = wlv->vcol;
|
wlv->vcol_sbr = wlv->vcol;
|
||||||
|
|
||||||
// Correct start of highlighted area for 'showbreak'.
|
// Correct start of highlighted area for 'showbreak'.
|
||||||
|
190
src/nvim/mouse.c
190
src/nvim/mouse.c
@ -280,6 +280,54 @@ static int get_fpos_of_mouse(pos_T *mpos)
|
|||||||
return IN_BUFFER;
|
return IN_BUFFER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_popup(int which_button, int m_pos_flag, pos_T m_pos)
|
||||||
|
{
|
||||||
|
int jump_flags = 0;
|
||||||
|
if (strcmp(p_mousem, "popup_setpos") == 0) {
|
||||||
|
// First set the cursor position before showing the popup menu.
|
||||||
|
if (VIsual_active) {
|
||||||
|
// set MOUSE_MAY_STOP_VIS if we are outside the selection
|
||||||
|
// or the current window (might have false negative here)
|
||||||
|
if (m_pos_flag != IN_BUFFER) {
|
||||||
|
jump_flags = MOUSE_MAY_STOP_VIS;
|
||||||
|
} else {
|
||||||
|
if (VIsual_mode == 'V') {
|
||||||
|
if ((curwin->w_cursor.lnum <= VIsual.lnum
|
||||||
|
&& (m_pos.lnum < curwin->w_cursor.lnum || VIsual.lnum < m_pos.lnum))
|
||||||
|
|| (VIsual.lnum < curwin->w_cursor.lnum
|
||||||
|
&& (m_pos.lnum < VIsual.lnum || curwin->w_cursor.lnum < m_pos.lnum))) {
|
||||||
|
jump_flags = MOUSE_MAY_STOP_VIS;
|
||||||
|
}
|
||||||
|
} else if ((ltoreq(curwin->w_cursor, VIsual)
|
||||||
|
&& (lt(m_pos, curwin->w_cursor) || lt(VIsual, m_pos)))
|
||||||
|
|| (lt(VIsual, curwin->w_cursor)
|
||||||
|
&& (lt(m_pos, VIsual) || lt(curwin->w_cursor, m_pos)))) {
|
||||||
|
jump_flags = MOUSE_MAY_STOP_VIS;
|
||||||
|
} else if (VIsual_mode == Ctrl_V) {
|
||||||
|
colnr_T leftcol, rightcol;
|
||||||
|
getvcols(curwin, &curwin->w_cursor, &VIsual, &leftcol, &rightcol);
|
||||||
|
getvcol(curwin, &m_pos, NULL, &m_pos.col, NULL);
|
||||||
|
if (m_pos.col < leftcol || m_pos.col > rightcol) {
|
||||||
|
jump_flags = MOUSE_MAY_STOP_VIS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
jump_flags = MOUSE_MAY_STOP_VIS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (jump_flags) {
|
||||||
|
jump_flags = jump_to_mouse(jump_flags, NULL, which_button);
|
||||||
|
redraw_curbuf_later(VIsual_active ? UPD_INVERTED : UPD_VALID);
|
||||||
|
update_screen();
|
||||||
|
setcursor();
|
||||||
|
ui_flush(); // Update before showing popup menu
|
||||||
|
}
|
||||||
|
show_popupmenu();
|
||||||
|
got_click = false; // ignore release events
|
||||||
|
return jump_flags;
|
||||||
|
}
|
||||||
|
|
||||||
/// Do the appropriate action for the current mouse click in the current mode.
|
/// Do the appropriate action for the current mouse click in the current mode.
|
||||||
/// Not used for Command-line mode.
|
/// Not used for Command-line mode.
|
||||||
///
|
///
|
||||||
@ -324,24 +372,8 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
|
|||||||
int which_button; // MOUSE_LEFT, _MIDDLE or _RIGHT
|
int which_button; // MOUSE_LEFT, _MIDDLE or _RIGHT
|
||||||
bool is_click; // If false it's a drag or release event
|
bool is_click; // If false it's a drag or release event
|
||||||
bool is_drag; // If true it's a drag event
|
bool is_drag; // If true it's a drag event
|
||||||
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_statuscol; // mouse in status column
|
|
||||||
bool in_status_line; // mouse in status line
|
|
||||||
static bool in_tab_line = false; // mouse clicked in tab line
|
static bool in_tab_line = false; // mouse clicked in tab line
|
||||||
bool in_sep_line; // mouse in vertical separator line
|
|
||||||
int c1;
|
|
||||||
win_T *old_curwin = curwin;
|
|
||||||
static pos_T orig_cursor;
|
static pos_T orig_cursor;
|
||||||
colnr_T leftcol, rightcol;
|
|
||||||
pos_T end_visual;
|
|
||||||
int old_active = VIsual_active;
|
|
||||||
int old_mode = VIsual_mode;
|
|
||||||
int regname;
|
|
||||||
|
|
||||||
pos_T save_cursor = curwin->w_cursor;
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
which_button = get_mouse_button(KEY2TERMCAP1(c), &is_click, &is_drag);
|
which_button = get_mouse_button(KEY2TERMCAP1(c), &is_click, &is_drag);
|
||||||
@ -434,12 +466,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oap != NULL) {
|
int regname = oap != NULL ? oap->regname : 0;
|
||||||
regname = oap->regname;
|
|
||||||
} else {
|
|
||||||
regname = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Middle mouse button does a 'put' of the selected text
|
// Middle mouse button does a 'put' of the selected text
|
||||||
if (which_button == MOUSE_MIDDLE) {
|
if (which_button == MOUSE_MIDDLE) {
|
||||||
if (State == MODE_NORMAL) {
|
if (State == MODE_NORMAL) {
|
||||||
@ -496,12 +523,10 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// flags for jump_to_mouse()
|
||||||
// When dragging or button-up stay in the same window.
|
// When dragging or button-up stay in the same window.
|
||||||
if (!is_click) {
|
int jump_flags = is_click ? 0 : (MOUSE_FOCUS|MOUSE_DID_MOVE);
|
||||||
jump_flags |= MOUSE_FOCUS | MOUSE_DID_MOVE;
|
win_T *old_curwin = curwin;
|
||||||
}
|
|
||||||
|
|
||||||
start_visual.lnum = 0;
|
|
||||||
|
|
||||||
if (tab_page_click_defs != NULL) { // only when initialized
|
if (tab_page_click_defs != NULL) { // only when initialized
|
||||||
// Check for clicking in the tab page line.
|
// Check for clicking in the tab page line.
|
||||||
@ -515,8 +540,8 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
|
|||||||
|
|
||||||
// click in a tab selects that tab page
|
// click in a tab selects that tab page
|
||||||
if (is_click && cmdwin_type == 0 && mouse_col < Columns) {
|
if (is_click && cmdwin_type == 0 && mouse_col < Columns) {
|
||||||
|
int tabnr = tab_page_click_defs[mouse_col].tabnr;
|
||||||
in_tab_line = true;
|
in_tab_line = true;
|
||||||
c1 = tab_page_click_defs[mouse_col].tabnr;
|
|
||||||
|
|
||||||
switch (tab_page_click_defs[mouse_col].type) {
|
switch (tab_page_click_defs[mouse_col].type) {
|
||||||
case kStlClickDisabled:
|
case kStlClickDisabled:
|
||||||
@ -527,11 +552,11 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
|
|||||||
// double click opens new page
|
// double click opens new page
|
||||||
end_visual_mode();
|
end_visual_mode();
|
||||||
tabpage_new();
|
tabpage_new();
|
||||||
tabpage_move(c1 == 0 ? 9999 : c1 - 1);
|
tabpage_move(tabnr == 0 ? 9999 : tabnr - 1);
|
||||||
} else {
|
} else {
|
||||||
// Go to specified tab page, or next one if not clicking
|
// Go to specified tab page, or next one if not clicking
|
||||||
// on a label.
|
// on a label.
|
||||||
goto_tabpage(c1);
|
goto_tabpage(tabnr);
|
||||||
|
|
||||||
// It's like clicking on the status line of a window.
|
// It's like clicking on the status line of a window.
|
||||||
if (curwin != old_curwin) {
|
if (curwin != old_curwin) {
|
||||||
@ -542,7 +567,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
|
|||||||
}
|
}
|
||||||
FALLTHROUGH;
|
FALLTHROUGH;
|
||||||
case kStlClickTabClose:
|
case kStlClickTabClose:
|
||||||
mouse_tab_close(c1);
|
mouse_tab_close(tabnr);
|
||||||
break;
|
break;
|
||||||
case kStlClickFuncRun:
|
case kStlClickFuncRun:
|
||||||
call_click_def_func(tab_page_click_defs, mouse_col, which_button);
|
call_click_def_func(tab_page_click_defs, mouse_col, which_button);
|
||||||
@ -556,75 +581,33 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int m_pos_flag = 0;
|
||||||
|
pos_T m_pos = { 0 };
|
||||||
// When 'mousemodel' is "popup" or "popup_setpos", translate mouse events:
|
// When 'mousemodel' is "popup" or "popup_setpos", translate mouse events:
|
||||||
// right button up -> pop-up menu
|
// right button up -> pop-up menu
|
||||||
// shift-left button -> right button
|
// shift-left button -> right button
|
||||||
// alt-left button -> alt-right button
|
// alt-left button -> alt-right button
|
||||||
if (mouse_model_popup()) {
|
if (mouse_model_popup()) {
|
||||||
pos_T m_pos;
|
m_pos_flag = get_fpos_of_mouse(&m_pos);
|
||||||
int m_pos_flag = get_fpos_of_mouse(&m_pos);
|
if (!(m_pos_flag & (IN_STATUS_LINE|MOUSE_WINBAR|MOUSE_STATUSCOL))
|
||||||
if (m_pos_flag & (IN_STATUS_LINE|MOUSE_WINBAR|MOUSE_STATUSCOL)) {
|
&& which_button == MOUSE_RIGHT && !(mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL))) {
|
||||||
goto popupexit;
|
|
||||||
}
|
|
||||||
if (which_button == MOUSE_RIGHT
|
|
||||||
&& !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))) {
|
|
||||||
if (!is_click) {
|
if (!is_click) {
|
||||||
// Ignore right button release events, only shows the popup
|
// Ignore right button release events, only shows the popup
|
||||||
// menu on the button down event.
|
// menu on the button down event.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
jump_flags = 0;
|
return (do_popup(which_button, m_pos_flag, m_pos) & CURSOR_MOVED);
|
||||||
if (strcmp(p_mousem, "popup_setpos") == 0) {
|
|
||||||
// First set the cursor position before showing the popup menu.
|
|
||||||
if (VIsual_active) {
|
|
||||||
// set MOUSE_MAY_STOP_VIS if we are outside the selection
|
|
||||||
// or the current window (might have false negative here)
|
|
||||||
if (m_pos_flag != IN_BUFFER) {
|
|
||||||
jump_flags = MOUSE_MAY_STOP_VIS;
|
|
||||||
} else {
|
|
||||||
if (VIsual_mode == 'V') {
|
|
||||||
if ((curwin->w_cursor.lnum <= VIsual.lnum
|
|
||||||
&& (m_pos.lnum < curwin->w_cursor.lnum || VIsual.lnum < m_pos.lnum))
|
|
||||||
|| (VIsual.lnum < curwin->w_cursor.lnum
|
|
||||||
&& (m_pos.lnum < VIsual.lnum || curwin->w_cursor.lnum < m_pos.lnum))) {
|
|
||||||
jump_flags = MOUSE_MAY_STOP_VIS;
|
|
||||||
}
|
|
||||||
} else if ((ltoreq(curwin->w_cursor, VIsual)
|
|
||||||
&& (lt(m_pos, curwin->w_cursor) || lt(VIsual, m_pos)))
|
|
||||||
|| (lt(VIsual, curwin->w_cursor)
|
|
||||||
&& (lt(m_pos, VIsual) || lt(curwin->w_cursor, m_pos)))) {
|
|
||||||
jump_flags = MOUSE_MAY_STOP_VIS;
|
|
||||||
} else if (VIsual_mode == Ctrl_V) {
|
|
||||||
getvcols(curwin, &curwin->w_cursor, &VIsual, &leftcol, &rightcol);
|
|
||||||
getvcol(curwin, &m_pos, NULL, &m_pos.col, NULL);
|
|
||||||
if (m_pos.col < leftcol || m_pos.col > rightcol) {
|
|
||||||
jump_flags = MOUSE_MAY_STOP_VIS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
jump_flags = MOUSE_MAY_STOP_VIS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (jump_flags) {
|
|
||||||
jump_flags = jump_to_mouse(jump_flags, NULL, which_button);
|
|
||||||
redraw_curbuf_later(VIsual_active ? UPD_INVERTED : UPD_VALID);
|
|
||||||
update_screen();
|
|
||||||
setcursor();
|
|
||||||
ui_flush(); // Update before showing popup menu
|
|
||||||
}
|
|
||||||
show_popupmenu();
|
|
||||||
got_click = false; // ignore release events
|
|
||||||
return (jump_flags & CURSOR_MOVED) != 0;
|
|
||||||
}
|
}
|
||||||
if (which_button == MOUSE_LEFT
|
// Only do this translation when mouse is over the buffer text
|
||||||
&& (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_ALT))) {
|
if (!(m_pos_flag & (IN_STATUS_LINE|MOUSE_WINBAR|MOUSE_STATUSCOL))
|
||||||
|
&& (which_button == MOUSE_LEFT && (mod_mask & (MOD_MASK_SHIFT|MOD_MASK_ALT)))) {
|
||||||
which_button = MOUSE_RIGHT;
|
which_button = MOUSE_RIGHT;
|
||||||
mod_mask &= ~MOD_MASK_SHIFT;
|
mod_mask &= ~MOD_MASK_SHIFT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
popupexit:
|
|
||||||
|
|
||||||
|
pos_T end_visual = { 0 };
|
||||||
|
pos_T start_visual = { 0 };
|
||||||
if ((State & (MODE_NORMAL | MODE_INSERT))
|
if ((State & (MODE_NORMAL | MODE_INSERT))
|
||||||
&& !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))) {
|
&& !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))) {
|
||||||
if (which_button == MOUSE_LEFT) {
|
if (which_button == MOUSE_LEFT) {
|
||||||
@ -664,15 +647,15 @@ popupexit:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// JUMP!
|
// JUMP!
|
||||||
jump_flags = jump_to_mouse(jump_flags,
|
int old_active = VIsual_active;
|
||||||
oap == NULL ? NULL : &(oap->inclusive),
|
pos_T save_cursor = curwin->w_cursor;
|
||||||
which_button);
|
jump_flags = jump_to_mouse(jump_flags, oap == NULL ? NULL : &(oap->inclusive), which_button);
|
||||||
|
|
||||||
moved = (jump_flags & CURSOR_MOVED);
|
bool moved = (jump_flags & CURSOR_MOVED);
|
||||||
in_winbar = (jump_flags & MOUSE_WINBAR);
|
bool in_winbar = (jump_flags & MOUSE_WINBAR);
|
||||||
in_statuscol = (jump_flags & MOUSE_STATUSCOL);
|
bool in_statuscol = (jump_flags & MOUSE_STATUSCOL);
|
||||||
in_status_line = (jump_flags & IN_STATUS_LINE);
|
bool in_status_line = (jump_flags & IN_STATUS_LINE);
|
||||||
in_sep_line = (jump_flags & IN_SEP_LINE);
|
bool in_sep_line = (jump_flags & IN_SEP_LINE);
|
||||||
|
|
||||||
if ((in_winbar || in_status_line || in_statuscol) && is_click) {
|
if ((in_winbar || in_status_line || in_statuscol) && is_click) {
|
||||||
// Handle click event on window bar, status line or status column
|
// Handle click event on window bar, status line or status column
|
||||||
@ -705,6 +688,12 @@ popupexit:
|
|||||||
if (click_defs != NULL) {
|
if (click_defs != NULL) {
|
||||||
switch (click_defs[click_col].type) {
|
switch (click_defs[click_col].type) {
|
||||||
case kStlClickDisabled:
|
case kStlClickDisabled:
|
||||||
|
// If there is no click definition, still open the popupmenu for a
|
||||||
|
// statuscolumn click like a click in the sign/number column does.
|
||||||
|
if (in_statuscol && mouse_model_popup()
|
||||||
|
&& which_button == MOUSE_RIGHT && !(mod_mask & (MOD_MASK_SHIFT|MOD_MASK_CTRL))) {
|
||||||
|
do_popup(which_button, m_pos_flag, m_pos);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case kStlClickFuncRun:
|
case kStlClickFuncRun:
|
||||||
call_click_def_func(click_defs, click_col, which_button);
|
call_click_def_func(click_defs, click_col, which_button);
|
||||||
@ -715,7 +704,9 @@ popupexit:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
if (!(in_statuscol && (jump_flags & (MOUSE_FOLD_CLOSE|MOUSE_FOLD_OPEN)))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else if (in_winbar || in_statuscol) {
|
} else if (in_winbar || in_statuscol) {
|
||||||
// A drag or release event in the window bar and status column has no side effects.
|
// A drag or release event in the window bar and status column has no side effects.
|
||||||
return false;
|
return false;
|
||||||
@ -760,6 +751,7 @@ popupexit:
|
|||||||
mouse_row = 0;
|
mouse_row = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int old_mode = VIsual_mode;
|
||||||
if (start_visual.lnum) { // right click in visual mode
|
if (start_visual.lnum) { // right click in visual mode
|
||||||
linenr_T diff;
|
linenr_T diff;
|
||||||
// When ALT is pressed make Visual mode blockwise.
|
// When ALT is pressed make Visual mode blockwise.
|
||||||
@ -770,6 +762,7 @@ popupexit:
|
|||||||
// In Visual-block mode, divide the area in four, pick up the corner
|
// In Visual-block mode, divide the area in four, pick up the corner
|
||||||
// that is in the quarter that the cursor is in.
|
// that is in the quarter that the cursor is in.
|
||||||
if (VIsual_mode == Ctrl_V) {
|
if (VIsual_mode == Ctrl_V) {
|
||||||
|
colnr_T leftcol, rightcol;
|
||||||
getvcols(curwin, &start_visual, &end_visual, &leftcol, &rightcol);
|
getvcols(curwin, &start_visual, &end_visual, &leftcol, &rightcol);
|
||||||
if (curwin->w_curswant > (leftcol + rightcol) / 2) {
|
if (curwin->w_curswant > (leftcol + rightcol) / 2) {
|
||||||
end_visual.col = leftcol;
|
end_visual.col = leftcol;
|
||||||
@ -831,7 +824,6 @@ popupexit:
|
|||||||
|
|
||||||
// Middle mouse click: Put text before cursor.
|
// Middle mouse click: Put text before cursor.
|
||||||
if (which_button == MOUSE_MIDDLE) {
|
if (which_button == MOUSE_MIDDLE) {
|
||||||
int c2;
|
|
||||||
if (regname == 0 && eval_has_provider("clipboard", false)) {
|
if (regname == 0 && eval_has_provider("clipboard", false)) {
|
||||||
regname = '*';
|
regname = '*';
|
||||||
}
|
}
|
||||||
@ -843,6 +835,7 @@ popupexit:
|
|||||||
dir = FORWARD;
|
dir = FORWARD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int c1, c2;
|
||||||
if (fixindent) {
|
if (fixindent) {
|
||||||
c1 = (dir == BACKWARD) ? '[' : ']';
|
c1 = (dir == BACKWARD) ? '[' : ']';
|
||||||
c2 = 'p';
|
c2 = 'p';
|
||||||
@ -1258,8 +1251,6 @@ retnomove:
|
|||||||
if (flags & MOUSE_SETPOS) {
|
if (flags & MOUSE_SETPOS) {
|
||||||
goto retnomove; // ugly goto...
|
goto retnomove; // ugly goto...
|
||||||
}
|
}
|
||||||
win_T *old_curwin = curwin;
|
|
||||||
pos_T old_cursor = curwin->w_cursor;
|
|
||||||
|
|
||||||
if (row < 0 || col < 0) { // check if it makes sense
|
if (row < 0 || col < 0) { // check if it makes sense
|
||||||
return IN_UNKNOWN;
|
return IN_UNKNOWN;
|
||||||
@ -1299,13 +1290,15 @@ retnomove:
|
|||||||
grid = mouse_grid;
|
grid = mouse_grid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
win_T *old_curwin = curwin;
|
||||||
|
pos_T old_cursor = curwin->w_cursor;
|
||||||
if (!keep_focus) {
|
if (!keep_focus) {
|
||||||
if (on_winbar) {
|
if (on_winbar) {
|
||||||
return IN_OTHER_WIN | MOUSE_WINBAR;
|
return IN_OTHER_WIN | MOUSE_WINBAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (on_statuscol) {
|
if (on_statuscol) {
|
||||||
return IN_OTHER_WIN | MOUSE_STATUSCOL;
|
goto foldclick;
|
||||||
}
|
}
|
||||||
|
|
||||||
fdc = win_fdccol_count(wp);
|
fdc = win_fdccol_count(wp);
|
||||||
@ -1497,6 +1490,7 @@ retnomove:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foldclick:;
|
||||||
colnr_T col_from_screen = -1;
|
colnr_T col_from_screen = -1;
|
||||||
int mouse_fold_flags = 0;
|
int mouse_fold_flags = 0;
|
||||||
mouse_check_grid(&col_from_screen, &mouse_fold_flags);
|
mouse_check_grid(&col_from_screen, &mouse_fold_flags);
|
||||||
@ -1535,7 +1529,7 @@ retnomove:
|
|||||||
*inclusive = false;
|
*inclusive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
count = IN_BUFFER;
|
count = on_statuscol ? (IN_OTHER_WIN|MOUSE_STATUSCOL) : IN_BUFFER;
|
||||||
if (curwin != old_curwin || curwin->w_cursor.lnum != old_cursor.lnum
|
if (curwin != old_curwin || curwin->w_cursor.lnum != old_cursor.lnum
|
||||||
|| curwin->w_cursor.col != old_cursor.col) {
|
|| curwin->w_cursor.col != old_cursor.col) {
|
||||||
count |= CURSOR_MOVED; // Cursor has moved
|
count |= CURSOR_MOVED; // Cursor has moved
|
||||||
|
@ -1157,9 +1157,11 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the group is longer than it is allowed to be
|
// If the group is longer than it is allowed to be truncate by removing
|
||||||
// truncate by removing bytes from the start of the group text.
|
// bytes from the start of the group text. Don't truncate when item is a
|
||||||
if (group_len > stl_items[stl_groupitems[groupdepth]].maxwid) {
|
// 'statuscolumn' fold item to ensure correctness of the mouse clicks.
|
||||||
|
if (group_len > stl_items[stl_groupitems[groupdepth]].maxwid
|
||||||
|
&& stl_items[stl_groupitems[groupdepth]].type != HighlightFold) {
|
||||||
// { Determine the number of bytes to remove
|
// { Determine the number of bytes to remove
|
||||||
|
|
||||||
// Find the first character that should be included.
|
// Find the first character that should be included.
|
||||||
@ -1637,7 +1639,7 @@ stcsign:
|
|||||||
|
|
||||||
if (fdc > 0) {
|
if (fdc > 0) {
|
||||||
schar_T fold_buf[9];
|
schar_T fold_buf[9];
|
||||||
fill_foldcolumn(wp, stcp->foldinfo, lnum, 0, fdc, NULL, fold_buf);
|
fill_foldcolumn(wp, stcp->foldinfo, lnum, 0, fdc, NULL, stcp->fold_vcol, fold_buf);
|
||||||
stl_items[curitem].minwid = -(use_cursor_line_highlight(wp, lnum) ? HLF_CLF : HLF_FC);
|
stl_items[curitem].minwid = -(use_cursor_line_highlight(wp, lnum) ? HLF_CLF : HLF_FC);
|
||||||
size_t buflen = 0;
|
size_t buflen = 0;
|
||||||
// TODO(bfredl): this is very backwards. we must support schar_T
|
// TODO(bfredl): this is very backwards. we must support schar_T
|
||||||
|
@ -103,5 +103,6 @@ typedef struct {
|
|||||||
bool draw; ///< whether to draw the statuscolumn
|
bool draw; ///< whether to draw the statuscolumn
|
||||||
stl_hlrec_t *hlrec; ///< highlight groups
|
stl_hlrec_t *hlrec; ///< highlight groups
|
||||||
foldinfo_T foldinfo; ///< fold information
|
foldinfo_T foldinfo; ///< fold information
|
||||||
|
colnr_T fold_vcol[9]; ///< vcol array filled for fold item
|
||||||
SignTextAttrs *sattrs; ///< sign attributes
|
SignTextAttrs *sattrs; ///< sign attributes
|
||||||
} statuscol_T;
|
} statuscol_T;
|
||||||
|
@ -13,8 +13,6 @@ local api = n.api
|
|||||||
local pcall_err = t.pcall_err
|
local pcall_err = t.pcall_err
|
||||||
local assert_alive = n.assert_alive
|
local assert_alive = n.assert_alive
|
||||||
|
|
||||||
local mousemodels = { 'extend', 'popup', 'popup_setpos' }
|
|
||||||
|
|
||||||
describe('statuscolumn', function()
|
describe('statuscolumn', function()
|
||||||
local screen
|
local screen
|
||||||
before_each(function()
|
before_each(function()
|
||||||
@ -592,7 +590,7 @@ describe('statuscolumn', function()
|
|||||||
]])
|
]])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
for _, model in ipairs(mousemodels) do
|
for _, model in ipairs({ 'extend', 'popup', 'popup_setpos' }) do
|
||||||
describe('with mousemodel=' .. model, function()
|
describe('with mousemodel=' .. model, function()
|
||||||
before_each(function()
|
before_each(function()
|
||||||
command('set mousemodel=' .. model)
|
command('set mousemodel=' .. model)
|
||||||
@ -651,23 +649,56 @@ describe('statuscolumn', function()
|
|||||||
-- Check that statusline click doesn't register as statuscolumn click
|
-- Check that statusline click doesn't register as statuscolumn click
|
||||||
api.nvim_input_mouse('right', 'press', '', 0, 12, 0)
|
api.nvim_input_mouse('right', 'press', '', 0, 12, 0)
|
||||||
eq('', eval('g:testvar'))
|
eq('', eval('g:testvar'))
|
||||||
|
-- Check that rightclick still opens popupmenu if there is no clickdef
|
||||||
|
if model == 'popup' then
|
||||||
|
api.nvim_set_option_value('statuscolumn', '%0@MyClickFunc@%=%l%TNoClick', {})
|
||||||
|
api.nvim_input_mouse('right', 'press', '', 0, 1, 0)
|
||||||
|
screen:expect([[
|
||||||
|
{5:[No Name] }|
|
||||||
|
{8: 4NoClick}^aaaaa |
|
||||||
|
{8: 5NoClick}aaaaa |
|
||||||
|
{8: 6NoClick}aaaaa |
|
||||||
|
{8: 7NoClick}aaaaa |
|
||||||
|
{8: 8NoClick}aaaaa |
|
||||||
|
{8: 9NoClick}aaaaa |
|
||||||
|
{8:10NoClick}aaaaa |
|
||||||
|
{8:11NoClick}aaaaa |
|
||||||
|
{8:12NoClick}aaaaa |
|
||||||
|
{8:13NoClick}aaaaa |
|
||||||
|
{8:14NoClick}aaaaa |
|
||||||
|
{3:[No Name] [+] }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
api.nvim_input_mouse('right', 'press', '', 0, 1, 3)
|
||||||
|
screen:expect([[
|
||||||
|
{5:[No Name] }|
|
||||||
|
{8: 4NoClick}^aaaaa |
|
||||||
|
{8: 5}{4: Inspect } |
|
||||||
|
{8: 6}{4: } |
|
||||||
|
{8: 7}{4: Paste } |
|
||||||
|
{8: 8}{4: Select All } |
|
||||||
|
{8: 9}{4: } |
|
||||||
|
{8:10}{4: How-to disable mouse } |
|
||||||
|
{8:11NoClick}aaaaa |
|
||||||
|
{8:12NoClick}aaaaa |
|
||||||
|
{8:13NoClick}aaaaa |
|
||||||
|
{8:14NoClick}aaaaa |
|
||||||
|
{3:[No Name] [+] }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('clicks and highlights work with control characters', function()
|
it('clicks and highlights work with control characters', function()
|
||||||
api.nvim_set_option_value('statuscolumn', '\t%#NonText#\1%0@MyClickFunc@\t\1%T\t%##\1', {})
|
api.nvim_set_option_value('statuscolumn', '\t%#NonText#\1%0@MyClickFunc@\t\1%T\t%##\1', {})
|
||||||
screen:expect {
|
screen:expect([[
|
||||||
grid = [[
|
{8:^I}{1:^A^I^A^I}{8:^A}aaaaa |*4
|
||||||
{1:^I}{0:^A^I^A^I}{1:^A}aaaaa |*4
|
{8:^I}{1:^A^I^A^I}{8:^A}^aaaaa |
|
||||||
{1:^I}{0:^A^I^A^I}{1:^A}^aaaaa |
|
{8:^I}{1:^A^I^A^I}{8:^A}aaaaa |*8
|
||||||
{1:^I}{0:^A^I^A^I}{1:^A}aaaaa |*8
|
|
||||||
|
|
|
|
||||||
]],
|
]])
|
||||||
attr_ids = {
|
|
||||||
[0] = { foreground = Screen.colors.Blue, bold = true }, -- NonText
|
|
||||||
[1] = { foreground = Screen.colors.Brown }, -- LineNr
|
|
||||||
},
|
|
||||||
}
|
|
||||||
api.nvim_input_mouse('right', 'press', '', 0, 4, 3)
|
api.nvim_input_mouse('right', 'press', '', 0, 4, 3)
|
||||||
|
feed('<Esc>') -- Close popupmenu
|
||||||
eq('', eval('g:testvar'))
|
eq('', eval('g:testvar'))
|
||||||
api.nvim_input_mouse('left', 'press', '', 0, 5, 8)
|
api.nvim_input_mouse('left', 'press', '', 0, 5, 8)
|
||||||
eq('', eval('g:testvar'))
|
eq('', eval('g:testvar'))
|
||||||
@ -713,6 +744,36 @@ describe('statuscolumn', function()
|
|||||||
|
|
|
|
||||||
]])
|
]])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('foldcolumn item can be clicked', function()
|
||||||
|
api.nvim_set_option_value('statuscolumn', '|%C|', {})
|
||||||
|
api.nvim_set_option_value('foldcolumn', '2', {})
|
||||||
|
api.nvim_set_option_value('mousetime', 0, {})
|
||||||
|
feed('ggzfjzfjzo')
|
||||||
|
local s1 = [[
|
||||||
|
{8:|}{7:-+}{8:|}{13:^+--- 2 lines: aaaaa·····························}|
|
||||||
|
{8:|}{7:│ }{8:|}aaaaa |
|
||||||
|
{8:|}{7: }{8:|}aaaaa |*11
|
||||||
|
|
|
||||||
|
]]
|
||||||
|
screen:expect(s1)
|
||||||
|
api.nvim_input_mouse('left', 'press', '', 0, 0, 2)
|
||||||
|
screen:expect([[
|
||||||
|
{8:|}{7:--}{8:|}^aaaaa |
|
||||||
|
{8:|}{7:││}{8:|}aaaaa |
|
||||||
|
{8:|}{7:│ }{8:|}aaaaa |
|
||||||
|
{8:|}{7: }{8:|}aaaaa |*10
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
api.nvim_input_mouse('left', 'press', '', 0, 0, 1)
|
||||||
|
screen:expect(s1)
|
||||||
|
api.nvim_input_mouse('left', 'press', '', 0, 0, 1)
|
||||||
|
screen:expect([[
|
||||||
|
{8:|}{7:+ }{8:|}{13:^+-- 3 lines: aaaaa······························}|
|
||||||
|
{8:|}{7: }{8:|}aaaaa |*12
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user