mirror of
https://github.com/tmux/tmux.git
synced 2025-09-06 00:37:06 +00:00
Merge branch 'obsd-master'
Conflicts: format.c osdep-openbsd.c
This commit is contained in:
210
server-client.c
210
server-client.c
@ -30,21 +30,22 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
void server_client_free(int, short, void *);
|
||||
void server_client_check_focus(struct window_pane *);
|
||||
void server_client_check_resize(struct window_pane *);
|
||||
key_code server_client_check_mouse(struct client *);
|
||||
void server_client_repeat_timer(int, short, void *);
|
||||
void server_client_check_exit(struct client *);
|
||||
void server_client_check_redraw(struct client *);
|
||||
void server_client_set_title(struct client *);
|
||||
void server_client_reset_state(struct client *);
|
||||
int server_client_assume_paste(struct session *);
|
||||
static void server_client_free(int, short, void *);
|
||||
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 *);
|
||||
static void server_client_reset_state(struct client *);
|
||||
static int server_client_assume_paste(struct session *);
|
||||
|
||||
void server_client_dispatch(struct imsg *, void *);
|
||||
void server_client_dispatch_command(struct client *, struct imsg *);
|
||||
void server_client_dispatch_identify(struct client *, struct imsg *);
|
||||
void server_client_dispatch_shell(struct client *);
|
||||
static void server_client_dispatch(struct imsg *, void *);
|
||||
static void server_client_dispatch_command(struct client *, struct imsg *);
|
||||
static void server_client_dispatch_identify(struct client *, struct imsg *);
|
||||
static void server_client_dispatch_shell(struct client *);
|
||||
|
||||
/* Check if this client is inside this server. */
|
||||
int
|
||||
@ -95,6 +96,13 @@ server_client_get_key_table(struct client *c)
|
||||
return (name);
|
||||
}
|
||||
|
||||
/* Is this client using the default key table? */
|
||||
int
|
||||
server_client_is_default_key_table(struct client *c)
|
||||
{
|
||||
return (strcmp(c->keytable->name, server_client_get_key_table(c)) == 0);
|
||||
}
|
||||
|
||||
/* Create a new client. */
|
||||
void
|
||||
server_client_create(int fd)
|
||||
@ -146,6 +154,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);
|
||||
@ -214,6 +223,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);
|
||||
|
||||
@ -262,7 +272,7 @@ server_client_unref(struct client *c)
|
||||
}
|
||||
|
||||
/* Free dead client. */
|
||||
void
|
||||
static void
|
||||
server_client_free(__unused int fd, __unused short events, void *arg)
|
||||
{
|
||||
struct client *c = arg;
|
||||
@ -287,17 +297,19 @@ server_client_detach(struct client *c, enum msgtype msgtype)
|
||||
}
|
||||
|
||||
/* Check for mouse keys. */
|
||||
key_code
|
||||
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);
|
||||
@ -321,10 +333,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);
|
||||
|
||||
@ -537,6 +584,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);
|
||||
@ -553,7 +656,7 @@ server_client_check_mouse(struct client *c)
|
||||
}
|
||||
|
||||
/* Is this fast enough to probably be a paste? */
|
||||
int
|
||||
static int
|
||||
server_client_assume_paste(struct session *s)
|
||||
{
|
||||
struct timeval tv;
|
||||
@ -585,6 +688,7 @@ server_client_handle_key(struct client *c, key_code key)
|
||||
struct window *w;
|
||||
struct window_pane *wp;
|
||||
struct timeval tv;
|
||||
const char *name;
|
||||
struct key_table *table;
|
||||
struct key_binding bd_find, *bd;
|
||||
int xtimeout;
|
||||
@ -593,6 +697,10 @@ server_client_handle_key(struct client *c, key_code key)
|
||||
if (s == NULL || (c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED)) != 0)
|
||||
return;
|
||||
w = s->curw->window;
|
||||
if (KEYC_IS_MOUSE(key))
|
||||
wp = cmd_mouse_pane(m, NULL, NULL);
|
||||
else
|
||||
wp = w->active;
|
||||
|
||||
/* Update the activity timer. */
|
||||
if (gettimeofday(&c->activity_time, NULL) != 0)
|
||||
@ -643,9 +751,21 @@ server_client_handle_key(struct client *c, key_code key)
|
||||
goto forward;
|
||||
|
||||
retry:
|
||||
/*
|
||||
* Work out the current key table. If the pane is in a mode, use
|
||||
* the mode table instead of the default key table.
|
||||
*/
|
||||
name = NULL;
|
||||
if (wp != NULL && wp->mode != NULL && wp->mode->key_table != NULL)
|
||||
name = wp->mode->key_table(wp);
|
||||
if (name == NULL || !server_client_is_default_key_table(c))
|
||||
table = c->keytable;
|
||||
else
|
||||
table = key_bindings_get_table(name, 1);
|
||||
|
||||
/* Try to see if there is a key binding in the current table. */
|
||||
bd_find.key = key;
|
||||
bd = RB_FIND(key_bindings, &c->keytable->key_bindings, &bd_find);
|
||||
bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find);
|
||||
if (bd != NULL) {
|
||||
/*
|
||||
* Key was matched in this table. If currently repeating but a
|
||||
@ -663,7 +783,6 @@ retry:
|
||||
* Take a reference to this table to make sure the key binding
|
||||
* doesn't disappear.
|
||||
*/
|
||||
table = c->keytable;
|
||||
table->references++;
|
||||
|
||||
/*
|
||||
@ -702,7 +821,7 @@ retry:
|
||||
}
|
||||
|
||||
/* If no match and we're not in the root table, that's it. */
|
||||
if (strcmp(c->keytable->name, server_client_get_key_table(c)) != 0) {
|
||||
if (name == NULL && !server_client_is_default_key_table(c)) {
|
||||
server_client_set_key_table(c, NULL);
|
||||
server_status_client(c);
|
||||
return;
|
||||
@ -722,10 +841,6 @@ retry:
|
||||
forward:
|
||||
if (c->flags & CLIENT_READONLY)
|
||||
return;
|
||||
if (KEYC_IS_MOUSE(key))
|
||||
wp = cmd_mouse_pane(m, NULL, NULL);
|
||||
else
|
||||
wp = w->active;
|
||||
if (wp != NULL)
|
||||
window_pane_key(wp, c, s, key, m);
|
||||
}
|
||||
@ -795,7 +910,7 @@ server_client_resize_event(__unused int fd, __unused short events, void *data)
|
||||
}
|
||||
|
||||
/* Check if pane should be resized. */
|
||||
void
|
||||
static void
|
||||
server_client_check_resize(struct window_pane *wp)
|
||||
{
|
||||
struct timeval tv = { .tv_usec = 250000 };
|
||||
@ -825,7 +940,7 @@ server_client_check_resize(struct window_pane *wp)
|
||||
}
|
||||
|
||||
/* Check whether pane should be focused. */
|
||||
void
|
||||
static void
|
||||
server_client_check_focus(struct window_pane *wp)
|
||||
{
|
||||
struct client *c;
|
||||
@ -886,7 +1001,7 @@ focused:
|
||||
* tty_region/tty_reset/tty_update_mode already take care of not resetting
|
||||
* things that are already in their default state.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
server_client_reset_state(struct client *c)
|
||||
{
|
||||
struct window *w = c->session->curw->window;
|
||||
@ -922,7 +1037,7 @@ server_client_reset_state(struct client *c)
|
||||
}
|
||||
|
||||
/* Repeat time callback. */
|
||||
void
|
||||
static void
|
||||
server_client_repeat_timer(__unused int fd, __unused short events, void *data)
|
||||
{
|
||||
struct client *c = data;
|
||||
@ -934,8 +1049,17 @@ 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. */
|
||||
void
|
||||
static void
|
||||
server_client_check_exit(struct client *c)
|
||||
{
|
||||
if (!(c->flags & CLIENT_EXIT))
|
||||
@ -953,7 +1077,7 @@ server_client_check_exit(struct client *c)
|
||||
}
|
||||
|
||||
/* Check for client redraws. */
|
||||
void
|
||||
static void
|
||||
server_client_check_redraw(struct client *c)
|
||||
{
|
||||
struct session *s = c->session;
|
||||
@ -1009,7 +1133,7 @@ server_client_check_redraw(struct client *c)
|
||||
}
|
||||
|
||||
/* Set client title. */
|
||||
void
|
||||
static void
|
||||
server_client_set_title(struct client *c)
|
||||
{
|
||||
struct session *s = c->session;
|
||||
@ -1034,7 +1158,7 @@ server_client_set_title(struct client *c)
|
||||
}
|
||||
|
||||
/* Dispatch message from client. */
|
||||
void
|
||||
static void
|
||||
server_client_dispatch(struct imsg *imsg, void *arg)
|
||||
{
|
||||
struct client *c = arg;
|
||||
@ -1138,7 +1262,7 @@ server_client_dispatch(struct imsg *imsg, void *arg)
|
||||
}
|
||||
|
||||
/* Handle command message. */
|
||||
void
|
||||
static void
|
||||
server_client_dispatch_command(struct client *c, struct imsg *imsg)
|
||||
{
|
||||
struct msg_command_data data;
|
||||
@ -1191,7 +1315,7 @@ error:
|
||||
}
|
||||
|
||||
/* Handle identify message. */
|
||||
void
|
||||
static void
|
||||
server_client_dispatch_identify(struct client *c, struct imsg *imsg)
|
||||
{
|
||||
const char *data, *home;
|
||||
@ -1303,7 +1427,7 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg)
|
||||
}
|
||||
|
||||
/* Handle shell message. */
|
||||
void
|
||||
static void
|
||||
server_client_dispatch_shell(struct client *c)
|
||||
{
|
||||
const char *shell;
|
||||
|
Reference in New Issue
Block a user