Rewrite of tmux mouse support which was a mess. Instead of having
authornicm <nicm@openbsd.org>
Sun, 19 Apr 2015 21:34:21 +0000 (21:34 +0000)
committernicm <nicm@openbsd.org>
Sun, 19 Apr 2015 21:34:21 +0000 (21:34 +0000)
options for "mouse-this" and "mouse-that", mouse events may be bound as
keys and there is one option "mouse" that turns on mouse support
entirely (set -g mouse on).

See the new MOUSE SUPPORT section of the man page for description of the
key names and new flags (-t= to specify the pane or window under mouse
as a target, and send-keys -M to pass through a mouse event).

The default builtin bindings for the mouse are:

    bind -n   MouseDown1Pane select-pane -t=; send-keys -M
    bind -n MouseDown1Status select-window -t=
    bind -n   MouseDrag1Pane copy-mode -M
    bind -n MouseDrag1Border resize-pane -M

To get the effect of turning mode-mouse off, do:

    unbind -n MouseDrag1Pane
    unbind -temacs-copy MouseDrag1Pane

The old mouse options are now gone, set-option -q may be used to
suppress warnings if mixing configuration files.

27 files changed:
usr.bin/tmux/cfg.c
usr.bin/tmux/cmd-command-prompt.c
usr.bin/tmux/cmd-confirm-before.c
usr.bin/tmux/cmd-copy-mode.c
usr.bin/tmux/cmd-if-shell.c
usr.bin/tmux/cmd-queue.c
usr.bin/tmux/cmd-resize-pane.c
usr.bin/tmux/cmd-send-keys.c
usr.bin/tmux/cmd.c
usr.bin/tmux/control.c
usr.bin/tmux/input-keys.c
usr.bin/tmux/key-bindings.c
usr.bin/tmux/key-string.c
usr.bin/tmux/layout.c
usr.bin/tmux/mode-key.c
usr.bin/tmux/options-table.c
usr.bin/tmux/server-client.c
usr.bin/tmux/server-fn.c
usr.bin/tmux/status.c
usr.bin/tmux/tmux.1
usr.bin/tmux/tmux.h
usr.bin/tmux/tty-keys.c
usr.bin/tmux/tty.c
usr.bin/tmux/window-choose.c
usr.bin/tmux/window-clock.c
usr.bin/tmux/window-copy.c
usr.bin/tmux/window.c

index 514c886..4919b5e 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cfg.c,v 1.33 2014/10/27 22:23:47 nicm Exp $ */
+/* $OpenBSD: cfg.c,v 1.34 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -75,7 +75,7 @@ load_cfg(const char *path, struct cmd_q *cmdq, char **cause)
 
                if (cmdlist == NULL)
                        continue;
-               cmdq_append(cmdq, cmdlist);
+               cmdq_append(cmdq, cmdlist, NULL);
                cmd_list_free(cmdlist);
                found++;
        }
index d7fcf3c..71b0eba 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-command-prompt.c,v 1.28 2014/10/20 22:29:25 nicm Exp $ */
+/* $OpenBSD: cmd-command-prompt.c,v 1.29 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -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)
index 26dab68..4a53398 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-confirm-before.c,v 1.22 2014/10/20 23:27:14 nicm Exp $ */
+/* $OpenBSD: cmd-confirm-before.c,v 1.23 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -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);
index 12adde1..0fa1f65 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-copy-mode.c,v 1.18 2015/02/09 23:18:19 nicm Exp $ */
+/* $OpenBSD: cmd-copy-mode.c,v 1.19 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -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);
 
index c03060b..e19d4c4 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-if-shell.c,v 1.28 2015/02/05 10:29:43 nicm Exp $ */
+/* $OpenBSD: cmd-if-shell.c,v 1.29 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -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);
 }
 
index bd400d7..0d26ff2 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-queue.c,v 1.22 2015/02/12 09:56:19 nicm Exp $ */
+/* $OpenBSD: cmd-queue.c,v 1.23 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2013 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -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. */
index 2335ae6..9e12c9e 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-resize-pane.c,v 1.17 2014/10/20 22:29:25 nicm Exp $ */
+/* $OpenBSD: cmd-resize-pane.c,v 1.18 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
 
 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;
+}
index e35f57f..99b574f 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-send-keys.c,v 1.18 2014/10/20 22:29:25 nicm Exp $ */
+/* $OpenBSD: cmd-send-keys.c,v 1.19 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -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);
                }
        }
 
index f81f0f1..8fe774c 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd.c,v 1.98 2014/10/08 17:35:58 nicm Exp $ */
+/* $OpenBSD: cmd.c,v 1.99 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -348,6 +348,7 @@ cmd_current_session(struct cmd_q *cmdq, int prefer_unattached)
        const char              *path;
        int                      found;
 
+       /* Try the queue session. */
        if (c != NULL && c->session != NULL)
                return (c->session);
 
