Rewrite of tmux mouse support which was a mess. Instead of having

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.
This commit is contained in:
nicm
2015-04-19 21:34:21 +00:00
parent ee123c2489
commit bf635e7741
27 changed files with 879 additions and 584 deletions

94
cmd.c
View File

@@ -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)