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
: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
the request by default instead of denying by default. See
: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]"
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 { NONE, MENUBAR, WINDOW, ALL } WindowTitleIn;
typedef enum { TILING, SCALED, MIRRORED } BackgroundImageLayout;

View File

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

View File

@ -66,7 +66,7 @@ encode_button(unsigned int button) {
static char mouse_event_buf[64];
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;
if (action == MOVE) {
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_ALT) cb |= ALT_INDICATOR;
if (mods & GLFW_MOD_CONTROL) cb |= CONTROL_INDICATOR;
int x = mpos->cell_x + 1, y = mpos->cell_y + 1;
switch(mouse_tracking_protocol) {
case SGR_PIXEL_PROTOCOL:
x = (unsigned int)round(mpos->x);
y = (unsigned int)round(mpos->y);
/* fallthrough */
case SGR_PROTOCOL:
return snprintf(mouse_event_buf, sizeof(mouse_event_buf), "<%d;%d;%d%s", cb, x, y, action == RELEASE ? "m" : "M");
break;
@ -106,9 +111,8 @@ encode_mouse_event_impl(unsigned int x, unsigned int y, int mouse_tracking_proto
static int
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;
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
@ -337,7 +341,7 @@ HANDLER(handle_move_event) {
if (handle_in_kitty) {
handle_mouse_movement_in_kitty(w, button, mouse_cell_changed | cell_half_changed);
} 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);
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;
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) {
mouse_event_buf[sz] = 0;
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;
int mouse_tracking_protocol, button, action, mods;
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);
}

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_UTF8_MODE, mouse_tracking_protocol, UTF8_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)
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;
case MOUSE_SGR_MODE:
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:
ans = self->pending_mode.activated_at ? 1 : 2; break;
}