diff --git a/.mailmap b/.mailmap new file mode 100644 index 00000000..a7a401ff --- /dev/null +++ b/.mailmap @@ -0,0 +1,24 @@ +Bob Beck beck +Igor Sobrado sobrado +Jacek Masiulaniec jacekm +Jason McIntyre jcm +Joel Sing jsing +Marc Espie espie +Matthew Dempsky matthew +Matthias Kilian kili +Matthieu Herrb matthieu +Miod Vallat miod +Nicholas Marriott nicm +Nicholas Marriott no_author + +Okan Demirmen okan +Philip Guenther guenther +Pierre-Yves Ritschard pyr +Ray Lai ray +Ryan McBride mcbride +Stefan Sperling stsp +Stuart Henderson sthen +Ted Unangst tedu +Theo Deraadt deraadt +Thomas Adam Thomas +William Yodlowsky william diff --git a/cfg.c b/cfg.c index 577f2d12..17287d86 100644 --- a/cfg.c +++ b/cfg.c @@ -173,3 +173,25 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes) return (retval); } + +void +show_cfg_causes(struct session *s) +{ + struct window_pane *wp; + char *cause; + u_int i; + + if (s == NULL || ARRAY_EMPTY(&cfg_causes)) + return; + + wp = s->curw->window->active; + + window_pane_set_mode(wp, &window_copy_mode); + window_copy_init_for_output(wp); + for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) { + cause = ARRAY_ITEM(&cfg_causes, i); + window_copy_add(wp, "%s", cause); + free(cause); + } + ARRAY_FREE(&cfg_causes); +} diff --git a/cmd-find-window.c b/cmd-find-window.c index 1a08c18b..9a0a8a42 100644 --- a/cmd-find-window.c +++ b/cmd-find-window.c @@ -193,6 +193,7 @@ cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx) ARRAY_ITEM(&find_list, i).list_ctx); format_session(cdata->ft, s); format_winlink(cdata->ft, s, wm); + format_window_pane(cdata->ft, wm->window->active); window_choose_add(wl->window->active, cdata); } diff --git a/cmd-list-clients.c b/cmd-list-clients.c index e906f63c..19976cfd 100644 --- a/cmd-list-clients.c +++ b/cmd-list-clients.c @@ -28,7 +28,7 @@ * List all clients. */ -int cmd_list_clients_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_list_clients_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_list_clients_entry = { "list-clients", "lsc", diff --git a/cmd-list-keys.c b/cmd-list-keys.c index afd5b4a3..51eeb674 100644 --- a/cmd-list-keys.c +++ b/cmd-list-keys.c @@ -97,7 +97,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmd_ctx *ctx) return (CMD_RETURN_NORMAL); } -int +enum cmd_retval cmd_list_keys_table(struct cmd *self, struct cmd_ctx *ctx) { struct args *args = self->args; diff --git a/cmd-list-windows.c b/cmd-list-windows.c index 3be8ade8..b36b5ee8 100644 --- a/cmd-list-windows.c +++ b/cmd-list-windows.c @@ -99,6 +99,7 @@ cmd_list_windows_session( format_add(ft, "line", "%u", n); format_session(ft, s); format_winlink(ft, s, wl); + format_window_pane(ft, wl->window->active); line = format_expand(ft, template); ctx->print(ctx, "%s", line); diff --git a/cmd-new-session.c b/cmd-new-session.c index 8477d9b2..93cf945a 100644 --- a/cmd-new-session.c +++ b/cmd-new-session.c @@ -58,14 +58,13 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) struct args *args = self->args; struct session *s, *old_s, *groupwith; struct window *w; - struct window_pane *wp; struct environ env; struct termios tio, *tiop; struct passwd *pw; const char *newname, *target, *update, *cwd, *errstr; char *cmd, *cause; int detached, idx; - u_int sx, sy, i; + u_int sx, sy; newname = args_get(args, 's'); if (newname != NULL) { @@ -257,17 +256,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx) * If there are still configuration file errors to display, put the new * session's current window into more mode and display them now. */ - if (cfg_finished && !ARRAY_EMPTY(&cfg_causes)) { - wp = s->curw->window->active; - window_pane_set_mode(wp, &window_copy_mode); - window_copy_init_for_output(wp); - for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) { - cause = ARRAY_ITEM(&cfg_causes, i); - window_copy_add(wp, "%s", cause); - free(cause); - } - ARRAY_FREE(&cfg_causes); - } + if (cfg_finished) + show_cfg_causes(s); return (detached ? CMD_RETURN_NORMAL : CMD_RETURN_ATTACH); } diff --git a/cmd-new-window.c b/cmd-new-window.c index 81919439..f8a76120 100644 --- a/cmd-new-window.c +++ b/cmd-new-window.c @@ -26,7 +26,7 @@ * Create a new window. */ -int cmd_new_window_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_new_window_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_new_window_entry = { "new-window", "neww", diff --git a/cmd-set-environment.c b/cmd-set-environment.c index 95336269..c7a4fc51 100644 --- a/cmd-set-environment.c +++ b/cmd-set-environment.c @@ -57,7 +57,7 @@ cmd_set_environment_exec(struct cmd *self, struct cmd_ctx *ctx) return (CMD_RETURN_ERROR); } - if (args->argc < 1) + if (args->argc < 2) value = NULL; else value = args->argv[1]; diff --git a/cmd-swap-window.c b/cmd-swap-window.c index 4c955402..f0c9ffe2 100644 --- a/cmd-swap-window.c +++ b/cmd-swap-window.c @@ -26,7 +26,7 @@ * Swap one window with another. */ -int cmd_swap_window_exec(struct cmd *, struct cmd_ctx *); +enum cmd_retval cmd_swap_window_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_swap_window_entry = { "swap-window", "swapw", diff --git a/input-keys.c b/input-keys.c index 2b30d4ba..483d410f 100644 --- a/input-keys.c +++ b/input-keys.c @@ -199,7 +199,7 @@ input_key(struct window_pane *wp, int key) /* Translate mouse and output. */ void -input_mouse(struct window_pane *wp, struct mouse_event *m) +input_mouse(struct window_pane *wp, struct session *s, struct mouse_event *m) { char buf[10]; size_t len; @@ -207,14 +207,14 @@ input_mouse(struct window_pane *wp, struct mouse_event *m) if (wp->screen->mode & ALL_MOUSE_MODES) { if (wp->screen->mode & MODE_MOUSE_UTF8) { len = xsnprintf(buf, sizeof buf, "\033[M"); - len += utf8_split2(m->b + 32, &buf[len]); + len += utf8_split2(m->xb + 32, &buf[len]); len += utf8_split2(m->x + 33, &buf[len]); len += utf8_split2(m->y + 33, &buf[len]); } else { - if (m->b > 223 || m->x >= 222 || m->y > 222) + if (m->xb > 223 || m->x >= 222 || m->y > 222) return; len = xsnprintf(buf, sizeof buf, "\033[M"); - buf[len++] = m->b + 32; + buf[len++] = m->xb + 32; buf[len++] = m->x + 33; buf[len++] = m->y + 33; } @@ -222,12 +222,12 @@ input_mouse(struct window_pane *wp, struct mouse_event *m) return; } - if ((m->b & 3) != 1 && + if ((m->xb & 3) != 1 && options_get_number(&wp->window->options, "mode-mouse") == 1) { if (window_pane_set_mode(wp, &window_copy_mode) == 0) { window_copy_init_from_pane(wp); if (wp->mode->mouse != NULL) - wp->mode->mouse(wp, NULL, m); + wp->mode->mouse(wp, s, m); } return; } diff --git a/layout.c b/layout.c index fc77c928..3eaeb5b7 100644 --- a/layout.c +++ b/layout.c @@ -488,50 +488,51 @@ layout_resize_pane(struct window_pane *wp, enum layout_type type, int change) } void -layout_resize_pane_mouse(struct client *c, struct mouse_event *mouse) +layout_resize_pane_mouse(struct client *c) { struct window *w; struct window_pane *wp; + struct mouse_event *m = &c->tty.mouse; int pane_border; w = c->session->curw->window; pane_border = 0; - if ((c->last_mouse.b & MOUSE_BUTTON) != MOUSE_UP && - (c->last_mouse.b & MOUSE_RESIZE_PANE)) { + if (m->event & MOUSE_EVENT_DRAG && m->flags & MOUSE_RESIZE_PANE) { TAILQ_FOREACH(wp, &w->panes, entry) { - if (wp->xoff + wp->sx == c->last_mouse.x && - wp->yoff <= 1 + c->last_mouse.y && - wp->yoff + wp->sy >= c->last_mouse.y) { + if (wp->xoff + wp->sx == m->lx && + wp->yoff <= 1 + m->ly && + wp->yoff + wp->sy >= m->ly) { layout_resize_pane(wp, LAYOUT_LEFTRIGHT, - mouse->x - c->last_mouse.x); + m->x - m->lx); pane_border = 1; } - if (wp->yoff + wp->sy == c->last_mouse.y && - wp->xoff <= 1 + c->last_mouse.x && - wp->xoff + wp->sx >= c->last_mouse.x) { + if (wp->yoff + wp->sy == m->ly && + wp->xoff <= 1 + m->lx && + wp->xoff + wp->sx >= m->lx) { layout_resize_pane(wp, LAYOUT_TOPBOTTOM, - mouse->y - c->last_mouse.y); + m->y - m->ly); pane_border = 1; } } if (pane_border) server_redraw_window(w); - } else if (mouse->b != MOUSE_UP && - mouse->b == (mouse->b & MOUSE_BUTTON)) { + } else if (~m->event & MOUSE_EVENT_UP) { TAILQ_FOREACH(wp, &w->panes, entry) { - if ((wp->xoff + wp->sx == mouse->x && - wp->yoff <= 1 + mouse->y && - wp->yoff + wp->sy >= mouse->y) || - (wp->yoff + wp->sy == mouse->y && - wp->xoff <= 1 + mouse->x && - wp->xoff + wp->sx >= mouse->x)) { + if ((wp->xoff + wp->sx == m->x && + wp->yoff <= 1 + m->y && + wp->yoff + wp->sy >= m->y) || + (wp->yoff + wp->sy == m->y && + wp->xoff <= 1 + m->x && + wp->xoff + wp->sx >= m->x)) { pane_border = 1; } } } if (pane_border) - mouse->b |= MOUSE_RESIZE_PANE; + m->flags |= MOUSE_RESIZE_PANE; + else + m->flags &= ~MOUSE_RESIZE_PANE; } int diff --git a/mode-key.c b/mode-key.c index 6ea2b2f0..7dea26d8 100644 --- a/mode-key.c +++ b/mode-key.c @@ -105,6 +105,8 @@ const struct mode_key_cmdstr mode_key_cmdstr_copy[] = { { MODEKEYCOPY_DOWN, "cursor-down" }, { MODEKEYCOPY_ENDOFLINE, "end-of-line" }, { MODEKEYCOPY_GOTOLINE, "goto-line" }, + { MODEKEYCOPY_HALFPAGEDOWN, "halfpage-down" }, + { MODEKEYCOPY_HALFPAGEUP, "halfpage-up" }, { MODEKEYCOPY_HISTORYBOTTOM, "history-bottom" }, { MODEKEYCOPY_HISTORYTOP, "history-top" }, { MODEKEYCOPY_JUMP, "jump-forward" }, diff --git a/server-client.c b/server-client.c index 435cd068..add5c75e 100644 --- a/server-client.c +++ b/server-client.c @@ -27,8 +27,7 @@ #include "tmux.h" -void server_client_check_mouse(struct client *, struct window_pane *, - struct mouse_event *); +void server_client_check_mouse(struct client *, struct window_pane *); void server_client_repeat_timer(int, short, void *); void server_client_check_exit(struct client *); void server_client_check_redraw(struct client *); @@ -86,8 +85,12 @@ server_client_create(int fd) c->prompt_buffer = NULL; c->prompt_index = 0; - c->last_mouse.b = MOUSE_UP; - c->last_mouse.x = c->last_mouse.y = -1; + c->tty.mouse.xb = c->tty.mouse.button = 3; + c->tty.mouse.x = c->tty.mouse.y = -1; + c->tty.mouse.lx = c->tty.mouse.ly = -1; + c->tty.mouse.sx = c->tty.mouse.sy = -1; + c->tty.mouse.event = MOUSE_EVENT_UP; + c->tty.mouse.flags = 0; evtimer_set(&c->repeat_timer, server_client_repeat_timer, c); @@ -270,37 +273,28 @@ server_client_status_timer(void) /* Check for mouse keys. */ void -server_client_check_mouse( - struct client *c, struct window_pane *wp, struct mouse_event *mouse) +server_client_check_mouse(struct client *c, struct window_pane *wp) { - struct session *s = c->session; - struct options *oo = &s->options; - int statusat; + struct session *s = c->session; + struct options *oo = &s->options; + struct mouse_event *m = &c->tty.mouse; + int statusat; statusat = status_at_line(c); /* Is this a window selection click on the status line? */ - if (statusat != -1 && mouse->y == (u_int)statusat && + if (statusat != -1 && m->y == (u_int)statusat && options_get_number(oo, "mouse-select-window")) { - if (mouse->b == MOUSE_UP && c->last_mouse.b != MOUSE_UP) { - status_set_window_at(c, mouse->x); - recalculate_sizes(); - return; - } - if (mouse->b & MOUSE_45) { - if ((mouse->b & MOUSE_BUTTON) == MOUSE_1) { + if (m->event & MOUSE_EVENT_CLICK) { + status_set_window_at(c, m->x); + } else if (m->event == MOUSE_EVENT_WHEEL) { + if (m->wheel == MOUSE_WHEEL_UP) session_previous(c->session, 0); - server_redraw_session(s); - recalculate_sizes(); - } - if ((mouse->b & MOUSE_BUTTON) == MOUSE_2) { + else if (m->wheel == MOUSE_WHEEL_DOWN) session_next(c->session, 0); - server_redraw_session(s); - recalculate_sizes(); - } - return; + server_redraw_session(s); } - memcpy(&c->last_mouse, mouse, sizeof c->last_mouse); + recalculate_sizes(); return; } @@ -309,27 +303,25 @@ server_client_check_mouse( * top and limit if at the bottom. From here on a struct mouse * represents the offset onto the window itself. */ - if (statusat == 0 &&mouse->y > 0) - mouse->y--; - else if (statusat > 0 && mouse->y >= (u_int)statusat) - mouse->y = statusat - 1; + if (statusat == 0 && m->y > 0) + m->y--; + else if (statusat > 0 && m->y >= (u_int)statusat) + m->y = statusat - 1; /* Is this a pane selection? Allow down only in copy mode. */ if (options_get_number(oo, "mouse-select-pane") && - ((!(mouse->b & MOUSE_DRAG) && mouse->b != MOUSE_UP) || - wp->mode != &window_copy_mode)) { - window_set_active_at(wp->window, mouse->x, mouse->y); + (m->event == MOUSE_EVENT_DOWN || wp->mode != &window_copy_mode)) { + window_set_active_at(wp->window, m->x, m->y); server_redraw_window_borders(wp->window); wp = wp->window->active; /* may have changed */ } /* Check if trying to resize pane. */ if (options_get_number(oo, "mouse-resize-pane")) - layout_resize_pane_mouse(c, mouse); + layout_resize_pane_mouse(c); /* Update last and pass through to client. */ - memcpy(&c->last_mouse, mouse, sizeof c->last_mouse); - window_pane_mouse(wp, c->session, mouse); + window_pane_mouse(wp, c->session, m); } /* Handle data key input from client. */ @@ -384,7 +376,7 @@ server_client_handle_key(struct client *c, int key) if (key == KEYC_MOUSE) { if (c->flags & CLIENT_READONLY) return; - server_client_check_mouse(c, wp, &c->tty.mouse); + server_client_check_mouse(c, wp); return; } @@ -523,7 +515,7 @@ server_client_reset_state(struct client *c) * a smooth appearance. */ mode = s->mode; - if ((c->last_mouse.b & MOUSE_RESIZE_PANE) && + if ((c->tty.mouse.flags & MOUSE_RESIZE_PANE) && !(mode & (MODE_MOUSE_BUTTON|MODE_MOUSE_ANY))) mode |= MODE_MOUSE_BUTTON; diff --git a/server-window.c b/server-window.c index 72203201..fce6439b 100644 --- a/server-window.c +++ b/server-window.c @@ -75,12 +75,14 @@ server_window_check_bell(struct session *s, struct winlink *wl) if (s->curw != wl || s->flags & SESSION_UNATTACHED) wl->flags |= WINLINK_BELL; if (s->flags & SESSION_UNATTACHED) - return (1); + return (0); if (s->curw->window == wl->window) w->flags &= ~WINDOW_BELL; visual = options_get_number(&s->options, "visual-bell"); action = options_get_number(&s->options, "bell-action"); + if (action == BELL_NONE) + return (0); for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); if (c == NULL || c->session != s) diff --git a/server.c b/server.c index 4da0739b..033707eb 100644 --- a/server.c +++ b/server.c @@ -105,11 +105,8 @@ server_create_socket(void) int server_start(int lockfd, char *lockfile) { - struct window_pane *wp; - int pair[2]; - char *cause; - struct timeval tv; - u_int i; + int pair[2]; + struct timeval tv; /* The first client is special and gets a socketpair; create it. */ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0) @@ -179,17 +176,9 @@ server_start(int lockfd, char *lockfile) * If there is a session already, put the current window and pane into * more mode. */ - if (!RB_EMPTY(&sessions) && !ARRAY_EMPTY(&cfg_causes)) { - wp = RB_MIN(sessions, &sessions)->curw->window->active; - window_pane_set_mode(wp, &window_copy_mode); - window_copy_init_for_output(wp); - for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) { - cause = ARRAY_ITEM(&cfg_causes, i); - window_copy_add(wp, "%s", cause); - free(cause); - } - ARRAY_FREE(&cfg_causes); - } + if (!RB_EMPTY(&sessions) && !ARRAY_EMPTY(&cfg_causes)) + show_cfg_causes(RB_MIN(sessions, &sessions)); + cfg_finished = 1; server_add_accept(0); diff --git a/tmux.1 b/tmux.1 index aec62478..9ad40e07 100644 --- a/tmux.1 +++ b/tmux.1 @@ -124,13 +124,19 @@ loads the system configuration file from .Pa /etc/tmux.conf , if present, then looks for a user configuration file at .Pa ~/.tmux.conf . +.Pp The configuration file is a set of .Nm commands which are executed in sequence when the server is first started. -.Pp -If a command in the configuration file fails, .Nm -will report an error and exit without executing further commands. +loads configuration files once when the server process has started. +The +.Ic source-file +command may be used to load a file later. +.Pp +.Nm +shows any error messages from commands in configuration files in the first +session created, and continues to process the rest of the configuration file. .It Fl L Ar socket-name .Nm stores the server socket in a directory under @@ -2043,7 +2049,7 @@ window of that session, .Ic none means all bells are ignored and .Ic current -means only bell in windows other than the current window are ignored. +means only bells in windows other than the current window are ignored. .It Xo Ic bell-on-alert .Op Ic on | off .Xc diff --git a/tmux.h b/tmux.h index 3751b672..aca96613 100644 --- a/tmux.h +++ b/tmux.h @@ -96,7 +96,8 @@ extern char **environ; #define CHOOSE_CLIENT_TEMPLATE \ "#{client_tty}: #{session_name} " \ "[#{client_width}x#{client_height} #{client_termname}]" \ - "#{?client_utf8, (utf8),} #{?client_readonly, (ro),}" + "#{?client_utf8, (utf8),}#{?client_readonly, (ro),} " \ + "(last used #{client_activity_string})" /* Default templates for choose-tree. */ #define CHOOSE_TREE_SESSION_TEMPLATE \ @@ -1115,29 +1116,6 @@ struct session { RB_HEAD(sessions, session); ARRAY_DECL(sessionslist, struct session *); -/* - * Mouse input. xterm mouse mode is fairly silly. Buttons are in the bottom two - * bits: 0 = button 1; 1 = button 2; 2 = button 3; 3 = buttons released. Bits - * 3, 4 and 5 are for keys. Bit 6 is set for dragging and 7 for mouse buttons 4 - * and 5. - */ -struct mouse_event { - u_int b; -#define MOUSE_1 0 -#define MOUSE_2 1 -#define MOUSE_3 2 -#define MOUSE_UP 3 -#define MOUSE_BUTTON 3 -#define MOUSE_SHIFT 4 -#define MOUSE_ESCAPE 8 -#define MOUSE_CTRL 16 -#define MOUSE_DRAG 32 -#define MOUSE_45 64 -#define MOUSE_RESIZE_PANE 128 /* marker for resizing */ - u_int x; - u_int y; -}; - /* TTY information. */ struct tty_key { char ch; @@ -1166,6 +1144,47 @@ struct tty_term { }; LIST_HEAD(tty_terms, tty_term); +/* Mouse wheel states. */ +#define MOUSE_WHEEL_UP 0 +#define MOUSE_WHEEL_DOWN 1 + +/* Mouse events. */ +#define MOUSE_EVENT_DOWN (1 << 0) +#define MOUSE_EVENT_DRAG (1 << 1) +#define MOUSE_EVENT_UP (1 << 2) +#define MOUSE_EVENT_CLICK (1 << 3) +#define MOUSE_EVENT_WHEEL (1 << 4) + +/* Mouse flags. */ +#define MOUSE_RESIZE_PANE (1 << 0) + +/* + * Mouse input. When sent by xterm: + * + * - buttons are in the bottom two bits: 0 = b1; 1 = b2; 2 = b3; 3 = released + * - bits 3, 4 and 5 are for keys + * - bit 6 is set for dragging + * - bit 7 for buttons 4 and 5 + */ +struct mouse_event { + u_int xb; + + u_int x; + u_int lx; + u_int sx; + + u_int y; + u_int ly; + u_int sy; + + u_int button; + u_int clicks; + + int wheel; + int event; + int flags; +}; + struct tty { struct client *client; @@ -1326,8 +1345,6 @@ struct client { struct session *session; struct session *last_session; - struct mouse_event last_mouse; - int wlmouse; int references; @@ -1499,6 +1516,7 @@ extern int cfg_finished; extern struct causelist cfg_causes; void printflike2 cfg_add_cause(struct causelist *, const char *, ...); int load_cfg(const char *, struct cmd_ctx *, struct causelist *); +void show_cfg_causes(struct session *); /* format.c */ int format_cmp(struct format_entry *, struct format_entry *); @@ -1922,7 +1940,8 @@ void input_parse(struct window_pane *); /* input-key.c */ void input_key(struct window_pane *, int); -void input_mouse(struct window_pane *, struct mouse_event *); +void input_mouse(struct window_pane *, struct session *, + struct mouse_event *); /* xterm-keys.c */ char *xterm_keys_lookup(int); @@ -2166,8 +2185,7 @@ void layout_free(struct window *); void layout_resize(struct window *, u_int, u_int); void layout_resize_pane( struct window_pane *, enum layout_type, int); -void layout_resize_pane_mouse( - struct client *c, struct mouse_event *mouse); +void layout_resize_pane_mouse(struct client *c); void layout_assign_pane(struct layout_cell *, struct window_pane *); struct layout_cell *layout_split_pane( struct window_pane *, enum layout_type, int, int); diff --git a/tty-keys.c b/tty-keys.c index de574f4f..9ed280e7 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -611,7 +611,7 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size) { struct mouse_event *m = &tty->mouse; struct utf8_data utf8data; - u_int i, value; + u_int i, value, x, y, b; /* * Standard mouse sequences are \033[M followed by three characters @@ -622,6 +622,7 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size) */ *size = 0; + x = y = b = 0; /* First three bytes are always \033[M. */ if (buf[0] != '\033') @@ -661,21 +662,58 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size) } if (i == 0) - m->b = value; + b = value; else if (i == 1) - m->x = value; + x = value; else - m->y = value; + y = value; } log_debug("mouse input: %.*s", (int) *size, buf); /* Check and return the mouse input. */ - if (m->b < 32 || m->x < 33 || m->y < 33) + if (b < 32 || x < 33 || y < 33) return (-1); - m->b -= 32; - m->x -= 33; - m->y -= 33; - log_debug("mouse position: x=%u y=%u b=%u", m->x, m->y, m->b); + b -= 32; + x -= 33; + y -= 33; + log_debug("mouse position: x=%u y=%u b=%u", x, y, b); + + /* Fill in mouse structure. */ + if (~m->event & MOUSE_EVENT_WHEEL) { + m->lx = m->x; + m->ly = m->y; + } + m->xb = b; + if (b & 64) { /* wheel button */ + b &= 3; + if (b == 0) + m->wheel = MOUSE_WHEEL_UP; + else if (b == 1) + m->wheel = MOUSE_WHEEL_DOWN; + m->event = MOUSE_EVENT_WHEEL; + } else if ((b & 3) == 3) { + if (~m->event & MOUSE_EVENT_DRAG && x == m->x && y == m->y) { + m->event = MOUSE_EVENT_CLICK; + } else + m->event = MOUSE_EVENT_DRAG; + m->event |= MOUSE_EVENT_UP; + } else { + if (b & 32) /* drag motion */ + m->event = MOUSE_EVENT_DRAG; + else { + if (m->event & MOUSE_EVENT_UP && x == m->x && y == m->y) + m->clicks = (m->clicks + 1) % 3; + else + m->clicks = 0; + m->sx = x; + m->sy = y; + m->event = MOUSE_EVENT_DOWN; + } + m->button = (b & 3); + } + m->x = x; + m->y = y; + return (0); } diff --git a/window-choose.c b/window-choose.c index 86980a4f..5bcca17c 100644 --- a/window-choose.c +++ b/window-choose.c @@ -623,7 +623,7 @@ window_choose_mouse( struct window_choose_mode_item *item; u_int idx; - if ((m->b & 3) == 3) + if (~m->event & MOUSE_EVENT_CLICK) return; if (m->x >= screen_size_x(s)) return; diff --git a/window-copy.c b/window-copy.c index 1284913b..480fdc70 100644 --- a/window-copy.c +++ b/window-copy.c @@ -829,11 +829,11 @@ window_copy_mouse( return; /* If mouse wheel (buttons 4 and 5), scroll. */ - if ((m->b & MOUSE_45)) { - if ((m->b & MOUSE_BUTTON) == MOUSE_1) { + if (m->event == MOUSE_EVENT_WHEEL) { + if (m->wheel == MOUSE_WHEEL_UP) { for (i = 0; i < 5; i++) window_copy_cursor_up(wp, 0); - } else if ((m->b & MOUSE_BUTTON) == MOUSE_2) { + } else if (m->wheel == MOUSE_WHEEL_DOWN) { for (i = 0; i < 5; i++) window_copy_cursor_down(wp, 0); if (data->oy == 0) @@ -847,7 +847,7 @@ window_copy_mouse( * pressed, or stop the selection on their release. */ if (s->mode & MODE_MOUSE_BUTTON) { - if ((m->b & MOUSE_BUTTON) != MOUSE_UP) { + if (~m->event & MOUSE_EVENT_UP) { window_copy_update_cursor(wp, m->x, m->y); if (window_copy_update_selection(wp)) window_copy_redraw_screen(wp); @@ -857,7 +857,7 @@ window_copy_mouse( } /* Otherwise if other buttons pressed, start selection and motion. */ - if ((m->b & MOUSE_BUTTON) != MOUSE_UP) { + if (~m->event & MOUSE_EVENT_UP) { s->mode &= ~MODE_MOUSE_STANDARD; s->mode |= MODE_MOUSE_BUTTON; diff --git a/window.c b/window.c index 5ef81959..5cdc504f 100644 --- a/window.c +++ b/window.c @@ -1021,7 +1021,7 @@ window_pane_mouse( options_get_number(&wp->window->options, "mode-mouse")) wp->mode->mouse(wp, sess, m); } else if (wp->fd != -1) - input_mouse(wp, m); + input_mouse(wp, sess, m); } int @@ -1203,7 +1203,7 @@ winlink_clear_flags(struct winlink *wl) void window_mode_attrs(struct grid_cell *gc, struct options *oo) { - memcpy(gc, &grid_default_cell, sizeof gc); + memcpy(gc, &grid_default_cell, sizeof *gc); colour_set_fg(gc, options_get_number(oo, "mode-fg")); colour_set_bg(gc, options_get_number(oo, "mode-bg")); gc->attr |= options_get_number(oo, "mode-attr");