aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2025-01-21 21:00:56 +0800
committerzeertzjq <zeertzjq@outlook.com>2025-01-21 22:21:05 +0800
commit06a1f82f1cc37225b6acc46e63bd2eb36e034b1a (patch)
treef02943412f92739d334a66892d03b5f4fa4bd3c8
parent44dbfcfba4b09bb0e38f4a3f1960fa256a7bed71 (diff)
downloadrneovim-06a1f82f1cc37225b6acc46e63bd2eb36e034b1a.tar.gz
rneovim-06a1f82f1cc37225b6acc46e63bd2eb36e034b1a.tar.bz2
rneovim-06a1f82f1cc37225b6acc46e63bd2eb36e034b1a.zip
feat(terminal): forward X1 and X2 mouse events
Ref: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Other-buttons
-rw-r--r--src/nvim/terminal.c22
-rw-r--r--src/nvim/vterm/mouse.c27
-rw-r--r--test/functional/terminal/buffer_spec.lua44
-rw-r--r--test/unit/vterm_spec.lua24
4 files changed, 93 insertions, 24 deletions
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 197a225209..897c393488 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -792,17 +792,23 @@ static int terminal_execute(VimState *state, int key)
case K_LEFTMOUSE:
case K_LEFTDRAG:
case K_LEFTRELEASE:
- case K_MOUSEMOVE:
case K_MIDDLEMOUSE:
case K_MIDDLEDRAG:
case K_MIDDLERELEASE:
case K_RIGHTMOUSE:
case K_RIGHTDRAG:
case K_RIGHTRELEASE:
+ case K_X1MOUSE:
+ case K_X1DRAG:
+ case K_X1RELEASE:
+ case K_X2MOUSE:
+ case K_X2DRAG:
+ case K_X2RELEASE:
case K_MOUSEDOWN:
case K_MOUSEUP:
case K_MOUSELEFT:
case K_MOUSERIGHT:
+ case K_MOUSEMOVE:
if (send_mouse_event(s->term, key)) {
return 0;
}
@@ -1804,8 +1810,6 @@ static bool send_mouse_event(Terminal *term, int c)
pressed = true; FALLTHROUGH;
case K_LEFTRELEASE:
button = 1; break;
- case K_MOUSEMOVE:
- button = 0; break;
case K_MIDDLEDRAG:
case K_MIDDLEMOUSE:
pressed = true; FALLTHROUGH;
@@ -1816,6 +1820,16 @@ static bool send_mouse_event(Terminal *term, int c)
pressed = true; FALLTHROUGH;
case K_RIGHTRELEASE:
button = 3; break;
+ case K_X1DRAG:
+ case K_X1MOUSE:
+ pressed = true; FALLTHROUGH;
+ case K_X1RELEASE:
+ button = 8; break;
+ case K_X2DRAG:
+ case K_X2MOUSE:
+ pressed = true; FALLTHROUGH;
+ case K_X2RELEASE:
+ button = 9; break;
case K_MOUSEDOWN:
pressed = true; button = 4; break;
case K_MOUSEUP:
@@ -1824,6 +1838,8 @@ static bool send_mouse_event(Terminal *term, int c)
pressed = true; button = 7; break;
case K_MOUSERIGHT:
pressed = true; button = 6; break;
+ case K_MOUSEMOVE:
+ button = 0; break;
default:
return false;
}
diff --git a/src/nvim/vterm/mouse.c b/src/nvim/vterm/mouse.c
index 9b8be4b60a..2f3b1d9e2f 100644
--- a/src/nvim/vterm/mouse.c
+++ b/src/nvim/vterm/mouse.c
@@ -1,3 +1,4 @@
+#include "nvim/math.h"
#include "nvim/tui/termkey/termkey.h"
#include "nvim/vterm/mouse.h"
#include "nvim/vterm/vterm.h"
@@ -24,6 +25,9 @@ static void output_mouse(VTermState *state, int code, int pressed, int modifiers
code = 3;
}
+ if (code & 0x80) {
+ break;
+ }
vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "M%c%c%c",
(code | modifiers) + 0x20, col + 0x21, row + 0x21);
break;
@@ -74,11 +78,16 @@ void vterm_mouse_move(VTerm *vt, int row, int col, VTermModifier mod)
if ((state->mouse_flags & MOUSE_WANT_DRAG && state->mouse_buttons)
|| (state->mouse_flags & MOUSE_WANT_MOVE)) {
- int button = state->mouse_buttons & 0x01 ? 1
- : state->mouse_buttons & 0x02 ? 2
- : state->mouse_buttons &
- 0x04 ? 3 : 4;
- output_mouse(state, button - 1 + 0x20, 1, (int)mod, col, row);
+ if (state->mouse_buttons) {
+ int button = xctz((uint64_t)state->mouse_buttons) + 1;
+ if (button < 4) {
+ output_mouse(state, button - 1 + 0x20, 1, (int)mod, col, row);
+ } else if (button >= 8 && button < 12) {
+ output_mouse(state, button - 8 + 0x80 + 0x20, 1, (int)mod, col, row);
+ }
+ } else {
+ output_mouse(state, 3 + 0x20, 1, (int)mod, col, row);
+ }
}
}
@@ -88,7 +97,7 @@ void vterm_mouse_button(VTerm *vt, int button, bool pressed, VTermModifier mod)
int old_buttons = state->mouse_buttons;
- if (button > 0 && button <= 3) {
+ if ((button > 0 && button <= 3) || (button >= 8 && button <= 11)) {
if (pressed) {
state->mouse_buttons |= (1 << (button - 1));
} else {
@@ -96,8 +105,8 @@ void vterm_mouse_button(VTerm *vt, int button, bool pressed, VTermModifier mod)
}
}
- // Most of the time we don't get button releases from 4/5
- if (state->mouse_buttons == old_buttons && button < 4) {
+ // Most of the time we don't get button releases from 4/5/6/7
+ if (state->mouse_buttons == old_buttons && (button < 4 || button > 7)) {
return;
}
@@ -109,5 +118,7 @@ void vterm_mouse_button(VTerm *vt, int button, bool pressed, VTermModifier mod)
output_mouse(state, button - 1, pressed, (int)mod, state->mouse_col, state->mouse_row);
} else if (button < 8) {
output_mouse(state, button - 4 + 0x40, pressed, (int)mod, state->mouse_col, state->mouse_row);
+ } else if (button < 12) {
+ output_mouse(state, button - 8 + 0x80, pressed, (int)mod, state->mouse_col, state->mouse_row);
}
}
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
index a524e49ef4..d36dc60a93 100644
--- a/test/functional/terminal/buffer_spec.lua
+++ b/test/functional/terminal/buffer_spec.lua
@@ -594,18 +594,36 @@ describe('terminal input', function()
'<S-End>',
'<C-End>',
'<End>',
- '<C-LeftMouse>',
- '<C-LeftRelease>',
- '<2-LeftMouse>',
- '<2-LeftRelease>',
- '<S-RightMouse>',
- '<S-RightRelease>',
- '<2-RightMouse>',
- '<2-RightRelease>',
- '<M-MiddleMouse>',
- '<M-MiddleRelease>',
- '<2-MiddleMouse>',
- '<2-MiddleRelease>',
+ '<C-LeftMouse><0,0>',
+ '<C-LeftDrag><0,1>',
+ '<C-LeftRelease><0,1>',
+ '<2-LeftMouse><0,1>',
+ '<2-LeftDrag><0,0>',
+ '<2-LeftRelease><0,0>',
+ '<M-MiddleMouse><0,0>',
+ '<M-MiddleDrag><0,1>',
+ '<M-MiddleRelease><0,1>',
+ '<2-MiddleMouse><0,1>',
+ '<2-MiddleDrag><0,0>',
+ '<2-MiddleRelease><0,0>',
+ '<S-RightMouse><0,0>',
+ '<S-RightDrag><0,1>',
+ '<S-RightRelease><0,1>',
+ '<2-RightMouse><0,1>',
+ '<2-RightDrag><0,0>',
+ '<2-RightRelease><0,0>',
+ '<S-X1Mouse><0,0>',
+ '<S-X1Drag><0,1>',
+ '<S-X1Release><0,1>',
+ '<2-X1Mouse><0,1>',
+ '<2-X1Drag><0,0>',
+ '<2-X1Release><0,0>',
+ '<S-X2Mouse><0,0>',
+ '<S-X2Drag><0,1>',
+ '<S-X2Release><0,1>',
+ '<2-X2Mouse><0,1>',
+ '<2-X2Drag><0,0>',
+ '<2-X2Release><0,0>',
'<S-ScrollWheelUp>',
'<S-ScrollWheelDown>',
'<ScrollWheelUp>',
@@ -622,7 +640,7 @@ describe('terminal input', function()
{5:[No Name] 0,0-1 All}|
%s^ {MATCH: *}|
{3:-- TERMINAL --} |
- ]]):format(key))
+ ]]):format(key:gsub('<%d+,%d+>$', '')))
end
end)
diff --git a/test/unit/vterm_spec.lua b/test/unit/vterm_spec.lua
index bad2b3e658..c5293a21cb 100644
--- a/test/unit/vterm_spec.lua
+++ b/test/unit/vterm_spec.lua
@@ -2079,6 +2079,18 @@ putglyph 1f3f4,200d,2620,fe0f 2 0,4]])
mousebtn('u', 1, vt)
expect_output('\x1b[<0;301;301m')
+ -- Button 8 on SGR extended encoding mode
+ mousebtn('d', 8, vt)
+ expect_output('\x1b[<128;301;301M')
+ mousebtn('u', 8, vt)
+ expect_output('\x1b[<128;301;301m')
+
+ -- Button 9 on SGR extended encoding mode
+ mousebtn('d', 9, vt)
+ expect_output('\x1b[<129;301;301M')
+ mousebtn('u', 9, vt)
+ expect_output('\x1b[<129;301;301m')
+
-- DECRQM on SGR extended encoding mode
push('\x1b[?1005$p', vt)
expect_output('\x1b[?1005;2$y')
@@ -2094,6 +2106,18 @@ putglyph 1f3f4,200d,2620,fe0f 2 0,4]])
mousebtn('u', 1, vt)
expect_output('\x1b[3;301;301M')
+ -- Button 8 on rxvt extended encoding mode
+ mousebtn('d', 8, vt)
+ expect_output('\x1b[128;301;301M')
+ mousebtn('u', 8, vt)
+ expect_output('\x1b[3;301;301M')
+
+ -- Button 9 on rxvt extended encoding mode
+ mousebtn('d', 9, vt)
+ expect_output('\x1b[129;301;301M')
+ mousebtn('u', 9, vt)
+ expect_output('\x1b[3;301;301M')
+
-- DECRQM on rxvt extended encoding mode
push('\x1b[?1005$p', vt)
expect_output('\x1b[?1005;2$y')