Disambiguate between click and doublepress

A doubleprpess should not generate a click event
This commit is contained in:
Kovid Goyal 2021-05-23 13:38:19 +05:30
parent c6c203da43
commit 76c9f46438
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 55 additions and 2 deletions

View File

@ -157,7 +157,9 @@ number ``b1 ... b8`` can be used to refer to upto eight buttons on a mouse.
``event-type`` is one ``press``, ``release``, ``doublepress``, ``triplepress``,
``click`` and ``doubleclick``. ``modes`` indicates whether the action is
performed when the mouse is grabbed by the terminal application or not. It can
have one or more or the values, ``grabbed,ungrabbed``.
have one or more or the values, ``grabbed,ungrabbed``. Note that the click
and double click events have a delay of :opt:`click_interval` to disambiguate
from double and triple presses.
You can run kitty with the :option:`kitty --debug-input` command line option
to see mouse events. See the builtin actions below to get a sense of what is possible.

View File

@ -480,11 +480,42 @@ mouse_open_url(Window *w) {
screen_open_url(screen);
}
typedef struct PendingClick {
id_type window_id;
int button, count, modifiers;
bool grabbed;
monotonic_t at;
} PendingClick;
static void
free_pending_click(id_type timer_id UNUSED, void *pc) { free(pc); }
void
send_pending_click_to_window(Window *w, void *data) {
PendingClick *pc = (PendingClick*)data;
ClickQueue *q = &w->click_queues[pc->button];
// only send click if no presses have happened since the release that triggered the click
if (q->length && q->clicks[q->length - 1].at <= pc->at) {
dispatch_mouse_event(w, pc->button, pc->count, pc->modifiers, pc->grabbed);
}
}
static void
dispatch_possible_click(Window *w, int button, int modifiers) {
Screen *screen = w->render_data.screen;
int count = multi_click_count(w, button);
if (release_is_click(w, button)) dispatch_mouse_event(w, button, count == 2 ? -3 : -2, modifiers, screen->modes.mouse_tracking_mode != 0);
if (release_is_click(w, button)) {
PendingClick *pc = calloc(sizeof(PendingClick), 1);
if (pc) {
pc->window_id = w->id;
pc->at = monotonic();
pc->button = button;
pc->count = count == 2 ? -3 : -2;
pc->modifiers = modifiers;
pc->grabbed = screen->modes.mouse_tracking_mode != 0;
add_main_loop_timer(OPT(click_interval), false, send_pending_click_to_window_id, pc, free_pending_click);
}
}
}
HANDLER(handle_button_event) {

View File

@ -525,6 +525,24 @@ make_window_context_current(id_type window_id) {
return false;
}
void
send_pending_click_to_window_id(id_type timer_id UNUSED, void *data) {
id_type window_id = *((id_type*)data);
for (size_t o = 0; o < global_state.num_os_windows; o++) {
OSWindow *osw = global_state.os_windows + o;
for (size_t t = 0; t < osw->num_tabs; t++) {
Tab *qtab = osw->tabs + t;
for (size_t w = 0; w < qtab->num_windows; w++) {
Window *window = qtab->windows + w;
if (window->id == window_id) {
send_pending_click_to_window(window, data);
return;
}
}
}
}
}
// Python API {{{
#define PYWRAP0(name) static PyObject* py##name(PYNOARG)

View File

@ -292,3 +292,5 @@ Window* window_for_window_id(id_type kitty_window_id);
void mouse_open_url(Window *w);
void mouse_selection(Window *w, int code, int button);
const char* format_mods(unsigned mods);
void send_pending_click_to_window_id(id_type, void*);
void send_pending_click_to_window(Window*, void*);