From a0ff625f6176dd2d73a0f6b947536d2817df9b10 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 23 Nov 2018 11:46:02 +0530 Subject: [PATCH] When double or triple clicking ignore clicks if they are "far" from each other Fixes #1093 --- docs/changelog.rst | 3 +++ kitty/mouse.c | 53 ++++++++++++++++++++++++++++++++-------------- kitty/state.h | 6 +++++- 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 142efe623..87a83456c 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -89,6 +89,9 @@ Changelog - Fix incorrect text-antialiasing when using very low background opacity (:iss:`1005`) +- When double or triple clicking ignore clicks if they are "far" from each + other (:iss:`1093`) + 0.12.3 [2018-09-29] ------------------------------ diff --git a/kitty/mouse.c b/kitty/mouse.c index e9d90a89c..d1eb76917 100644 --- a/kitty/mouse.c +++ b/kitty/mouse.c @@ -85,7 +85,7 @@ 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_cell_x + 1, y = w->mouse_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; return encode_mouse_event_impl(x, y, screen->modes.mouse_tracking_protocol, button, action, mods); @@ -142,6 +142,7 @@ cell_for_pos(Window *w, unsigned int *x, unsigned int *y, OSWindow *os_window) { mouse_x = MIN(MAX(mouse_x, left), right); mouse_y = MIN(MAX(mouse_y, top), bottom); } + w->mouse_pos.x = mouse_x - left; w->mouse_pos.y = mouse_y - top; if (mouse_x < left || mouse_y < top || mouse_x > right || mouse_y > bottom) return false; if (mouse_x >= g->right) qx = screen->columns - 1; else if (mouse_x >= g->left) qx = (unsigned int)((double)(mouse_x - g->left) / os_window->fonts_data->cell_width); @@ -164,14 +165,14 @@ update_drag(bool from_button, Window *w, bool is_release, int modifiers) { global_state.active_drag_in_window = 0; w->last_drag_scroll_at = 0; if (screen->selection.in_progress) - screen_update_selection(screen, w->mouse_cell_x, w->mouse_cell_y, true); + screen_update_selection(screen, w->mouse_pos.cell_x, w->mouse_pos.cell_y, true); } else { global_state.active_drag_in_window = w->id; - screen_start_selection(screen, w->mouse_cell_x, w->mouse_cell_y, modifiers == (int)OPT(rectangle_select_modifiers) || modifiers == ((int)OPT(rectangle_select_modifiers) | GLFW_MOD_SHIFT), EXTEND_CELL); + screen_start_selection(screen, w->mouse_pos.cell_x, w->mouse_pos.cell_y, modifiers == (int)OPT(rectangle_select_modifiers) || modifiers == ((int)OPT(rectangle_select_modifiers) | GLFW_MOD_SHIFT), EXTEND_CELL); } } else if (screen->selection.in_progress) { - screen_update_selection(screen, w->mouse_cell_x, w->mouse_cell_y, false); + screen_update_selection(screen, w->mouse_pos.cell_x, w->mouse_pos.cell_y, false); } } @@ -201,7 +202,7 @@ static inline void extend_selection(Window *w) { Screen *screen = w->render_data.screen; if (screen_has_selection(screen)) { - screen_update_selection(screen, w->mouse_cell_x, w->mouse_cell_y, false); + screen_update_selection(screen, w->mouse_pos.cell_x, w->mouse_pos.cell_y, false); } } @@ -276,8 +277,8 @@ HANDLER(handle_move_event) { if (!cell_for_pos(w, &x, &y, global_state.callback_os_window)) return; Screen *screen = w->render_data.screen; detect_url(screen, x, y); - bool mouse_cell_changed = x != w->mouse_cell_x || y != w->mouse_cell_y; - w->mouse_cell_x = x; w->mouse_cell_y = y; + bool mouse_cell_changed = x != w->mouse_pos.cell_x || y != w->mouse_pos.cell_y; + w->mouse_pos.cell_x = x; w->mouse_pos.cell_y = y; bool handle_in_kitty = ( (screen->modes.mouse_tracking_mode == ANY_MODE || (screen->modes.mouse_tracking_mode == MOTION_MODE && button >= 0)) && @@ -304,14 +305,14 @@ multi_click(Window *w, unsigned int count) { index_type start, end; bool found_selection = false; SelectionExtendMode mode = EXTEND_CELL; - unsigned int y1 = w->mouse_cell_y, y2 = w->mouse_cell_y; + unsigned int y1 = w->mouse_pos.cell_y, y2 = w->mouse_pos.cell_y; switch(count) { case 2: - found_selection = screen_selection_range_for_word(screen, w->mouse_cell_x, &y1, &y2, &start, &end); + found_selection = screen_selection_range_for_word(screen, w->mouse_pos.cell_x, &y1, &y2, &start, &end); mode = EXTEND_WORD; break; case 3: - found_selection = screen_selection_range_for_line(screen, w->mouse_cell_y, &start, &end); + found_selection = screen_selection_range_for_line(screen, w->mouse_pos.cell_y, &start, &end); mode = EXTEND_LINE; break; default: @@ -323,19 +324,39 @@ multi_click(Window *w, unsigned int count) { } } +static inline double +distance(double x1, double y1, double x2, double y2) { + return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); +} + HANDLER(add_click) { ClickQueue *q = &w->click_queue; if (q->length == CLICK_QUEUE_SZ) { memmove(q->clicks, q->clicks + 1, sizeof(Click) * (CLICK_QUEUE_SZ - 1)); q->length--; } double now = monotonic(); #define N(n) (q->clicks[q->length - n]) - N(0).at = now; N(0).button = button; N(0).modifiers = modifiers; + N(0).at = now; N(0).button = button; N(0).modifiers = modifiers; N(0).x = w->mouse_pos.x; N(0).y = w->mouse_pos.y; q->length++; + double multi_click_allowed_radius = 1.2 * global_state.callback_os_window->fonts_data->cell_height; // Now dispatch the multi-click if any - if (q->length > 2 && N(1).at - N(3).at <= 2 * OPT(click_interval)) { - multi_click(w, 3); - q->length = 0; - } else if (q->length > 1 && N(1).at - N(2).at <= OPT(click_interval)) { - multi_click(w, 2); + if (q->length > 2) { + // possible triple-click + if ( + N(1).at - N(3).at <= 2 * OPT(click_interval) && + distance(N(1).x, N(1).y, N(3).x, N(3).y) <= multi_click_allowed_radius + ) { + multi_click(w, 3); + q->length = 0; + } + } + if (q->length > 1) { + // possible double-click + if ( + N(1).at - N(2).at <= OPT(click_interval) && + distance(N(1).x, N(1).y, N(2).x, N(2).y) <= multi_click_allowed_radius + ) { + multi_click(w, 2); + } + } #undef N } diff --git a/kitty/state.h b/kitty/state.h index be9f6d4ba..e8d5ddf12 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -52,6 +52,7 @@ typedef struct { typedef struct { double at; int button, modifiers; + double x, y; } Click; #define CLICK_QUEUE_SZ 3 @@ -67,7 +68,10 @@ typedef struct { CursorShape last_cursor_shape; PyObject *title; ScreenRenderData render_data; - unsigned int mouse_cell_x, mouse_cell_y; + struct { + unsigned int cell_x, cell_y; + double x, y; + } mouse_pos; WindowGeometry geometry; ClickQueue click_queue; double last_drag_scroll_at;