Merge branch 'mouse-events' of https://github.com/trygveaa/kitty
This commit is contained in:
commit
9fa97e6187
@ -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::
|
||||||
|
|
||||||
|
|||||||
28
kitty/glfw.c
28
kitty/glfw.c
@ -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;
|
||||||
|
|||||||
@ -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);
|
||||||
break;
|
} else {
|
||||||
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);
|
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--) {
|
||||||
|
|||||||
@ -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):
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user