feat(tui): support 'mousemoveevent'

This commit is contained in:
zeertzjq 2022-07-24 11:26:54 +08:00
parent a5fe7940c8
commit 04bd700ac3
5 changed files with 67 additions and 16 deletions

View File

@ -4234,14 +4234,11 @@ A jump table for the options with a short description can be found at |Q_op|.
*'mousemoveevent'* *'mousemev'* *'mousemoveevent'* *'mousemev'*
'mousemoveevent' 'mousemev' boolean (default off) 'mousemoveevent' 'mousemev' boolean (default off)
global global
{only works in the GUI}
When on, mouse move events are delivered to the input queue and are When on, mouse move events are delivered to the input queue and are
available for mapping. The default, off, avoids the mouse movement available for mapping. The default, off, avoids the mouse movement
overhead except when needed. overhead except when needed.
Warning: Setting this option can make pending mappings to be aborted Warning: Setting this option can make pending mappings to be aborted
when the mouse is moved. when the mouse is moved.
Currently only works in the GUI, may be made to work in a terminal
later.
*'mousescroll'* *'mousescroll'*
'mousescroll' string (default "ver:3,hor:6") 'mousescroll' string (default "ver:3,hor:6")

View File

@ -293,7 +293,8 @@ static uint8_t check_multiclick(int code, int grid, int row, int col)
|| code == KE_MOUSEDOWN || code == KE_MOUSEDOWN
|| code == KE_MOUSEUP || code == KE_MOUSEUP
|| code == KE_MOUSELEFT || code == KE_MOUSELEFT
|| code == KE_MOUSERIGHT) { || code == KE_MOUSERIGHT
|| code == KE_MOUSEMOVE) {
return 0; return 0;
} }
uint64_t mouse_time = os_hrtime(); // time of current mouse click (ns) uint64_t mouse_time = os_hrtime(); // time of current mouse click (ns)
@ -347,7 +348,8 @@ static unsigned int handle_mouse_event(char **ptr, uint8_t *buf, unsigned int bu
if (type != KS_EXTRA if (type != KS_EXTRA
|| !((mouse_code >= KE_LEFTMOUSE && mouse_code <= KE_RIGHTRELEASE) || !((mouse_code >= KE_LEFTMOUSE && mouse_code <= KE_RIGHTRELEASE)
|| (mouse_code >= KE_MOUSEDOWN && mouse_code <= KE_MOUSERIGHT))) { || (mouse_code >= KE_MOUSEDOWN && mouse_code <= KE_MOUSERIGHT)
|| mouse_code == KE_MOUSEMOVE)) {
return bufsize; return bufsize;
} }

View File

@ -406,8 +406,8 @@ static void forward_mouse_event(TermInput *input, TermKeyKey *key)
} }
} }
if (button == 0 || (ev != TERMKEY_MOUSE_PRESS && ev != TERMKEY_MOUSE_DRAG if ((button == 0 && ev != TERMKEY_MOUSE_RELEASE)
&& ev != TERMKEY_MOUSE_RELEASE)) { || (ev != TERMKEY_MOUSE_PRESS && ev != TERMKEY_MOUSE_DRAG && ev != TERMKEY_MOUSE_RELEASE)) {
return; return;
} }
@ -453,7 +453,8 @@ static void forward_mouse_event(TermInput *input, TermKeyKey *key)
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "Drag"); len += (size_t)snprintf(buf + len, sizeof(buf) - len, "Drag");
break; break;
case TERMKEY_MOUSE_RELEASE: case TERMKEY_MOUSE_RELEASE:
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "Release"); len += (size_t)snprintf(buf + len, sizeof(buf) - len, button ? "Release" : "MouseMove");
last_pressed_button = 0;
break; break;
case TERMKEY_MOUSE_UNKNOWN: case TERMKEY_MOUSE_UNKNOWN:
abort(); abort();

View File

