From 4efd45628d28e41a1d84091b4b6091484586ca28 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Wed, 18 May 2011 20:30:14 +0000 Subject: [PATCH] Sync OpenBSD patchset 905: Add a new option, mouse-resize-pane. When on, panes may be resized by dragging their borders. From hsim at gmx.li. --- layout.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- options-table.c | 7 ++++++- server-client.c | 20 ++++++++++++++++++-- tmux.1 | 8 +++++++- tmux.h | 7 ++++++- 5 files changed, 85 insertions(+), 6 deletions(-) diff --git a/layout.c b/layout.c index 3b087d47..e0acbda6 100644 --- a/layout.c +++ b/layout.c @@ -1,4 +1,4 @@ -/* $Id: layout.c,v 1.19 2010-07-02 02:54:52 tcunha Exp $ */ +/* $Id: layout.c,v 1.20 2011-05-18 20:30:14 tcunha Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott @@ -485,6 +485,53 @@ layout_resize_pane(struct window_pane *wp, enum layout_type type, int change) layout_fix_panes(wp->window, wp->window->sx, wp->window->sy); } +void +layout_resize_pane_mouse(struct client *c, struct mouse_event *mouse) +{ + struct window *w; + struct window_pane *wp; + int pane_border; + + w = c->session->curw->window; + + pane_border = 0; + if ((c->last_mouse.b & MOUSE_BUTTON) != MOUSE_UP && + (c->last_mouse.b & MOUSE_RESIZE_PANE)) { + TAILQ_FOREACH(wp, &w->panes, entry) { + if (wp->xoff + wp->sx == c->last_mouse.x && + wp->yoff <= 1 + c->last_mouse.y && + wp->yoff + wp->sy >= c->last_mouse.y) { + layout_resize_pane(wp, LAYOUT_LEFTRIGHT, + mouse->x - c->last_mouse.x); + pane_border = 1; + } + if (wp->yoff + wp->sy == c->last_mouse.y && + wp->xoff <= 1 + c->last_mouse.x && + wp->xoff + wp->sx >= c->last_mouse.x) { + layout_resize_pane(wp, LAYOUT_TOPBOTTOM, + mouse->y - c->last_mouse.y); + pane_border = 1; + } + } + if (pane_border) + server_redraw_window(w); + } else if (mouse->b != MOUSE_UP && + mouse->b == (mouse->b & MOUSE_BUTTON)) { + TAILQ_FOREACH(wp, &w->panes, entry) { + if ((wp->xoff + wp->sx == mouse->x && + wp->yoff <= 1 + mouse->y && + wp->yoff + wp->sy >= mouse->y) || + (wp->yoff + wp->sy == mouse->y && + wp->xoff <= 1 + mouse->x && + wp->xoff + wp->sx >= mouse->x)) { + pane_border = 1; + } + } + } + if (pane_border) + mouse->b |= MOUSE_RESIZE_PANE; +} + int layout_resize_pane_grow( struct layout_cell *lc, enum layout_type type, int needed) diff --git a/options-table.c b/options-table.c index 59f16d14..42d50335 100644 --- a/options-table.c +++ b/options-table.c @@ -1,4 +1,4 @@ -/* $Id: options-table.c,v 1.8 2011-05-18 20:28:40 tcunha Exp $ */ +/* $Id: options-table.c,v 1.9 2011-05-18 20:30:14 tcunha Exp $ */ /* * Copyright (c) 2011 Nicholas Marriott @@ -192,6 +192,11 @@ const struct options_table_entry session_options_table[] = { .default_num = 20 }, + { .name = "mouse-resize-pane", + .type = OPTIONS_TABLE_FLAG, + .default_num = 0 + }, + { .name = "mouse-select-pane", .type = OPTIONS_TABLE_FLAG, .default_num = 0 diff --git a/server-client.c b/server-client.c index 8e54fd33..826529be 100644 --- a/server-client.c +++ b/server-client.c @@ -1,4 +1,4 @@ -/* $Id: server-client.c,v 1.59 2011-05-05 10:12:33 tcunha Exp $ */ +/* $Id: server-client.c,v 1.60 2011-05-18 20:30:14 tcunha Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott @@ -88,6 +88,9 @@ server_client_create(int fd) c->prompt_buffer = NULL; c->prompt_index = 0; + c->last_mouse.b = MOUSE_UP; + c->last_mouse.x = c->last_mouse.y = -1; + evtimer_set(&c->repeat_timer, server_client_repeat_timer, c); for (i = 0; i < ARRAY_LENGTH(&clients); i++) { @@ -343,6 +346,9 @@ server_client_handle_key(int key, struct mouse_event *mouse, void *data) return; } } + if (options_get_number(oo, "mouse-resize-pane")) + layout_resize_pane_mouse(c, mouse); + memcpy(&c->last_mouse, mouse, sizeof c->last_mouse); window_pane_mouse(wp, c->session, mouse); return; } @@ -474,15 +480,25 @@ server_client_reset_state(struct client *c) else tty_cursor(&c->tty, wp->xoff + s->cx, wp->yoff + s->cy); + /* + * Resizing panes with the mouse requires at least button mode to give + * a smooth appearance. + */ + mode = s->mode; + if ((c->last_mouse.b & MOUSE_RESIZE_PANE) && + !(mode & (MODE_MOUSE_BUTTON|MODE_MOUSE_ANY))) + mode |= MODE_MOUSE_BUTTON; + /* * Any mode will do for mouse-select-pane, but set standard mode if * none. */ - mode = s->mode; 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")) diff --git a/tmux.1 b/tmux.1 index c48bf761..3cbc5d11 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1,4 +1,4 @@ -.\" $Id: tmux.1,v 1.311 2011-05-18 20:28:40 tcunha Exp $ +.\" $Id: tmux.1,v 1.312 2011-05-18 20:30:14 tcunha Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott .\" @@ -1892,6 +1892,12 @@ Set status line message foreground colour. Set the number of error or information messages to save in the message log for each client. The default is 20. +.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 .Op Ic on | off .Xc diff --git a/tmux.h b/tmux.h index f5a76a47..8b992fe1 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $Id: tmux.h,v 1.622 2011-05-18 20:28:41 tcunha Exp $ */ +/* $Id: tmux.h,v 1.623 2011-05-18 20:30:14 tcunha Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -1082,6 +1082,7 @@ struct mouse_event { #define MOUSE_BUTTON 3 #define MOUSE_DRAG 32 #define MOUSE_45 64 +#define MOUSE_RESIZE_PANE 128 /* marker for resizing */ u_int x; u_int y; }; @@ -1173,6 +1174,8 @@ struct client { struct session *session; struct session *last_session; + struct mouse_event last_mouse; + int references; }; ARRAY_DECL(clients, struct client *); @@ -1921,6 +1924,8 @@ void layout_free(struct window *); void layout_resize(struct window *, u_int, u_int); void layout_resize_pane( struct window_pane *, enum layout_type, int); +void layout_resize_pane_mouse( + struct client *c, struct mouse_event *mouse); void layout_assign_pane(struct layout_cell *, struct window_pane *); struct layout_cell *layout_split_pane( struct window_pane *, enum layout_type, int);