Merge branch 'mouse-events' of https://github.com/trygveaa/kitty

This commit is contained in:
Kovid Goyal 2020-06-06 22:27:54 +05:30
commit 9fa97e6187
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 78 additions and 33 deletions

View File

@ -142,12 +142,13 @@ those using::
send_mouse_event(screen, x, y, button, action, mods) send_mouse_event(screen, x, y, button, action, mods)
``screen`` is the ``screen`` attribute of the window you want to send the event ``screen`` is the ``screen`` attribute of the window you want to send the event
to. ``x`` and ``y`` are the 0-indexed coordinates. ``button`` is to. ``x`` and ``y`` are the 0-indexed coordinates. ``button`` is a number using
``GLFW_MOUSE_BUTTON_{button}`` where ``{button}`` is one of ``LEFT``, the same numbering as X11 (left: ``1``, middle: ``2``, right: ``3``, scroll up:
``RIGHT``, ``MIDDLE`` or a digit from ``1`` to ``8``. ``action`` is one of ``4``, scroll down: ``5``, scroll left: ``6``, scroll right: ``7``, back:
``PRESS``, ``RELEASE``, ``DRAG`` or ``MOVE``. ``mods`` is a bitmask of ``8``, forward: ``9``). ``action`` is one of ``PRESS``, ``RELEASE``, ``DRAG``
``GLFW_MOD_{mod}`` where ``{mod}`` is one of ``SHIFT``, ``CONTROL`` or ``ALT``. or ``MOVE``. ``mods`` is a bitmask of ``GLFW_MOD_{mod}`` where ``{mod}`` is one
All the mentioned constants are imported from ``kitty.fast_data_types``. of ``SHIFT``, ``CONTROL`` or ``ALT``. All the mentioned constants are imported
from ``kitty.fast_data_types``.
For example, to send a left click at position x: 2, y: 3 to the active window:: For example, to send a left click at position x: 2, y: 3 to the active window::

View File