@@ -504,6 +505,74 @@ cmd_choose_client(struct clients *cc)
        return (cbest);
 }
 
+/* Adjust current mouse position for a pane. */
+int
+cmd_mouse_at(struct window_pane *wp, struct mouse_event *m, u_int *xp,
+    u_int *yp, int last)
+{
+       u_int   x, y;
+
+       if (last) {
+               x = m->lx;
+               y = m->ly;
+       } else {
+               x = m->x;
+               y = m->y;
+       }
+
+       if (m->statusat == 0 && y > 0)
+               y--;
+       else if (m->statusat > 0 && y >= (u_int)m->statusat)
+               y = m->statusat - 1;
+
+       if (x < wp->xoff || x >= wp->xoff + wp->sx)
+               return (-1);
+       if (y < wp->yoff || y >= wp->yoff + wp->sy)
+               return (-1);
+
+       *xp = x - wp->xoff;
+       *yp = y - wp->yoff;
+       return (0);
+}
+
+/* Get current mouse window if any. */
+struct winlink *
+cmd_mouse_window(struct mouse_event *m, struct session **sp)
+{
+       struct session  *s;
+       struct window   *w;
+
+       if (!m->valid || m->s == -1 || m->w == -1)
+               return (NULL);
+       if ((s = session_find_by_id(m->s)) == NULL)
+               return (NULL);
+       if ((w = window_find_by_id(m->w)) == NULL)
+               return (NULL);
+
+       if (sp != NULL)
+               *sp = s;
+       return (winlink_find_by_window(&s->windows, w));
+}
+
+/* Get current mouse pane if any. */
+struct window_pane *
+cmd_mouse_pane(struct mouse_event *m, struct session **sp, struct winlink **wlp)
+{
+       struct winlink          *wl;
+       struct window_pane      *wp;
+
+       if ((wl = cmd_mouse_window(m, sp)) == NULL)
+               return (NULL);
+       if ((wp = window_pane_find_by_id(m->wp)) == NULL)
+               return (NULL);
+       if (!window_has_pane(wl->window, wp))
+               return (NULL);
+
+       if (wlp != NULL)
+               *wlp = wl;
+       return (wp);
+}
+
 /* Find the target client or report an error and return NULL. */
 struct client *
 cmd_find_client(struct cmd_q *cmdq, const char *arg, int quiet)
@@ -928,7 +997,12 @@ no_colon:
         * No colon in the string, first try special cases, then as a window
         * and lastly as a session.
         */
