summaryrefslogtreecommitdiffstats
path: root/server-client.c
diff options
context:
space:
mode:
authornicm <nicm>2016-10-11 09:30:36 +0000
committernicm <nicm>2016-10-11 09:30:36 +0000
commit85d7afaefc1e2cf8008575a776ec70f51d24e1a6 (patch)
treea21793f0c47a4683a2cf40ea07387e9e402b052d /server-client.c
parent76d6d3641f271be1756e41494960d96714e7ee58 (diff)
Support double and triple clicks (they are cumulative, so double is
fired then triple), and use for select-word and select-line in copy mode. Inspired by a different solution from Omar Sandoval.
Diffstat (limited to 'server-client.c')
-rw-r--r--server-client.c121
1 files changed, 113 insertions, 8 deletions
diff --git a/server-client.c b/server-client.c
index 70fdd51a..d5c0cf23 100644
--- a/server-client.c
+++ b/server-client.c
@@ -37,6 +37,7 @@ static void server_client_check_focus(struct window_pane *);
static void server_client_check_resize(struct window_pane *);
static key_code server_client_check_mouse(struct client *);
static void server_client_repeat_timer(int, short, void *);
+static void server_client_click_timer(int, short, void *);
static void server_client_check_exit(struct client *);
static void server_client_check_redraw(struct client *);
static void server_client_set_title(struct client *);
@@ -155,6 +156,7 @@ server_client_create(int fd)
c->keytable->references++;
evtimer_set(&c->repeat_timer, server_client_repeat_timer, c);
+ evtimer_set(&c->click_timer, server_client_click_timer, c);
TAILQ_INSERT_TAIL(&clients, c, entry);
log_debug("new client %p", c);
@@ -223,6 +225,7 @@ server_client_lost(struct client *c)
free((void *)c->cwd);
evtimer_del(&c->repeat_timer);
+ evtimer_del(&c->click_timer);
key_bindings_unref_table(c->keytable);
@@ -299,14 +302,16 @@ server_client_detach(struct client *c, enum msgtype msgtype)
static key_code
server_client_check_mouse(struct client *c)
{
- struct session *s = c->session;
- struct mouse_event *m = &c->tty.mouse;
- struct window *w;
- struct window_pane *wp;
- enum { NOTYPE, DOWN, UP, DRAG, WHEEL } type = NOTYPE;
- enum { NOWHERE, PANE, STATUS, BORDER } where = NOWHERE;
- u_int x, y, b;
- key_code key;
+ struct session *s = c->session;
+ struct mouse_event *m = &c->tty.mouse;
+ struct window *w;
+ struct window_pane *wp;
+ u_int x, y, b;
+ int flag;
+ key_code key;
+ struct timeval tv;
+ enum { NOTYPE, DOWN, UP, DRAG, WHEEL, DOUBLE, TRIPLE } type = NOTYPE;
+ enum { NOWHERE, PANE, STATUS, BORDER } where = NOWHERE;
log_debug("mouse %02x at %u,%u (last %u,%u) (%d)", m->b, m->x, m->y,
m->lx, m->ly, c->tty.mouse_drag_flag);
@@ -330,10 +335,45 @@ server_client_check_mouse(struct client *c)
x = m->x, y = m->y, b = m->lb;
log_debug("up at %u,%u", x, y);
} else {
+ if (c->flags & CLIENT_DOUBLECLICK) {
+ evtimer_del(&c->click_timer);
+ c->flags &= ~CLIENT_DOUBLECLICK;
+ if (m->b == c->click_button) {
+ type = DOUBLE;
+ x = m->x, y = m->y, b = m->b;
+ log_debug("double-click at %u,%u", x, y);
+ flag = CLIENT_TRIPLECLICK;
+ goto add_timer;
+ }
+ } else if (c->flags & CLIENT_TRIPLECLICK) {
+ evtimer_del(&c->click_timer);
+ c->flags &= ~CLIENT_TRIPLECLICK;
+ if (m->b == c->click_button) {
+ type = TRIPLE;
+ x = m->x, y = m->y, b = m->b;
+ log_debug("triple-click at %u,%u", x, y);
+ goto have_event;
+ }
+ }
+
type = DOWN;
x = m->x, y = m->y, b = m->b;
log_debug("down at %u,%u", x, y);
+ flag = CLIENT_DOUBLECLICK;
+
+ add_timer:
+ if (KEYC_CLICK_TIMEOUT != 0) {
+ c->flags |= flag;
+ c->click_button = m->b;
+
+ tv.tv_sec = KEYC_CLICK_TIMEOUT / 1000;
+ tv.tv_usec = (KEYC_CLICK_TIMEOUT % 1000) * 1000L;
+ evtimer_del(&c->click_timer);
+ evtimer_add(&c->click_timer, &tv);
+ }
}
+
+have_event:
if (type == NOTYPE)
return (KEYC_UNKNOWN);
@@ -546,6 +586,62 @@ server_client_check_mouse(struct client *c)
break;
}
break;
+ case DOUBLE:
+ switch (MOUSE_BUTTONS(b)) {
+ case 0:
+ if (where == PANE)
+ key = KEYC_DOUBLECLICK1_PANE;
+ if (where == STATUS)
+ key = KEYC_DOUBLECLICK1_STATUS;
+ if (where == BORDER)
+ key = KEYC_DOUBLECLICK1_BORDER;
+ break;
+ case 1:
+ if (where == PANE)
+ key = KEYC_DOUBLECLICK2_PANE;
+ if (where == STATUS)
+ key = KEYC_DOUBLECLICK2_STATUS;
+ if (where == BORDER)
+ key = KEYC_DOUBLECLICK2_BORDER;
+ break;
+ case 2:
+ if (where == PANE)
+ key = KEYC_DOUBLECLICK3_PANE;
+ if (where == STATUS)
+ key = KEYC_DOUBLECLICK3_STATUS;
+ if (where == BORDER)
+ key = KEYC_DOUBLECLICK3_BORDER;
+ break;
+ }
+ break;
+ case TRIPLE:
+ switch (MOUSE_BUTTONS(b)) {
+ case 0:
+ if (where == PANE)
+ key = KEYC_TRIPLECLICK1_PANE;
+ if (where == STATUS)
+ key = KEYC_TRIPLECLICK1_STATUS;
+ if (where == BORDER)
+ key = KEYC_TRIPLECLICK1_BORDER;
+ break;
+ case 1:
+ if (where == PANE)
+ key = KEYC_TRIPLECLICK2_PANE;
+ if (where == STATUS)
+ key = KEYC_TRIPLECLICK2_STATUS;
+ if (where == BORDER)
+ key = KEYC_TRIPLECLICK2_BORDER;
+ break;
+ case 2:
+ if (where == PANE)
+ key = KEYC_TRIPLECLICK3_PANE;
+ if (where == STATUS)
+ key = KEYC_TRIPLECLICK3_STATUS;
+ if (where == BORDER)
+ key = KEYC_TRIPLECLICK3_BORDER;
+ break;
+ }
+ break;
}
if (key == KEYC_UNKNOWN)
return (KEYC_UNKNOWN);
@@ -945,6 +1041,15 @@ server_client_repeat_timer(__unused int fd, __unused short events, void *data)
}
}
+/* Double-click callback. */
+static void
+server_client_click_timer(__unused int fd, __unused short events, void *data)
+{
+ struct client *c = data;
+
+ c->flags &= ~(CLIENT_DOUBLECLICK|CLIENT_TRIPLECLICK);
+}
+
/* Check if client should be exited. */
static void
server_client_check_exit(struct client *c)