@ -227,10 +227,38 @@ refresh_callback(GLFWwindow *w) {
static int mods_at_last_key_or_button_event = 0; static int mods_at_last_key_or_button_event = 0;
static inline int
key_to_modifier(int key) {
switch(key) {
case GLFW_KEY_LEFT_SHIFT:
case GLFW_KEY_RIGHT_SHIFT:
return GLFW_MOD_SHIFT;
case GLFW_KEY_LEFT_CONTROL:
case GLFW_KEY_RIGHT_CONTROL:
return GLFW_MOD_CONTROL;
case GLFW_KEY_LEFT_ALT:
case GLFW_KEY_RIGHT_ALT:
return GLFW_MOD_ALT;
case GLFW_KEY_LEFT_SUPER:
case GLFW_KEY_RIGHT_SUPER:
return GLFW_MOD_SUPER;
default:
return -1;
}
}
static void static void
key_callback(GLFWwindow *w, GLFWkeyevent *ev) { key_callback(GLFWwindow *w, GLFWkeyevent *ev) {
if (!set_callback_window(w)) return; if (!set_callback_window(w)) return;
mods_at_last_key_or_button_event = ev->mods; mods_at_last_key_or_button_event = ev->mods;
int key_modifier = key_to_modifier(ev->key);
if (key_modifier != -1) {
if (ev->action == GLFW_RELEASE) {
mods_at_last_key_or_button_event &= ~key_modifier;
} else {
mods_at_last_key_or_button_event |= key_modifier;
}
}
global_state.callback_os_window->cursor_blink_zero_time = monotonic(); global_state.callback_os_window->cursor_blink_zero_time = monotonic();
if (ev->key >= 0 && ev->key <= GLFW_KEY_LAST) { if (ev->key >= 0 && ev->key <= GLFW_KEY_LAST) {
global_state.callback_os_window->is_key_pressed[ev->key] = ev->action == GLFW_RELEASE ? false : true; global_state.callback_os_window->is_key_pressed[ev->key] = ev->action == GLFW_RELEASE ? false : true;

View File

@ -25,27 +25,43 @@ typedef enum MouseActions { PRESS, RELEASE, DRAG, MOVE } MouseAction;
#define ALT_INDICATOR (1 << 3) #define ALT_INDICATOR (1 << 3)
#define CONTROL_INDICATOR (1 << 4) #define CONTROL_INDICATOR (1 << 4)
#define MOTION_INDICATOR (1 << 5) #define MOTION_INDICATOR (1 << 5)
#define EXTRA_BUTTON_INDICATOR (1 << 6) #define SCROLL_BUTTON_INDICATOR (1 << 6)
#define EXTRA_BUTTON_INDICATOR (1 << 7)
static inline unsigned int static inline unsigned int
button_map(int button) { button_map(int button) {
switch(button) { switch(button) {
case GLFW_MOUSE_BUTTON_LEFT: case GLFW_MOUSE_BUTTON_LEFT:
return 0;
case GLFW_MOUSE_BUTTON_RIGHT:
return 2;
case GLFW_MOUSE_BUTTON_MIDDLE:
return 1; return 1;
case GLFW_MOUSE_BUTTON_RIGHT:
return 3;
case GLFW_MOUSE_BUTTON_MIDDLE:
return 2;
case GLFW_MOUSE_BUTTON_4: case GLFW_MOUSE_BUTTON_4:
return EXTRA_BUTTON_INDICATOR;
case GLFW_MOUSE_BUTTON_5: case GLFW_MOUSE_BUTTON_5:
return EXTRA_BUTTON_INDICATOR | 1; case GLFW_MOUSE_BUTTON_6:
case GLFW_MOUSE_BUTTON_7:
case GLFW_MOUSE_BUTTON_8:
return button + 5;
default: default:
return UINT_MAX; return UINT_MAX;
} }
} }
static inline unsigned int
encode_button(unsigned int button) {
if (button >= 8 && button <= 11) {
return (button - 8) | EXTRA_BUTTON_INDICATOR;
} else if (button >= 4 && button <= 7) {
return (button - 4) | SCROLL_BUTTON_INDICATOR;
} else if (button >= 1 && button <= 3) {
return button - 1;
} else {
return UINT_MAX;
}
}
static char mouse_event_buf[64]; static char mouse_event_buf[64];
static inline int static inline int
@ -54,7 +70,7 @@ encode_mouse_event_impl(unsigned int x, unsigned int y, int mouse_tracking_proto
if (action == MOVE) { if (action == MOVE) {
cb = 3; cb = 3;
} else { } else {
cb = button_map(button); cb = encode_button(button);
if (cb == UINT_MAX) return 0; if (cb == UINT_MAX) return 0;
} }
if (action == DRAG || action == MOVE) cb |= MOTION_INDICATOR; if (action == DRAG || action == MOVE) cb |= MOTION_INDICATOR;
@ -92,7 +108,16 @@ 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 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(x, y, screen->modes.mouse_tracking_protocol, button, action, mods);
}
static int
encode_mouse_button(Window *w, int button, MouseAction action, int mods) {
return encode_mouse_event(w, button_map(button), action, mods);
}
static int
encode_mouse_scroll(Window *w, bool upwards, int mods) {
return encode_mouse_event(w, upwards ? 4 : 5, PRESS, mods);
} }
// }}} // }}}
@ -341,7 +366,7 @@ HANDLER(handle_move_event) {
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) return;
int sz = encode_mouse_event(w, MAX(0, button), button >=0 ? DRAG : MOVE, 0); 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); }
} }
} }
@ -450,34 +475,25 @@ HANDLER(handle_button_event) {
); );
if (handle_in_kitty) handle_button_event_in_kitty(w, button, modifiers, is_release); if (handle_in_kitty) handle_button_event_in_kitty(w, button, modifiers, is_release);
else { else {
int sz = encode_mouse_event(w, button, is_release ? RELEASE : PRESS, modifiers); int sz = encode_mouse_button(w, button, is_release ? RELEASE : PRESS, 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); }
} }
} }
static inline int static inline int
currently_pressed_button(void) { currently_pressed_button(void) {
for (int i = 0; i < GLFW_MOUSE_BUTTON_5; i++) { for (int i = 0; i <= GLFW_MOUSE_BUTTON_8; i++) {
if (global_state.callback_os_window->mouse_button_pressed[i]) return i; if (global_state.callback_os_window->mouse_button_pressed[i]) return i;
} }
return -1; return -1;
} }
HANDLER(handle_event) { HANDLER(handle_event) {
switch(button) { if (button == -1) {
case -1: button = currently_pressed_button();
button = currently_pressed_button(); handle_move_event(w, button, modifiers, window_idx);
handle_move_event(w, button, modifiers, window_idx); } else {
break; handle_button_event(w, button, modifiers, window_idx);
case GLFW_MOUSE_BUTTON_LEFT:
case GLFW_MOUSE_BUTTON_RIGHT:
case GLFW_MOUSE_BUTTON_MIDDLE:
case GLFW_MOUSE_BUTTON_4:
case GLFW_MOUSE_BUTTON_5:
handle_button_event(w, button, modifiers, window_idx);
break;
default:
break;
} }
} }
@ -690,7 +706,7 @@ scroll_event(double UNUSED xoffset, double yoffset, int flags, int modifiers) {
screen_history_scroll(screen, abs(s), upwards); screen_history_scroll(screen, abs(s), upwards);
} else { } else {
if (screen->modes.mouse_tracking_mode) { if (screen->modes.mouse_tracking_mode) {
int sz = encode_mouse_event(w, upwards ? GLFW_MOUSE_BUTTON_4 : GLFW_MOUSE_BUTTON_5, PRESS, modifiers); int sz = encode_mouse_scroll(w, upwards, modifiers);
if (sz > 0) { if (sz > 0) {
mouse_event_buf[sz] = 0; mouse_event_buf[sz] = 0;
for (s = abs(s); s > 0; s--) { for (s = abs(s); s > 0; s--) {

View File

@ -81,7 +81,7 @@ class TestParser(BaseTest):
def test_encode_mouse_event(self): def test_encode_mouse_event(self):
NORMAL_PROTOCOL, UTF8_PROTOCOL, SGR_PROTOCOL, URXVT_PROTOCOL = range(4) NORMAL_PROTOCOL, UTF8_PROTOCOL, SGR_PROTOCOL, URXVT_PROTOCOL = range(4)
L, M, R = defines.GLFW_MOUSE_BUTTON_LEFT, defines.GLFW_MOUSE_BUTTON_MIDDLE, defines.GLFW_MOUSE_BUTTON_RIGHT L, M, R = 1, 2, 3
protocol = SGR_PROTOCOL protocol = SGR_PROTOCOL
def enc(button=L, action=defines.PRESS, mods=0, x=1, y=1): def enc(button=L, action=defines.PRESS, mods=0, x=1, y=1):