Change layout sets to build the layout using the new mechanics, from

Dane Jensen.
This commit is contained in:
nicm
2026-07-01 16:43:14 +00:00
parent 565db46a19
commit 824ef37f5f
6 changed files with 178 additions and 192 deletions

View File

@@ -265,7 +265,7 @@ layout_parse(struct window *w, const char *layout, char **cause)
window_resize(w, tiled_lc->sx, tiled_lc->sy, -1, -1); window_resize(w, tiled_lc->sx, tiled_lc->sy, -1, -1);
/* Destroy the old layout and swap to the new. */ /* Destroy the old layout and swap to the new. */
layout_free_cell(w->layout_root); layout_free_cell(w->layout_root, 0);
w->layout_root = tiled_lc; w->layout_root = tiled_lc;
/* Assign the panes into the cells. */ /* Assign the panes into the cells. */
@@ -291,7 +291,7 @@ layout_parse(struct window *w, const char *layout, char **cause)
return (0); return (0);
fail: fail:
layout_free_cell(tiled_lc); layout_free_cell(tiled_lc, 0);
return (-1); return (-1);
} }
@@ -423,6 +423,6 @@ layout_construct(struct layout_cell *lcparent, const char **layout,
return (0); return (0);
fail: fail:
layout_free_cell(*lc); layout_free_cell(*lc, 0);
return (-1); return (-1);
} }

View File

