diff options
author | zeertzjq <zeertzjq@outlook.com> | 2025-01-21 22:50:39 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-01-21 22:50:39 +0800 |
commit | 3a25995f304039517b99b8c7d79654adf65c7562 (patch) | |
tree | f02943412f92739d334a66892d03b5f4fa4bd3c8 | |
parent | d7aba51d39c7409ef388ed7cffe3e31d9fcec163 (diff) | |
parent | 06a1f82f1cc37225b6acc46e63bd2eb36e034b1a (diff) | |
download | rneovim-3a25995f304039517b99b8c7d79654adf65c7562.tar.gz rneovim-3a25995f304039517b99b8c7d79654adf65c7562.tar.bz2 rneovim-3a25995f304039517b99b8c7d79654adf65c7562.zip |
Merge pull request #32144 from zeertzjq/termkey-x1-x2
feat(tui/terminal): support X1 and X2 mouse events
-rw-r--r-- | src/nvim/os/input.c | 1 | ||||
-rw-r--r-- | src/nvim/terminal.c | 22 | ||||
-rw-r--r-- | src/nvim/tui/input.c | 4 | ||||
-rw-r--r-- | src/nvim/tui/termkey/driver-csi.c | 6 | ||||
-rw-r--r-- | src/nvim/vterm/mouse.c | 27 | ||||
-rw-r--r-- | test/functional/terminal/buffer_spec.lua | 44 | ||||
-rw-r--r-- | test/unit/vterm_spec.lua | 24 |
7 files changed, 104 insertions, 24 deletions
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index 579b08c554..3259fb500b 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -403,6 +403,7 @@ static unsigned handle_mouse_event(const char **ptr, uint8_t *buf, unsigned bufs if (type != KS_EXTRA || !((mouse_code >= KE_LEFTMOUSE && mouse_code <= KE_RIGHTRELEASE) + || (mouse_code >= KE_X1MOUSE && mouse_code <= KE_X2RELEASE) || (mouse_code >= KE_MOUSEDOWN && mouse_code <= KE_MOUSERIGHT) || mouse_code == KE_MOUSEMOVE)) { return bufsize; 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/tui/input.c b/src/nvim/tui/input.c index 9d901e94ce..1f73f2d135 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -387,6 +387,10 @@ static void forward_mouse_event(TermInput *input, TermKeyKey *key) len += (size_t)snprintf(buf + len, sizeof(buf) - len, "Middle"); } else if (button == 3) { len += (size_t)snprintf(buf + len, sizeof(buf) - len, "Right"); + } else if (button == 8) { + len += (size_t)snprintf(buf + len, sizeof(buf) - len, "X1"); + } else if (button == 9) { + len += (size_t)snprintf(buf + len, sizeof(buf) - len, "X2"); } switch (ev) { diff --git a/src/nvim/tui/termkey/driver-csi.c b/src/nvim/tui/termkey/driver-csi.c index 9741ec72b9..d427be50ff 100644 --- a/src/nvim/tui/termkey/driver-csi.c +++ b/src/nvim/tui/termkey/driver-csi.c @@ -327,6 +327,12 @@ TermKeyResult termkey_interpret_mouse(TermKey *tk, const TermKeyKey *key, TermKe btn = code + 4 - 64; break; + case 128: + case 129: + *event = drag ? TERMKEY_MOUSE_DRAG : TERMKEY_MOUSE_PRESS; + btn = code + 8 - 128; + break; + default: *event = TERMKEY_MOUSE_UNKNOWN; } 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') |