Add support for reporting mouse events with pixel co-ordinates using the SGR_PIXEL_PROTOCOL introduced in xterm 359

This commit is contained in:
Kovid Goyal 2021-09-28 11:41:35 +05:30
parent f3447d187d
commit 9a3d99515f
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
5 changed files with 22 additions and 7 deletions

View File

@ -18,6 +18,9 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
- Allow the user to supply a custom Python function to draw tab bar. See - Allow the user to supply a custom Python function to draw tab bar. See
:opt:`tab_bar_style` :opt:`tab_bar_style`
- Add support for reporting mouse events with pixel co-ordinates using the
``SGR_PIXEL_PROTOCOL`` introduced in xterm 359
- When programs ask to read from the clipboard prompt the user to allow - When programs ask to read from the clipboard prompt the user to allow
the request by default instead of denying by default. See the request by default instead of denying by default. See
:opt:`clipboard_control` for details (:iss:`4022`) :opt:`clipboard_control` for details (:iss:`4022`)

View File

@ -60,7 +60,7 @@ typedef enum { DISABLE_LIGATURES_NEVER, DISABLE_LIGATURES_CURSOR, DISABLE_LIGATU
#define ERROR_PREFIX "[PARSE ERROR]" #define ERROR_PREFIX "[PARSE ERROR]"
typedef enum MouseTrackingModes { NO_TRACKING, BUTTON_MODE, MOTION_MODE, ANY_MODE } MouseTrackingMode; typedef enum MouseTrackingModes { NO_TRACKING, BUTTON_MODE, MOTION_MODE, ANY_MODE } MouseTrackingMode;
typedef enum MouseTrackingProtocols { NORMAL_PROTOCOL, UTF8_PROTOCOL, SGR_PROTOCOL, URXVT_PROTOCOL} MouseTrackingProtocol; typedef enum MouseTrackingProtocols { NORMAL_PROTOCOL, UTF8_PROTOCOL, SGR_PROTOCOL, URXVT_PROTOCOL, SGR_PIXEL_PROTOCOL} MouseTrackingProtocol;
typedef enum MouseShapes { BEAM, HAND, ARROW } MouseShape; typedef enum MouseShapes { BEAM, HAND, ARROW } MouseShape;
typedef enum { NONE, MENUBAR, WINDOW, ALL } WindowTitleIn; typedef enum { NONE, MENUBAR, WINDOW, ALL } WindowTitleIn;
typedef enum { TILING, SCALED, MIRRORED } BackgroundImageLayout; typedef enum { TILING, SCALED, MIRRORED } BackgroundImageLayout;

View File

@ -66,6 +66,7 @@
#define MOUSE_UTF8_MODE (1005 << 5) #define MOUSE_UTF8_MODE (1005 << 5)
#define MOUSE_SGR_MODE (1006 << 5) #define MOUSE_SGR_MODE (1006 << 5)
#define MOUSE_URXVT_MODE (1015 << 5) #define MOUSE_URXVT_MODE (1015 << 5)
#define MOUSE_SGR_PIXEL_MODE (1016 << 5)
// Save cursor (DECSC) // Save cursor (DECSC)
#define SAVE_CURSOR (1048 << 5) #define SAVE_CURSOR (1048 << 5)

View File

@ -66,7 +66,7 @@ encode_button(unsigned int button) {
static char mouse_event_buf[64]; static char mouse_event_buf[64];
static int static int
encode_mouse_event_impl(unsigned int x, unsigned int y, int mouse_tracking_protocol, int button, MouseAction action, int mods) { encode_mouse_event_impl(const MousePosition *mpos, int mouse_tracking_protocol, int button, MouseAction action, int mods) {
unsigned int cb = 0; unsigned int cb = 0;
if (action == MOVE) { if (action == MOVE) {
cb = 3; cb = 3;
@ -79,7 +79,12 @@ encode_mouse_event_impl(unsigned int x, unsigned int y, int mouse_tracking_proto
if (mods & GLFW_MOD_SHIFT) cb |= SHIFT_INDICATOR; if (mods & GLFW_MOD_SHIFT) cb |= SHIFT_INDICATOR;
if (mods & GLFW_MOD_ALT) cb |= ALT_INDICATOR; if (mods & GLFW_MOD_ALT) cb |= ALT_INDICATOR;
if (mods & GLFW_MOD_CONTROL) cb |= CONTROL_INDICATOR; if (mods & GLFW_MOD_CONTROL) cb |= CONTROL_INDICATOR;
int x = mpos->cell_x + 1, y = mpos->cell_y + 1;
switch(mouse_tracking_protocol) { switch(mouse_tracking_protocol) {
case SGR_PIXEL_PROTOCOL:
x = (unsigned int)round(mpos->x);
y = (unsigned int)round(mpos->y);
/* fallthrough */
case SGR_PROTOCOL: case SGR_PROTOCOL:
return snprintf(mouse_event_buf, sizeof(mouse_event_buf), "<%d;%d;%d%s", cb, x, y, action == RELEASE ? "m" : "M"); return snprintf(mouse_event_buf, sizeof(mouse_event_buf), "<%d;%d;%d%s", cb, x, y, action == RELEASE ? "m" : "M");
break; break;
@ -106,9 +111,8 @@ encode_mouse_event_impl(unsigned int x, unsigned int y, int mouse_tracking_proto
static int static int
encode_mouse_event(Window *w, int button, MouseAction action, int mods) { encode_mouse_event(Window *w, int button, MouseAction action, int mods) {
unsigned int x = w->mouse_pos.cell_x + 1, y = w->mouse_pos.cell_y + 1; // 1 based indexing
Screen *screen = w->render_data.screen; Screen *screen = w->render_data.screen;
return encode_mouse_event_impl(x, y, screen->modes.mouse_tracking_protocol, button, action, mods); return encode_mouse_event_impl(&w->mouse_pos, screen->modes.mouse_tracking_protocol, button, action, mods);
} }
static int static int
@ -337,7 +341,7 @@ HANDLER(handle_move_event) {
if (handle_in_kitty) { if (handle_in_kitty) {
handle_mouse_movement_in_kitty(w, button, mouse_cell_changed | cell_half_changed); handle_mouse_movement_in_kitty(w, button, mouse_cell_changed | cell_half_changed);
} else { } else {
if (!mouse_cell_changed) return; if (!mouse_cell_changed && screen->modes.mouse_tracking_protocol != SGR_PIXEL_PROTOCOL) return;
int sz = encode_mouse_button(w, MAX(0, button), button >=0 ? DRAG : MOVE, modifiers); int sz = encode_mouse_button(w, MAX(0, button), button >=0 ? DRAG : MOVE, modifiers);
if (sz > 0) { mouse_event_buf[sz] = 0; write_escape_code_to_child(screen, CSI, mouse_event_buf); } if (sz > 0) { mouse_event_buf[sz] = 0; write_escape_code_to_child(screen, CSI, mouse_event_buf); }
} }
@ -799,7 +803,8 @@ send_mouse_event(PyObject *self UNUSED, PyObject *args) {
MouseTrackingMode mode = screen->modes.mouse_tracking_mode; MouseTrackingMode mode = screen->modes.mouse_tracking_mode;
if (mode == ANY_MODE || (mode == MOTION_MODE && action != MOVE) || (mode == BUTTON_MODE && (action == PRESS || action == RELEASE))) { if (mode == ANY_MODE || (mode == MOTION_MODE && action != MOVE) || (mode == BUTTON_MODE && (action == PRESS || action == RELEASE))) {
int sz = encode_mouse_event_impl(x + 1, y + 1, screen->modes.mouse_tracking_protocol, button, action, mods); MousePosition mpos = {.cell_x = x, .cell_y = y};
int sz = encode_mouse_event_impl(&mpos, screen->modes.mouse_tracking_protocol, button, action, mods);
if (sz > 0) { if (sz > 0) {
mouse_event_buf[sz] = 0; mouse_event_buf[sz] = 0;
write_escape_code_to_child(screen, CSI, mouse_event_buf); write_escape_code_to_child(screen, CSI, mouse_event_buf);
@ -814,7 +819,8 @@ test_encode_mouse(PyObject *self UNUSED, PyObject *args) {
unsigned int x, y; unsigned int x, y;
int mouse_tracking_protocol, button, action, mods; int mouse_tracking_protocol, button, action, mods;
if (!PyArg_ParseTuple(args, "IIiiii", &x, &y, &mouse_tracking_protocol, &button, &action, &mods)) return NULL; if (!PyArg_ParseTuple(args, "IIiiii", &x, &y, &mouse_tracking_protocol, &button, &action, &mods)) return NULL;
int sz = encode_mouse_event_impl(x, y, mouse_tracking_protocol, button, action, mods); MousePosition mpos = {.cell_x = x - 1, .cell_y = y - 1};
int sz = encode_mouse_event_impl(&mpos, mouse_tracking_protocol, button, action, mods);
return PyUnicode_FromStringAndSize(mouse_event_buf, sz); return PyUnicode_FromStringAndSize(mouse_event_buf, sz);
} }

View File

@ -921,6 +921,7 @@ set_mode_from_const(Screen *self, unsigned int mode, bool val) {
MOUSE_MODE(MOUSE_MOVE_TRACKING, mouse_tracking_mode, ANY_MODE) MOUSE_MODE(MOUSE_MOVE_TRACKING, mouse_tracking_mode, ANY_MODE)
MOUSE_MODE(MOUSE_UTF8_MODE, mouse_tracking_protocol, UTF8_PROTOCOL) MOUSE_MODE(MOUSE_UTF8_MODE, mouse_tracking_protocol, UTF8_PROTOCOL)
MOUSE_MODE(MOUSE_SGR_MODE, mouse_tracking_protocol, SGR_PROTOCOL) MOUSE_MODE(MOUSE_SGR_MODE, mouse_tracking_protocol, SGR_PROTOCOL)
MOUSE_MODE(MOUSE_SGR_PIXEL_MODE, mouse_tracking_protocol, SGR_PIXEL_PROTOCOL)
MOUSE_MODE(MOUSE_URXVT_MODE, mouse_tracking_protocol, URXVT_PROTOCOL) MOUSE_MODE(MOUSE_URXVT_MODE, mouse_tracking_protocol, URXVT_PROTOCOL)
case DECSCLM: case DECSCLM:
@ -1816,6 +1817,10 @@ report_mode_status(Screen *self, unsigned int which, bool private) {
ans = self->modes.mouse_tracking_mode == ANY_MODE ? 1 : 2; break; ans = self->modes.mouse_tracking_mode == ANY_MODE ? 1 : 2; break;
case MOUSE_SGR_MODE: case MOUSE_SGR_MODE:
ans = self->modes.mouse_tracking_protocol == SGR_PROTOCOL ? 1 : 2; break; ans = self->modes.mouse_tracking_protocol == SGR_PROTOCOL ? 1 : 2; break;
case MOUSE_UTF8_MODE:
ans = self->modes.mouse_tracking_protocol == UTF8_PROTOCOL ? 1 : 2; break;
case MOUSE_SGR_PIXEL_MODE:
ans = self->modes.mouse_tracking_protocol == SGR_PIXEL_PROTOCOL ? 1 : 2; break;
case PENDING_UPDATE: case PENDING_UPDATE:
ans = self->pending_mode.activated_at ? 1 : 2; break; ans = self->pending_mode.activated_at ? 1 : 2; break;
} }