@@ -124,12 +124,12 @@ layout_set_previous(struct window *w)
} }
static struct window_pane * static struct window_pane *
layout_first_tiled(struct window *w) layout_set_first_tiled(struct window *w)
{ {
struct window_pane *wp; struct window_pane *wp;
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (!window_pane_is_floating(wp)) if (wp->layout_cell && layout_cell_is_tiled(wp->layout_cell))
return (wp); return (wp);
} }
return (NULL); return (NULL);
@@ -139,19 +139,15 @@ static void
layout_set_even(struct window *w, enum layout_type type) 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 *lcroot, *lcchild;
u_int n, sx, sy; u_int n, sx, sy;
layout_print_cell(w->layout_root, __func__, 1); layout_print_cell(w->layout_root, __func__, 1);
/* Get number of panes. */
n = window_count_panes(w, 0); n = window_count_panes(w, 0);
if (n <= 1) if (n <= 1)
return; return;
/* Free the old root and construct a new. */
layout_free(w);
lc = w->layout_root = layout_create_cell(NULL);
if (type == LAYOUT_LEFTRIGHT) { if (type == LAYOUT_LEFTRIGHT) {
sx = (n * (PANE_MINIMUM + 1)) - 1; sx = (n * (PANE_MINIMUM + 1)) - 1;
if (sx < w->sx) if (sx < w->sx)
@@ -163,30 +159,30 @@ layout_set_even(struct window *w, enum layout_type type)
sy = w->sy; sy = w->sy;
sx = w->sx; sx = w->sx;
} }
layout_set_size(lc, sx, sy, 0, 0);
layout_make_node(lc, type);
/* Build new leaf cells. */ layout_free(w, 1);
lcroot = w->layout_root = layout_create_cell(NULL);
layout_set_size(lcroot, sx, sy, 0, 0);
layout_make_node(lcroot, type);
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (window_pane_is_floating(wp)) lcchild = wp->layout_cell;
continue; TAILQ_INSERT_TAIL(&lcroot->cells, lcchild, entry);
lcnew = layout_create_cell(lc); lcchild->parent = lcroot;
layout_make_leaf(lcnew, wp); if (layout_cell_is_tiled(lcchild)) {
lcnew->sx = w->sx; lcchild->sx = w->sx;
lcnew->sy = w->sy; lcchild->sy = w->sy;
TAILQ_INSERT_TAIL(&lc->cells, lcnew, entry); }
} }
/* Spread out cells. */ layout_spread_cell(w, lcroot);
layout_spread_cell(w, lc);
/* Fix cell offsets. */
layout_fix_offsets(w); layout_fix_offsets(w);
layout_fix_panes(w, NULL); layout_fix_panes(w, NULL);
layout_print_cell(w->layout_root, __func__, 1); layout_print_cell(w->layout_root, __func__, 1);
window_resize(w, lc->sx, lc->sy, -1, -1); window_resize(w, lcroot->sx, lcroot->sy, -1, -1);
notify_window("window-layout-changed", w); notify_window("window-layout-changed", w);
server_redraw_window(w); server_redraw_window(w);
} }
@@ -206,15 +202,14 @@ layout_set_even_v(struct window *w)
static void static void
layout_set_main_h(struct window *w) layout_set_main_h(struct window *w)
{ {
struct window_pane *wp; struct window_pane *wp, *wpmain;
struct layout_cell *lc, *lcmain, *lcother, *lcchild; struct layout_cell *lcroot, *lcmain, *lcother, *lcchild;
u_int n, mainh, otherh, sx, sy; u_int n, mainh, otherh, sx, sy;
char *cause; char *cause;
const char *s; const char *s;
layout_print_cell(w->layout_root, __func__, 1); layout_print_cell(w->layout_root, __func__, 1);
/* Get number of panes. */
n = window_count_panes(w, 0); n = window_count_panes(w, 0);
if (n <= 1) if (n <= 1)
return; return;
@@ -255,52 +250,48 @@ layout_set_main_h(struct window *w)
if (sx < w->sx) if (sx < w->sx)
sx = w->sx; sx = w->sx;
/* Free old tree and create a new root. */ layout_free(w, 1);
layout_free(w); lcroot = w->layout_root = layout_create_cell(NULL);
lc = w->layout_root = layout_create_cell(NULL); layout_set_size(lcroot, sx, mainh + otherh + 1, 0, 0);
layout_set_size(lc, sx, mainh + otherh + 1, 0, 0); layout_make_node(lcroot, LAYOUT_TOPBOTTOM);
layout_make_node(lc, LAYOUT_TOPBOTTOM);
/* Create the main pane. */ wpmain = layout_set_first_tiled(w);
lcmain = layout_create_cell(lc); lcmain = wpmain->layout_cell;
lcmain->parent = lcroot;
layout_set_size(lcmain, sx, mainh, 0, 0); layout_set_size(lcmain, sx, mainh, 0, 0);
layout_make_leaf(lcmain, layout_first_tiled(w)); TAILQ_INSERT_TAIL(&lcroot->cells, lcmain, entry);
TAILQ_INSERT_TAIL(&lc->cells, lcmain, entry);
/* Create the other pane. */
lcother = layout_create_cell(lc);
layout_set_size(lcother, sx, otherh, 0, 0);
if (n == 1) { if (n == 1) {
wp = TAILQ_NEXT(layout_first_tiled(w), entry); wp = TAILQ_NEXT(wpmain, entry);
while (wp != NULL && window_pane_is_floating(wp)) while (wp != NULL && !layout_cell_is_tiled(wp->layout_cell))
wp = TAILQ_NEXT(wp, entry); wp = TAILQ_NEXT(wp, entry);
layout_make_leaf(lcother, wp); TAILQ_INSERT_TAIL(&lcroot->cells, wp->layout_cell, entry);
TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); wp->layout_cell->parent = lcroot;
} else { } else {
lcother = layout_create_cell(lcroot);
layout_set_size(lcother, sx, otherh, 0, 0);
layout_make_node(lcother, LAYOUT_LEFTRIGHT); layout_make_node(lcother, LAYOUT_LEFTRIGHT);
TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); TAILQ_INSERT_TAIL(&lcroot->cells, lcother, entry);
/* Add the remaining panes as children. */
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (window_pane_is_floating(wp)) if (wp == wpmain)
continue; continue;
if (wp == layout_first_tiled(w)) lcchild = wp->layout_cell;
continue;
lcchild = layout_create_cell(lcother);
layout_set_size(lcchild, PANE_MINIMUM, otherh, 0, 0);
layout_make_leaf(lcchild, wp);
TAILQ_INSERT_TAIL(&lcother->cells, lcchild, entry); TAILQ_INSERT_TAIL(&lcother->cells, lcchild, entry);
lcchild->parent = lcother;
if (layout_cell_is_tiled(lcchild))
layout_set_size(lcchild, PANE_MINIMUM, otherh,
0, 0);
} }
layout_spread_cell(w, lcother); layout_spread_cell(w, lcother);
} }
/* Fix cell offsets. */
layout_fix_offsets(w); layout_fix_offsets(w);
layout_fix_panes(w, NULL); layout_fix_panes(w, NULL);
layout_print_cell(w->layout_root, __func__, 1); layout_print_cell(w->layout_root, __func__, 1);
window_resize(w, lc->sx, lc->sy, -1, -1); window_resize(w, lcroot->sx, lcroot->sy, -1, -1);
notify_window("window-layout-changed", w); notify_window("window-layout-changed", w);
server_redraw_window(w); server_redraw_window(w);
} }
@@ -308,15 +299,14 @@ layout_set_main_h(struct window *w)
static void static void
layout_set_main_h_mirrored(struct window *w) layout_set_main_h_mirrored(struct window *w)
{ {
struct window_pane *wp; struct window_pane *wp, *wpmain;
struct layout_cell *lc, *lcmain, *lcother, *lcchild; struct layout_cell *lcroot, *lcmain, *lcother, *lcchild;
u_int n, mainh, otherh, sx, sy; u_int n, mainh, otherh, sx, sy;
char *cause; char *cause;
const char *s; const char *s;
layout_print_cell(w->layout_root, __func__, 1); layout_print_cell(w->layout_root, __func__, 1);
/* Get number of panes. */
n = window_count_panes(w, 0); n = window_count_panes(w, 0);
if (n <= 1) if (n <= 1)
return; return;
@@ -357,52 +347,48 @@ layout_set_main_h_mirrored(struct window *w)
if (sx < w->sx) if (sx < w->sx)
sx = w->sx; sx = w->sx;
/* Free old tree and create a new root. */ layout_free(w, 1);
layout_free(w); lcroot = w->layout_root = layout_create_cell(NULL);
lc = w->layout_root = layout_create_cell(NULL); layout_set_size(lcroot, sx, mainh + otherh + 1, 0, 0);
layout_set_size(lc, sx, mainh + otherh + 1, 0, 0); layout_make_node(lcroot, LAYOUT_TOPBOTTOM);
layout_make_node(lc, LAYOUT_TOPBOTTOM);
wpmain = layout_set_first_tiled(w);
lcmain = wpmain->layout_cell;
lcmain->parent = lcroot;
layout_set_size(lcmain, sx, mainh, 0, 0);
TAILQ_INSERT_TAIL(&lcroot->cells, lcmain, entry);
/* Create the other pane. */
lcother = layout_create_cell(lc);
layout_set_size(lcother, sx, otherh, 0, 0);
if (n == 1) { if (n == 1) {
wp = TAILQ_NEXT(layout_first_tiled(w), entry); wp = TAILQ_NEXT(wpmain, entry);
while (wp != NULL && window_pane_is_floating(wp)) while (wp != NULL && !layout_cell_is_tiled(wp->layout_cell))
wp = TAILQ_NEXT(wp, entry); wp = TAILQ_NEXT(wp, entry);
layout_make_leaf(lcother, wp); TAILQ_INSERT_HEAD(&lcroot->cells, wp->layout_cell, entry);
TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); wp->layout_cell->parent = lcroot;
} else { } else {
lcother = layout_create_cell(lcroot);
layout_set_size(lcother, sx, otherh, 0, 0);
layout_make_node(lcother, LAYOUT_LEFTRIGHT); layout_make_node(lcother, LAYOUT_LEFTRIGHT);
TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); TAILQ_INSERT_HEAD(&lcroot->cells, lcother, entry);
/* Add the remaining panes as children. */
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (window_pane_is_floating(wp)) if (wp == wpmain)
continue; continue;
if (wp == layout_first_tiled(w)) lcchild = wp->layout_cell;
continue;
lcchild = layout_create_cell(lcother);
layout_set_size(lcchild, PANE_MINIMUM, otherh, 0, 0);
layout_make_leaf(lcchild, wp);
TAILQ_INSERT_TAIL(&lcother->cells, lcchild, entry); TAILQ_INSERT_TAIL(&lcother->cells, lcchild, entry);
lcchild->parent = lcother;
if (layout_cell_is_tiled(lcchild))
layout_set_size(lcchild, PANE_MINIMUM, otherh,
0, 0);
} }
layout_spread_cell(w, lcother); layout_spread_cell(w, lcother);
} }
/* Create the main pane. */
lcmain = layout_create_cell(lc);
layout_set_size(lcmain, sx, mainh, 0, 0);
layout_make_leaf(lcmain, layout_first_tiled(w));
TAILQ_INSERT_TAIL(&lc->cells, lcmain, entry);
/* Fix cell offsets. */
layout_fix_offsets(w); layout_fix_offsets(w);
layout_fix_panes(w, NULL); layout_fix_panes(w, NULL);
layout_print_cell(w->layout_root, __func__, 1); layout_print_cell(w->layout_root, __func__, 1);
window_resize(w, lc->sx, lc->sy, -1, -1); window_resize(w, lcroot->sx, lcroot->sy, -1, -1);
notify_window("window-layout-changed", w); notify_window("window-layout-changed", w);
server_redraw_window(w); server_redraw_window(w);
} }
@@ -410,21 +396,20 @@ layout_set_main_h_mirrored(struct window *w)
static void static void
layout_set_main_v(struct window *w) layout_set_main_v(struct window *w)
{ {
struct window_pane *wp; struct window_pane *wp, *wpmain;
struct layout_cell *lc, *lcmain, *lcother, *lcchild; struct layout_cell *lcroot, *lcmain, *lcother, *lcchild;
u_int n, mainw, otherw, sx, sy; u_int n, mainw, otherw, sx, sy;
char *cause; char *cause;
const char *s; const char *s;
layout_print_cell(w->layout_root, __func__, 1); layout_print_cell(w->layout_root, __func__, 1);
/* Get number of panes. */
n = window_count_panes(w, 0); n = window_count_panes(w, 0);
if (n <= 1) if (n <= 1)
return; return;
n--; /* take off main pane */ n--; /* take off main pane */
/* Find available width - take off one line for the border. */ /* Find available width - take off one column for the border. */
sx = w->sx - 1; sx = w->sx - 1;
/* Get the main pane width. */ /* Get the main pane width. */
@@ -459,52 +444,48 @@ layout_set_main_v(struct window *w)
if (sy < w->sy) if (sy < w->sy)
sy = w->sy; sy = w->sy;
/* Free old tree and create a new root. */ layout_free(w, 1);
layout_free(w); lcroot = w->layout_root = layout_create_cell(NULL);
lc = w->layout_root = layout_create_cell(NULL); layout_set_size(lcroot, mainw + otherw + 1, sy, 0, 0);
layout_set_size(lc, mainw + otherw + 1, sy, 0, 0); layout_make_node(lcroot, LAYOUT_LEFTRIGHT);
layout_make_node(lc, LAYOUT_LEFTRIGHT);
/* Create the main pane. */ wpmain = layout_set_first_tiled(w);
lcmain = layout_create_cell(lc); lcmain = wpmain->layout_cell;
lcmain->parent = lcroot;
layout_set_size(lcmain, mainw, sy, 0, 0); layout_set_size(lcmain, mainw, sy, 0, 0);
layout_make_leaf(lcmain, layout_first_tiled(w)); TAILQ_INSERT_TAIL(&lcroot->cells, lcmain, entry);
TAILQ_INSERT_TAIL(&lc->cells, lcmain, entry);
/* Create the other pane. */
lcother = layout_create_cell(lc);
layout_set_size(lcother, otherw, sy, 0, 0);
if (n == 1) { if (n == 1) {
wp = TAILQ_NEXT(layout_first_tiled(w), entry); wp = TAILQ_NEXT(wpmain, entry);
while (wp != NULL && window_pane_is_floating(wp)) while (wp != NULL && !layout_cell_is_tiled(wp->layout_cell))
wp = TAILQ_NEXT(wp, entry); wp = TAILQ_NEXT(wp, entry);
layout_make_leaf(lcother, wp); TAILQ_INSERT_TAIL(&lcroot->cells, wp->layout_cell, entry);
TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); wp->layout_cell->parent = lcroot;
} else { } else {
lcother = layout_create_cell(lcroot);
layout_make_node(lcother, LAYOUT_TOPBOTTOM); layout_make_node(lcother, LAYOUT_TOPBOTTOM);
TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); layout_set_size(lcother, otherw, sy, 0, 0);
TAILQ_INSERT_TAIL(&lcroot->cells, lcother, entry);
/* Add the remaining panes as children. */
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (window_pane_is_floating(wp)) if (wp == wpmain)
continue; continue;
if (wp == layout_first_tiled(w)) lcchild = wp->layout_cell;
continue;
lcchild = layout_create_cell(lcother);
layout_set_size(lcchild, otherw, PANE_MINIMUM, 0, 0);
layout_make_leaf(lcchild, wp);
TAILQ_INSERT_TAIL(&lcother->cells, lcchild, entry); TAILQ_INSERT_TAIL(&lcother->cells, lcchild, entry);
lcchild->parent = lcother;
if (layout_cell_is_tiled(lcchild))
layout_set_size(lcchild, otherw, PANE_MINIMUM,
0, 0);
} }
layout_spread_cell(w, lcother); layout_spread_cell(w, lcother);
} }
/* Fix cell offsets. */
layout_fix_offsets(w); layout_fix_offsets(w);
layout_fix_panes(w, NULL); layout_fix_panes(w, NULL);
layout_print_cell(w->layout_root, __func__, 1); layout_print_cell(w->layout_root, __func__, 1);
window_resize(w, lc->sx, lc->sy, -1, -1); window_resize(w, lcroot->sx, lcroot->sy, -1, -1);
notify_window("window-layout-changed", w); notify_window("window-layout-changed", w);
server_redraw_window(w); server_redraw_window(w);
} }
@@ -512,8 +493,8 @@ layout_set_main_v(struct window *w)
static void static void
layout_set_main_v_mirrored(struct window *w) layout_set_main_v_mirrored(struct window *w)
{ {
struct window_pane *wp; struct window_pane *wp, *wpmain;
struct layout_cell *lc, *lcmain, *lcother, *lcchild; struct layout_cell *lcroot, *lcmain, *lcother, *lcchild;
u_int n, mainw, otherw, sx, sy; u_int n, mainw, otherw, sx, sy;
char *cause; char *cause;
const char *s; const char *s;
@@ -526,7 +507,7 @@ layout_set_main_v_mirrored(struct window *w)
return; return;
n--; /* take off main pane */ n--; /* take off main pane */
/* Find available width - take off one line for the border. */ /* Find available width - take off one column for the border. */
sx = w->sx - 1; sx = w->sx - 1;
/* Get the main pane width. */ /* Get the main pane width. */
@@ -561,62 +542,58 @@ layout_set_main_v_mirrored(struct window *w)
if (sy < w->sy) if (sy < w->sy)
sy = w->sy; sy = w->sy;
/* Free old tree and create a new root. */ layout_free(w, 1);
layout_free(w); lcroot = w->layout_root = layout_create_cell(NULL);
lc = w->layout_root = layout_create_cell(NULL); layout_set_size(lcroot, mainw + otherw + 1, sy, 0, 0);
layout_set_size(lc, mainw + otherw + 1, sy, 0, 0); layout_make_node(lcroot, LAYOUT_LEFTRIGHT);
layout_make_node(lc, LAYOUT_LEFTRIGHT);
wpmain = layout_set_first_tiled(w);
lcmain = wpmain->layout_cell;
lcmain->parent = lcroot;
layout_set_size(lcmain, mainw, sy, 0, 0);
TAILQ_INSERT_TAIL(&lcroot->cells, lcmain, entry);
/* Create the other pane. */
lcother = layout_create_cell(lc);
layout_set_size(lcother, otherw, sy, 0, 0);
if (n == 1) { if (n == 1) {
wp = TAILQ_NEXT(layout_first_tiled(w), entry); wp = TAILQ_NEXT(wpmain, entry);
while (wp != NULL && window_pane_is_floating(wp)) while (wp != NULL && !layout_cell_is_tiled(wp->layout_cell))
wp = TAILQ_NEXT(wp, entry); wp = TAILQ_NEXT(wp, entry);
layout_make_leaf(lcother, wp); TAILQ_INSERT_HEAD(&lcroot->cells, wp->layout_cell, entry);
TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); wp->layout_cell->parent = lcroot;
} else { } else {
lcother = layout_create_cell(lcroot);
layout_make_node(lcother, LAYOUT_TOPBOTTOM); layout_make_node(lcother, LAYOUT_TOPBOTTOM);
TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); layout_set_size(lcother, otherw, sy, 0, 0);
TAILQ_INSERT_HEAD(&lcroot->cells, lcother, entry);
/* Add the remaining panes as children. */
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (window_pane_is_floating(wp)) if (wp == wpmain)
continue; continue;
if (wp == layout_first_tiled(w)) lcchild = wp->layout_cell;
continue;
lcchild = layout_create_cell(lcother);
layout_set_size(lcchild, otherw, PANE_MINIMUM, 0, 0);
layout_make_leaf(lcchild, wp);
TAILQ_INSERT_TAIL(&lcother->cells, lcchild, entry); TAILQ_INSERT_TAIL(&lcother->cells, lcchild, entry);
lcchild->parent = lcother;
if (layout_cell_is_tiled(lcchild))
layout_set_size(lcchild, otherw, PANE_MINIMUM,
0, 0);
} }
layout_spread_cell(w, lcother); layout_spread_cell(w, lcother);
} }
/* Create the main pane. */
lcmain = layout_create_cell(lc);
layout_set_size(lcmain, mainw, sy, 0, 0);
layout_make_leaf(lcmain, layout_first_tiled(w));
TAILQ_INSERT_TAIL(&lc->cells, lcmain, entry);
/* Fix cell offsets. */
layout_fix_offsets(w); layout_fix_offsets(w);
layout_fix_panes(w, NULL); layout_fix_panes(w, NULL);
layout_print_cell(w->layout_root, __func__, 1); layout_print_cell(w->layout_root, __func__, 1);
window_resize(w, lc->sx, lc->sy, -1, -1); window_resize(w, lcroot->sx, lcroot->sy, -1, -1);
notify_window("window-layout-changed", w); notify_window("window-layout-changed", w);
server_redraw_window(w); server_redraw_window(w);
} }
void static void
layout_set_tiled(struct window *w) layout_set_tiled(struct window *w)
{ {
struct options *oo = w->options; struct options *oo = w->options;
struct window_pane *wp; struct window_pane *wp;
struct layout_cell *lc, *lcrow, *lcchild; struct layout_cell *lcroot, *lcrow, *lcchild;
u_int n, width, height, used, sx, sy; u_int n, width, height, used, sx, sy;
u_int i, j, columns, rows, max_columns; u_int i, j, columns, rows, max_columns;
@@ -647,56 +624,59 @@ layout_set_tiled(struct window *w)
if (height < PANE_MINIMUM) if (height < PANE_MINIMUM)
height = PANE_MINIMUM; height = PANE_MINIMUM;
/* Free old tree and create a new root. */
layout_free(w);
lc = w->layout_root = layout_create_cell(NULL);
sx = ((width + 1) * columns) - 1; sx = ((width + 1) * columns) - 1;
if (sx < w->sx) if (sx < w->sx)
sx = w->sx; sx = w->sx;
sy = ((height + 1) * rows) - 1; sy = ((height + 1) * rows) - 1;
if (sy < w->sy) if (sy < w->sy)
sy = w->sy; sy = w->sy;
layout_set_size(lc, sx, sy, 0, 0);
layout_make_node(lc, LAYOUT_TOPBOTTOM);
/* Create a grid of the cells, skipping any floating panes. */ layout_free(w, 1);
lcroot = w->layout_root = layout_create_cell(NULL);
layout_set_size(lcroot, sx, sy, 0, 0);
layout_make_node(lcroot, LAYOUT_TOPBOTTOM);
/* Create a grid of the tiled cells. */
wp = TAILQ_FIRST(&w->panes); wp = TAILQ_FIRST(&w->panes);
while (wp != NULL && window_pane_is_floating(wp))
wp = TAILQ_NEXT(wp, entry);
for (j = 0; j < rows; j++) { for (j = 0; j < rows; j++) {
while (wp != NULL && !layout_cell_is_tiled(wp->layout_cell))
wp = TAILQ_NEXT(wp, entry);
/* If this is the last cell, all done. */ /* If this is the last cell, all done. */
if (wp == NULL) if (wp == NULL)
break; break;
/* Create the new row. */ lcchild = wp->layout_cell;
lcrow = layout_create_cell(lc);
layout_set_size(lcrow, w->sx, height, 0, 0);
TAILQ_INSERT_TAIL(&lc->cells, lcrow, entry);
/* If only one column, just use the row directly. */ /* If only one column, just use the row directly. */
if (n - (j * columns) == 1 || columns == 1) { if (n - (j * columns) == 1 || columns == 1) {
layout_make_leaf(lcrow, wp); lcchild->parent = lcroot;
TAILQ_INSERT_TAIL(&lcroot->cells, lcchild, entry);
layout_set_size(lcchild, w->sx, height, 0, 0);
wp = TAILQ_NEXT(wp, entry); wp = TAILQ_NEXT(wp, entry);
while (wp != NULL && window_pane_is_floating(wp))
wp = TAILQ_NEXT(wp, entry);
continue; continue;
} }
/* Add in the columns. */ /* Create the new row. */
lcrow = layout_create_cell(lcroot);
layout_make_node(lcrow, LAYOUT_LEFTRIGHT); layout_make_node(lcrow, LAYOUT_LEFTRIGHT);
layout_set_size(lcrow, w->sx, height, 0, 0);
TAILQ_INSERT_TAIL(&lcroot->cells, lcrow, entry);
/* Add in the columns. */
for (i = 0; i < columns; i++) { for (i = 0; i < columns; i++) {
/* Create and add a pane cell. */ /* Create and add a pane cell. */
lcchild = layout_create_cell(lcrow); lcchild->parent = lcrow;
layout_set_size(lcchild, width, height, 0, 0);
layout_make_leaf(lcchild, wp);
TAILQ_INSERT_TAIL(&lcrow->cells, lcchild, entry); TAILQ_INSERT_TAIL(&lcrow->cells, lcchild, entry);
layout_set_size(lcchild, width, height, 0, 0);
/* Move to the next non-floating cell. */ /* Move to the next non-floating cell. */
wp = TAILQ_NEXT(wp, entry); wp = TAILQ_NEXT(wp, entry);
while (wp != NULL && window_pane_is_floating(wp)) while (wp != NULL &&
!layout_cell_is_tiled(wp->layout_cell))
wp = TAILQ_NEXT(wp, entry); wp = TAILQ_NEXT(wp, entry);
if (wp == NULL) if (wp == NULL)
break; break;
lcchild = wp->layout_cell;
} }
/* /*
@@ -713,21 +693,19 @@ layout_set_tiled(struct window *w)
w->sx - used); w->sx - used);
} }
/* Adjust the last row height to fit if necessary. */
used = (rows * height) + rows - 1; used = (rows * height) + rows - 1;
if (w->sy > used) { if (w->sy > used) {
lcrow = TAILQ_LAST(&lc->cells, layout_cells); lcrow = TAILQ_LAST(&lcroot->cells, layout_cells);
layout_resize_adjust(w, lcrow, LAYOUT_TOPBOTTOM, layout_resize_adjust(w, lcrow, LAYOUT_TOPBOTTOM,
w->sy - used); w->sy - used);
} }
/* Fix cell offsets. */
layout_fix_offsets(w); layout_fix_offsets(w);
layout_fix_panes(w, NULL); layout_fix_panes(w, NULL);
layout_print_cell(w->layout_root, __func__, 1); layout_print_cell(w->layout_root, __func__, 1);
window_resize(w, lc->sx, lc->sy, -1, -1); window_resize(w, lcroot->sx, lcroot->sy, -1, -1);
notify_window("window-layout-changed", w); notify_window("window-layout-changed", w);
server_redraw_window(w); server_redraw_window(w);
} }

View File

@@ -88,20 +88,24 @@ layout_create_cell(struct layout_cell *lcparent)
/* Free a layout cell. */ /* Free a layout cell. */
void void
layout_free_cell(struct layout_cell *lc) layout_free_cell(struct layout_cell *lc, int only_nodes)
{ {
struct layout_cell *lcchild; struct layout_cell *lcchild, *lcnext;
if (lc == NULL) if (lc == NULL || (only_nodes && lc->type == LAYOUT_WINDOWPANE))
return; return;
switch (lc->type) { switch (lc->type) {
case LAYOUT_LEFTRIGHT: case LAYOUT_LEFTRIGHT:
case LAYOUT_TOPBOTTOM: case LAYOUT_TOPBOTTOM:
while (!TAILQ_EMPTY(&lc->cells)) { lcchild = TAILQ_FIRST(&lc->cells);
lcchild = TAILQ_FIRST(&lc->cells); while (lcchild != NULL) {
TAILQ_REMOVE(&lc->cells, lcchild, entry); lcnext = TAILQ_NEXT(lcchild, entry);
layout_free_cell(lcchild); if (!only_nodes || lcchild->type != LAYOUT_WINDOWPANE) {
TAILQ_REMOVE(&lc->cells, lcchild, entry);
layout_free_cell(lcchild, only_nodes);
}
lcchild = lcnext;
} }
break; break;
case LAYOUT_WINDOWPANE: case LAYOUT_WINDOWPANE:
@@ -255,7 +259,7 @@ layout_fix_zindexes(struct window *w, struct layout_cell *lc)
} }
} }
static int int
layout_cell_is_tiled(struct layout_cell *lc) layout_cell_is_tiled(struct layout_cell *lc)
{ {
int is_leaf = lc->type == LAYOUT_WINDOWPANE; int is_leaf = lc->type == LAYOUT_WINDOWPANE;
@@ -699,13 +703,13 @@ layout_destroy_cell(struct window *w, struct layout_cell *lc,
if (lcparent == NULL) { if (lcparent == NULL) {
if (lc->wp != NULL) if (lc->wp != NULL)
*lcroot = NULL; *lcroot = NULL;
layout_free_cell(lc); layout_free_cell(lc, 0);
return; return;
} }
if (!layout_cell_is_tiled(lc)) { if (!layout_cell_is_tiled(lc)) {
TAILQ_REMOVE(&lcparent->cells, lc, entry); TAILQ_REMOVE(&lcparent->cells, lc, entry);
layout_free_cell(lc); layout_free_cell(lc, 0);
goto out; goto out;
} }
@@ -721,7 +725,7 @@ layout_destroy_cell(struct window *w, struct layout_cell *lc,
/* Remove this from the parent's list. */ /* Remove this from the parent's list. */
TAILQ_REMOVE(&lcparent->cells, lc, entry); TAILQ_REMOVE(&lcparent->cells, lc, entry);
layout_free_cell(lc); layout_free_cell(lc, 0);
out: out:
/* /*
@@ -742,7 +746,7 @@ out:
} else } else
TAILQ_REPLACE(&lc->parent->cells, lcparent, lc, entry); TAILQ_REPLACE(&lc->parent->cells, lcparent, lc, entry);
layout_free_cell(lcparent); layout_free_cell(lcparent, 0);
} }
} }
@@ -760,9 +764,9 @@ layout_init(struct window *w, struct window_pane *wp)
/* Free layout for pane. */ /* Free layout for pane. */
void void
layout_free(struct window *w) layout_free(struct window *w, int only_nodes)
{ {
layout_free_cell(w->layout_root); layout_free_cell(w->layout_root, only_nodes);
} }
/* Resize the entire layout after window resize. */ /* Resize the entire layout after window resize. */
@@ -1507,7 +1511,8 @@ layout_spread_cell(struct window *w, struct layout_cell *parent)
number = 0; number = 0;
TAILQ_FOREACH (lc, &parent->cells, entry) TAILQ_FOREACH (lc, &parent->cells, entry)
number++; if (layout_cell_is_tiled(lc))
number++;
if (number <= 1) if (number <= 1)
return (0); return (0);
status = window_get_pane_status(w); status = window_get_pane_status(w);
@@ -1535,6 +1540,8 @@ layout_spread_cell(struct window *w, struct layout_cell *parent)
changed = 0; changed = 0;
TAILQ_FOREACH (lc, &parent->cells, entry) { TAILQ_FOREACH (lc, &parent->cells, entry) {
if (!layout_cell_is_tiled(lc))
continue;
change = 0; change = 0;
if (parent->type == LAYOUT_LEFTRIGHT) { if (parent->type == LAYOUT_LEFTRIGHT) {
change = each - (int)lc->sx; change = each - (int)lc->sx;

View File

@@ -106,7 +106,7 @@ spawn_window(struct spawn_context *sc, char **cause)
sc->wp0 = TAILQ_FIRST(&w->panes); sc->wp0 = TAILQ_FIRST(&w->panes);
TAILQ_REMOVE(&w->panes, sc->wp0, entry); TAILQ_REMOVE(&w->panes, sc->wp0, entry);
layout_free(w); layout_free(w, 0);
window_destroy_panes(w); window_destroy_panes(w);
TAILQ_INSERT_HEAD(&w->panes, sc->wp0, entry); TAILQ_INSERT_HEAD(&w->panes, sc->wp0, entry);

5
tmux.h
View File

@@ -3630,7 +3630,7 @@ struct visible_ranges *window_visible_ranges(struct window_pane *, int, int,
/* layout.c */ /* layout.c */
u_int layout_count_cells(struct layout_cell *); u_int layout_count_cells(struct layout_cell *);
struct layout_cell *layout_create_cell(struct layout_cell *); struct layout_cell *layout_create_cell(struct layout_cell *);
void layout_free_cell(struct layout_cell *); void layout_free_cell(struct layout_cell *, int);
void layout_print_cell(struct layout_cell *, const char *, u_int); void layout_print_cell(struct layout_cell *, const char *, u_int);
void layout_destroy_cell(struct window *, struct layout_cell *, void layout_destroy_cell(struct window *, struct layout_cell *,
struct layout_cell **); struct layout_cell **);
@@ -3641,6 +3641,7 @@ void layout_set_size(struct layout_cell *, u_int, u_int, int, int);
void layout_make_leaf(struct layout_cell *, struct window_pane *); void layout_make_leaf(struct layout_cell *, struct window_pane *);
void layout_make_node(struct layout_cell *, enum layout_type); void layout_make_node(struct layout_cell *, enum layout_type);
void layout_fix_zindexes(struct window *, struct layout_cell *); void layout_fix_zindexes(struct window *, struct layout_cell *);
int layout_cell_is_tiled(struct layout_cell *);
void layout_fix_offsets(struct window *); void layout_fix_offsets(struct window *);
void layout_fix_panes(struct window *, struct window_pane *); void layout_fix_panes(struct window *, struct window_pane *);
void layout_resize_adjust(struct window *, struct layout_cell *, void layout_resize_adjust(struct window *, struct layout_cell *,
@@ -3649,7 +3650,7 @@ void layout_resize_set_size(struct window *, struct layout_cell *,
enum layout_type, u_int); enum layout_type, u_int);
struct layout_cell *layout_cell_get_neighbour(struct layout_cell *); struct layout_cell *layout_cell_get_neighbour(struct layout_cell *);
void layout_init(struct window *, struct window_pane *); void layout_init(struct window *, struct window_pane *);
void layout_free(struct window *); void layout_free(struct window *, int);
void layout_resize(struct window *, u_int, u_int); void layout_resize(struct window *, u_int, u_int);
void layout_resize_pane(struct window_pane *, enum layout_type, void layout_resize_pane(struct window_pane *, enum layout_type,
int, int); int, int);

View File

@@ -359,8 +359,8 @@ window_destroy(struct window *w)
window_unzoom(w, 0); window_unzoom(w, 0);
RB_REMOVE(windows, &windows, w); RB_REMOVE(windows, &windows, w);
layout_free_cell(w->layout_root); layout_free_cell(w->layout_root, 0);
layout_free_cell(w->saved_layout_root); layout_free_cell(w->saved_layout_root, 0);
free(w->old_layout); free(w->old_layout);
window_destroy_panes(w); window_destroy_panes(w);
@@ -778,7 +778,7 @@ window_unzoom(struct window *w, int notify)
return (-1); return (-1);
w->flags &= ~WINDOW_ZOOMED; w->flags &= ~WINDOW_ZOOMED;
layout_free(w); layout_free(w, 0);
w->layout_root = w->saved_layout_root; w->layout_root = w->saved_layout_root;
w->saved_layout_root = NULL; w->saved_layout_root = NULL;