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.
This commit is contained in:
nicm 2017-11-15 19:59:27 +00:00
parent 533a5719c5
commit 3b649d2fcd
6 changed files with 92 additions and 82 deletions

View File

@ -33,10 +33,10 @@ const struct cmd_entry cmd_select_layout_entry = {
.name = "select-layout", .name = "select-layout",
.alias = "selectl", .alias = "selectl",
.args = { "nopt:", 0, 1 }, .args = { "Enopt:", 0, 1 },
.usage = "[-nop] " CMD_TARGET_WINDOW_USAGE " [layout-name]", .usage = "[-Enop] " CMD_TARGET_PANE_USAGE " [layout-name]",
.target = { 't', CMD_FIND_WINDOW, 0 }, .target = { 't', CMD_FIND_PANE, 0 },
.flags = CMD_AFTERHOOK, .flags = CMD_AFTERHOOK,
.exec = cmd_select_layout_exec .exec = cmd_select_layout_exec
@ -71,14 +71,14 @@ const struct cmd_entry cmd_previous_layout_entry = {
static enum cmd_retval static enum cmd_retval
cmd_select_layout_exec(struct cmd *self, struct cmdq_item *item) cmd_select_layout_exec(struct cmd *self, struct cmdq_item *item)
{ {
struct args *args = self->args; struct args *args = self->args;
struct winlink *wl = item->target.wl; struct winlink *wl = item->target.wl;
struct window *w; struct window *w = wl->window;
const char *layoutname; struct window_pane *wp = item->target.wp;
char *oldlayout; const char *layoutname;
int next, previous, layout; char *oldlayout;
int next, previous, layout;
w = wl->window;
server_unzoom_window(w); server_unzoom_window(w);
next = self->entry == &cmd_next_layout_entry; next = self->entry == &cmd_next_layout_entry;
@ -99,6 +99,11 @@ cmd_select_layout_exec(struct cmd *self, struct cmdq_item *item)
goto changed; goto changed;
} }
if (args_has(args, 'E')) {
layout_spread_out(wp);
goto changed;
}
if (!args_has(args, 'o')) { if (!args_has(args, 'o')) {
if (args->argc == 0) if (args->argc == 0)
layout = w->lastlayout; layout = w->lastlayout;

View File

@ -186,6 +186,7 @@ key_bindings_init(void)
"bind = choose-buffer", "bind = choose-buffer",
"bind ? list-keys", "bind ? list-keys",
"bind D choose-client", "bind D choose-client",
"bind E select-layout -E",
"bind L switch-client -l", "bind L switch-client -l",
"bind M select-pane -M", "bind M select-pane -M",
"bind [ copy-mode", "bind [ copy-mode",

View File

@ -115,11 +115,11 @@ layout_set_previous(struct window *w)
} }
static void static void
layout_set_even_h(struct window *w) layout_set_even(struct window *w, enum layout_type type)
{ {
struct window_pane *wp; struct window_pane *wp;
struct layout_cell *lc, *lcnew; struct layout_cell *lc, *lcnew;
u_int i, n, width, xoff; u_int n;
layout_print_cell(w->layout_root, __func__, 1); layout_print_cell(w->layout_root, __func__, 1);
@ -128,36 +128,21 @@ layout_set_even_h(struct window *w)
if (n <= 1) if (n <= 1)
return; 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. */ /* Free the old root and construct a new. */
layout_free(w); layout_free(w);
lc = w->layout_root = layout_create_cell(NULL); lc = w->layout_root = layout_create_cell(NULL);
layout_set_size(lc, w->sx, w->sy, 0, 0); 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. */ /* Build new leaf cells. */
i = xoff = 0;
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
/* Create child cell. */
lcnew = layout_create_cell(lc); lcnew = layout_create_cell(lc);
layout_set_size(lcnew, width, w->sy, xoff, 0);
layout_make_leaf(lcnew, wp); layout_make_leaf(lcnew, wp);
TAILQ_INSERT_TAIL(&lc->cells, lcnew, entry); TAILQ_INSERT_TAIL(&lc->cells, lcnew, entry);
i++;
xoff += width + 1;
} }
/* Allocate any remaining space. */ /* Spread out cells. */
if (w->sx > xoff - 1) { layout_spread_cell(w, lc);
lc = TAILQ_LAST(&lc->cells, layout_cells);
layout_resize_adjust(w, lc, LAYOUT_LEFTRIGHT,
w->sx - (xoff - 1));
}
/* Fix cell offsets. */ /* Fix cell offsets. */
layout_fix_offsets(lc); layout_fix_offsets(lc);
@ -169,59 +154,16 @@ layout_set_even_h(struct window *w)
server_redraw_window(w); server_redraw_window(w);
} }
static void
layout_set_even_h(struct window *w)
{
layout_set_even(w, LAYOUT_LEFTRIGHT);
}
static void static void
layout_set_even_v(struct window *w) layout_set_even_v(struct window *w)
{ {
struct window_pane *wp; layout_set_even(w, LAYOUT_TOPBOTTOM);
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);
notify_window("window-layout-changed", w);
server_redraw_window(w);
} }
static void static void

View File

@ -983,3 +983,61 @@ layout_close_pane(struct window_pane *wp)
} }
notify_window("window-layout-changed", w); 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);
}

6
tmux.1
View File

@ -1923,8 +1923,8 @@ lower) with
.Fl U .Fl U
or downward (numerically higher). or downward (numerically higher).
.It Xo Ic select-layout .It Xo Ic select-layout
.Op Fl nop .Op Fl Enop
.Op Fl t Ar target-window .Op Fl t Ar target-pane
.Op Ar layout-name .Op Ar layout-name
.Xc .Xc
.D1 (alias: Ic selectl ) .D1 (alias: Ic selectl )
@ -1942,6 +1942,8 @@ and
commands. commands.
.Fl o .Fl o
applies the last set layout if possible (undoes the most recent layout change). 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 .It Xo Ic select-pane
.Op Fl DdegLlMmRU .Op Fl DdegLlMmRU
.Op Fl P Ar style .Op Fl P Ar style

2
tmux.h
View File

@ -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, struct layout_cell *layout_split_pane(struct window_pane *, enum layout_type,
int, int, int); int, int, int);
void layout_close_pane(struct window_pane *); 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 */ /* layout-custom.c */
char *layout_dump(struct layout_cell *); char *layout_dump(struct layout_cell *);