summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cfg.c2
-rw-r--r--cmd-command-prompt.c2
-rw-r--r--cmd-confirm-before.c2
-rw-r--r--cmd-copy-mode.c15
-rw-r--r--cmd-if-shell.c4
-rw-r--r--cmd-queue.c12
-rw-r--r--cmd-resize-pane.c66
-rw-r--r--cmd-send-keys.c21
-rw-r--r--cmd.c94
-rw-r--r--control.c2
-rw-r--r--input-keys.c97
-rw-r--r--key-bindings.c13
-rw-r--r--key-string.c17
-rw-r--r--layout.c52
-rw-r--r--mode-key.c14
-rw-r--r--options-table.c21
-rw-r--r--server-client.c331
-rw-r--r--server-fn.c7
-rw-r--r--status.c13
-rw-r--r--tmux.199
-rw-r--r--tmux.h140
-rw-r--r--tty-keys.c81
-rw-r--r--tty.c4
-rw-r--r--window-choose.c107
-rw-r--r--window-clock.c8
-rw-r--r--window-copy.c198
-rw-r--r--window.c49
27 files changed, 883 insertions, 588 deletions
diff --git a/cfg.c b/cfg.c
index 23828923..b4c9bff4 100644
--- a/cfg.c
+++ b/cfg.c
@@ -75,7 +75,7 @@ load_cfg(const char *path, struct cmd_q *cmdq, char **cause)
if (cmdlist == NULL)
continue;
- cmdq_append(cmdq, cmdlist);
+ cmdq_append(cmdq, cmdlist, NULL);
cmd_list_free(cmdlist);
found++;
}
diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c
index 22b1d84e..1622e0b7 100644
--- a/cmd-command-prompt.c
+++ b/cmd-command-prompt.c
@@ -151,7 +151,7 @@ cmd_command_prompt_callback(void *data, const char *s)
return (0);
}
- cmdq_run(c->cmdq, cmdlist);
+ cmdq_run(c->cmdq, cmdlist, NULL);
cmd_list_free(cmdlist);
if (c->prompt_callbackfn != (void *) &cmd_command_prompt_callback)
diff --git a/cmd-confirm-before.c b/cmd-confirm-before.c
index 0bf58449..5e4816ed 100644
--- a/cmd-confirm-before.c
+++ b/cmd-confirm-before.c
@@ -105,7 +105,7 @@ cmd_confirm_before_callback(void *data, const char *s)
return (0);
}
- cmdq_run(c->cmdq, cmdlist);
+ cmdq_run(c->cmdq, cmdlist, NULL);
cmd_list_free(cmdlist);
return (0);
diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c
index b46a5a46..19dca5ff 100644
--- a/cmd-copy-mode.c
+++ b/cmd-copy-mode.c
@@ -28,8 +28,8 @@ enum cmd_retval cmd_copy_mode_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_copy_mode_entry = {
"copy-mode", NULL,
- "t:u", 0, 0,
- "[-u] " CMD_TARGET_PANE_USAGE,
+ "Mt:u", 0, 0,
+ "[-Mu] " CMD_TARGET_PANE_USAGE,
0,
cmd_copy_mode_exec
};
@@ -46,9 +46,16 @@ enum cmd_retval
cmd_copy_mode_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
+ struct client *c = cmdq->client;
+ struct session *s;
struct window_pane *wp;
- if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
+ if (args_has(args, 'M')) {
+ if ((wp = cmd_mouse_pane(&cmdq->item->mouse, &s, NULL)) == NULL)
+ return (CMD_RETURN_NORMAL);
+ if (c == NULL || c->session != s)
+ return (CMD_RETURN_NORMAL);
+ } else if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
return (CMD_RETURN_ERROR);
if (self->entry == &cmd_clock_mode_entry) {
@@ -61,6 +68,8 @@ cmd_copy_mode_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_NORMAL);
window_copy_init_from_pane(wp);
}
+ if (args_has(args, 'M'))
+ window_copy_start_drag(c, &cmdq->item->mouse);
if (wp->mode == &window_copy_mode && args_has(self->args, 'u'))
window_copy_pageup(wp);
diff --git a/cmd-if-shell.c b/cmd-if-shell.c
index 8c6620da..9659511e 100644
--- a/cmd-if-shell.c
+++ b/cmd-if-shell.c
@@ -95,7 +95,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq)
}
return (CMD_RETURN_ERROR);
}
- cmdq_run(cmdq, cmdlist);
+ cmdq_run(cmdq, cmdlist, NULL);
cmd_list_free(cmdlist);
return (CMD_RETURN_NORMAL);
}
@@ -152,7 +152,7 @@ cmd_if_shell_callback(struct job *job)
cmdq1->emptyfn = cmd_if_shell_done;
cmdq1->data = cdata;
- cmdq_run(cmdq1, cmdlist);
+ cmdq_run(cmdq1, cmdlist, NULL);
cmd_list_free(cmdlist);
}
diff --git a/cmd-queue.c b/cmd-queue.c
index 6be532a8..61b14147 100644
--- a/cmd-queue.c
+++ b/cmd-queue.c
@@ -20,6 +20,7 @@
#include <ctype.h>
#include <stdlib.h>
+#include <string.h>
#include <time.h>
#include "tmux.h"
@@ -132,9 +133,9 @@ cmdq_guard(struct cmd_q *cmdq, const char *guard, int flags)
/* Add command list to queue and begin processing if needed. */
void
-cmdq_run(struct cmd_q *cmdq, struct cmd_list *cmdlist)
+cmdq_run(struct cmd_q *cmdq, struct cmd_list *cmdlist, struct mouse_event *m)
{
- cmdq_append(cmdq, cmdlist);
+ cmdq_append(cmdq, cmdlist, m);
if (cmdq->item == NULL) {
cmdq->cmd = NULL;
@@ -144,7 +145,7 @@ cmdq_run(struct cmd_q *cmdq, struct cmd_list *cmdlist)
/* Add command list to queue. */
void
-cmdq_append(struct cmd_q *cmdq, struct cmd_list *cmdlist)
+cmdq_append(struct cmd_q *cmdq, struct cmd_list *cmdlist, struct mouse_event *m)
{
struct cmd_q_item *item;
@@ -152,6 +153,11 @@ cmdq_append(struct cmd_q *cmdq, struct cmd_list *cmdlist)
item->cmdlist = cmdlist;
TAILQ_INSERT_TAIL(&cmdq->queue, item, qentry);
cmdlist->references++;
+
+ if (m != NULL)
+ memcpy(&item->mouse, m, sizeof item->mouse);
+ else
+ item->mouse.valid = 0;
}
/* Continue processing command queue. Returns 1 if finishes empty. */
diff --git a/cmd-resize-pane.c b/cmd-resize-pane.c
index 42f0f39a..b342307d 100644
--- a/cmd-resize-pane.c
+++ b/cmd-resize-pane.c
@@ -28,10 +28,13 @@
enum cmd_retval cmd_resize_pane_exec(struct cmd *, struct cmd_q *);
+void cmd_resize_pane_mouse_update(struct client *, struct mouse_event *);
+
const struct cmd_entry cmd_resize_pane_entry = {
"resize-pane", "resizep",
- "DLRt:Ux:y:Z", 0, 1,
- "[-DLRUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " [adjustment]",
+ "DLMRt:Ux:y:Z", 0, 1,
+ "[-DLMRUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE
+ " [adjustment]",
0,
cmd_resize_pane_exec
};
@@ -40,6 +43,8 @@ enum cmd_retval
cmd_resize_pane_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
+ struct client *c = cmdq->client;
+ struct session *s;
struct winlink *wl;
struct window *w;
const char *errstr;
@@ -48,6 +53,16 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_q *cmdq)
u_int adjust;
int x, y;
+ if (args_has(args, 'M')) {
+ if (cmd_mouse_window(&cmdq->item->mouse, &s) == NULL)
+ return (CMD_RETURN_NORMAL);
+ if (c == NULL || c->session != s)
+ return (CMD_RETURN_NORMAL);
+ c->tty.mouse_drag_update = cmd_resize_pane_mouse_update;
+ cmd_resize_pane_mouse_update(c, &cmdq->item->mouse);
+ return (CMD_RETURN_NORMAL);
+ }
+
if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp)) == NULL)
return (CMD_RETURN_ERROR);
w = wl->window;
@@ -106,3 +121,50 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_NORMAL);
}
+
+void
+cmd_resize_pane_mouse_update(struct client *c, struct mouse_event *m)
+{
+ struct winlink *wl;
+ struct window_pane *wp;
+ int found;
+ u_int y, ly;
+
+ wl = cmd_mouse_window(m, NULL);
+ if (wl == NULL) {
+ c->tty.mouse_drag_update = NULL;
+ return;
+ }
+
+ y = m->y;
+ if (m->statusat == 0 && y > 0)
+ y--;
+ else if (m->statusat > 0 && y >= (u_int)m->statusat)
+ y = m->statusat - 1;
+ ly = m->ly;
+ if (m->statusat == 0 && ly > 0)
+ ly--;
+ else if (m->statusat > 0 && ly >= (u_int)m->statusat)
+ ly = m->statusat - 1;
+
+ found = 0;
+ TAILQ_FOREACH(wp, &wl->window->panes, entry) {
+ if (!window_pane_visible(wp))
+ continue;
+
+ if (wp->xoff + wp->sx == m->lx &&
+ wp->yoff <= 1 + ly && wp->yoff + wp->sy >= ly) {
+ layout_resize_pane(wp, LAYOUT_LEFTRIGHT, m->x - m->lx);
+ found = 1;
+ }
+ if (wp->yoff + wp->sy == ly &&
+ wp->xoff <= 1 + m->lx && wp->xoff + wp->sx >= m->lx) {
+ layout_resize_pane(wp, LAYOUT_TOPBOTTOM, y - ly);
+ found = 1;
+ }
+ }
+ if (found)
+ server_redraw_window(wl->window);
+ else
+ c->tty.mouse_drag_update = NULL;
+}
diff --git a/cmd-send-keys.c b/cmd-send-keys.c
index 7a4d97d5..27da410d 100644
--- a/cmd-send-keys.c
+++ b/cmd-send-keys.c
@@ -31,8 +31,8 @@ enum cmd_retval cmd_send_keys_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_send_keys_entry = {
"send-keys", "send",
- "lRt:", 0, -1,
- "[-lR] " CMD_TARGET_PANE_USAGE " key ...",
+ "lRMt:", 0, -1,
+ "[-lRM] " CMD_TARGET_PANE_USAGE " key ...",
0,
cmd_send_keys_exec
};
@@ -49,12 +49,23 @@ enum cmd_retval
cmd_send_keys_exec(struct cmd *self, struct cmd_q *cmdq)
{
struct args *args = self->args;
+ struct mouse_event *m = &cmdq->item->mouse;
struct window_pane *wp;
struct session *s;
struct input_ctx *ictx;
const u_char *str;
int i, key;
+ if (args_has(args, 'M')) {
+ wp = cmd_mouse_pane(m, &s, NULL);
+ if (wp == NULL) {
+ cmdq_error(cmdq, "no mouse target");
+ return (CMD_RETURN_ERROR);
+ }
+ window_pane_key(wp, NULL, s, m->key, m);
+ return (CMD_RETURN_NORMAL);
+ }
+
if (cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp) == NULL)
return (CMD_RETURN_ERROR);
@@ -63,7 +74,7 @@ cmd_send_keys_exec(struct cmd *self, struct cmd_q *cmdq)
key = options_get_number(&s->options, "prefix2");
else
key = options_get_number(&s->options, "prefix");
- window_pane_key(wp, s, key);
+ window_pane_key(wp, NULL, s, key, NULL);
return (CMD_RETURN_NORMAL);
}
@@ -88,10 +99,10 @@ cmd_send_keys_exec(struct cmd *self, struct cmd_q *cmdq)
if (!args_has(args, 'l') &&
(key = key_string_lookup_string(str)) != KEYC_NONE) {
- window_pane_key(wp, s, key);
+ window_pane_key(wp, NULL, s, key, NULL);
} else {
for (; *str != '\0'; str++)
- window_pane_key(wp, s, *str);
+ window_pane_key(wp, NULL, s, *str, NULL);
}
}
diff --git a/cmd.c b/cmd.c
index 66ac58b8..dd1a0a7b 100644
--- a/cmd.c
+++ b/cmd.c
@@ -348,6 +348,7 @@ cmd_current_session(struct cmd_q *cmdq, int prefer_unattached)
const char *path;
int found;
+ /* Try the queue session. */
if (c != NULL && c->session != NULL)
return (c->session);
@@ -504,6 +505,74 @@ cmd_choose_client(struct clients *cc)
return (cbest);
}
+/* Adjust current mouse position for a pane. */
+int
+cmd_mouse_at(struct window_pane *wp, struct mouse_event *m, u_int *xp,
+ u_int *yp, int last)
+{
+ u_int x, y;
+
+ if (last) {
+ x = m->lx;
+ y = m->ly;
+ } else {
+ x = m->x;
+ y = m->y;
+ }
+
+ if (m->statusat == 0 && y > 0)
+ y--;
+ else if (m->statusat > 0 && y >= (u_int)m->statusat)
+ y = m->statusat - 1;
+
+ if (x < wp->xoff || x >= wp->xoff + wp->sx)
+ return (-1);
+ if (y < wp->yoff || y >= wp->yoff + wp->sy)
+ return (-1);
+
+ *xp = x - wp->xoff;
+ *yp = y - wp->yoff;
+ return (0);
+}
+
+/* Get current mouse window if any. */
+struct winlink *
+cmd_mouse_window(struct mouse_event *m, struct session **sp)
+{
+ struct session *s;
+ struct window *w;
+
+ if (!m->valid || m->s == -1 || m->w == -1)
+ return (NULL);
+ if ((s = session_find_by_id(m->s)) == NULL)
+ return (NULL);
+ if ((w = window_find_by_id(m->w)) == NULL)
+ return (NULL);
+
+ if (sp != NULL)
+ *sp = s;
+ return (winlink_find_by_window(&s->windows, w));
+}
+
+/* Get current mouse pane if any. */
+struct window_pane *
+cmd_mouse_pane(struct mouse_event *m, struct session **sp, struct winlink **wlp)
+{
+ struct winlink *wl;
+ struct window_pane *wp;
+
+ if ((wl = cmd_mouse_window(m, sp)) == NULL)
+ return (NULL);
+ if ((wp = window_pane_find_by_id(m->wp)) == NULL)
+ return (NULL);
+ if (!window_has_pane(wl->window, wp))
+ return (NULL);
+
+ if (wlp != NULL)
+ *wlp = wl;
+ return (wp);
+}
+
/* Find the target client or report an error and return NULL. */
struct client *
cmd_find_client(struct cmd_q *cmdq, const char *arg, int quiet)
@@ -928,7 +997,12 @@ no_colon:
* No colon in the string, first try special cases, then as a window
* and lastly as a session.
*/
- if (arg[0] == '!' && arg[1] == '\0') {
+ if (arg[0] == '=' && arg[1] == '\0') {
+ if ((wl = cmd_mouse_window(&cmdq->item->mouse, &s)) == NULL) {
+ cmdq_error(cmdq, "no mouse target");
+ goto error;
+ }
+ } else if (arg[0] == '!' && arg[1] == '\0') {
if ((wl = TAILQ_FIRST(&s->lastw)) == NULL)
goto not_found;
} else if (arg[0] == '+' || arg[0] == '-') {
@@ -959,14 +1033,16 @@ no_session:
cmdq_error(cmdq, "multiple sessions: %s", arg);
else
cmdq_error(cmdq, "session not found: %s", arg);
- free(sessptr);
- return (NULL);
+ goto error;
not_found:
if (ambiguous)
cmdq_error(cmdq, "multiple windows: %s", arg);
else
cmdq_error(cmdq, "window not found: %s", arg);
+ goto error;
+
+error:
free(sessptr);
return (NULL);
}
@@ -1228,6 +1304,18 @@ lookup_string:
return (wl);
no_period:
+ /* Check mouse event. */
+ if (arg[0] == '=' && arg[1] == '\0') {
+ *wpp = cmd_mouse_pane(&cmdq->item->mouse, &s, &wl);
+ if (*wpp == NULL) {
+ cmdq_error(cmdq, "no mouse target");
+ return (NULL);
+ }
+ if (sp != NULL)
+ *sp = s;
+ return (wl);
+ }
+
/* Try as a pane number alone. */
idx = strtonum(arg, 0, INT_MAX, &errstr);
if (errstr != NULL)
diff --git a/control.c b/control.c
index 0ace6c12..11fa2d80 100644
--- a/control.c
+++ b/control.c
@@ -81,7 +81,7 @@ control_callback(struct client *c, int closed, unused void *data)
} else {
TAILQ_FOREACH(cmd, &cmdlist->list, qentry)
cmd->flags |= CMD_CONTROL;
- cmdq_run(c->cmdq, cmdlist);
+ cmdq_run(c->cmdq, cmdlist, NULL);
cmd_list_free(cmdlist);
}
diff --git a/input-keys.c b/input-keys.c
index f2d010d8..ae00e4a9 100644
--- a/input-keys.c
+++ b/input-keys.c
@@ -31,6 +31,8 @@
* direction with output).
*/
+void input_key_mouse(struct window_pane *, struct mouse_event *);
+
struct input_key_ent {
int key;
const char *data;
@@ -135,7 +137,7 @@ const struct input_key_ent input_keys[] = {
/* Translate a key code into an output key sequence. */
void
-input_key(struct window_pane *wp, int key)
+input_key(struct window_pane *wp, int key, struct mouse_event *m)
{
const struct input_key_ent *ike;
u_int i;
@@ -143,7 +145,14 @@ input_key(struct window_pane *wp, int key)
char *out;
u_char ch;
- log_debug("writing key 0x%x", key);
+ log_debug("writing key 0x%x (%s)", key, key_string_lookup_key(key));
+
+ /* If this is a mouse key, pass off to mouse function. */
+ if (KEYC_IS_MOUSE(key)) {
+ if (m != NULL && m->wp != -1 && (u_int)m->wp == wp->id)
+ input_key_mouse(wp, m);
+ return;
+ }
/*
* If this is a normal 7-bit key, just send it, with a leading escape
@@ -200,55 +209,47 @@ input_key(struct window_pane *wp, int key)
/* Translate mouse and output. */
void
-input_mouse(struct window_pane *wp, struct session *s, struct mouse_event *m)
+input_key_mouse(struct window_pane *wp, struct mouse_event *m)
{
- char buf[40];
- size_t len;
- struct paste_buffer *pb;
- int event;
-
- if (wp->screen->mode & ALL_MOUSE_MODES) {
- /*
- * Use the SGR (1006) extension only if the application
- * requested it and the underlying terminal also sent the event
- * in this format (this is because an old style mouse release
- * event cannot be converted into the new SGR format, since the
- * released button is unknown). Otherwise pretend that tmux
- * doesn't speak this extension, and fall back to the UTF-8
- * (1005) extension if the application requested, or to the
- * legacy format.
- */
- if (m->sgr && (wp->screen->mode & MODE_MOUSE_SGR)) {
- len = xsnprintf(buf, sizeof buf, "\033[<%u;%u;%u%c",
- m->sgr_xb, m->x + 1, m->y + 1,
- m->sgr_rel ? 'm' : 'M');
- } else if (wp->screen->mode & MODE_MOUSE_UTF8) {
- len = xsnprintf(buf, sizeof buf, "\033[M");
- 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->xb > 223)
- return;
- len = xsnprintf(buf, sizeof buf, "\033[M");
- buf[len++] = m->xb + 32;
- buf[len++] = m->x + 33;
- buf[len++] = m->y + 33;
- }
- bufferevent_write(wp->event, buf, len);
+ char buf[40];
+ size_t len;
+ u_int x, y;
+
+ if ((wp->screen->mode & ALL_MOUSE_MODES) == 0)
+ return;
+ if (!window_pane_visible(wp))
+ return;
+ if (cmd_mouse_at(wp, m, &x, &y, 0) != 0)
return;
- }
- if (options_get_number(&wp->window->options, "mode-mouse") != 1)
+ /* If this pane is not in button mode, discard motion events. */
+ if (!(wp->screen->mode & MODE_MOUSE_BUTTON) && (m->b & MOUSE_MASK_DRAG))
return;
- event = m->event & (MOUSE_EVENT_CLICK|MOUSE_EVENT_WHEEL);
- if (wp->mode == NULL && m->button == 1 && event == MOUSE_EVENT_CLICK) {
- pb = paste_get_top();
- if (pb != NULL)
- paste_send_pane(pb, wp, "\r", 1);
- } else 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, s, m);
+
+ /*
+ * Use the SGR (1006) extension only if the application requested it
+ * and the underlying terminal also sent the event in this format (this
+ * is because an old style mouse release event cannot be converted into
+ * the new SGR format, since the released button is unknown). Otherwise
+ * pretend that tmux doesn't speak this extension, and fall back to the
+ * UTF-8 (1005) extension if the application requested, or to the
+ * legacy format.
+ */
+ if (m->sgr_type != ' ' && (wp->screen->mode & MODE_MOUSE_SGR)) {
+ len = xsnprintf(buf, sizeof buf, "\033[<%u;%u;%u%c",
+ m->sgr_b, x + 1, y + 1, m->sgr_type);
+ } else 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(x + 33, &buf[len]);
+ len += utf8_split2(y + 33, &buf[len]);
+ } else {
+ if (m->b > 223)
+ return;
+ len = xsnprintf(buf, sizeof buf, "\033[M");
+ buf[len++] = m->b + 32;
+ buf[len++] = x + 33;
+ buf[len++] = y + 33;
}
+ bufferevent_write(wp->event, buf, len);
}
diff --git a/key-bindings.c b/key-bindings.c
index 00f73d73..c6cdeeb7 100644
--- a/key-bindings.c
+++ b/key-bindings.c
@@ -158,6 +158,10 @@ key_bindings_init(void)
"bind -r C-Down resize-pane -D",
"bind -r C-Left resize-pane -L",
"bind -r C-Right resize-pane -R",
+ "bind -n MouseDown1Pane select-pane -t=\\; send-keys -M",
+ "bind -n MouseDrag1Border resize-pane -M",
+ "bind -n MouseDown1Status select-window -t=",
+ "bind -n MouseDrag1Pane copy-mode -M",
};
u_int i;
struct cmd_list *cmdlist;
@@ -173,14 +177,15 @@ key_bindings_init(void)
"<default-keys>", i, &cause);
if (error != 0)
fatalx("bad default key");
- cmdq_run(cmdq, cmdlist);
- cmd_list_free(cmdlist);
+ cmdq_run(cmdq, cmdlist, NULL);
+ cmd_list_free (cmdlist);
}
cmdq_free(cmdq);
}
void
-key_bindings_dispatch(struct key_binding *bd, struct client *c)
+key_bindings_dispatch(struct key_binding *bd, struct client *c,
+ struct mouse_event *m)
{
struct cmd *cmd;
int readonly;
@@ -195,5 +200,5 @@ key_bindings_dispatch(struct key_binding *bd, struct client *c)
return;
}
- cmdq_run(c->cmdq, bd->cmdlist);
+ cmdq_run(c->cmdq, bd->cmdlist, m);
}
diff --git a/key-string.c b/key-string.c
index db968279..b6474c4f 100644
--- a/key-string.c
+++ b/key-string.c
@@ -82,6 +82,19 @@ const struct {
{ "KPEnter", KEYC_KP_ENTER },
{ "KP0", KEYC_KP_ZERO },
{ "KP.", KEYC_KP_PERIOD },
+
+ /* Mouse keys. */
+ KEYC_MOUSE_STRING(MOUSEDOWN1, MouseDown1),
+ KEYC_MOUSE_STRING(MOUSEDOWN2, MouseDown2),
+ KEYC_MOUSE_STRING(MOUSEDOWN3, MouseDown3),
+ KEYC_MOUSE_STRING(MOUSEUP1, MouseUp1),
+ KEYC_MOUSE_STRING(MOUSEUP2, MouseUp2),
+ KEYC_MOUSE_STRING(MOUSEUP3, MouseUp3),
+ KEYC_MOUSE_STRING(MOUSEDRAG1, MouseDrag1),
+ KEYC_MOUSE_STRING(MOUSEDRAG2, MouseDrag2),
+ KEYC_MOUSE_STRING(MOUSEDRAG3, MouseDrag3),
+ KEYC_MOUSE_STRING(WHEELUP, WheelUp),
+ KEYC_MOUSE_STRING(WHEELDOWN, WheelDown),
};
/* Find key string in table. */
@@ -192,7 +205,9 @@ key_string_lookup_key(int key)
/* Handle no key. */
if (key == KEYC_NONE)
- return ("none");
+ return ("<NONE>");
+ if (key == KEYC_MOUSE)
+ return ("<MOUSE>");
/*
* Special case: display C-@ as C-Space. Could do this below in
diff --git a/layout.c b/layout.c
index b91b86cd..bb1bbf8d 100644
--- a/layout.c
+++ b/layout.c
@@ -519,58 +519,6 @@ layout_resize_pane(struct window_pane *wp, enum layout_type type, int change)
notify_window_layout_changed(wp->window);
}
-/* Resize pane based on mouse events. */
-void
-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 (m->event & MOUSE_EVENT_DRAG && m->flags & MOUSE_RESIZE_PANE) {
- TAILQ_FOREACH(wp, &w->panes, entry) {
- if (!window_pane_visible(wp))
- continue;
-
- if (wp->xoff + wp->sx == m->lx &&
- wp->yoff <= 1 + m->ly &&
- wp->yoff + wp->sy >= m->ly) {
- layout_resize_pane(wp, LAYOUT_LEFTRIGHT,
- m->x - m->lx);
- pane_border = 1;
- }
- if (wp->yoff + wp->sy == m->ly &&
- wp->xoff <= 1 + m->lx &&
- wp->xoff + wp->sx >= m->lx) {
- layout_resize_pane(wp, LAYOUT_TOPBOTTOM,
- m->y - m->ly);
- pane_border = 1;
- }
- }
- if (pane_border)
- server_redraw_window(w);
- } else if (m->event & MOUSE_EVENT_DOWN) {
- TAILQ_FOREACH(wp, &w->panes, entry) {
- 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)
- m->flags |= MOUSE_RESIZE_PANE;
- else
- m->flags &= ~MOUSE_RESIZE_PANE;
-}
-
/* Helper function to grow pane. */
int
layout_resize_pane_grow(
diff --git a/mode-key.c b/mode-key.c
index 72d66f37..c06d7ed5 100644
--- a/mode-key.c
+++ b/mode-key.c
@@ -251,6 +251,10 @@ const struct mode_key_entry mode_key_vi_choice[] = {
{ KEYC_RIGHT, 0, MODEKEYCHOICE_TREE_EXPAND },
{ KEYC_LEFT | KEYC_CTRL, 0, MODEKEYCHOICE_TREE_COLLAPSE_ALL },
{ KEYC_RIGHT | KEYC_CTRL, 0, MODEKEYCHOICE_TREE_EXPAND_ALL },
+ { KEYC_MOUSEDOWN1_PANE, 0, MODEKEYCHOICE_CHOOSE },
+ { KEYC_MOUSEDOWN3_PANE, 0, MODEKEYCHOICE_TREE_TOGGLE },
+ { KEYC_WHEELUP_PANE, 0, MODEKEYCHOICE_UP },
+ { KEYC_WHEELDOWN_PANE, 0, MODEKEYCHOICE_DOWN },
{ 0, -1, 0 }
};
@@ -326,6 +330,9 @@ const struct mode_key_entry mode_key_vi_copy[] = {
{ KEYC_RIGHT, 0, MODEKEYCOPY_RIGHT },
{ KEYC_UP | KEYC_CTRL, 0, MODEKEYCOPY_SCROLLUP },
{ KEYC_UP, 0, MODEKEYCOPY_UP },
+ { KEYC_WHEELUP_PANE, 0, MODEKEYCOPY_SCROLLUP },
+ { KEYC_WHEELDOWN_PANE, 0, MODEKEYCOPY_SCROLLDOWN },
+ { KEYC_MOUSEDRAG1_PANE, 0, MODEKEYCOPY_STARTSELECTION },
{ 0, -1, 0 }
};
@@ -405,6 +412,10 @@ const struct mode_key_entry mode_key_emacs_choice[] = {
{ KEYC_RIGHT, 0, MODEKEYCHOICE_TREE_EXPAND },
{ KEYC_LEFT | KEYC_CTRL, 0, MODEKEYCHOICE_TREE_COLLAPSE_ALL },
{ KEYC_RIGHT | KEYC_CTRL, 0, MODEKEYCHOICE_TREE_EXPAND_ALL },
+ { KEYC_MOUSEDOWN1_PANE, 0, MODEKEYCHOICE_CHOOSE },
+ { KEYC_MOUSEDOWN3_PANE, 0, MODEKEYCHOICE_TREE_TOGGLE },
+ { KEYC_WHEELUP_PANE, 0, MODEKEYCHOICE_UP },
+ { KEYC_WHEELDOWN_PANE, 0, MODEKEYCHOICE_DOWN },
{ 0, -1, 0 }
};
@@ -467,6 +478,9 @@ const struct mode_key_entry mode_key_emacs_copy[] = {
{ KEYC_UP | KEYC_CTRL, 0, MODEKEYCOPY_SCROLLUP },
{ KEYC_UP | KEYC_ESCAPE, 0, MODEKEYCOPY_HALFPAGEUP },
{ KEYC_UP, 0, MODEKEYCOPY_UP },
+ { KEYC_WHEELUP_PANE, 0, MODEKEYCOPY_SCROLLUP },
+ { KEYC_WHEELDOWN_PANE, 0, MODEKEYCOPY_SCROLLDOWN },
+ { KEYC_MOUSEDRAG1_PANE, 0, MODEKEYCOPY_STARTSELECTION },
{ 0, -1, 0 }
};
diff --git a/options-table.c b/options-table.c
index 5e72d14f..5e21c692 100644
--- a/options-table.c
+++ b/options-table.c
@@ -36,9 +36,6 @@
const char *options_table_mode_keys_list[] = {
"emacs", "vi", NULL
};
-const char *options_table_mode_mouse_list[] = {
- "off", "on", "copy-mode", NULL
-};
const char *options_table_clock_mode_style_list[] = {
"12", "24", NULL
};
@@ -255,17 +252,7 @@ const struct options_table_entry session_options_table[] = {
.default_str = "bg=yellow,fg=black"
},
- { .name = "mouse-resize-pane",
- .type = OPTIONS_TABLE_FLAG,
- .default_num = 0
- },
-
- { .name = "mouse-select-pane",
- .type = OPTIONS_TABLE_FLAG,
- .default_num = 0
- },
-
- { .name = "mouse-select-window",
+ { .name = "mouse",
.type = OPTIONS_TABLE_FLAG,
.default_num = 0
},
@@ -575,12 +562,6 @@ const struct options_table_entry window_options_table[] = {
.default_num = MODEKEY_EMACS
},
- { .name = "mode-mouse",
- .type = OPTIONS_TABLE_CHOICE,
- .choices = options_table_mode_mouse_list,
- .default_num = 0
- },
-
{ .name = "mode-style",
.type = OPTIONS_TABLE_STYLE,
.default_str = "bg=yellow,fg=black"
diff --git a/server-client.c b/server-client.c
index 352e8ab6..3968c50b 100644
--- a/server-client.c
+++ b/server-client.c
@@ -32,7 +32,7 @@
void server_client_check_focus(struct window_pane *);
void server_client_check_resize(struct window_pane *);
-void server_client_check_mouse(struct client *, struct window_pane *);
+int 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 *);
@@ -91,13 +91,6 @@ server_client_create(int fd)
c->prompt_buffer = NULL;
c->prompt_index = 0;
- 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;
-
c->flags |= CLIENT_FOCUSED;
evtimer_set(&c->repeat_timer, server_client_repeat_timer, c);
@@ -289,56 +282,228 @@ server_client_status_timer(void)
}
/* Check for mouse keys. */
-void
-server_client_check_mouse(struct client *c, struct window_pane *wp)
+int
+server_client_check_mouse(struct client *c)
{
- 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 && m->y == (u_int)statusat &&
- options_get_number(oo, "mouse-select-window")) {
- 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);
- else if (m->wheel == MOUSE_WHEEL_DOWN)
- session_next(c->session, 0);
- server_redraw_session(s);
+ 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;
+ int key;
+
+ 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);
+
+ /* What type of event is this? */
+ if (MOUSE_DRAG(m->b)) {
+ type = DRAG;
+ if (c->tty.mouse_drag_flag) {
+ x = m->x, y = m->y, b = m->b;
+ log_debug("drag update at %u,%u", x, y);
+ } else {
+ x = m->lx, y = m->ly, b = m->lb;<