Add functions to work out cell neighbours, and to remove a tiled cell.

From Dane Jensen.
This commit is contained in:
nicm
2026-06-18 09:11:24 +00:00
parent 1a6de01210
commit b1b184cdb8
2 changed files with 101 additions and 18 deletions

113
layout.c
View File

@@ -588,12 +588,57 @@ layout_resize_adjust(struct window *w, struct layout_cell *lc,
} }
} }
/* Find and return the nearest neighbour to a cell in a specific direction. */
static struct layout_cell *
layout_cell_get_neighbour_direction(struct layout_cell *lc, int direction)
{
struct layout_cell *lcn = lc;
while (1) {
if (direction)
lcn = TAILQ_NEXT(lcn, entry);
else
lcn = TAILQ_PREV(lcn, layout_cells, entry);
if (lcn == NULL ||
layout_cell_is_tiled(lcn) ||
layout_cell_has_tiled_child(lcn))
return (lcn);
}
}
/*
* Find and return the nearest neighbour. Prefers cells "after" the specified
* cell. This behavior defines how cell dimensions are redistributed when a cell
* is hidden/shown and floated/tiled.
*/
struct layout_cell *
layout_cell_get_neighbour(struct layout_cell *lc)
{
struct layout_cell *lcother, *lcparent = lc->parent;
int direction = 1;
if (lcparent == NULL)
return (NULL);
if (lc == TAILQ_LAST(&lcparent->cells, layout_cells))
direction = !direction;
lcother = layout_cell_get_neighbour_direction(lc, direction);
if (lcother == NULL)
lcother = layout_cell_get_neighbour_direction(lc, !direction);
return (lcother);
}
/* Destroy a cell and redistribute the space. */ /* Destroy a cell and redistribute the space. */
void void
layout_destroy_cell(struct window *w, struct layout_cell *lc, layout_destroy_cell(struct window *w, struct layout_cell *lc,
struct layout_cell **lcroot) struct layout_cell **lcroot)
{ {
struct layout_cell *lcother = NULL, *lcparent; struct layout_cell *lcother = NULL, *lcparent;
int change;
/* If no parent, this is the last pane in a window. */ /* If no parent, this is the last pane in a window. */
lcparent = lc->parent; lcparent = lc->parent;
@@ -604,27 +649,27 @@ layout_destroy_cell(struct window *w, struct layout_cell *lc,
return; return;
} }
if (~lc->flags & LAYOUT_CELL_FLOATING) { if (!layout_cell_is_tiled(lc)) {
/* Merge the space into the previous or next cell. */ TAILQ_REMOVE(&lcparent->cells, lc, entry);
if (lc == TAILQ_FIRST(&lcparent->cells)) layout_free_cell(lc);
lcother = TAILQ_NEXT(lc, entry); goto out;
}
lcother = layout_cell_get_neighbour(lc);
if (lcother != NULL) {
if (lcparent->type == LAYOUT_LEFTRIGHT)
change = lc->sx + 1;
else else
lcother = TAILQ_PREV(lc, layout_cells, entry); change = lc->sy + 1;
} layout_resize_adjust(w, lcother, lcparent->type, change);
if (lcother != NULL && (~lcother->flags & LAYOUT_CELL_FLOATING)) { } else
if (lcparent->type == LAYOUT_LEFTRIGHT) { layout_remove_tile(w, lcparent);
layout_resize_adjust(w, lcother, lcparent->type,
lc->sx + 1);
} else {
layout_resize_adjust(w, lcother, lcparent->type,
lc->sy + 1);
}
}
/* 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);
out:
/* /*
* If the parent now has one cell, remove the parent from the tree and * If the parent now has one cell, remove the parent from the tree and
* replace it by that cell. * replace it by that cell.
@@ -1564,3 +1609,39 @@ layout_get_floating_cell(struct cmdq_item *item, struct args *args,
lcnew = layout_floating_pane(w, sx, sy, ox, oy); lcnew = layout_floating_pane(w, sx, sy, ox, oy);
return (lcnew); return (lcnew);
} }
/*
* Removes a cell from the tiled layout by giving the cell's space to the
* nearest neighbour.
*/
int
layout_remove_tile(struct window *w, struct layout_cell *lc)
{
struct layout_cell *lcneighbour, *lcparent;
enum layout_type type;
int change;
if (lc->flags & LAYOUT_CELL_FLOATING)
return (0);
lcneighbour = layout_cell_get_neighbour(lc);
if (lcneighbour == NULL) {
if (lc->parent != NULL)
layout_remove_tile(w, lc->parent);
} else if ((lcparent = lcneighbour->parent) != NULL) {
type = lcparent->type;
/*
* Adding the size of the layout cell plus its border to the
* neighbour.
*/
if (type == LAYOUT_TOPBOTTOM)
change = lc->sy + 1;
else
change = lc->sx + 1;
layout_resize_adjust(w, lcneighbour, type, change);
}
/* Zeroing out the cell geometry until the cell is retiled. */
layout_set_size(lc, 0, 0, 0, 0);
return (1);
}

6
tmux.h
View File

@@ -3504,6 +3504,7 @@ 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 *,
enum layout_type, int); enum layout_type, int);
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 *);
void layout_resize(struct window *, u_int, u_int); void layout_resize(struct window *, u_int, u_int);
@@ -3524,10 +3525,11 @@ struct layout_cell *layout_floating_pane(struct window *, u_int, u_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 *); int layout_spread_cell(struct window *, struct layout_cell *);
void layout_spread_out(struct window_pane *); void layout_spread_out(struct window_pane *);
struct layout_cell *layout_get_floating_cell(struct cmdq_item *, struct args *,
struct window *, struct window_pane *, char **);
struct layout_cell *layout_get_tiled_cell(struct cmdq_item *, struct args *, struct layout_cell *layout_get_tiled_cell(struct cmdq_item *, struct args *,
struct window *, struct window_pane *, int, char **); struct window *, struct window_pane *, int, char **);
struct layout_cell *layout_get_floating_cell(struct cmdq_item *, struct args *,
struct window *, struct window_pane *, char **);
int layout_remove_tile(struct window *, struct layout_cell *);
/* layout-custom.c */ /* layout-custom.c */
char *layout_dump(struct window *, struct layout_cell *); char *layout_dump(struct window *, struct layout_cell *);