-       if (arg[0] == '!' && arg[1] == '\0') {
+       if (arg[0] == '=' && arg[1] == '\0') {
+               if ((wl = cmd_mouse_window(&cmdq->item->mouse, &s)) == NULL) {
+                       cmdq_error(cmdq, "no mouse target");
+                       goto error;
+               }
+       } else if (arg[0] == '!' && arg[1] == '\0') {
                if ((wl = TAILQ_FIRST(&s->lastw)) == NULL)
                        goto not_found;
        } else if (arg[0] == '+' || arg[0] == '-') {
@@ -959,14 +1033,16 @@ no_session:
                cmdq_error(cmdq, "multiple sessions: %s", arg);
        else
                cmdq_error(cmdq, "session not found: %s", arg);
-       free(sessptr);
-       return (NULL);
+       goto error;
 
 not_found:
        if (ambiguous)
                cmdq_error(cmdq, "multiple windows: %s", arg);
        else
                cmdq_error(cmdq, "window not found: %s", arg);
+       goto error;
+
+error:
        free(sessptr);
        return (NULL);
 }
@@ -1228,6 +1304,18 @@ lookup_string:
        return (wl);
 
 no_period:
+       /* Check mouse event. */
+       if (arg[0] == '=' && arg[1] == '\0') {
+               *wpp = cmd_mouse_pane(&cmdq->item->mouse, &s, &wl);
+               if (*wpp == NULL) {
+                       cmdq_error(cmdq, "no mouse target");
+                       return (NULL);
+               }
+               if (sp != NULL)
+                       *sp = s;
+               return (wl);
+       }
+
        /* Try as a pane number alone. */
        idx = strtonum(arg, 0, INT_MAX, &errstr);
        if (errstr != NULL)
index d439a56..99996f4 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.13 2014/10/20 23:57:13 nicm Exp $ */
+/* $OpenBSD: control.c,v 1.14 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2012 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -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);
                }
 
index 1f0a549..3a6b6b7 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: input-keys.c,v 1.41 2015/03/31 17:45:10 nicm Exp $ */
+/* $OpenBSD: input-keys.c,v 1.42 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -31,6 +31,8 @@
  * direction with output).
  */
 
+void    input_key_mouse(struct window_pane *, struct mouse_event *);
+
 struct input_key_ent {
        int              key;
        const char      *data;
@@ -135,7 +137,7 @@ const struct input_key_ent input_keys[] = {
 
 /* Translate a key code into an output key sequence. */
 void
-input_key(struct window_pane *wp, int key)
+input_key(struct window_pane *wp, int key, struct mouse_event *m)
 {
        const struct input_key_ent     *ike;
        u_int                           i;
@@ -143,7 +145,14 @@ input_key(struct window_pane *wp, int key)
        char                           *out;
        u_char                          ch;
 
-       log_debug("writing key 0x%x", key);
+       log_debug("writing key 0x%x (%s)", key, key_string_lookup_key(key));
+
+       /* If this is a mouse key, pass off to mouse function. */
+       if (KEYC_IS_MOUSE(key)) {
+               if (m != NULL && m->wp != -1 && (u_int)m->wp == wp->id)
+                       input_key_mouse(wp, m);
+               return;
+       }
 
        /*
         * If this is a normal 7-bit key, just send it, with a leading escape
@@ -200,55 +209,47 @@ input_key(struct window_pane *wp, int key)
 
 /* Translate mouse and output. */
 void
-input_mouse(struct window_pane *wp, struct session *s, struct mouse_event *m)
+input_key_mouse(struct window_pane *wp, struct mouse_event *m)
 {
-       char                     buf[40];
-       size_t                   len;
-       struct paste_buffer     *pb;
-       int                      event;
-
-       if (wp->screen->mode & ALL_MOUSE_MODES) {
-               /*
-                * Use the SGR (1006) extension only if the application
-                * requested it and the underlying terminal also sent the event
-                * in this format (this is because an old style mouse release
-                * event cannot be converted into the new SGR format, since the
-                * released button is unknown). Otherwise pretend that tmux
-                * doesn't speak this extension, and fall back to the UTF-8
-                * (1005) extension if the application requested, or to the
-                * legacy format.
-                */
-               if (m->sgr && (wp->screen->mode & MODE_MOUSE_SGR)) {
-                       len = xsnprintf(buf, sizeof buf, "\033[<%u;%u;%u%c",
-                           m->sgr_xb, m->x + 1, m->y + 1,
-                           m->sgr_rel ? 'm' : 'M');
-               } else if (wp->screen->mode & MODE_MOUSE_UTF8) {
-                       len = xsnprintf(buf, sizeof buf, "\033[M");
-                       len += utf8_split2(m->xb + 32, &buf[len]);
-                       len += utf8_split2(m->x + 33, &buf[len]);
-                       len += utf8_split2(m->y + 33, &buf[len]);
-               } else {
-                       if (m->xb > 223)
-                               return;
-                       len = xsnprintf(buf, sizeof buf, "\033[M");
-                       buf[len++] = m->xb + 32;
-                       buf[len++] = m->x + 33;
-                       buf[len++] = m->y + 33;
-               }
-               bufferevent_write(wp->event, buf, len);
+       char    buf[40];
+       size_t  len;
+       u_int   x, y;
+
+       if ((wp->screen->mode & ALL_MOUSE_MODES) == 0)
+               return;
+       if (!window_pane_visible(wp))
+               return;
+       if (cmd_mouse_at(wp, m, &x, &y, 0) != 0)
                return;
-       }
 
-       if (options_get_number(&wp->window->options, "mode-mouse") != 1)
+       /* If this pane is not in button mode, discard motion events. */
+       if (!(wp->screen->mode & MODE_MOUSE_BUTTON) && (m->b & MOUSE_MASK_DRAG))
                return;
-       event = m->event & (MOUSE_EVENT_CLICK|MOUSE_EVENT_WHEEL);
-       if (wp->mode == NULL && m->button == 1 && event == MOUSE_EVENT_CLICK) {
-               pb = paste_get_top();
-               if (pb != NULL)
-                       paste_send_pane(pb, wp, "\r", 1);
-       } else if (window_pane_set_mode(wp, &window_copy_mode) == 0) {
-               window_copy_init_from_pane(wp);
-               if (wp->mode->mouse != NULL)
-                       wp->mode->mouse(wp, s, m);
+
+       /*
+        * Use the SGR (1006) extension only if the application requested it
+        * and the underlying terminal also sent the event in this format (this
+        * is because an old style mouse release event cannot be converted into
+        * the new SGR format, since the released button is unknown). Otherwise
+        * pretend that tmux doesn't speak this extension, and fall back to the
+        * UTF-8 (1005) extension if the application requested, or to the
+        * legacy format.
+        */
+       if (m->sgr_type != ' ' && (wp->screen->mode & MODE_MOUSE_SGR)) {
+               len = xsnprintf(buf, sizeof buf, "\033[<%u;%u;%u%c",
+                   m->sgr_b, x + 1, y + 1, m->sgr_type);
+       } else if (wp->screen->mode & MODE_MOUSE_UTF8) {
+               len = xsnprintf(buf, sizeof buf, "\033[M");
+               len += utf8_split2(m->b + 32, &buf[len]);
+               len += utf8_split2(x + 33, &buf[len]);
+               len += utf8_split2(y + 33, &buf[len]);
+       } else {
+               if (m->b > 223)
+                       return;
+               len = xsnprintf(buf, sizeof buf, "\033[M");
+               buf[len++] = m->b + 32;
+               buf[len++] = x + 33;
+               buf[len++] = y + 33;
        }
+       bufferevent_write(wp->event, buf, len);
 }
index c0f54df..acea8ac 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: key-bindings.c,v 1.43 2014/10/22 23:18:53 nicm Exp $ */
+/* $OpenBSD: key-bindings.c,v 1.44 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -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);
 }
index c889102..b8e68b2 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: key-string.c,v 1.25 2014/07/21 10:25:48 nicm Exp $ */
+/* $OpenBSD: key-string.c,v 1.26 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -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
index f7bc3c4..743ffe6 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: layout.c,v 1.22 2014/05/08 06:03:30 nicm Exp $ */
+/* $OpenBSD: layout.c,v 1.23 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -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(
index e7ad7b7..e62ff52 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: mode-key.c,v 1.61 2014/11/06 09:17:25 nicm Exp $ */
+/* $OpenBSD: mode-key.c,v 1.62 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -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 }
 };
index cb329b9..d8af5e3 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: options-table.c,v 1.54 2015/04/19 21:05:27 nicm Exp $ */
+/* $OpenBSD: options-table.c,v 1.55 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2011 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -36,9 +36,6 @@
 const char *options_table_mode_keys_list[] = {
        "emacs", "vi", NULL
 };
-const char *options_table_mode_mouse_list[] = {
-       "off", "on", "copy-mode", NULL
-};
 const char *options_table_clock_mode_style_list[] = {
        "12", "24", NULL
 };
@@ -255,17 +252,7 @@ const struct options_table_entry session_options_table[] = {
          .default_str = "bg=yellow,fg=black"
        },
 
-       { .name = "mouse-resize-pane",
-         .type = OPTIONS_TABLE_FLAG,
-         .default_num = 0
-       },
-
-       { .name = "mouse-select-pane",
-         .type = OPTIONS_TABLE_FLAG,
-         .default_num = 0
-       },
-
-       { .name = "mouse-select-window",
+       { .name = "mouse",
          .type = OPTIONS_TABLE_FLAG,
          .default_num = 0
        },
@@ -575,12 +562,6 @@ const struct options_table_entry window_options_table[] = {
          .default_num = MODEKEY_EMACS
        },
 
-       { .name = "mode-mouse",
-         .type = OPTIONS_TABLE_CHOICE,
-         .choices = options_table_mode_mouse_list,
-         .default_num = 0
-       },
-
        { .name = "mode-style",
          .type = OPTIONS_TABLE_STYLE,
          .default_str = "bg=yellow,fg=black"
index c38b7c5..4c9d40a 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: server-client.c,v 1.130 2015/04/19 21:05:27 nicm Exp $ */
+/* $OpenBSD: server-client.c,v 1.131 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -32,7 +32,7 @@
 
 void   server_client_check_focus(struct window_pane *);
 void   server_client_check_resize(struct window_pane *);
-void   server_client_check_mouse(struct client *, struct window_pane *);
+int    server_client_check_mouse(struct client *);
 void   server_client_repeat_timer(int, short, void *);
 void   server_client_check_exit(struct client *);
 void   server_client_check_redraw(struct client *);
@@ -91,13 +91,6 @@ server_client_create(int fd)
        c->prompt_buffer = NULL;
        c->prompt_index = 0;
 
-       c->tty.mouse.xb = c->tty.mouse.button = 3;
-       c->tty.mouse.x = c->tty.mouse.y = -1;
-       c->tty.mouse.lx = c->tty.mouse.ly = -1;
-       c->tty.mouse.sx = c->tty.mouse.sy = -1;
-       c->tty.mouse.event = MOUSE_EVENT_UP;
-       c->tty.mouse.flags = 0;
-
        c->flags |= CLIENT_FOCUSED;
 
        evtimer_set(&c->repeat_timer, server_client_repeat_timer, c);
@@ -289,56 +282,228 @@ server_client_status_timer(void)
 }
 
 /* Check for mouse keys. */
-void
-server_client_check_mouse(struct client *c, struct window_pane *wp)
+int
+server_client_check_mouse(struct client *c)
 {
-       struct session          *s = c->session;
-       struct options          *oo = &s->options;
-       struct mouse_event      *m = &c->tty.mouse;
-       int                      statusat;
-
-       statusat = status_at_line(c);
-
-       /* Is this a window selection click on the status line? */
-       if (statusat != -1 && m->y == (u_int)statusat &&
-           options_get_number(oo, "mouse-select-window")) {
-               if (m->event & MOUSE_EVENT_CLICK) {
-                       status_set_window_at(c, m->x);
-               } else if (m->event == MOUSE_EVENT_WHEEL) {
-                       if (m->wheel == MOUSE_WHEEL_UP)
-                               session_previous(c->session, 0);
-                       else if (m->wheel == MOUSE_WHEEL_DOWN)
-                               session_next(c->session, 0);
-                       server_redraw_session(s);
+       struct session                          *s = c->session;
+       struct mouse_event                      *m = &c->tty.mouse;
+       struct window                           *w;
+       struct window_pane                      *wp;
+       enum { NOTYPE, DOWN, UP, DRAG, WHEEL }   type = NOTYPE;
+       enum { NOWHERE, PANE, STATUS, BORDER }   where = NOWHERE;
+       u_int                                    x, y, b;
+       int                                      key;
+
+       log_debug("mouse %02x at %u,%u (last %u,%u) (%d)", m->b, m->x, m->y,
+           m->lx, m->ly, c->tty.mouse_drag_flag);
+
+       /* What type of event is this? */
+       if (MOUSE_DRAG(m->b)) {
+               type = DRAG;
+               if (c->tty.mouse_drag_flag) {
+                       x = m->x, y = m->y, b = m->b;
+                       log_debug("drag update at %u,%u", x, y);
+               } else {
+                       x = m->lx, y = m->ly, b = m->lb;
+                       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_redraw_window(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 +526,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 +538,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 +579,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 +617,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 +633,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 +644,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 +660,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. */
@@ -622,7 +797,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)
@@ -642,29 +816,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
@@ -945,9 +1102,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;
 
index e8ec836..335eacf 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: server-fn.c,v 1.79 2015/03/31 17:45:10 nicm Exp $ */
+/* $OpenBSD: server-fn.c,v 1.80 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -604,7 +604,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);
+       }
 }
index fde52a8..b39a47c 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: status.c,v 1.124 2015/02/06 23:28:52 nicm Exp $ */
+/* $OpenBSD: status.c,v 1.125 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -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. */
index 2899f45..67ce519 100644 (file)
@@ -1,4 +1,4 @@
-.\" $OpenBSD: tmux.1,v 1.418 2015/04/19 21:05:27 nicm Exp $
+.\" $OpenBSD: tmux.1,v 1.419 2015/04/19 21:34:21 nicm Exp $
 .\"
 .\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 .\"
@@ -1019,13 +1019,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 Ns ).
 .El
 .Pp
 Each window displayed by
@@ -1643,7 +1646,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
@@ -1672,6 +1675,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 Ns ).
 .It Xo Ic respawn-pane
 .Op Fl k
 .Op Fl t Ar target-pane
@@ -1980,7 +1987,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
@@ -2001,6 +2008,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 Ns ).
 .It Xo Ic send-prefix
 .Op Fl 2
 .Op Fl t Ar target-pane
@@ -2449,25 +2460,15 @@ For how to specify
 see the
 .Ic message-command-style
 option.
-.It Xo Ic mouse-resize-pane
-.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
+.It Xo Ic mouse
 .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
@@ -2855,18 +2856,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
@@ -3083,6 +3072,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"
+.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
index 4784796..34c602f 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.491 2015/04/19 21:05:27 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.492 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -95,10 +95,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,
@@ -147,9 +176,6 @@ enum key_code {
        KEYC_KP_ENTER,
        KEYC_KP_ZERO,
        KEYC_KP_PERIOD,
-
-       KEYC_FOCUS_IN,
-       KEYC_FOCUS_OUT,
 };
 
 /* Termcap codes. */
@@ -818,16 +844,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 *);
 };
 
@@ -1114,54 +1139,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 {
@@ -1207,6 +1213,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;
@@ -1382,6 +1393,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);
@@ -1723,6 +1737,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);
@@ -1839,8 +1858,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 *);
 
@@ -1862,7 +1883,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 *);
@@ -1930,7 +1952,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 *);
@@ -1951,9 +1973,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);
@@ -2118,6 +2138,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);
@@ -2148,9 +2169,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 *);
@@ -2186,7 +2206,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);
@@ -2215,6 +2234,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;
index 89f04ad..ce38e7b 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tty-keys.c,v 1.71 2014/10/22 23:18:53 nicm Exp $ */
+/* $OpenBSD: tty-keys.c,v 1.72 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -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);
 }
index e71d004..2f37a30 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tty.c,v 1.176 2015/04/19 21:05:27 nicm Exp $ */
+/* $OpenBSD: tty.c,v 1.177 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -241,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
index dbc423b..dda0a0f 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: window-choose.c,v 1.60 2015/03/31 17:45:10 nicm Exp $ */
+/* $OpenBSD: window-choose.c,v 1.61 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
 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);
@@ -711,48 +734,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)
index 473ed48..a706d58 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: window-clock.c,v 1.10 2014/03/31 21:34:08 nicm Exp $ */
+/* $OpenBSD: window-clock.c,v 1.11 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -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);
 }
index 95b2f04..9c74d0a 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: window-copy.c,v 1.125 2015/04/10 16:00:08 nicm Exp $ */
+/* $OpenBSD: window-copy.c,v 1.126 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
 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);
@@ -84,13 +83,14 @@ 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 ||
@@ -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;
@@ -887,75 +891,6 @@ window_copy_key_numeric_prefix(struct window_pane *wp, int key)
        return (0);
 }
 
-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)
 {
@@ -2274,3 +2209,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);
+}
index 5f4c6ce..0d7832d 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: window.c,v 1.117 2015/04/19 21:05:27 nicm Exp $ */
+/* $OpenBSD: window.c,v 1.118 2015/04/19 21:34:21 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -386,6 +386,18 @@ window_resize(struct window *w, u_int sx, u_int sy)
        w->sy = 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)
 {
@@ -1052,52 +1064,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)
 {