mouse.c (3254B)
1 #include "nvim/math.h" 2 #include "nvim/tui/termkey/termkey.h" 3 #include "nvim/vterm/mouse.h" 4 #include "nvim/vterm/vterm.h" 5 #include "nvim/vterm/vterm_internal_defs.h" 6 7 #include "vterm/mouse.c.generated.h" 8 9 static void output_mouse(VTermState *state, int code, int pressed, int modifiers, int col, int row) 10 { 11 modifiers <<= 2; 12 13 switch (state->mouse_protocol) { 14 case MOUSE_X10: 15 if (col + 0x21 > 0xff) { 16 col = 0xff - 0x21; 17 } 18 if (row + 0x21 > 0xff) { 19 row = 0xff - 0x21; 20 } 21 22 if (!pressed) { 23 code = 3; 24 } 25 26 if (code & 0x80) { 27 break; 28 } 29 vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "M%c%c%c", 30 (code | modifiers) + 0x20, col + 0x21, row + 0x21); 31 break; 32 33 case MOUSE_UTF8: { 34 char utf8[18]; 35 size_t len = 0; 36 37 if (!pressed) { 38 code = 3; 39 } 40 41 len += (size_t)fill_utf8((code | modifiers) + 0x20, utf8 + len); 42 len += (size_t)fill_utf8(col + 0x21, utf8 + len); 43 len += (size_t)fill_utf8(row + 0x21, utf8 + len); 44 utf8[len] = 0; 45 46 vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "M%s", utf8); 47 } 48 break; 49 50 case MOUSE_SGR: 51 vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "<%d;%d;%d%c", 52 code | modifiers, col + 1, row + 1, pressed ? 'M' : 'm'); 53 break; 54 55 case MOUSE_RXVT: 56 if (!pressed) { 57 code = 3; 58 } 59 60 vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "%d;%d;%dM", 61 code | modifiers, col + 1, row + 1); 62 break; 63 } 64 } 65 66 void vterm_mouse_move(VTerm *vt, int row, int col, VTermModifier mod) 67 { 68 VTermState *state = vt->state; 69 70 if (col == state->mouse_col && row == state->mouse_row) { 71 return; 72 } 73 74 state->mouse_col = col; 75 state->mouse_row = row; 76 77 if ((state->mouse_flags & MOUSE_WANT_DRAG && state->mouse_buttons) 78 || (state->mouse_flags & MOUSE_WANT_MOVE)) { 79 if (state->mouse_buttons) { 80 int button = xctz((uint64_t)state->mouse_buttons) + 1; 81 if (button < 4) { 82 output_mouse(state, button - 1 + 0x20, 1, (int)mod, col, row); 83 } else if (button >= 8 && button < 12) { 84 output_mouse(state, button - 8 + 0x80 + 0x20, 1, (int)mod, col, row); 85 } 86 } else { 87 output_mouse(state, 3 + 0x20, 1, (int)mod, col, row); 88 } 89 } 90 } 91 92 void vterm_mouse_button(VTerm *vt, int button, bool pressed, VTermModifier mod) 93 { 94 VTermState *state = vt->state; 95 96 int old_buttons = state->mouse_buttons; 97 98 if ((button > 0 && button <= 3) || (button >= 8 && button <= 11)) { 99 if (pressed) { 100 state->mouse_buttons |= (1 << (button - 1)); 101 } else { 102 state->mouse_buttons &= ~(1 << (button - 1)); 103 } 104 } 105 106 // Most of the time we don't get button releases from 4/5/6/7 107 if (state->mouse_buttons == old_buttons && (button < 4 || button > 7)) { 108 return; 109 } 110 111 if (!state->mouse_flags) { 112 return; 113 } 114 115 if (button < 4) { 116 output_mouse(state, button - 1, pressed, (int)mod, state->mouse_col, state->mouse_row); 117 } else if (button < 8) { 118 output_mouse(state, button - 4 + 0x40, pressed, (int)mod, state->mouse_col, state->mouse_row); 119 } else if (button < 12) { 120 output_mouse(state, button - 8 + 0x80, pressed, (int)mod, state->mouse_col, state->mouse_row); 121 } 122 }