When double or triple clicking ignore clicks if they are "far" from each other

Fixes #1093
This commit is contained in:
Kovid Goyal 2018-11-23 11:46:02 +05:30
parent b44345d78e
commit a0ff625f61
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 45 additions and 17 deletions

View File

@ -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]
------------------------------

View File

@ -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
}

View File

@ -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;