@ -103,6 +103,7 @@ struct TUIData {
bool immediate_wrap_after_last_column; bool immediate_wrap_after_last_column;
bool bce; bool bce;
bool mouse_enabled; bool mouse_enabled;
bool mouse_move_enabled;
bool busy, is_invisible, want_invisible; bool busy, is_invisible, want_invisible;
bool cork, overflow; bool cork, overflow;
bool cursor_color_changed; bool cursor_color_changed;
@ -117,6 +118,7 @@ struct TUIData {
ModeShape showing_mode; ModeShape showing_mode;
struct { struct {
int enable_mouse, disable_mouse; int enable_mouse, disable_mouse;
int enable_mouse_move, disable_mouse_move;
int enable_bracketed_paste, disable_bracketed_paste; int enable_bracketed_paste, disable_bracketed_paste;
int enable_lr_margin, disable_lr_margin; int enable_lr_margin, disable_lr_margin;
int enter_strikethrough_mode; int enter_strikethrough_mode;
@ -236,6 +238,8 @@ static void terminfo_start(UI *ui)
data->showing_mode = SHAPE_IDX_N; data->showing_mode = SHAPE_IDX_N;
data->unibi_ext.enable_mouse = -1; data->unibi_ext.enable_mouse = -1;
data->unibi_ext.disable_mouse = -1; data->unibi_ext.disable_mouse = -1;
data->unibi_ext.enable_mouse_move = -1;
data->unibi_ext.disable_mouse_move = -1;
data->unibi_ext.set_cursor_color = -1; data->unibi_ext.set_cursor_color = -1;
data->unibi_ext.reset_cursor_color = -1; data->unibi_ext.reset_cursor_color = -1;
data->unibi_ext.enable_bracketed_paste = -1; data->unibi_ext.enable_bracketed_paste = -1;
@ -1138,6 +1142,9 @@ static void tui_mouse_on(UI *ui)
TUIData *data = ui->data; TUIData *data = ui->data;
if (!data->mouse_enabled) { if (!data->mouse_enabled) {
unibi_out_ext(ui, data->unibi_ext.enable_mouse); unibi_out_ext(ui, data->unibi_ext.enable_mouse);
if (data->mouse_move_enabled) {
unibi_out_ext(ui, data->unibi_ext.enable_mouse_move);
}
data->mouse_enabled = true; data->mouse_enabled = true;
} }
} }
@ -1146,6 +1153,9 @@ static void tui_mouse_off(UI *ui)
{ {
TUIData *data = ui->data; TUIData *data = ui->data;
if (data->mouse_enabled) { if (data->mouse_enabled) {
if (data->mouse_move_enabled) {
unibi_out_ext(ui, data->unibi_ext.disable_mouse_move);
}
unibi_out_ext(ui, data->unibi_ext.disable_mouse); unibi_out_ext(ui, data->unibi_ext.disable_mouse);
data->mouse_enabled = false; data->mouse_enabled = false;
} }
@ -1457,9 +1467,18 @@ static void tui_screenshot(UI *ui, String path)
static void tui_option_set(UI *ui, String name, Object value) static void tui_option_set(UI *ui, String name, Object value)
{ {
TUIData *data = ui->data; TUIData *data = ui->data;
if (strequal(name.data, "termguicolors")) { if (strequal(name.data, "mousemoveevent")) {
if (data->mouse_move_enabled != value.data.boolean) {
if (data->mouse_enabled) {
tui_mouse_off(ui);
data->mouse_move_enabled = value.data.boolean;
tui_mouse_on(ui);
} else {
data->mouse_move_enabled = value.data.boolean;
}
}
} else if (strequal(name.data, "termguicolors")) {
ui->rgb = value.data.boolean; ui->rgb = value.data.boolean;
data->print_attr_id = -1; data->print_attr_id = -1;
invalidate(ui, 0, data->grid.height, 0, data->grid.width); invalidate(ui, 0, data->grid.height, 0, data->grid.width);
} else if (strequal(name.data, "ttimeout")) { } else if (strequal(name.data, "ttimeout")) {
@ -2135,6 +2154,10 @@ static void augment_terminfo(TUIData *data, const char *term, long vte_version,
"\x1b[?1002h\x1b[?1006h"); "\x1b[?1002h\x1b[?1006h");
data->unibi_ext.disable_mouse = (int)unibi_add_ext_str(ut, "ext.disable_mouse", data->unibi_ext.disable_mouse = (int)unibi_add_ext_str(ut, "ext.disable_mouse",
"\x1b[?1002l\x1b[?1006l"); "\x1b[?1002l\x1b[?1006l");
data->unibi_ext.enable_mouse_move = (int)unibi_add_ext_str(ut, "ext.enable_mouse_move",
"\x1b[?1003h");
data->unibi_ext.disable_mouse_move = (int)unibi_add_ext_str(ut, "ext.disable_mouse_move",
"\x1b[?1003l");
// Extended underline. // Extended underline.
// terminfo will have Smulx for this (but no support for colors yet). // terminfo will have Smulx for this (but no support for colors yet).

View File

@ -2755,7 +2755,7 @@ describe('builtin popupmenu', function()
menu PopUp.bar :let g:menustr = 'bar'<CR> menu PopUp.bar :let g:menustr = 'bar'<CR>
menu PopUp.baz :let g:menustr = 'baz'<CR> menu PopUp.baz :let g:menustr = 'baz'<CR>
]]) ]])
meths.input_mouse('right', 'press', '', 0, 0, 4) feed('<RightMouse><4,0>')
screen:expect([[ screen:expect([[
^popup menu test | ^popup menu test |
{1:~ }{n: foo }{1: }| {1:~ }{n: foo }{1: }|
@ -2792,7 +2792,7 @@ describe('builtin popupmenu', function()
:let g:menustr = 'bar' | :let g:menustr = 'bar' |
]]) ]])
eq('bar', meths.get_var('menustr')) eq('bar', meths.get_var('menustr'))
meths.input_mouse('right', 'press', '', 0, 1, 20) feed('<RightMouse><20,1>')
screen:expect([[ screen:expect([[
^popup menu test | ^popup menu test |
{1:~ }| {1:~ }|
@ -2801,7 +2801,7 @@ describe('builtin popupmenu', function()
{1:~ }{n: baz }{1: }| {1:~ }{n: baz }{1: }|
:let g:menustr = 'bar' | :let g:menustr = 'bar' |
]]) ]])
meths.input_mouse('left', 'press', '', 0, 4, 22) feed('<LeftMouse><22,4>')
screen:expect([[ screen:expect([[
^popup menu test | ^popup menu test |
{1:~ }| {1:~ }|
@ -2811,7 +2811,7 @@ describe('builtin popupmenu', function()
:let g:menustr = 'baz' | :let g:menustr = 'baz' |
]]) ]])
eq('baz', meths.get_var('menustr')) eq('baz', meths.get_var('menustr'))
meths.input_mouse('right', 'press', '', 0, 0, 4) feed('<RightMouse><4,0>')
screen:expect([[ screen:expect([[
^popup menu test | ^popup menu test |
{1:~ }{n: foo }{1: }| {1:~ }{n: foo }{1: }|
@ -2820,7 +2820,7 @@ describe('builtin popupmenu', function()
{1:~ }| {1:~ }|
:let g:menustr = 'baz' | :let g:menustr = 'baz' |
]]) ]])
meths.input_mouse('right', 'drag', '', 0, 3, 6) feed('<RightDrag><6,3>')
screen:expect([[ screen:expect([[
^popup menu test | ^popup menu test |
{1:~ }{n: foo }{1: }| {1:~ }{n: foo }{1: }|
@ -2829,7 +2829,7 @@ describe('builtin popupmenu', function()
{1:~ }| {1:~ }|
:let g:menustr = 'baz' | :let g:menustr = 'baz' |
]]) ]])
meths.input_mouse('right', 'release', '', 0, 1, 6) feed('<RightRelease><6,1>')
screen:expect([[ screen:expect([[
^popup menu test | ^popup menu test |
{1:~ }| {1:~ }|
@ -2839,6 +2839,34 @@ describe('builtin popupmenu', function()
:let g:menustr = 'foo' | :let g:menustr = 'foo' |
]]) ]])
eq('foo', meths.get_var('menustr')) eq('foo', meths.get_var('menustr'))
feed('<RightMouse><4,0>')
screen:expect([[
^popup menu test |
{1:~ }{n: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{n: baz }{1: }|
{1:~ }|
:let g:menustr = 'foo' |
]])
feed('<MouseMove><6,3>')
screen:expect([[
^popup menu test |
{1:~ }{n: foo }{1: }|
{1:~ }{n: bar }{1: }|
{1:~ }{s: baz }{1: }|
{1:~ }|
:let g:menustr = 'foo' |
]])
feed('<LeftMouse><6,2>')
screen:expect([[
^popup menu test |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
:let g:menustr = 'bar' |
]])
eq('bar', meths.get_var('menustr'))
end) end)
end) end)