aboutsummaryrefslogtreecommitdiff
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-select-pane.c20
-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.c31
-rw-r--r--screen-redraw.c20
-rw-r--r--server-client.c332
-rw-r--r--server-fn.c8
-rw-r--r--status.c13
-rw-r--r--tmux.1140
-rw-r--r--tmux.h151
-rw-r--r--tty-keys.c81
-rw-r--r--tty-term.c1
-rw-r--r--tty.c174
-rw-r--r--window-choose.c107
-rw-r--r--window-clock.c8
-rw-r--r--window-copy.c223
-rw-r--r--window.c53
30 files changed, 1110 insertions, 665 deletions
diff --git a/cfg.c b/cfg.c
index b3b86e76..08159a6c 100644
--- a/cfg.c
+++ b/cfg.c
@@ -74,7 +74,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-select-pane.c b/cmd-select-pane.c
index 5810eeab..c84b4149 100644
--- a/cmd-select-pane.c
+++ b/cmd-select-pane.c
@@ -28,8 +28,8 @@ enum cmd_retval cmd_select_pane_exec(struct cmd *, struct cmd_q *);
const struct cmd_entry cmd_select_pane_entry = {
"select-pane", "selectp",
- "DdeLlRt:U", 0, 0,
- "[-DdeLlRU] " CMD_TARGET_PANE_USAGE,
+ "DdegLlP:Rt:U", 0, 0,
+ "[-DdegLlRU] [-P style] " CMD_TARGET_PANE_USAGE,
0,
cmd_select_pane_exec
};
@@ -48,6 +48,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_q *cmdq)
struct args *args = self->args;
struct winlink *wl;
struct window_pane *wp;
+ const char *style;
if (self->entry == &cmd_last_pane_entry || args_has(args, 'l')) {
wl = cmd_find_window(cmdq, args_get(args, 't'), NULL);
@@ -82,6 +83,21 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
}
+ if (args_has(self->args, 'P') || args_has(self->args, 'g')) {
+ if (args_has(args, 'P')) {
+ style = args_get(args, 'P');
+ if (style_parse(&grid_default_cell, &wp->colgc,
+ style) == -1) {
+ cmdq_error(cmdq, "bad style: %s", style);
+ return (CMD_RETURN_ERROR);
+ }
+ wp->flags |= PANE_REDRAW;
+ }
+ if (args_has(self->args, 'g'))
+ cmdq_print(cmdq, "%s", style_tostring(&wp->colgc));
+ return (CMD_RETURN_NORMAL);
+ }
+
if (args_has(self->args, 'L'))
wp = window_pane_find_left(wp);
else if (args_has(self->args, 'R'))
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 eeffe4c7..9e41c1f9 100644
--- a/cmd.c
+++ b/cmd.c
@@ -347,6 +347,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);
@@ -503,6 +504,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)
@@ -927,7 +996,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] == '-') {
@@ -958,14 +1032,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);
}
@@ -1227,6 +1303,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 762e86b9..ed5556f1 100644
--- a/input-keys.c
+++ b/input-keys.c
@@ -30,6 +30,8 @@
* direction with output).
*/
+void input_key_mouse(struct window_pane *, struct mouse_event *);
+
struct input_key_ent {
int key;
const char *data;
@@ -134,7 +136,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;
@@ -142,7 +144,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
@@ -199,55 +208,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 2bcf29b4..d3959626 100644
--- a/options-table.c
+++ b/options-table.c
@@ -35,9 +35,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
};
@@ -254,17 +251,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
},
@@ -574,12 +561,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"
@@ -667,6 +648,16 @@ const struct options_table_entry window_options_table[] = {
.default_num = 0 /* overridden in main() */
},
+ { .name = "window-active-style",
+ .type = OPTIONS_TABLE_STYLE,
+ .default_str = "default"
+ },
+
+ { .name = "window-style",
+ .type = OPTIONS_TABLE_STYLE,
+ .default_str = "default"
+ },
+
{ .name = "window-status-activity-attr",
.type = OPTIONS_TABLE_ATTRIBUTES,
.default_num = GRID_ATTR_REVERSE,
diff --git a/screen-redraw.c b/screen-redraw.c
index c2b2ece6..e3369b82 100644
--- a/screen-redraw.c
+++ b/screen-redraw.c
@@ -266,7 +266,7 @@ screen_redraw_pane(struct client *c, struct window_pane *wp)
yoff++;
for (i = 0; i < wp->sy; i++)
- tty_draw_line(&c->tty, wp->screen, i, wp->xoff, yoff);
+ tty_draw_pane(&c->tty, wp, i, wp->xoff, yoff);
tty_reset(&c->tty);
}
@@ -323,9 +323,9 @@ screen_redraw_draw_borders(struct client *c, int status, u_int top)
small && i > msgx && j == msgy)
continue;
if (screen_redraw_check_active(i, j, type, w, wp))
- tty_attributes(tty, &active_gc);
+ tty_attributes(tty, &active_gc, NULL);
else
- tty_attributes(tty, &other_gc);
+ tty_attributes(tty, &other_gc, NULL);
tty_cursor(tty, i, top + j);
tty_putc(tty, CELL_BORDERS[type]);
}
@@ -333,7 +333,7 @@ screen_redraw_draw_borders(struct client *c, int status, u_int top)
if (small) {
memcpy(&msg_gc, &grid_default_cell, sizeof msg_gc);
- tty_attributes(tty, &msg_gc);
+ tty_attributes(tty, &msg_gc, NULL);
tty_cursor(tty, msgx, msgy);
tty_puts(tty, msg);
}
@@ -346,15 +346,13 @@ screen_redraw_draw_panes(struct client *c, u_int top)
struct window *w = c->session->curw->window;
struct tty *tty = &c->tty;
struct window_pane *wp;
- struct screen *s;
u_int i;
TAILQ_FOREACH(wp, &w->panes, entry) {
if (!window_pane_visible(wp))
continue;
- s = wp->screen;
for (i = 0; i < wp->sy; i++)
- tty_draw_line(tty, s, i, wp->xoff, top + wp->yoff);
+ tty_draw_pane(tty, wp, i, wp->xoff, top + wp->yoff);
if (c->flags & CLIENT_IDENTIFY)
screen_redraw_draw_number(c, wp);
}
@@ -367,9 +365,9 @@ screen_redraw_draw_status(struct client *c, u_int top)
struct tty *tty = &c->tty;
if (top)
- tty_draw_line(tty, &c->status, 0, 0, 0);
+ tty_draw_line(tty, NULL, &c->status, 0, 0, 0);
else
- tty_draw_line(tty, &c->status, 0, 0, tty->sy - 1);
+ tty_draw_line(tty, NULL, &c->status, 0, 0, tty->sy - 1);
}
/* Draw number on a pane. */
@@ -411,7 +409,7 @@ screen_redraw_draw_number(struct client *c, struct window_pane *wp)
colour_set_bg(&gc, active_colour);
else
colour_set_bg(&gc, colour);
- tty_attributes(tty, &gc);
+ tty_attributes(tty, &gc, wp);
for (ptr = buf; *ptr != '\0'; ptr++) {
if (*ptr < '0' || *ptr > '9')
continue;
@@ -438,7 +436,7 @@ draw_text:
colour_set_fg(&gc, active_colour);
else
colour_set_fg(&gc, colour);
- tty_attributes(tty, &gc);
+ tty_attributes(tty, &gc, wp);
tty_puts(tty, buf);
tty_cursor(tty, 0, 0);
diff --git a/server-client.c b/server-client.c
index f7ce35c8..e0abd90c 100644
--- a/server-client.c
+++ b/server-client.c
@@ -31,7 +31,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 *);
@@ -90,13 +90,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);
@@ -288,57 +281,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;
+ log_debug("drag start at %u,%u", x, y);
}
- recalculate_sizes();
- return;
+ } else if (MOUSE_WHEEL(m->b)) {
+ type = WHEEL;
+ x = m->x, y = m->y, b = m->b;
+ log_debug("wheel at %u,%u", x, y);
+ } else if (MOUSE_BUTTONS(m->b) == 3) {
+ type = UP;
+ x = m->x, y = m->y, b = m->lb;
+ log_debug("up at %u,%u", x, y);
+ } else {
+ type = DOWN;
+ x = m->x, y = m->y, b = m->b;
+ log_debug("down at %u,%u", x, y);
}
+ if (type == NOTYPE)
+ return (KEYC_NONE);
- /*
- * Not on status line - adjust mouse position if status line is at the
- * top and limit if at the bottom. From here on a struct mouse
- * represents the offset onto the window itself.
- */
- 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? */
- if (options_get_number(oo, "mouse-select-pane") &&
- (m->event == MOUSE_EVENT_DOWN || m->event == MOUSE_EVENT_WHEEL)) {
- window_set_active_at(wp->window, m->x, m->y);
- server_status_window(wp->window);
- server_redraw_window_borders(wp->window);
- wp = wp->window->active; /* may have changed */
+ /* Always save the session. */
+ m->s = s->id;
+
+ /* Is this on the status line? */
+ m->statusat = status_at_line(c);
+ if (m->statusat != -1 && y == (u_int)m->statusat) {
+ w = status_get_window_at(c, x);
+ if (w == NULL)
+ return (KEYC_NONE);
+ m->w = w->id;
+ where = STATUS;
+ } else
+ m->w = -1;
+
+ /* Not on status line. Adjust position and check for border or pane. */
+ if (where == NOWHERE) {
+ if (m->statusat == 0 && y > 0)
+ y--;
+ else if (m->statusat > 0 && y >= (u_int)m->statusat)
+ y = m->statusat - 1;
+
+ TAILQ_FOREACH(wp, &s->curw->window->panes, entry) {
+ if ((wp->xoff + wp->sx == x &&
+ wp->yoff <= 1 + y &&
+ wp->yoff + wp->sy >= y) ||
+ (wp->yoff + wp->sy == y &&
+ wp->xoff <= 1 + x &&
+ wp->xoff + wp->sx >= x))
+ break;
+ }
+ if (wp != NULL)
+ where = BORDER;
+ else {
+ wp = window_get_active_at(s->curw->window, x, y);
+ if (wp != NULL)
+ where = PANE;
+ }
+ if (where == NOWHERE)
+ return (KEYC_NONE);
+ m->wp = wp->id;
+ m->w = wp->window->id;
+ } else
+ m->wp = -1;
+
+ /* Stop dragging if needed. */
+ if (type != DRAG && c->tty.mouse_drag_flag) {
+ if (c->tty.mouse_drag_release != NULL)
+ c->tty.mouse_drag_release(c, m);
+
+ c->tty.mouse_drag_update = NULL;
+ c->tty.mouse_drag_release = NULL;
+
+ c->tty.mouse_drag_flag = 0;
+ return (KEYC_NONE);
}
- /* Check if trying to resize pane. */
- if (options_get_number(oo, "mouse-resize-pane"))
- layout_resize_pane_mouse(c);
+ /* Convert to a key binding. */
+ key = KEYC_NONE;
+ switch (type) {
+ case NOTYPE:
+ break;
+ case DRAG:
+ if (c->tty.mouse_drag_update != NULL)
+ c->tty.mouse_drag_update(c, m);
+ else {
+ switch (MOUSE_BUTTONS(b)) {
+ case 0:
+ if (where == PANE)
+ key = KEYC_MOUSEDRAG1_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDRAG1_STATUS;
+ if (where == BORDER)
+ key = KEYC_MOUSEDRAG1_BORDER;
+ break;
+ case 1:
+ if (where == PANE)
+ key = KEYC_MOUSEDRAG2_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDRAG2_STATUS;
+ if (where == BORDER)
+ key = KEYC_MOUSEDRAG2_BORDER;
+ break;
+ case 2:
+ if (where == PANE)
+ key = KEYC_MOUSEDRAG3_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDRAG3_STATUS;
+ if (where == BORDER)
+ key = KEYC_MOUSEDRAG3_BORDER;
+ break;
+ }
+ }
- /* Update last and pass through to client. */
- window_pane_mouse(wp, c->session, m);
+ c->tty.mouse_drag_flag = 1;
+ break;
+ case WHEEL:
+ if (MOUSE_BUTTONS(b) == MOUSE_WHEEL_UP) {
+ if (where == PANE)
+ key = KEYC_WHEELUP_PANE;
+ if (where == STATUS)
+ key = KEYC_WHEELUP_STATUS;
+ if (where == BORDER)
+ key = KEYC_WHEELUP_BORDER;
+ } else {
+ if (where == PANE)
+ key = KEYC_WHEELDOWN_PANE;
+ if (where == STATUS)
+ key = KEYC_WHEELDOWN_STATUS;
+ if (where == BORDER)
+ key = KEYC_WHEELDOWN_BORDER;
+ }
+ break;
+ case UP:
+ switch (MOUSE_BUTTONS(b)) {
+ case 0:
+ if (where == PANE)
+ key = KEYC_MOUSEUP1_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEUP1_STATUS;
+ if (where == BORDER)
+ key = KEYC_MOUSEUP1_BORDER;
+ break;
+ case 1:
+ if (where == PANE)
+ key = KEYC_MOUSEUP2_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEUP2_STATUS;
+ if (where == BORDER)
+ key = KEYC_MOUSEUP2_BORDER;
+ break;
+ case 2:
+ if (where == PANE)
+ key = KEYC_MOUSEUP3_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEUP3_STATUS;
+ if (where == BORDER)
+ key = KEYC_MOUSEUP3_BORDER;
+ break;
+ }
+ break;
+ case DOWN:
+ switch (MOUSE_BUTTONS(b)) {
+ case 0:
+ if (where == PANE)
+ key = KEYC_MOUSEDOWN1_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDOWN1_STATUS;
+ if (where == BORDER)
+ key = KEYC_MOUSEDOWN1_BORDER;
+ break;
+ case 1:
+ if (where == PANE)
+ key = KEYC_MOUSEDOWN2_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDOWN2_STATUS;
+ if (where == BORDER)
+ key = KEYC_MOUSEDOWN2_BORDER;
+ break;
+ case 2:
+ if (where == PANE)
+ key = KEYC_MOUSEDOWN3_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDOWN3_STATUS;
+ if (where == BORDER)
+ key = KEYC_MOUSEDOWN3_BORDER;
+ break;
+ }
+ break;
+ }
+ if (key == KEYC_NONE)
+ return (KEYC_NONE);
+
+ /* Apply modifiers if any. */
+ if (b & MOUSE_MASK_META)
+ key |= KEYC_ESCAPE;
+ if (b & MOUSE_MASK_CTRL)
+ key |= KEYC_CTRL;
+ if (b & MOUSE_MASK_SHIFT)
+ key |= KEYC_SHIFT;
+
+ return (key);
}
/* Is this fast enough to probably be a paste? */
@@ -361,6 +525,7 @@ server_client_assume_paste(struct session *s)
void
server_client_handle_key(struct client *c, int key)
{
+ struct mouse_event *m = &c->tty.mouse;
struct session *s;
struct window *w;
struct window_pane *wp;
@@ -372,21 +537,20 @@ server_client_handle_key(struct client *c, int key)
if ((c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED)) != 0)
return;
+ /* No session, do nothing. */
if (c->session == NULL)
return;
s = c->session;
+ w = c->session->curw->window;
+ wp = w->active;
/* Update the activity timer. */
if (gettimeofday(&c->activity_time, NULL) != 0)
fatal("gettimeofday failed");
-
memcpy(&s->last_activity_time, &s->activity_time,
sizeof s->last_activity_time);
memcpy(&s->activity_time, &c->activity_time, sizeof s->activity_time);
- w = c->session->curw->window;
- wp = w->active;
-
/* Special case: number keys jump to pane in identify mode. */
if (c->flags & CLIENT_IDENTIFY && key >= '0' && key <= '9') {
if (c->flags & CLIENT_READONLY)
@@ -414,9 +578,19 @@ 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);
- return;
- }
+ key = server_client_check_mouse(c);
+ if (key == KEYC_NONE)
+ return;
+
+ m->valid = 1;
+ m->key = key;
+
+ if (!options_get_number(&s->options, "mouse")) {
+ window_pane_key(wp, c, s, key, m);
+ return;
+ }
+ } else
+ m->valid = 0;
/* Is this a prefix key? */
if (key == options_get_number(&s->options, "prefix"))
@@ -442,9 +616,9 @@ server_client_handle_key(struct client *c, int key)
/* Try as a non-prefix key binding. */
if (ispaste || (bd = key_bindings_lookup(key)) == NULL) {
if (!(c->flags & CLIENT_READONLY))
- window_pane_key(wp, s, key);
+ window_pane_key(wp, c, s, key, m);
} else
- key_bindings_dispatch(bd, c);
+ key_bindings_dispatch(bd, c, m);
return;
}
@@ -458,7 +632,7 @@ server_client_handle_key(struct client *c, int key)
if (isprefix)
c->flags |= CLIENT_PREFIX;
else if (!(c->flags & CLIENT_READONLY))
- window_pane_key(wp, s, key);
+ window_pane_key(wp, c, s, key, m);
}
return;
}
@@ -469,7 +643,7 @@ server_client_handle_key(struct client *c, int key)
if (isprefix)
c->flags |= CLIENT_PREFIX;
else if (!(c->flags & CLIENT_READONLY))
- window_pane_key(wp, s, key);
+ window_pane_key(wp, c, s, key, m);
return;
}
@@ -485,7 +659,7 @@ server_client_handle_key(struct client *c, int key)
}
/* Dispatch the command. */
- key_bindings_dispatch(bd, c);
+ key_bindings_dispatch(bd, c, m);
}
/* Client functions that need to happen every loop. */
@@ -632,7 +806,6 @@ server_client_reset_state(struct client *c)
struct window_pane *wp = w->active;
struct screen *s = wp->screen;
struct options *oo = &c->session->options;
- struct options *wo = &w->options;
int status, mode, o;
if (c->flags & CLIENT_SUSPENDED)
@@ -652,29 +825,12 @@ server_client_reset_state(struct client *c)
}
/*
- * Resizing panes with the mouse requires at least button mode to give
- * a smooth appearance.
+ * Set mouse mode if requested. To support dragging, always use button
+ * mode.
*/
mode = s->mode;
- if ((c->tty.mouse.flags & MOUSE_RESIZE_PANE) &&
- !(mode & MODE_MOUSE_BUTTON))
- mode |= MODE_MOUSE_BUTTON;
-
- /*
- * Any mode will do for mouse-select-pane, but set standard mode if
- * none.
- */
- if ((mode & ALL_MOUSE_MODES) == 0) {
- if (TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry) != NULL &&
- options_get_number(oo, "mouse-select-pane"))
- mode |= MODE_MOUSE_STANDARD;
- else if (options_get_number(oo, "mouse-resize-pane"))
- mode |= MODE_MOUSE_STANDARD;
- else if (options_get_number(oo, "mouse-select-window"))
- mode |= MODE_MOUSE_STANDARD;
- else if (options_get_number(wo, "mode-mouse"))
- mode |= MODE_MOUSE_STANDARD;
- }
+ if (options_get_number(oo, "mouse"))
+ mode = (mode & ~ALL_MOUSE_MODES) | MODE_MOUSE_BUTTON;
/*
* Set UTF-8 mouse input if required. If the terminal is UTF-8, the
@@ -955,9 +1111,9 @@ server_client_msg_command(struct client *c, struct imsg *imsg)
cmd_free_argv(argc, argv);
if (c != cfg_client || cfg_finished)
- cmdq_run(c->cmdq, cmdlist);
+ cmdq_run(c->cmdq, cmdlist, NULL);
else
- cmdq_append(c->cmdq, cmdlist);
+ cmdq_append(c->cmdq, cmdlist, NULL);
cmd_list_free(cmdlist);
return;
diff --git a/server-fn.c b/server-fn.c
index 71745d7c..b35eace0 100644
--- a/server-fn.c
+++ b/server-fn.c
@@ -351,6 +351,7 @@ server_unlink_window(struct session *s, struct winlink *wl)
server_destroy_session_group(s);
else
server_redraw_session_group(s);
+ session_renumber_windows(s);
}
void
@@ -607,7 +608,8 @@ server_set_stdin_callback(struct client *c, void (*cb)(struct client *, int,
void
server_unzoom_window(struct window *w)
{
- window_unzoom(w);
- server_redraw_window(w);
- server_status_window(w);
+ if (window_unzoom(w) == 0) {
+ server_redraw_window(w);
+ server_status_window(w);
+ }
}
diff --git a/status.c b/status.c
index 5f8895fb..ae5d99ab 100644
--- a/status.c
+++ b/status.c
@@ -118,9 +118,9 @@ status_redraw_get_right(struct client *c, time_t t, int utf8flag,
return (right);
}
-/* Set window at window list position. */
-void
-status_set_window_at(struct client *c, u_int x)
+/* Get window at window list position. */
+struct window *
+status_get_window_at(struct client *c, u_int x)
{
struct session *s = c->session;
struct winlink *wl;
@@ -130,12 +130,13 @@ status_set_window_at(struct client *c, u_int x)
x += c->wlmouse;
RB_FOREACH(wl, winlinks, &s->windows) {
oo = &wl->window->options;
-
len = strlen(options_get_string(oo, "window-status-separator"));
- if (x < wl->status_width && session_select(s, wl->idx) == 0)
- server_redraw_session(s);
+
+ if (x < wl->status_width)
+ return (wl->window);
x -= wl->status_width + len;
}
+ return (NULL);
}
/* Draw status for client on the last lines of given context. */
diff --git a/tmux.1 b/tmux.1
index 8a0879b7..ec5dfc3f 100644
--- a/tmux.1
+++ b/tmux.1
@@ -1023,13 +1023,16 @@ The synopsis for the
command is:
.Bl -tag -width Ds
.It Xo Ic copy-mode
-.Op Fl u
+.Op Fl Mu
.Op Fl t Ar target-pane
.Xc
Enter copy mode.
The
.Fl u
option scrolls one page up.
+.Fl M
+begins a mouse drag (only valid if bound to a mouse key binding, see
+.Sx MOUSE SUPPORT ) .
.El
.Pp
Each window displayed by
@@ -1647,7 +1650,7 @@ Rename the current window, or the window at
if specified, to
.Ar new-name .
.It Xo Ic resize-pane
-.Op Fl DLRUZ
+.Op Fl DLMRUZ
.Op Fl t Ar target-pane
.Op Fl x Ar width
.Op Fl y Ar height
@@ -1676,6 +1679,10 @@ With
.Fl Z ,
the active pane is toggled between zoomed (occupying the whole of the window)
and unzoomed (its normal position in the layout).
+.Pp
+.Fl M
+begins mouse resizing (only valid if bound to a mouse key binding, see
+.Sx MOUSE SUPPORT ) .
.It Xo Ic respawn-pane
.Op Fl k
.Op Fl t Ar target-pane
@@ -1734,14 +1741,17 @@ and
.Ic previous-layout
commands.
.It Xo Ic select-pane
-.Op Fl DdeLlRU
+.Op Fl DdegLlRU
+.Op Fl P Ar style
.Op Fl t Ar target-pane
.Xc
.D1 (alias: Ic selectp )
Make pane
.Ar target-pane
the active pane in window
-.Ar target-window .
+.Ar target-window ,
+or set its style (with
+.Fl P ) .
If one of
.Fl D ,
.Fl L ,
@@ -1758,6 +1768,22 @@ command.
enables or
.Fl d
disables input to the pane.
+.Pp
+Each pane has a style: by default the
+.Ic window-style
+and
+.Ic window-active-style
+options are used,
+.Ic select-pane
+.Fl P
+sets the style for a single pane.
+For example, to set the pane 1 background to red:
+.Bd -literal -offset indent
+select-pane -t:.1 -P 'bg=red'
+.Ed
+.Pp
+.Fl g
+shows the current pane style.
.It Xo Ic select-window
.Op Fl lnpT
.Op Fl t Ar target-window
@@ -1965,7 +1991,7 @@ are listed; this may be one of:
or
.Em emacs-copy .
.It Xo Ic send-keys
-.Op Fl lR
+.Op Fl lMR
.Op Fl t Ar target-pane
.Ar key Ar ...
.Xc
@@ -1986,6 +2012,10 @@ All arguments are sent sequentially from first to last.
The
.Fl R
flag causes the terminal state to be reset.
+.Pp
+.Fl M
+passes through a mouse event (only valid if bound to a mouse key binding, see
+.Sx MOUSE SUPPORT ) .
.It Xo Ic send-prefix
.Op Fl 2
.Op Fl t Ar target-pane
@@ -2074,7 +2104,7 @@ also supports user options which are prefixed with a
User options may have any name, so long as they are prefixed with
.Ql \&@ ,
and be set to any string.
-For example
+For example:
.Bd -literal -offset indent
$ tmux setw -q @foo "abc123"
$ tmux showw -v @foo
@@ -2434,25 +2464,15 @@ For how to specify
see the
.Ic message-command-style
option.
-.It Xo Ic mouse-resize-pane
+.It Xo Ic mouse
.Op Ic on | off
.Xc
If on,
.Nm
-captures the mouse and allows panes to be resized by dragging on their borders.
-.It Xo Ic mouse-select-pane
-.Op Ic on | off
-.Xc
-If on,
-.Nm
-captures the mouse and when a window is split into multiple panes the mouse may
-be used to select the current pane.
-The mouse click is also passed through to the application as normal.
-.It Xo Ic mouse-select-window
-.Op Ic on | off
-.Xc
-If on, clicking the mouse on a window name in the status line will select that
-window.
+captures the mouse and allows mouse events to be bound as key bindings.
+See the
+.Sx MOUSE SUPPORT
+section for details.
.It Xo Ic mouse-utf8
.Op Ic on | off
.Xc
@@ -2840,18 +2860,6 @@ or
contains
.Ql vi .
.Pp
-.It Xo Ic mode-mouse
-.Op Ic on | off | copy-mode
-.Xc
-Mouse state in modes.
-If on, the mouse may be used to enter copy mode and copy a selection by
-dragging, to enter copy mode and scroll with the mouse wheel, or to select an
-option in choice mode.
-If set to
-.Em copy-mode ,
-the mouse behaves as set to on, but cannot be used to enter copy
-mode.
-.Pp
.It Ic mode-style Ar style
Set window modes style.
For how to specify
@@ -2940,6 +2948,14 @@ Instructs
.Nm
to expect UTF-8 sequences to appear in this window.
.Pp
+.It Ic window-active-style Ar style
+Set the style for the window's active pane.
+For how to specify
+.Ar style ,
+see the
+.Ic message-command-style
+option.
+.Pp
.It Ic window-status-activity-style Ar style
Set status line style for windows with an activity alert.
For how to specify
@@ -2997,6 +3013,14 @@ see the
.Ic message-command-style
option.
.Pp
+.It Ic window-style Ar style
+Set the default window style.
+For how to specify
+.Ar style ,
+see the
+.Ic message-command-style
+option.
+.Pp
.It Xo Ic xterm-keys
.Op Ic on | off
.Xc
@@ -3052,6 +3076,56 @@ is used.
.Fl v
shows only the option value, not the name.
.El
+.Sh MOUSE SUPPORT
+If the
+.Ic mouse
+option is on (the default is off),
+.Nm
+allows mouse events to be bound as keys.
+The name of each key is made up of a mouse event (such as
+.Ql MouseUp1 )
+and a location suffix (one of
+.Ql Pane
+for the contents of a pane,
+.Ql Border
+for a pane border or
+.Ql Status
+for the status line).
+The following mouse events are available:
+.Bl -column "MouseDown1" "MouseDrag1" "WheelDown" -offset indent
+.It Li "MouseDown1" Ta "MouseUp1" Ta "MouseDrag1"
+.It Li "MouseDown2" Ta "MouseUp2" Ta "MouseDrag2"
+.It Li "MouseDown3" Ta "MouseUp3" Ta "MouseDrag3"
+.It Li "WheelUp" Ta "WheelDown" Ta ""
+.El
+.Pp
+Each should be suffixed with a location, for example
+.Ql MouseDown1Status .
+.Pp
+The special character
+.Ql =
+may be used as
+.Ar target-window
+or
+.Ar target-pane
+in commands bound to mouse key bindings.
+It resolves to the window or pane over which the mouse event took place
+(for example, the window in the status line over which button 1 was released for a
+.Ql MouseUp1Status
+binding, or the pane over which the wheel was scrolled for a
+.Ql WheelDownPane
+binding).
+.Pp
+The
+.Ic send-keys
+.Fl M
+flag may be used to forward a mouse event to a pane.
+.Pp
+The default key bindings allow the mouse to be used to select and resize panes,
+to copy text and to change window using the status line.
+These take effect if the
+.Ic mouse
+option is turned on.
.Sh FORMATS
Certain commands accept the
.Fl F
diff --git a/tmux.h b/tmux.h
index e296ac7c..b0b13c2d 100644
--- a/tmux.h
+++ b/tmux.h
@@ -93,10 +93,39 @@ extern char **environ;
#define KEYC_MASK_MOD (KEYC_ESCAPE|KEYC_CTRL|KEYC_SHIFT|KEYC_PREFIX)
#define KEYC_MASK_KEY (~KEYC_MASK_MOD)
-/* Other key codes. */
+/* Is this a mouse key? */
+#define KEYC_IS_MOUSE(key) (((key) & KEYC_MASK_KEY) >= KEYC_MOUSE && \
+ ((key) & KEYC_MASK_KEY) < KEYC_BSPACE)
+
+/* Mouse key codes. */
+#define KEYC_MOUSE_KEY(name) \
+ KEYC_ ## name ## _PANE, \
+ KEYC_ ## name ## _STATUS, \
+ KEYC_ ## name ## _BORDER
+#define KEYC_MOUSE_STRING(name, s) \
+ { #s "Pane", KEYC_ ## name ## _PANE }, \
+ { #s "Status", KEYC_ ## name ## _STATUS }, \
+ { #s "Border", KEYC_ ## name ## _BORDER }
+
+/* Special key codes. */
enum key_code {
- /* Mouse key. */
- KEYC_MOUSE = KEYC_BASE,
+ /* Focus events. */
+ KEYC_FOCUS_IN = KEYC_BASE,
+ KEYC_FOCUS_OUT,
+
+ /* Mouse keys. */
+ KEYC_MOUSE, /* unclassified mouse event */
+ KEYC_MOUSE_KEY(MOUSEDOWN1),
+ KEYC_MOUSE_KEY(MOUSEDOWN2),
+ KEYC_MOUSE_KEY(MOUSEDOWN3),
+ KEYC_MOUSE_KEY(MOUSEUP1),
+ KEYC_MOUSE_KEY(MOUSEUP2),
+ KEYC_MOUSE_KEY(MOUSEUP3),
+ KEYC_MOUSE_KEY(MOUSEDRAG1),
+ KEYC_MOUSE_KEY(MOUSEDRAG2),
+ KEYC_MOUSE_KEY(MOUSEDRAG3),
+ KEYC_MOUSE_KEY(WHEELUP),
+ KEYC_MOUSE_KEY(WHEELDOWN),
/* Backspace key. */
KEYC_BSPACE,
@@ -145,15 +174,13 @@ enum key_code {
KEYC_KP_ENTER,
KEYC_KP_ZERO,
KEYC_KP_PERIOD,
-
- KEYC_FOCUS_IN,
- KEYC_FOCUS_OUT,
};
/* Termcap codes. */
enum tty_code_code {
TTYC_AX = 0,
TTYC_ACSC, /* acs_chars, ac */
+ TTYC_BCE, /* back_color_erase, ut */
TTYC_BEL, /* bell, bl */
TTYC_BLINK, /* enter_blink_mode, mb */
TTYC_BOLD, /* enter_bold_mode, md */
@@ -815,16 +842,15 @@ struct input_ctx {
* Window mode. Windows can be in several modes and this is used to call the
* right function to handle input and output.
*/
+struct client;
struct session;
-struct window;
struct mouse_event;
struct window_mode {
struct screen *(*init)(struct window_pane *);
void (*free)(struct window_pane *);
void (*resize)(struct window_pane *, u_int, u_int);
- void (*key)(struct window_pane *, struct session *, int);
- void (*mouse)(struct window_pane *,
- struct session *, struct mouse_event *);
+ void (*key)(struct window_pane *, struct client *, struct session *,
+ int, struct mouse_event *);
void (*timer)(struct window_pane *);
};
@@ -900,6 +926,8 @@ struct window_pane {
struct input_ctx ictx;
+ struct grid_cell colgc;
+
int pipe_fd;
struct bufferevent *pipe_event;
size_t pipe_off;
@@ -1109,54 +1137,35 @@ LIST_HEAD(tty_terms, tty_term);
/* Mouse wheel states. */
#define MOUSE_WHEEL_UP 0
-#define MOUSE_WHEEL_DOWN 1
+#define MOUSE_WHEEL_DOWN 64
-/* Mouse wheel multipler. */
-#define MOUSE_WHEEL_SCALE 3
+/* Mouse helpers. */
+#define MOUSE_BUTTONS(b) ((b) & MOUSE_MASK_BUTTONS)
+#define MOUSE_WHEEL(b) ((b) & MOUSE_MASK_WHEEL)
+#define MOUSE_DRAG(b) ((b) & MOUSE_MASK_DRAG)
+#define MOUSE_RELEASE(b) (((b) & MOUSE_MASK_BUTTONS) == 3)
-/* Mouse event bits. */
-#define MOUSE_EVENT_DOWN 0x1
-#define MOUSE_EVENT_DRAG 0x2
-#define MOUSE_EVENT_UP 0x4
-#define MOUSE_EVENT_CLICK 0x8
-#define MOUSE_EVENT_WHEEL 0x10
-
-/* Mouse flag bits. */
-#define MOUSE_RESIZE_PANE 0x1
-
-/*
- * 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
- *
- * With the SGR 1006 extension the released button becomes known. Store these
- * in separate fields and store the value converted to the old format in xb.
- */
+/* Mouse input. */
struct mouse_event {
- u_int xb;
+ int valid;
- u_int x;
- u_int lx;
- u_int sx;
+ int key;
+ int statusat;
+ u_int x;
u_int y;
- u_int ly;
- u_int sy;
+ u_int b;
- u_int sgr; /* whether the input arrived in SGR format */
- u_int sgr_xb; /* only for SGR: the unmangled button */
- u_int sgr_rel; /* only for SGR: if it is a release event */
+ u_int lx;
+ u_int ly;
+ u_int lb;
- u_int button;
- u_int clicks;
- u_int scroll;
+ int s;
+ int w;
+ int wp;
- int wheel;
- int event;
- int flags;
+ u_int sgr_type;
+ u_int sgr_b;
};
struct tty {
@@ -1202,6 +1211,11 @@ struct tty {
int term_flags;
struct mouse_event mouse;
+ int mouse_drag_flag;
+ void (*mouse_drag_update)(struct client *,
+ struct mouse_event *);
+ void (*mouse_drag_release)(struct client *,
+ struct mouse_event *);
struct event key_timer;
struct tty_key *key_tree;
@@ -1377,6 +1391,9 @@ enum cmd_retval {
/* Command queue entry. */
struct cmd_q_item {
struct cmd_list *cmdlist;
+
+ struct mouse_event mouse;
+
TAILQ_ENTRY(cmd_q_item) qentry;
};
TAILQ_HEAD(cmd_q_items, cmd_q_item);
@@ -1604,7 +1621,8 @@ void environ_push(struct environ *);
/* tty.c */
void tty_init_termios(int, struct termios *, struct bufferevent *);
void tty_raw(struct tty *, const char *);
-void tty_attributes(struct tty *, const struct grid_cell *);
+void tty_attributes(struct tty *, const struct grid_cell *,
+ const struct window_pane *);
void tty_reset(struct tty *);
void tty_region_pane(struct tty *, const struct tty_ctx *, u_int, u_int);
void tty_region(struct tty *, u_int, u_int);
@@ -1628,7 +1646,10 @@ void tty_stop_tty(struct tty *);
void tty_set_title(struct tty *, const char *);
void tty_update_mode(struct tty *, int, struct screen *);
void tty_force_cursor_colour(struct tty *, const char *);
-void tty_draw_line(struct tty *, struct screen *, u_int, u_int, u_int);
+void tty_draw_pane(struct tty *, const struct window_pane *, u_int, u_int,
+ u_int);
+void tty_draw_line(struct tty *, const struct window_pane *, struct screen *,
+ u_int, u_int, u_int);
int tty_open(struct tty *, char **);
void tty_close(struct tty *);
void tty_free(struct tty *);
@@ -1714,6 +1735,11 @@ void cmd_free_argv(int, char **);
char *cmd_stringify_argv(int, char **);
struct cmd *cmd_parse(int, char **, const char *, u_int, char **);
size_t cmd_print(struct cmd *, char *, size_t);
+int cmd_mouse_at(struct window_pane *, struct mouse_event *,
+ u_int *, u_int *, int);
+struct winlink *cmd_mouse_window(struct mouse_event *, struct session **);
+struct window_pane *cmd_mouse_pane(struct mouse_event *, struct session **,
+ struct winlink **);
struct session *cmd_current_session(struct cmd_q *, int);
struct client *cmd_current_client(struct cmd_q *);
struct client *cmd_find_client(struct cmd_q *, const char *, int);
@@ -1830,8 +1856,10 @@ int cmdq_free(struct cmd_q *);
void printflike(2, 3) cmdq_print(struct cmd_q *, const char *, ...);
void printflike(2, 3) cmdq_error(struct cmd_q *, const char *, ...);
void cmdq_guard(struct cmd_q *, const char *, int);
-void cmdq_run(struct cmd_q *, struct cmd_list *);
-void cmdq_append(struct cmd_q *, struct cmd_list *);
+void cmdq_run(struct cmd_q *, struct cmd_list *,
+ struct mouse_event *);
+void cmdq_append(struct cmd_q *, struct cmd_list *,
+ struct mouse_event *);
int cmdq_continue(struct cmd_q *);
void cmdq_flush(struct cmd_q *);
@@ -1853,7 +1881,8 @@ struct key_binding *key_bindings_lookup(int);
void key_bindings_add(int, int, struct cmd_list *);
void key_bindings_remove(int);
void key_bindings_init(void);
-void key_bindings_dispatch(struct key_binding *, struct client *);
+void key_bindings_dispatch(struct key_binding *, struct client *,
+ struct mouse_event *);
/* key-string.c */
int key_string_lookup_string(const char *);
@@ -1921,7 +1950,7 @@ RB_PROTOTYPE(status_out_tree, status_out, entry, status_out_cmp);
int status_at_line(struct client *);
void status_free_jobs(struct status_out_tree *);
void status_update_jobs(struct client *);
-void status_set_window_at(struct client *, u_int);
+struct window *status_get_window_at(struct client *, u_int);
int status_redraw(struct client *);
void printflike(2, 3) status_message_set(struct client *, const char *, ...);
void status_message_clear(struct client *);
@@ -1942,9 +1971,7 @@ void input_free(struct window_pane *);
void input_parse(struct window_pane *);
/* input-key.c */
-void input_key(struct window_pane *, int);
-void input_mouse(struct window_pane *, struct session *,
- struct mouse_event *);
+void input_key(struct window_pane *, int, struct mouse_event *);
/* xterm-keys.c */
char *xterm_keys_lookup(int);
@@ -2109,6 +2136,7 @@ void window_destroy(struct window *);
struct window_pane *window_get_active_at(struct window *, u_int, u_int);
void window_set_active_at(struct window *, u_int, u_int);
struct window_pane *window_find_string(struct window *, const char *);
+int window_has_pane(struct window *, struct window_pane *);
int window_set_active_pane(struct window *, struct window_pane *);
struct window_pane *window_add_pane(struct window *, u_int);
void window_resize(struct window *, u_int, u_int);
@@ -2139,9 +2167,8 @@ void window_pane_alternate_off(struct window_pane *,
int window_pane_set_mode(
struct window_pane *, const struct window_mode *);
void window_pane_reset_mode(struct window_pane *);
-void window_pane_key(struct window_pane *, struct session *, int);
-void window_pane_mouse(struct window_pane *,
- struct session *, struct mouse_event *);
+void window_pane_key(struct window_pane *, struct client *,
+ struct session *, int, struct mouse_event *);
int window_pane_visible(struct window_pane *);
char *window_pane_search(
struct window_pane *, const char *, u_int *);
@@ -2177,7 +2204,6 @@ void layout_resize_pane(struct window_pane *, enum layout_type,
int);
void layout_resize_pane_to(struct window_pane *, enum layout_type,
u_int);
-void layout_resize_pane_mouse(struct client *);
void layout_assign_pane(struct layout_cell *, struct window_pane *);
struct layout_cell *layout_split_pane(
struct window_pane *, enum layout_type, int, int);
@@ -2206,6 +2232,7 @@ void window_copy_init_for_output(struct window_pane *);
void printflike(2, 3) window_copy_add(struct window_pane *, const char *, ...);
void window_copy_vadd(struct window_pane *, const char *, va_list);
void window_copy_pageup(struct window_pane *);
+void window_copy_start_drag(struct client *, struct mouse_event *);
/* window-choose.c */
extern const struct window_mode window_choose_mode;
diff --git a/tty-keys.c b/tty-keys.c
index a987c44b..1df22d4c 100644
--- a/tty-keys.c
+++ b/tty-keys.c
@@ -644,8 +644,8 @@ 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, x, y, b, sgr, sgr_b, sgr_rel;
- unsigned char c;
+ u_int i, value, x, y, b, sgr_b;
+ u_char sgr_type, c;
/*
* Standard mouse sequences are \033[M followed by three characters
@@ -661,7 +661,8 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size)
*/
*size = 0;
- x = y = b = sgr = sgr_b = sgr_rel = 0;
+ x = y = b = sgr_b = 0;
+ sgr_type = ' ';
/* First two bytes are always \033[. */
if (buf[0] != '\033')
@@ -708,7 +709,7 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size)
else
y = value;
}
- log_debug("mouse input: %.*s", (int) *size, buf);
+ log_debug("mouse input: %.*s", (int)*size, buf);
/* Check and return the mouse input. */
if (b < 32)
@@ -748,22 +749,26 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size)
while (1) {
if (len <= *size)
return (1);
- c = (u_char) buf[(*size)++];
+ c = (u_char)buf[(*size)++];
if (c == 'M' || c == 'm')
break;
if (c < '0' || c > '9')
return (-1);
y = 10 * y + (c - '0');
}
- log_debug("mouse input (sgr): %.*s", (int) *size, buf);
+ log_debug("mouse input (SGR): %.*s", (int)*size, buf);
/* Check and return the mouse input. */
if (x < 1 || y < 1)
return (-1);
x--;
y--;
- sgr = 1;
- sgr_rel = (c == 'm');
+ b = sgr_b;
+
+ /* Type is M for press, m for release. */
+ sgr_type = c;
+ if (sgr_type == 'm')
+ b |= 3;
/*
* Some terminals (like PuTTY 0.63) mistakenly send
@@ -771,64 +776,20 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size)
* Discard it before it reaches any program running inside
* tmux.
*/
- if (sgr_rel && (sgr_b & 64))
+ if (sgr_type == 'm' && (sgr_b & 64))
return (-2);
-
- /* Figure out what b would be in old format. */
- b = sgr_b;
- if (sgr_rel)
- b |= 3;
} else
return (-1);
- /* Fill in mouse structure. */
- if (~m->event & MOUSE_EVENT_WHEEL) {
- m->lx = m->x;
- m->ly = m->y;
- }
- m->xb = b;
- m->sgr = sgr;
- m->sgr_xb = sgr_b;
- m->sgr_rel = sgr_rel;
+ /* Fill mouse event. */
+ m->lx = m->x;
m->x = x;
+ m->ly = m->y;
m->y = y;
- if (b & MOUSE_MASK_WHEEL) {
- if (b & MOUSE_MASK_SHIFT)
- m->scroll = 1;
- else
- m->scroll = MOUSE_WHEEL_SCALE;
- if (b & MOUSE_MASK_META)
- m->scroll *= MOUSE_WHEEL_SCALE;
- if (b & MOUSE_MASK_CTRL)
- m->scroll *= MOUSE_WHEEL_SCALE;
-
- b &= MOUSE_MASK_BUTTONS;
- if (b == 0)
- m->wheel = MOUSE_WHEEL_UP;
- else if (b == 1)
- m->wheel = MOUSE_WHEEL_DOWN;
- m->event = MOUSE_EVENT_WHEEL;
-
- m->button = 3;
- } else if ((b & MOUSE_MASK_BUTTONS) == 3) {
- if (~m->event & MOUSE_EVENT_DRAG && x == m->sx && y == m->sy) {
- m->event = MOUSE_EVENT_CLICK;
- m->clicks = (m->clicks + 1) % 3;
- } else
- m->event = MOUSE_EVENT_DRAG;
- m->event |= MOUSE_EVENT_UP;
- } else {
- if (b & MOUSE_MASK_DRAG)
- m->event = MOUSE_EVENT_DRAG;
- else {
- m->event = MOUSE_EVENT_DOWN;
- if (x != m->sx || y != m->sy)
- m->clicks = 0;
- }
- m->button = (b & MOUSE_MASK_BUTTONS);
- }
- m->sx = x;
- m->sy = y;
+ m->lb = m->b;
+ m->b = b;
+ m->sgr_type = sgr_type;
+ m->sgr_b = sgr_b;
return (0);
}
diff --git a/tty-term.c b/tty-term.c
index 365da5fb..d177c197 100644
--- a/tty-term.c
+++ b/tty-term.c
@@ -38,6 +38,7 @@ struct tty_terms tty_terms = LIST_HEAD_INITIALIZER(tty_terms);
const struct tty_term_code_entry tty_term_codes[NTTYCODE] = {
{ TTYC_ACSC, TTYCODE_STRING, "acsc" },
{ TTYC_AX, TTYCODE_FLAG, "AX" },
+ { TTYC_BCE, TTYCODE_FLAG, "bce" },
{ TTYC_BEL, TTYCODE_STRING, "bel" },
{ TTYC_BLINK, TTYCODE_STRING, "blink" },
{ TTYC_BOLD, TTYCODE_STRING, "bold" },
diff --git a/tty.c b/tty.c
index 83ae8282..a5067b12 100644
--- a/tty.c
+++ b/tty.c
@@ -43,11 +43,14 @@ void tty_colours_fg(struct tty *, const struct grid_cell *);
void tty_colours_bg(struct tty *, const struct grid_cell *);
int tty_large_region(struct tty *, const struct tty_ctx *);
+int tty_fake_bce(const struct tty *, const struct window_pane *);
void tty_redraw_region(struct tty *, const struct tty_ctx *);
void tty_emulate_repeat(
struct tty *, enum tty_code_code, enum tty_code_code, u_int);
void tty_repeat_space(struct tty *, u_int);
-void tty_cell(struct tty *, const struct grid_cell *);
+void tty_cell(struct tty *, const struct grid_cell *,
+ const struct window_pane *);
+void tty_default_colours(struct grid_cell *, const struct window_pane *);
#define tty_use_acs(tty) \
(tty_term_has((tty)->term, TTYC_ACSC) && !((tty)->flags & TTY_UTF8))
@@ -238,6 +241,10 @@ tty_start_tty(struct tty *tty)
tty->flags |= TTY_STARTED;
tty_force_cursor_colour(tty, "");
+
+ tty->mouse_drag_flag = 0;
+ tty->mouse_drag_update = NULL;
+ tty->mouse_drag_release = NULL;
}
void
@@ -582,6 +589,23 @@ tty_large_region(unused struct tty *tty, const struct tty_ctx *ctx)
}
/*
+ * Return if BCE is needed but the terminal doesn't have it - it'll need to be
+ * emulated.
+ */
+int
+tty_fake_bce(const struct tty *tty, const struct window_pane *wp)
+{
+ struct grid_cell gc;
+
+ memcpy(&gc, &grid_default_cell, sizeof gc);
+ tty_default_colours(&gc, wp);
+
+ if (gc.bg == 8 && !(gc.flags & GRID_FLAG_BG256))
+ return (0);
+ return (!tty_term_flag(tty->term, TTYC_BCE));
+}
+
+/*
* Redraw scroll region using data from screen (already updated). Used when
* CSR not supported, or window is a pane that doesn't take up the full
* width of the terminal.
@@ -604,15 +628,23 @@ tty_redraw_region(struct tty *tty, const struct tty_ctx *ctx)
if (ctx->ocy < ctx->orupper || ctx->ocy > ctx->orlower) {
for (i = ctx->ocy; i < screen_size_y(s); i++)
- tty_draw_line(tty, s, i, ctx->xoff, ctx->yoff);
+ tty_draw_pane(tty, wp, i, ctx->xoff, ctx->yoff);
} else {
for (i = ctx->orupper; i <= ctx->orlower; i++)
- tty_draw_line(tty, s, i, ctx->xoff, ctx->yoff);
+ tty_draw_pane(tty, wp, i, ctx->xoff, ctx->yoff);
}
}
void
-tty_draw_line(struct tty *tty, struct screen *s, u_int py, u_int ox, u_int oy)
+tty_draw_pane(struct tty *tty, const struct window_pane *wp, u_int py, u_int ox,
+ u_int oy)
+{
+ tty_draw_line(tty, wp, wp->screen, py, ox, oy);
+}
+
+void
+tty_draw_line(struct tty *tty, const struct window_pane *wp,
+ struct screen *s, u_int py, u_int ox, u_int oy)
{
const struct grid_cell *gc;
struct grid_line *gl;
@@ -650,20 +682,20 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int py, u_int ox, u_int oy)
~(GRID_FLAG_FG256|GRID_FLAG_BG256);
tmpgc.flags |= s->sel.cell.flags &
(GRID_FLAG_FG256|GRID_FLAG_BG256);
- tty_cell(tty, &tmpgc);
+ tty_cell(tty, &tmpgc, wp);
} else
- tty_cell(tty, gc);
+ tty_cell(tty, gc, wp);
}
if (sx >= tty->sx) {
tty_update_mode(tty, tty->mode, s);
return;
}
- tty_reset(tty);
+ tty_attributes(tty, &grid_default_cell, wp);
tty_cursor(tty, ox + sx, oy + py);
if (sx != screen_size_x(s) && ox + screen_size_x(s) >= tty->sx &&
- tty_term_has(tty->term, TTYC_EL))
+ tty_term_has(tty->term, TTYC_EL) && !tty_fake_bce(tty, wp))
tty_putcode(tty, TTYC_EL);
else
tty_repeat_space(tty, screen_size_x(s) - sx);
@@ -713,19 +745,19 @@ tty_cmd_insertcharacter(struct tty *tty, const struct tty_ctx *ctx)
struct window_pane *wp = ctx->wp;
if (!tty_pane_full_width(tty, ctx)) {
- tty_draw_line(tty, wp->screen, ctx->ocy, ctx->xoff, ctx->yoff);
+ tty_draw_pane(tty, wp, ctx->ocy, ctx->xoff, ctx->yoff);
return;
}
- tty_reset(tty);
+ tty_attributes(tty, &grid_default_cell, wp);
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
- if (tty_term_has(tty->term, TTYC_ICH) ||
- tty_term_has(tty->term, TTYC_ICH1))
+ if (!tty_fake_bce(tty, wp) && (tty_term_has(tty->term, TTYC_ICH) ||
+ tty_term_has(tty->term, TTYC_ICH1)))
tty_emulate_repeat(tty, TTYC_ICH, TTYC_ICH1, ctx->num);
else
- tty_draw_line(tty, wp->screen, ctx->ocy, ctx->xoff, ctx->yoff);
+ tty_draw_pane(tty, wp, ctx->ocy, ctx->xoff, ctx->yoff);
}
void
@@ -733,14 +765,14 @@ tty_cmd_deletecharacter(struct tty *tty, const struct tty_ctx *ctx)
{
struct window_pane *wp = ctx->wp;
- if (!tty_pane_full_width(tty, ctx) ||
+ if (!tty_pane_full_width(tty, ctx) || tty_fake_bce(tty, wp) ||
(!tty_term_has(tty->term, TTYC_DCH) &&
!tty_term_has(tty->term, TTYC_DCH1))) {
- tty_draw_line(tty, wp->screen, ctx->ocy, ctx->xoff, ctx->yoff);
+ tty_draw_pane(tty, wp, ctx->ocy, ctx->xoff, ctx->yoff);
return;
}
- tty_reset(tty);
+ tty_attributes(tty, &grid_default_cell, wp);
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
@@ -754,11 +786,11 @@ tty_cmd_clearcharacter(struct tty *tty, const struct tty_ctx *ctx)
{
u_int i;
- tty_reset(tty);
+ tty_attributes(tty, &grid_default_cell, ctx->wp);
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
- if (tty_term_has(tty->term, TTYC_ECH))
+ if (tty_term_has(tty->term, TTYC_ECH) && !tty_fake_bce(tty, ctx->wp))
tty_putcode1(tty, TTYC_ECH, ctx->num);
else {
for (i = 0; i < ctx->num; i++)
@@ -769,14 +801,14 @@ tty_cmd_clearcharacter(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_insertline(struct tty *tty, const struct tty_ctx *ctx)
{
- if (!tty_pane_full_width(tty, ctx) ||
+ if (!tty_pane_full_width(tty, ctx) || tty_fake_bce(tty, ctx->wp) ||
!tty_term_has(tty->term, TTYC_CSR) ||
!tty_term_has(tty->term, TTYC_IL1)) {
tty_redraw_region(tty, ctx);
return;
}
- tty_reset(tty);
+ tty_attributes(tty, &grid_default_cell, ctx->wp);
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
@@ -787,14 +819,14 @@ tty_cmd_insertline(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx)
{
- if (!tty_pane_full_width(tty, ctx) ||
+ if (!tty_pane_full_width(tty, ctx) || tty_fake_bce(tty, ctx->wp) ||
!tty_term_has(tty->term, TTYC_CSR) ||
!tty_term_has(tty->term, TTYC_DL1)) {
tty_redraw_region(tty, ctx);
return;
}
- tty_reset(tty);
+ tty_attributes(tty, &grid_default_cell, ctx->wp);
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
@@ -808,11 +840,12 @@ tty_cmd_clearline(struct tty *tty, const struct tty_ctx *ctx)
struct window_pane *wp = ctx->wp;
struct screen *s = wp->screen;
- tty_reset(tty);
+ tty_attributes(tty, &grid_default_cell, wp);
tty_cursor_pane(tty, ctx, 0, ctx->ocy);
- if (tty_pane_full_width(tty, ctx) && tty_term_has(tty->term, TTYC_EL))
+ if (tty_pane_full_width(tty, ctx) && !tty_fake_bce(tty, wp) &&
+ tty_term_has(tty->term, TTYC_EL))
tty_putcode(tty, TTYC_EL);
else
tty_repeat_space(tty, screen_size_x(s));
@@ -824,11 +857,12 @@ tty_cmd_clearendofline(struct tty *tty, const struct tty_ctx *ctx)
struct window_pane *wp = ctx->wp;
struct screen *s = wp->screen;
- tty_reset(tty);
+ tty_attributes(tty, &grid_default_cell, wp);
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
- if (tty_pane_full_width(tty, ctx) && tty_term_has(tty->term, TTYC_EL))
+ if (tty_pane_full_width(tty, ctx) &&
+ tty_term_has(tty->term, TTYC_EL) && !tty_fake_bce(tty, wp))
tty_putcode(tty, TTYC_EL);
else
tty_repeat_space(tty, screen_size_x(s) - ctx->ocx);
@@ -837,9 +871,10 @@ tty_cmd_clearendofline(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_clearstartofline(struct tty *tty, const struct tty_ctx *ctx)
{
- tty_reset(tty);
+ tty_attributes(tty, &grid_default_cell, ctx->wp);
- if (ctx->xoff == 0 && tty_term_has(tty->term, TTYC_EL1)) {
+ if (ctx->xoff == 0 && tty_term_has(tty->term, TTYC_EL1) &&
+ !tty_fake_bce(tty, ctx->wp)) {
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
tty_putcode(tty, TTYC_EL1);
} else {
@@ -854,14 +889,14 @@ tty_cmd_reverseindex(struct tty *tty, const struct tty_ctx *ctx)
if (ctx->ocy != ctx->orupper)
return;
- if (!tty_pane_full_width(tty, ctx) ||
+ if (!tty_pane_full_width(tty, ctx) || tty_fake_bce(tty, ctx->wp) ||
!tty_term_has(tty->term, TTYC_CSR) ||
!tty_term_has(tty->term, TTYC_RI)) {
tty_redraw_region(tty, ctx);
return;
}
- tty_reset(tty);
+ tty_attributes(tty, &grid_default_cell, ctx->wp);
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->orupper);
@@ -877,7 +912,7 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx)
if (ctx->ocy != ctx->orlower)
return;
- if (!tty_pane_full_width(tty, ctx) ||
+ if (!tty_pane_full_width(tty, ctx) || tty_fake_bce(tty, wp) ||
!tty_term_has(tty->term, TTYC_CSR)) {
if (tty_large_region(tty, ctx))
wp->flags |= PANE_REDRAW;
@@ -894,7 +929,7 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx)
if (ctx->num && !(tty->term->flags & TERM_EARLYWRAP))
return;
- tty_reset(tty);
+ tty_attributes(tty, &grid_default_cell, wp);
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
@@ -909,12 +944,13 @@ tty_cmd_clearendofscreen(struct tty *tty, const struct tty_ctx *ctx)
struct screen *s = wp->screen;
u_int i, j;
- tty_reset(tty);
+ tty_attributes(tty, &grid_default_cell, wp);
tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1);
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
- if (tty_pane_full_width(tty, ctx) && tty_term_has(tty->term, TTYC_EL)) {
+ if (tty_pane_full_width(tty, ctx) &&
+ tty_term_has(tty->term, TTYC_EL) && !tty_fake_bce(tty, wp)) {
tty_putcode(tty, TTYC_EL);
if (ctx->ocy != screen_size_y(s) - 1) {
tty_cursor_pane(tty, ctx, 0, ctx->ocy + 1);
@@ -942,12 +978,13 @@ tty_cmd_clearstartofscreen(struct tty *tty, const struct tty_ctx *ctx)
struct screen *s = wp->screen;
u_int i, j;
- tty_reset(tty);
+ tty_attributes(tty, &grid_default_cell, wp);
tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1);
tty_cursor_pane(tty, ctx, 0, 0);
- if (tty_pane_full_width(tty, ctx) && tty_term_has(tty->term, TTYC_EL)) {
+ if (tty_pane_full_width(tty, ctx) &&
+ tty_term_has(tty->term, TTYC_EL) && !tty_fake_bce(tty, wp)) {
for (i = 0; i < ctx->ocy; i++) {
tty_putcode(tty, TTYC_EL);
tty_emulate_repeat(tty, TTYC_CUD, TTYC_CUD1, 1);
@@ -969,12 +1006,13 @@ tty_cmd_clearscreen(struct tty *tty, const struct tty_ctx *ctx)
struct screen *s = wp->screen;
u_int i, j;
- tty_reset(tty);
+ tty_attributes(tty, &grid_default_cell, wp);
tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1);
tty_cursor_pane(tty, ctx, 0, 0);
- if (tty_pane_full_width(tty, ctx) && tty_term_has(tty->term, TTYC_EL)) {
+ if (tty_pane_full_width(tty, ctx) &&
+ tty_term_has(tty->term, TTYC_EL) && !tty_fake_bce(tty, wp)) {
for (i = 0; i < screen_size_y(s); i++) {
tty_putcode(tty, TTYC_EL);
if (i != screen_size_y(s) - 1) {
@@ -997,7 +1035,7 @@ tty_cmd_alignmenttest(struct tty *tty, const struct tty_ctx *ctx)
struct screen *s = wp->screen;
u_int i, j;
- tty_reset(tty);
+ tty_attributes(tty, &grid_default_cell, wp);
tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1);
@@ -1038,12 +1076,12 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
*/
cx = screen_size_x(s) - grid_cell_width(&ctx->last_cell);
tty_cursor_pane(tty, ctx, cx, ctx->ocy);
- tty_cell(tty, &ctx->last_cell);
+ tty_cell(tty, &ctx->last_cell, wp);
}
} else
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
- tty_cell(tty, ctx->cell);
+ tty_cell(tty, ctx->cell, wp);
}
void
@@ -1055,7 +1093,7 @@ tty_cmd_utf8character(struct tty *tty, const struct tty_ctx *ctx)
* Cannot rely on not being a partial character, so just redraw the
* whole line.
*/
- tty_draw_line(tty, wp->screen, ctx->ocy, ctx->xoff, ctx->yoff);
+ tty_draw_pane(tty, wp, ctx->ocy, ctx->xoff, ctx->yoff);
}
void
@@ -1088,12 +1126,13 @@ tty_cmd_rawstring(struct tty *tty, const struct tty_ctx *ctx)
tty->cx = tty->cy = UINT_MAX;
tty->rupper = tty->rlower = UINT_MAX;
- tty_reset(tty);
+ tty_attributes(tty, &grid_default_cell, ctx->wp);
tty_cursor(tty, 0, 0);
}
void
-tty_cell(struct tty *tty, const struct grid_cell *gc)
+tty_cell(struct tty *tty, const struct grid_cell *gc,
+ const struct window_pane *wp)
{
struct utf8_data ud;
u_int i;
@@ -1108,7 +1147,7 @@ tty_cell(struct tty *tty, const struct grid_cell *gc)
return;
/* Set the attributes. */
- tty_attributes(tty, gc);
+ tty_attributes(tty, gc, wp);
/* Get the cell and if ASCII write with putc to do ACS translation. */
grid_cell_get(gc, &ud);
@@ -1312,12 +1351,14 @@ out:
}
void
-tty_attributes(struct tty *tty, const struct grid_cell *gc)
+tty_attributes(struct tty *tty, const struct grid_cell *gc,
+ const struct window_pane *wp)
{
struct grid_cell *tc = &tty->cell, gc2;
u_char changed;
memcpy(&gc2, gc, sizeof gc2);
+ tty_default_colours(&gc2, wp);
/*
* If no setab, try to use the reverse attribute as a best-effort for a
@@ -1610,6 +1651,47 @@ tty_try_256(struct tty *tty, u_char colour, const char *type)
}
void
+tty_default_colours(struct grid_cell *gc, const struct window_pane *wp)
+{
+ const struct grid_cell *agc, *pgc, *wgc;
+
+ if (wp == NULL)
+ return;
+
+ pgc = &wp->colgc;
+ agc = options_get_style(&wp->window->options, "window-active-style");
+ wgc = options_get_style(&wp->window->options, "window-style");
+
+ if (gc->fg == 8 && !(gc->flags & GRID_FLAG_FG256)) {
+ if (pgc->fg != 8 || (pgc->flags & GRID_FLAG_FG256)) {
+ gc->fg = pgc->fg;
+ gc->flags |= (pgc->flags & GRID_FLAG_FG256);
+ } else if (wp == wp->window->active &&
+ (agc->fg != 8 || (agc->flags & GRID_FLAG_FG256))) {
+ gc->fg = agc->fg;
+ gc->flags |= (agc->flags & GRID_FLAG_FG256);
+ } else {
+ gc->fg = wgc->fg;
+ gc->flags |= (wgc->flags & GRID_FLAG_FG256);
+ }
+ }
+
+ if (gc->bg == 8 && !(gc->flags & GRID_FLAG_BG256)) {
+ if (pgc->bg != 8 || (pgc->flags & GRID_FLAG_BG256)) {
+ gc->bg = pgc->bg;
+ gc->flags |= (pgc->flags & GRID_FLAG_BG256);
+ } else if (wp == wp->window->active &&
+ (agc->bg != 8 || (agc->flags & GRID_FLAG_BG256))) {
+ gc->bg = agc->bg;
+ gc->flags |= (agc->flags & GRID_FLAG_BG256);
+ } else {
+ gc->bg = wgc->bg;
+ gc->flags |= (wgc->flags & GRID_FLAG_BG256);
+ }
+ }
+}
+
+void
tty_bell(struct tty *tty)
{
tty_putcode(tty, TTYC_BEL);
diff --git a/window-choose.c b/window-choose.c
index 8bed8d45..5de87572 100644
--- a/window-choose.c
+++ b/window-choose.c
@@ -27,11 +27,12 @@
struct screen *window_choose_init(struct window_pane *);
void window_choose_free(struct window_pane *);
void window_choose_resize(struct window_pane *, u_int, u_int);
-void window_choose_key(struct window_pane *, struct session *, int);
-void window_choose_mouse(
- struct window_pane *, struct session *, struct mouse_event *);
+void window_choose_key(struct window_pane *, struct client *,
+ struct session *, int, struct mouse_event *);
void window_choose_default_callback(struct window_choose_data *);
+struct window_choose_mode_item *window_choose_get_item(struct window_pane *,
+ int, struct mouse_event *);
void window_choose_fire_callback(
struct window_pane *, struct window_choose_data *);
@@ -42,7 +43,7 @@ void window_choose_write_line(
void window_choose_scroll_up(struct window_pane *);
void window_choose_scroll_down(struct window_pane *);
-void window_choose_collapse(struct window_pane *, struct session *);
+void window_choose_collapse(struct window_pane *, struct session *, u_int);
void window_choose_expand(struct window_pane *, struct session *, u_int);
enum window_choose_input_type {
@@ -55,7 +56,6 @@ const struct window_mode window_choose_mode = {
window_choose_free,
window_choose_resize,
window_choose_key,
- window_choose_mouse,
NULL,
};
@@ -160,8 +160,6 @@ window_choose_init(struct window_pane *wp)
s = &data->screen;
screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
s->mode &= ~MODE_CURSOR;
- if (options_get_number(&wp->window->options, "mode-mouse"))
- s->mode |= MODE_MOUSE_STANDARD;
keys = options_get_number(&wp->window->options, "mode-keys");
if (keys == MODEKEY_EMACS)
@@ -237,7 +235,7 @@ window_choose_data_run(struct window_choose_data *cdata)
return;
}
- cmdq_run(cdata->start_client->cmdq, cmdlist);
+ cmdq_run(cdata->start_client->cmdq, cmdlist, NULL);
cmd_list_free(cmdlist);
}
@@ -325,7 +323,7 @@ window_choose_prompt_input(enum window_choose_input_type input_type,
}
void
-window_choose_collapse(struct window_pane *wp, struct session *s)
+window_choose_collapse(struct window_pane *wp, struct session *s, u_int pos)
{
struct window_choose_mode_data *data = wp->modedata;
struct window_choose_mode_item *item, *chosen;
@@ -335,7 +333,7 @@ window_choose_collapse(struct window_pane *wp, struct session *s)
ARRAY_DECL(, struct window_choose_mode_item) list_copy;
ARRAY_INIT(&list_copy);
- chosen = &ARRAY_ITEM(&data->list, data->selected);
+ chosen = &ARRAY_ITEM(&data->list, pos);
chosen->state &= ~TREE_EXPANDED;
/*
@@ -383,7 +381,7 @@ window_choose_collapse_all(struct window_pane *wp)
chosen = ARRAY_ITEM(&data->list, data->selected).wcd->start_session;
RB_FOREACH(s, sessions, &sessions)
- window_choose_collapse(wp, s);
+ window_choose_collapse(wp, s, data->selected);
/* Reset the selection back to the starting session. */
for (i = 0; i < ARRAY_LENGTH(&data->list); i++) {
@@ -483,8 +481,27 @@ window_choose_expand(struct window_pane *wp, struct session *s, u_int pos)
}
}
+struct window_choose_mode_item *
+window_choose_get_item(struct window_pane *wp, int key, struct mouse_event *m)
+{
+ struct window_choose_mode_data *data = wp->modedata;
+ u_int x, y, idx;
+
+ if (!KEYC_IS_MOUSE(key))
+ return (&ARRAY_ITEM(&data->list, data->selected));
+
+ if (cmd_mouse_at(wp, m, &x, &y, 0) != 0)
+ return (NULL);
+
+ idx = data->top + y;
+ if (idx >= ARRAY_LENGTH(&data->list))
+ return (NULL);
+ return (&ARRAY_ITEM(&data->list, idx));
+}
+
void
-window_choose_key(struct window_pane *wp, unused struct session *sess, int key)
+window_choose_key(struct window_pane *wp, unused struct client *c,
+ unused struct session *sess, int key, struct mouse_event *m)
{
struct window_choose_mode_data *data = wp->modedata;
struct screen *s = &data->screen;
@@ -533,23 +550,28 @@ window_choose_key(struct window_pane *wp, unused struct session *sess, int key)
window_choose_fire_callback(wp, NULL);
break;
case MODEKEYCHOICE_CHOOSE:
- item = &ARRAY_ITEM(&data->list, data->selected);
+ if ((item = window_choose_get_item(wp, key, m)) == NULL)
+ break;
window_choose_fire_callback(wp, item->wcd);
break;
case MODEKEYCHOICE_TREE_TOGGLE:
- item = &ARRAY_ITEM(&data->list, data->selected);
- if (item->state & TREE_EXPANDED)
- window_choose_collapse(wp, item->wcd->tree_session);
- else {
+ if ((item = window_choose_get_item(wp, key, m)) == NULL)
+ break;
+ if (item->state & TREE_EXPANDED) {
+ window_choose_collapse(wp, item->wcd->tree_session,
+ item->wcd->idx);
+ } else {
window_choose_expand(wp, item->wcd->tree_session,
- data->selected);
+ item->wcd->idx);
}
window_choose_redraw_screen(wp);
break;
case MODEKEYCHOICE_TREE_COLLAPSE:
- item = &ARRAY_ITEM(&data->list, data->selected);
+ if ((item = window_choose_get_item(wp, key, m)) == NULL)
+ break;
if (item->state & TREE_EXPANDED) {
- window_choose_collapse(wp, item->wcd->tree_session);
+ window_choose_collapse(wp, item->wcd->tree_session,
+ data->selected);
window_choose_redraw_screen(wp);
}
break;
@@ -557,7 +579,8 @@ window_choose_key(struct window_pane *wp, unused struct session *sess, int key)
window_choose_collapse_all(wp);
break;
case MODEKEYCHOICE_TREE_EXPAND:
- item = &ARRAY_ITEM(&data->list, data->selected);
+ if ((item = window_choose_get_item(wp, key, m)) == NULL)
+ break;
if (!(item->state & TREE_EXPANDED)) {
window_choose_expand(wp, item->wcd->tree_session,
data->selected);
@@ -712,48 +735,6 @@ window_choose_key(struct window_pane *wp, unused struct session *sess, int key)
}
void
-window_choose_mouse(struct window_pane *wp, struct session *sess,
- struct mouse_event *m)
-{
- struct window_choose_mode_data *data = wp->modedata;
- struct screen *s = &data->screen;
- struct window_choose_mode_item *item;
- u_int idx, i, n;
-
- if (m->event == MOUSE_EVENT_WHEEL) {
- /*
- * Multiple line scrolling by default is annoying, so scale
- * m->scroll back down.
- */
- n = m->scroll;
- if (n >= MOUSE_WHEEL_SCALE)
- n /= MOUSE_WHEEL_SCALE;
- for (i = 0; i < n; i++) {
- if (m->wheel == MOUSE_WHEEL_UP)
- window_choose_key(wp, sess, KEYC_UP);
- else
- window_choose_key(wp, sess, KEYC_DOWN);
- }
- return;
- }
-
- if (~m->event & MOUSE_EVENT_CLICK)
- return;
- if (m->x >= screen_size_x(s))
- return;
- if (m->y >= screen_size_y(s))
- return;
-
- idx = data->top + m->y;
- if (idx >= ARRAY_LENGTH(&data->list))
- return;
- data->selected = idx;
-
- item = &ARRAY_ITEM(&data->list, data->selected);
- window_choose_fire_callback(wp, item->wcd);
-}
-
-void
window_choose_write_line(
struct window_pane *wp, struct screen_write_ctx *ctx, u_int py)
{
diff --git a/window-clock.c b/window-clock.c
index ede8df5b..3cabd9e9 100644
--- a/window-clock.c
+++ b/window-clock.c
@@ -27,7 +27,8 @@
struct screen *window_clock_init(struct window_pane *);
void window_clock_free(struct window_pane *);
void window_clock_resize(struct window_pane *, u_int, u_int);
-void window_clock_key(struct window_pane *, struct session *, int);
+void window_clock_key(struct window_pane *, struct client *,
+ struct session *, int, struct mouse_event *);
void window_clock_timer(struct window_pane *);
void window_clock_draw_screen(struct window_pane *);
@@ -37,7 +38,6 @@ const struct window_mode window_clock_mode = {
window_clock_free,
window_clock_resize,
window_clock_key,
- NULL,
window_clock_timer,
};
@@ -157,8 +157,8 @@ window_clock_resize(struct window_pane *wp, u_int sx, u_int sy)
}
void
-window_clock_key(
- struct window_pane *wp, unused struct session *sess, unused int key)
+window_clock_key(struct window_pane *wp, unused struct client *c,
+ unused struct session *sess, unused int key, unused struct mouse_event *m)
{
window_pane_reset_mode(wp);
}
diff --git a/window-copy.c b/window-copy.c
index feb8c481..afa609ed 100644
--- a/window-copy.c
+++ b/window-copy.c
@@ -27,11 +27,10 @@
struct screen *window_copy_init(struct window_pane *);
void window_copy_free(struct window_pane *);
void window_copy_resize(struct window_pane *, u_int, u_int);
-void window_copy_key(struct window_pane *, struct session *, int);
+void window_copy_key(struct window_pane *, struct client *, struct session *,
+ int, struct mouse_event *);
int window_copy_key_input(struct window_pane *, int);
int window_copy_key_numeric_prefix(struct window_pane *, int);
-void window_copy_mouse(struct window_pane *, struct session *,
- struct mouse_event *);
void window_copy_redraw_selection(struct window_pane *, u_int);
void window_copy_redraw_lines(struct window_pane *, u_int, u_int);
@@ -76,21 +75,22 @@ void window_copy_cursor_up(struct window_pane *, int);
void window_copy_cursor_down(struct window_pane *, int);
void window_copy_cursor_jump(struct window_pane *);
void window_copy_cursor_jump_back(struct window_pane *);
-void window_copy_cursor_jump_to(struct window_pane *);
-void window_copy_cursor_jump_to_back(struct window_pane *);
+void window_copy_cursor_jump_to(struct window_pane *, int);
+void window_copy_cursor_jump_to_back(struct window_pane *, int);
void window_copy_cursor_next_word(struct window_pane *, const char *);
void window_copy_cursor_next_word_end(struct window_pane *, const char *);
void window_copy_cursor_previous_word(struct window_pane *, const char *);
void window_copy_scroll_up(struct window_pane *, u_int);
void window_copy_scroll_down(struct window_pane *, u_int);
void window_copy_rectangle_toggle(struct window_pane *);
+void window_copy_drag_update(struct client *, struct mouse_event *);
+void window_copy_drag_release(struct client *, struct mouse_event *);
const struct window_mode window_copy_mode = {
window_copy_init,
window_copy_free,
window_copy_resize,
window_copy_key,
- window_copy_mouse,
NULL,
};
@@ -124,38 +124,38 @@ enum window_copy_input_type {
* mode ends).
*/
struct window_copy_mode_data {
- struct screen screen;
+ struct screen screen;
- struct screen *backing;
- int backing_written; /* backing display has started */
+ struct screen *backing;
+ int backing_written; /* backing display started */
- struct mode_key_data mdata;
+ struct mode_key_data mdata;
- u_int oy;
+ u_int oy;
- u_int selx;
- u_int sely;
+ u_int selx;
+ u_int sely;
- u_int rectflag; /* are we in rectangle copy mode? */
+ u_int rectflag; /* are we in rectangle copy mode? */
- u_int cx;
- u_int cy;
+ u_int cx;
+ u_int cy;
- u_int lastcx; /* position in last line with content */
- u_int lastsx; /* size of last line with content */
+ u_int lastcx; /* position in last line w/ content */
+ u_int lastsx; /* size of last line w/ content */
enum window_copy_input_type inputtype;
- const char *inputprompt;
- char *inputstr;
- int inputexit;
+ const char *inputprompt;
+ char *inputstr;
+ int inputexit;
- int numprefix;
+ int numprefix;
enum window_copy_input_type searchtype;
- char *searchstr;
+ char *searchstr;
enum window_copy_input_type jumptype;
- char jumpchar;
+ char jumpchar;
};
struct screen *
@@ -193,8 +193,6 @@ window_copy_init(struct window_pane *wp)
s = &data->screen;
screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
- if (options_get_number(&wp->window->options, "mode-mouse"))
- s->mode |= MODE_MOUSE_STANDARD;
keys = options_get_number(&wp->window->options, "mode-keys");
if (keys == MODEKEY_EMACS)
@@ -367,19 +365,20 @@ window_copy_resize(struct window_pane *wp, u_int sx, u_int sy)
}
void
-window_copy_key(struct window_pane *wp, struct session *sess, int key)
+window_copy_key(struct window_pane *wp, struct client *c, struct session *sess,
+ int key, struct mouse_event *m)
{
const char *word_separators;
struct window_copy_mode_data *data = wp->modedata;
struct screen *s = &data->screen;
- u_int n;
- int np, keys;
+ u_int n, np;
+ int keys;
enum mode_key_cmd cmd;
const char *arg, *ss;
- np = data->numprefix;
- if (np <= 0)
- np = 1;
+ np = 1;
+ if (data->numprefix > 0)
+ np = data->numprefix;
if (data->inputtype == WINDOW_COPY_JUMPFORWARD ||
data->inputtype == WINDOW_COPY_JUMPBACK ||
@@ -398,11 +397,11 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
}
if (data->inputtype == WINDOW_COPY_JUMPTOFORWARD) {
for (; np != 0; np--)
- window_copy_cursor_jump_to(wp);
+ window_copy_cursor_jump_to(wp, 0);
}
if (data->inputtype == WINDOW_COPY_JUMPTOBACK) {
for (; np != 0; np--)
- window_copy_cursor_jump_to_back(wp);
+ window_copy_cursor_jump_to_back(wp, 0);
}
}
data->jumptype = data->inputtype;
@@ -536,9 +535,14 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
window_copy_redraw_screen(wp);
break;
case MODEKEYCOPY_STARTSELECTION:
- s->sel.lineflag = LINE_SEL_NONE;
- window_copy_start_selection(wp);
- window_copy_redraw_screen(wp);
+ if (KEYC_IS_MOUSE(key)) {
+ if (c != NULL)
+ window_copy_start_drag(c, m);
+ } else {
+ s->sel.lineflag = LINE_SEL_NONE;
+ window_copy_start_selection(wp);
+ window_copy_redraw_screen(wp);
+ }
break;
case MODEKEYCOPY_SELECTLINE:
s->sel.lineflag = LINE_SEL_LEFT_RIGHT;
@@ -639,10 +643,10 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
window_copy_cursor_jump_back(wp);
} else if (data->jumptype == WINDOW_COPY_JUMPTOFORWARD) {
for (; np != 0; np--)
- window_copy_cursor_jump_to(wp);
+ window_copy_cursor_jump_to(wp, 1);
} else if (data->jumptype == WINDOW_COPY_JUMPTOBACK) {
for (; np != 0; np--)
- window_copy_cursor_jump_to_back(wp);
+ window_copy_cursor_jump_to_back(wp, 1);
}
break;
case MODEKEYCOPY_JUMPREVERSE:
@@ -654,10 +658,10 @@ window_copy_key(struct window_pane *wp, struct session *sess, int key)
window_copy_cursor_jump(wp);
} else if (data->jumptype == WINDOW_COPY_JUMPTOFORWARD) {
for (; np != 0; np--)
- window_copy_cursor_jump_to_back(wp);
+ window_copy_cursor_jump_to_back(wp, 1);
} else if (data->jumptype == WINDOW_COPY_JUMPTOBACK) {
for (; np != 0; np--)
- window_copy_cursor_jump_to(wp);
+ window_copy_cursor_jump_to(wp, 1);
}
break;
case MODEKEYCOPY_JUMPBACK:
@@ -888,75 +892,6 @@ window_copy_key_numeric_prefix(struct window_pane *wp, int key)
}
void
-window_copy_mouse(struct window_pane *wp, struct session *sess,
- struct mouse_event *m)
-{
- struct window_copy_mode_data *data = wp->modedata;
- struct screen *s = &data->screen;
- u_int i, old_cy;
-
- if (m->x >= screen_size_x(s))
- return;
- if (m->y >= screen_size_y(s))
- return;
-
- /* If mouse wheel (buttons 4 and 5), scroll. */
- if (m->event == MOUSE_EVENT_WHEEL) {
- for (i = 0; i < m->scroll; i++) {
- if (m->wheel == MOUSE_WHEEL_UP)
- window_copy_cursor_up(wp, 1);
- else {
- window_copy_cursor_down(wp, 1);
-
- /*
- * We reached the bottom, leave copy mode, but
- * only if no selection is in progress.
- */
- if (data->oy == 0 && !s->sel.flag &&
- s->sel.lineflag == LINE_SEL_NONE)
- goto reset_mode;
- }
- }
- return;
- }
-
- /*
- * If already reading motion, move the cursor while buttons are still
- * pressed, or stop the selection on their release.
- */
- if (s->mode & MODE_MOUSE_BUTTON) {
- if (~m->event & MOUSE_EVENT_UP) {
- old_cy = data->cy;
- window_copy_update_cursor(wp, m->x, m->y);
- if (window_copy_update_selection(wp, 1))
- window_copy_redraw_selection(wp, old_cy);
- return;
- }
- goto reset_mode;
- }
-
- /* Otherwise if other buttons pressed, start selection and motion. */
- if (~m->event & MOUSE_EVENT_UP) {
- s->mode &= ~MODE_MOUSE_STANDARD;
- s->mode |= MODE_MOUSE_BUTTON;
-
- window_copy_update_cursor(wp, m->x, m->y);
- window_copy_start_selection(wp);
- window_copy_redraw_screen(wp);
- }
-
- return;
-
-reset_mode:
- s->mode &= ~MODE_MOUSE_BUTTON;
- s->mode |= MODE_MOUSE_STANDARD;
- if (sess != NULL) {
- window_copy_copy_selection(wp, NULL);
- window_pane_reset_mode(wp);
- }
-}
-
-void
window_copy_scroll_to(struct window_pane *wp, u_int px, u_int py)
{
struct window_copy_mode_data *data = wp->modedata;
@@ -2009,7 +1944,7 @@ window_copy_cursor_jump_back(struct window_pane *wp)
}
void
-window_copy_cursor_jump_to(struct window_pane *wp)
+window_copy_cursor_jump_to(struct window_pane *wp, int jump_again)
{
struct window_copy_mode_data *data = wp->modedata;
struct screen *back_s = data->backing;
@@ -2017,7 +1952,7 @@ window_copy_cursor_jump_to(struct window_pane *wp)
struct utf8_data ud;
u_int px, py, xx;
- px = data->cx + 1;
+ px = data->cx + 1 + jump_again;
py = screen_hsize(back_s) + data->cy - data->oy;
xx = window_copy_find_length(wp, py);
@@ -2036,7 +1971,7 @@ window_copy_cursor_jump_to(struct window_pane *wp)
}
void
-window_copy_cursor_jump_to_back(struct window_pane *wp)
+window_copy_cursor_jump_to_back(struct window_pane *wp, int jump_again)
{
struct window_copy_mode_data *data = wp->modedata;
struct screen *back_s = data->backing;
@@ -2050,6 +1985,9 @@ window_copy_cursor_jump_to_back(struct window_pane *wp)
if (px > 0)
px--;
+ if (jump_again && px > 0)
+ px--;
+
for (;;) {
gc = grid_peek_cell(back_s->grid, px, py);
grid_cell_get(gc, &ud);
@@ -2274,3 +2212,62 @@ window_copy_rectangle_toggle(struct window_pane *wp)
window_copy_update_selection(wp, 1);
window_copy_redraw_screen(wp);
}
+
+void
+window_copy_start_drag(struct client *c, unused struct mouse_event *m)
+{
+ struct window_pane *wp;
+ struct window_copy_mode_data *data;
+ u_int x, y;
+
+ wp = cmd_mouse_pane(m, NULL, NULL);
+ if (wp->mode != &window_copy_mode)
+ return;
+ data = wp->modedata;
+
+ if (cmd_mouse_at(wp, m, &x, &y, 1) != 0)
+ return;
+
+ c->tty.mouse_drag_update = window_copy_drag_update;
+ c->tty.mouse_drag_release = window_copy_drag_release;
+
+ window_copy_update_cursor(wp, x, y);
+ window_copy_start_selection(wp);
+ window_copy_redraw_screen(wp);
+}
+
+void
+window_copy_drag_update(unused struct client *c, struct mouse_event *m)
+{
+ struct window_pane *wp;
+ struct window_copy_mode_data *data;
+ u_int x, y, old_cy;
+
+ wp = cmd_mouse_pane(m, NULL, NULL);
+ if (wp->mode != &window_copy_mode)
+ return;
+ data = wp->modedata;
+
+ if (cmd_mouse_at(wp, m, &x, &y, 0) != 0)
+ return;
+ old_cy = data->cy;
+
+ window_copy_update_cursor(wp, x, y);
+ if (window_copy_update_selection(wp, 1))
+ window_copy_redraw_selection(wp, old_cy);
+}
+
+void
+window_copy_drag_release(unused struct client *c, struct mouse_event *m)
+{
+ struct window_pane *wp;
+ struct window_copy_mode_data *data;
+
+ wp = cmd_mouse_pane(m, NULL, NULL);
+ if (wp->mode != &window_copy_mode)
+ return;
+ data = wp->modedata;
+
+ window_copy_copy_selection(wp, NULL);
+ window_pane_reset_mode(wp);
+}
diff --git a/window.c b/window.c
index fff2cfc3..38c49a76 100644
--- a/window.c
+++ b/window.c
@@ -386,6 +386,18 @@ window_resize(struct window *w, u_int sx, u_int sy)
}
int
+window_has_pane(struct window *w, struct window_pane *wp)
+{
+ struct window_pane *wp1;
+
+ TAILQ_FOREACH(wp1, &w->panes, entry) {
+ if (wp1 == wp)
+ return (1);
+ }
+ return (0);
+}
+
+int
window_set_active_pane(struct window *w, struct window_pane *wp)
{
if (wp == w->active)
@@ -637,7 +649,7 @@ window_destroy_panes(struct window *w)
char *
window_printable_flags(struct session *s, struct winlink *wl)
{
- char flags[BUFSIZ];
+ char flags[32];
int pos;
pos = 0;
@@ -704,6 +716,8 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
wp->saved_grid = NULL;
+ memcpy(&wp->colgc, &grid_default_cell, sizeof wp->colgc);
+
screen_init(&wp->base, sx, sy, hlimit);
wp->screen = &wp->base;
@@ -1064,52 +1078,37 @@ window_pane_reset_mode(struct window_pane *wp)
}
void
-window_pane_key(struct window_pane *wp, struct session *sess, int key)
+window_pane_key(struct window_pane *wp, struct client *c, struct session *s,
+ int key, struct mouse_event *m)
{
struct window_pane *wp2;
+ if (KEYC_IS_MOUSE(key) && m == NULL)
+ return;
+
if (wp->mode != NULL) {
if (wp->mode->key != NULL)
- wp->mode->key(wp, sess, key);
+ wp->mode->key(wp, c, s, key, m);
return;
}
if (wp->fd == -1 || wp->flags & PANE_INPUTOFF)
return;
- input_key(wp, key);
+ input_key(wp, key, m);
+
+ if (KEYC_IS_MOUSE(key))
+ return;
if (options_get_number(&wp->window->options, "synchronize-panes")) {
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
if (wp2 == wp || wp2->mode != NULL)
continue;
if (wp2->fd != -1 && window_pane_visible(wp2))
- input_key(wp2, key);
+ input_key(wp2, key, NULL);
}
}
}
-void
-window_pane_mouse(struct window_pane *wp, struct session *sess,
- struct mouse_event *m)
-{
- if (!window_pane_visible(wp))
- return;
-
- if (m->x < wp->xoff || m->x >= wp->xoff + wp->sx)
- return;
- if (m->y < wp->yoff || m->y >= wp->yoff + wp->sy)
- return;
- m->x -= wp->xoff;
- m->y -= wp->yoff;
-
- if (wp->mode != NULL) {
- if (wp->mode->mouse != NULL &&
- options_get_number(&wp->window->options, "mode-mouse"))
- wp->mode->mouse(wp, sess, m);
- } else if (wp->fd != -1)
- input_mouse(wp, sess, m);
-}
-
int
window_pane_visible(struct window_pane *wp)
{