From f6bad7efd76109de122bb3b670d0e18f86ec38bb Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 8 Jun 2018 20:54:22 +0000 Subject: [PATCH] Instead of working out which pane to resize with the mouse by walking the panes list, look through the layout cells for the nearest border and resize that cell. From Dan Aloni in GitHub issue 1374. --- cmd-resize-pane.c | 49 ++++++++----------------- layout.c | 91 ++++++++++++++++++++++++++++++++++------------- tmux.h | 3 ++ 3 files changed, 85 insertions(+), 58 deletions(-) diff --git a/cmd-resize-pane.c b/cmd-resize-pane.c index bbb78de7..cfde83b3 100644 --- a/cmd-resize-pane.c +++ b/cmd-resize-pane.c @@ -129,14 +129,16 @@ static void cmd_resize_pane_mouse_update(struct client *c, struct mouse_event *m) { struct winlink *wl; - struct window_pane *loop, *wp_x, *wp_y; - u_int y, ly, x, lx, sx, sy, ex, ey; + struct window *w; + u_int y, ly, x, lx; + struct layout_cell *lc; wl = cmd_mouse_window(m, NULL); if (wl == NULL) { c->tty.mouse_drag_update = NULL; return; } + w = wl->window; y = m->y; x = m->x; if (m->statusat == 0 && y > 0) @@ -149,37 +151,16 @@ cmd_resize_pane_mouse_update(struct client *c, struct mouse_event *m) else if (m->statusat > 0 && ly >= (u_int)m->statusat) ly = m->statusat - 1; - wp_x = wp_y = NULL; - TAILQ_FOREACH(loop, &wl->window->panes, entry) { - if (!window_pane_visible(loop)) - continue; - - sx = loop->xoff; - if (sx != 0) - sx--; - ex = loop->xoff + loop->sx; - - sy = loop->yoff; - if (sy != 0) - sy--; - ey = loop->yoff + loop->sy; - - if ((lx == sx || lx == ex) && - (ly >= sy && ly <= ey) && - (wp_x == NULL || loop->sy > wp_x->sy)) - wp_x = loop; - if ((ly == sy || ly == ey) && - (lx >= sx && lx <= ex) && - (wp_y == NULL || loop->sx > wp_y->sx)) - wp_y = loop; - } - if (wp_x == NULL && wp_y == NULL) { - c->tty.mouse_drag_update = NULL; + lc = layout_search_by_border(w->layout_root, lx, ly); + if (lc == NULL) return; - } - if (wp_x != NULL) - layout_resize_pane(wp_x, LAYOUT_LEFTRIGHT, x - lx, 0); - if (wp_y != NULL) - layout_resize_pane(wp_y, LAYOUT_TOPBOTTOM, y - ly, 0); - server_redraw_window(wl->window); + + if (y != ly && lc->parent->type == LAYOUT_TOPBOTTOM) + layout_resize_layout(w, lc, LAYOUT_TOPBOTTOM, y - ly, 0); + else if (x != lx && lc->parent->type == LAYOUT_LEFTRIGHT) + layout_resize_layout(w, lc, LAYOUT_LEFTRIGHT, x - lx, 0); + else + return; + + server_redraw_window(w); } diff --git a/layout.c b/layout.c index bab95868..e1112ffa 100644 --- a/layout.c +++ b/layout.c @@ -127,6 +127,42 @@ layout_print_cell(struct layout_cell *lc, const char *hdr, u_int n) } } +struct layout_cell * +layout_search_by_border(struct layout_cell *lc, u_int x, u_int y) +{ + struct layout_cell *lcchild, *last = NULL; + + TAILQ_FOREACH(lcchild, &lc->cells, entry) { + if (x >= lcchild->xoff && x < lcchild->xoff + lcchild->sx && + y >= lcchild->yoff && y < lcchild->yoff + lcchild->sy) { + /* Inside the cell - recurse. */ + return (layout_search_by_border(lcchild, x, y)); + } + + if (last == NULL) { + last = lcchild; + continue; + } + + switch (lc->type) { + case LAYOUT_LEFTRIGHT: + if (x < lcchild->xoff && x >= last->xoff + last->sx) + return (last); + break; + case LAYOUT_TOPBOTTOM: + if (y < lcchild->yoff && y >= last->yoff + last->sy) + return (last); + break; + case LAYOUT_WINDOWPANE: + break; + } + + last = lcchild; + } + + return (NULL); +} + void layout_set_size(struct layout_cell *lc, u_int sx, u_int sy, u_int xoff, u_int yoff) @@ -550,29 +586,11 @@ layout_resize_pane_to(struct window_pane *wp, enum layout_type type, layout_resize_pane(wp, type, change, 1); } -/* Resize a single pane within the layout. */ void -layout_resize_pane(struct window_pane *wp, enum layout_type type, int change, - int opposite) +layout_resize_layout(struct window *w, struct layout_cell *lc, + enum layout_type type, int change, int opposite) { - struct window *w = wp->window; - struct layout_cell *lc, *lcparent; - int needed, size; - - lc = wp->layout_cell; - - /* Find next parent of the same type. */ - lcparent = lc->parent; - while (lcparent != NULL && lcparent->type != type) { - lc = lcparent; - lcparent = lc->parent; - } - if (lcparent == NULL) - return; - - /* If this is the last cell, move back one. */ - if (lc == TAILQ_LAST(&lcparent->cells, layout_cells)) - lc = TAILQ_PREV(lc, layout_cells, entry); + int needed, size; /* Grow or shrink the cell. */ needed = change; @@ -591,9 +609,34 @@ layout_resize_pane(struct window_pane *wp, enum layout_type type, int change, } /* Fix cell offsets. */ - layout_fix_offsets(wp->window->layout_root); - layout_fix_panes(wp->window, wp->window->sx, wp->window->sy); - notify_window("window-layout-changed", wp->window); + layout_fix_offsets(w->layout_root); + layout_fix_panes(w, w->sx, w->sy); + notify_window("window-layout-changed", w); +} + +/* Resize a single pane within the layout. */ +void +layout_resize_pane(struct window_pane *wp, enum layout_type type, int change, + int opposite) +{ + struct layout_cell *lc, *lcparent; + + lc = wp->layout_cell; + + /* Find next parent of the same type. */ + lcparent = lc->parent; + while (lcparent != NULL && lcparent->type != type) { + lc = lcparent; + lcparent = lc->parent; + } + if (lcparent == NULL) + return; + + /* If this is the last cell, move back one. */ + if (lc == TAILQ_LAST(&lcparent->cells, layout_cells)) + lc = TAILQ_PREV(lc, layout_cells, entry); + + layout_resize_layout(wp->window, lc, type, change, opposite); } /* Helper function to grow pane. */ diff --git a/tmux.h b/tmux.h index d46dca2e..d6e4ae0b 100644 --- a/tmux.h +++ b/tmux.h @@ -2203,6 +2203,9 @@ void layout_free_cell(struct layout_cell *); void layout_print_cell(struct layout_cell *, const char *, u_int); void layout_destroy_cell(struct window *, struct layout_cell *, struct layout_cell **); +void layout_resize_layout(struct window *, struct layout_cell *, + enum layout_type, int, int); +struct layout_cell *layout_search_by_border(struct layout_cell *, u_int, u_int); void layout_set_size(struct layout_cell *, u_int, u_int, u_int, u_int); void layout_make_leaf(struct layout_cell *, struct window_pane *);