From 3b649d2fcdc8a15c69efbce69ae9e559481d36cb Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 15 Nov 2017 19:59:27 +0000 Subject: Add a common function for spreading out cells and use it for the two even layouts and to add a -E flag to select-layout to spread out cells evenly without changing parent cells. --- cmd-select-layout.c | 27 +++++++++++------- key-bindings.c | 1 + layout-set.c | 82 ++++++++--------------------------------------------- layout.c | 58 +++++++++++++++++++++++++++++++++++++ tmux.1 | 6 ++-- tmux.h | 2 ++ 6 files changed, 93 insertions(+), 83 deletions(-) diff --git a/cmd-select-layout.c b/cmd-select-layout.c index e32f115d..28737c18 100644 --- a/cmd-select-layout.c +++ b/cmd-select-layout.c @@ -33,10 +33,10 @@ const struct cmd_entry cmd_select_layout_entry = { .name = "select-layout", .alias = "selectl", - .args = { "nopt:", 0, 1 }, - .usage = "[-nop] " CMD_TARGET_WINDOW_USAGE " [layout-name]", + .args = { "Enopt:", 0, 1 }, + .usage = "[-Enop] " CMD_TARGET_PANE_USAGE " [layout-name]", - .target = { 't', CMD_FIND_WINDOW, 0 }, + .target = { 't', CMD_FIND_PANE, 0 }, .flags = CMD_AFTERHOOK, .exec = cmd_select_layout_exec @@ -71,14 +71,14 @@ const struct cmd_entry cmd_previous_layout_entry = { static enum cmd_retval cmd_select_layout_exec(struct cmd *self, struct cmdq_item *item) { - struct args *args = self->args; - struct winlink *wl = item->target.wl; - struct window *w; - const char *layoutname; - char *oldlayout; - int next, previous, layout; - - w = wl->window; + struct args *args = self->args; + struct winlink *wl = item->target.wl; + struct window *w = wl->window; + struct window_pane *wp = item->target.wp; + const char *layoutname; + char *oldlayout; + int next, previous, layout; + server_unzoom_window(w); next = self->entry == &cmd_next_layout_entry; @@ -99,6 +99,11 @@ cmd_select_layout_exec(struct cmd *self, struct cmdq_item *item) goto changed; } + if (args_has(args, 'E')) { + layout_spread_out(wp); + goto changed; + } + if (!args_has(args, 'o')) { if (args->argc == 0) layout = w->lastlayout; diff --git a/key-bindings.c b/key-bindings.c index 76778009..a13c7977 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -186,6 +186,7 @@ key_bindings_init(void) "bind = choose-buffer", "bind ? list-keys", "bind D choose-client", + "bind E select-layout -E", "bind L switch-client -l", "bind M select-pane -M", "bind [ copy-mode", diff --git a/layout-set.c b/layout-set.c index 7ba18fea..0f01cbcc 100644 --- a/layout-set.c +++ b/layout-set.c @@ -115,11 +115,11 @@ layout_set_previous(struct window *w) } static void -layout_set_even_h(struct window *w) +layout_set_even(struct window *w, enum layout_type type) { struct window_pane *wp; struct layout_cell *lc, *lcnew; - u_int i, n, width, xoff; + u_int n; layout_print_cell(w->layout_root, __func__, 1); @@ -128,36 +128,21 @@ layout_set_even_h(struct window *w) if (n <= 1) return; - /* How many can we fit? */ - width = (w->sx - (n - 1)) / n; - if (width < PANE_MINIMUM) - width = PANE_MINIMUM; - /* Free the old root and construct a new. */ layout_free(w); lc = w->layout_root = layout_create_cell(NULL); layout_set_size(lc, w->sx, w->sy, 0, 0); - layout_make_node(lc, LAYOUT_LEFTRIGHT); + layout_make_node(lc, type); /* Build new leaf cells. */ - i = xoff = 0; TAILQ_FOREACH(wp, &w->panes, entry) { - /* Create child cell. */ lcnew = layout_create_cell(lc); - layout_set_size(lcnew, width, w->sy, xoff, 0); layout_make_leaf(lcnew, wp); TAILQ_INSERT_TAIL(&lc->cells, lcnew, entry); - - i++; - xoff += width + 1; } - /* Allocate any remaining space. */ - if (w->sx > xoff - 1) { - lc = TAILQ_LAST(&lc->cells, layout_cells); - layout_resize_adjust(w, lc, LAYOUT_LEFTRIGHT, - w->sx - (xoff - 1)); - } + /* Spread out cells. */ + layout_spread_cell(w, lc); /* Fix cell offsets. */ layout_fix_offsets(lc); @@ -170,58 +155,15 @@ layout_set_even_h(struct window *w) } static void -layout_set_even_v(struct window *w) +layout_set_even_h(struct window *w) { - struct window_pane *wp; - struct layout_cell *lc, *lcnew; - u_int i, n, height, yoff; - - layout_print_cell(w->layout_root, __func__, 1); - - /* Get number of panes. */ - n = window_count_panes(w); - if (n <= 1) - return; - - /* How many can we fit? */ - height = (w->sy - (n - 1)) / n; - if (height < PANE_MINIMUM) - height = PANE_MINIMUM; - - /* Free the old root and construct a new. */ - layout_free(w); - lc = w->layout_root = layout_create_cell(NULL); - layout_set_size(lc, w->sx, w->sy, 0, 0); - layout_make_node(lc, LAYOUT_TOPBOTTOM); - - /* Build new leaf cells. */ - i = yoff = 0; - TAILQ_FOREACH(wp, &w->panes, entry) { - /* Create child cell. */ - lcnew = layout_create_cell(lc); - layout_set_size(lcnew, w->sx, height, 0, yoff); - layout_make_leaf(lcnew, wp); - TAILQ_INSERT_TAIL(&lc->cells, lcnew, entry); - - i++; - yoff += height + 1; - } - - /* Allocate any remaining space. */ - if (w->sy > yoff - 1) { - lc = TAILQ_LAST(&lc->cells, layout_cells); - layout_resize_adjust(w, lc, LAYOUT_TOPBOTTOM, - w->sy - (yoff - 1)); - } - - /* Fix cell offsets. */ - layout_fix_offsets(lc); - layout_fix_panes(w, w->sx, w->sy); - - layout_print_cell(w->layout_root, __func__, 1); + layout_set_even(w, LAYOUT_LEFTRIGHT); +} - notify_window("window-layout-changed", w); - server_redraw_window(w); +static void +layout_set_even_v(struct window *w) +{ + layout_set_even(w, LAYOUT_TOPBOTTOM); } static void diff --git a/layout.c b/layout.c index 5c2224bb..2c6fe2b2 100644 --- a/layout.c +++ b/layout.c @@ -983,3 +983,61 @@ layout_close_pane(struct window_pane *wp) } notify_window("window-layout-changed", w); } + +int +layout_spread_cell(struct window *w, struct layout_cell *parent) +{ + struct layout_cell *lc; + u_int number, each, size; + int change, changed; + + number = 0; + TAILQ_FOREACH (lc, &parent->cells, entry) + number++; + if (number <= 1) + return (0); + + if (parent->type == LAYOUT_LEFTRIGHT) + size = parent->sx; + else if (parent->type == LAYOUT_TOPBOTTOM) + size = parent->sy; + else + return (0); + each = (size - (number - 1)) / number; + + changed = 0; + TAILQ_FOREACH (lc, &parent->cells, entry) { + if (TAILQ_NEXT(lc, entry) == NULL) + each = size - (each * (number - 1)); + change = 0; + if (parent->type == LAYOUT_LEFTRIGHT) { + change = each - (int)lc->sx; + layout_resize_adjust(w, lc, LAYOUT_LEFTRIGHT, change); + } else if (parent->type == LAYOUT_TOPBOTTOM) { + change = each - (int)lc->sy; + layout_resize_adjust(w, lc, LAYOUT_TOPBOTTOM, change); + } + if (change != 0) + changed = 1; + } + return (changed); +} + +void +layout_spread_out(struct window_pane *wp) +{ + struct layout_cell *parent; + struct window *w = wp->window; + + parent = wp->layout_cell->parent; + if (parent == NULL) + return; + + do { + if (layout_spread_cell(w, parent)) { + layout_fix_offsets(parent); + layout_fix_panes(w, w->sx, w->sy); + break; + } + } while ((parent = parent->parent) != NULL); +} diff --git a/tmux.1 b/tmux.1 index a67a7274..4451283f 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1923,8 +1923,8 @@ lower) with .Fl U or downward (numerically higher). .It Xo Ic select-layout -.Op Fl nop -.Op Fl t Ar target-window +.Op Fl Enop +.Op Fl t Ar target-pane .Op Ar layout-name .Xc .D1 (alias: Ic selectl ) @@ -1942,6 +1942,8 @@ and commands. .Fl o applies the last set layout if possible (undoes the most recent layout change). +.Fl E +spreads the current pane and any panes next to it out evenly. .It Xo Ic select-pane .Op Fl DdegLlMmRU .Op Fl P Ar style diff --git a/tmux.h b/tmux.h index 6381ff00..43d9d846 100644 --- a/tmux.h +++ b/tmux.h @@ -2213,6 +2213,8 @@ void layout_assign_pane(struct layout_cell *, struct window_pane *); struct layout_cell *layout_split_pane(struct window_pane *, enum layout_type, int, int, int); void layout_close_pane(struct window_pane *); +int layout_spread_cell(struct window *, struct layout_cell *); +void layout_spread_out(struct window_pane *); /* layout-custom.c */ char *layout_dump(struct layout_cell *); -- cgit v1.2.3