Merge branch 'obsd-master'

This commit is contained in:
Thomas Adam
2026-06-02 20:30:06 +01:00
4 changed files with 150 additions and 184 deletions

View File

@@ -69,63 +69,6 @@ const struct cmd_entry cmd_split_window_entry = {
.exec = cmd_split_window_exec
};
static struct layout_cell *
cmd_split_window_get_floating_cell(struct cmdq_item *item, struct args *args,
struct window *w, struct window_pane *wp)
{
struct layout_cell *lc = NULL;
char *cause = NULL;
u_int x, y, sx, sy;
if (window_pane_floating_geometry(w, wp, &x, &y, &sx, &sy, item, args,
&cause) != 0) {
cmdq_error(item, "invalid floating pane geometry %s", cause);
free(cause);
return (NULL);
}
/*
* Floating panes sit in layout cells which are not in the layout_root
* tree so we call it with parent == NULL.
*/
lc = layout_create_cell(NULL);
lc->xoff = x;
lc->yoff = y;
lc->sx = sx;
lc->sy = sy;
return (lc);
}
static struct layout_cell *
cmd_split_window_get_tiled_cell(struct cmdq_item *item, struct args *args,
struct window *w, struct window_pane *wp, int flags)
{
enum layout_type type;
struct layout_cell *lc = NULL;
char *cause = NULL;
int size;
if (window_pane_is_floating(wp)) {
cmdq_error(item, "can't split a floating pane");
return (NULL);
}
if (window_pane_tiled_geometry(w, wp, &size, &flags, &type, item, args,
&cause) != 0) {
cmdq_error(item, "invalid tiled geometry %s", cause);
free(cause);
return (NULL);
}
window_push_zoom(wp->window, 1, args_has(args, 'Z'));
lc = layout_split_pane(wp, type, size, flags);
if (lc == NULL)
cmdq_error(item, "no space for new pane");
return (lc);
}
static enum cmd_retval
cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
{
@@ -161,11 +104,13 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
flags |= SPAWN_EMPTY;
if (is_floating)
lc = cmd_split_window_get_floating_cell(item, args, w, wp);
lc = layout_get_floating_cell(item, args, w, wp, lc, &cause);
else
lc = cmd_split_window_get_tiled_cell(item, args, w, wp, flags);
if (lc == NULL)
lc = layout_get_tiled_cell(item, args, w, wp, flags, &cause);
if (cause != NULL) {
cmdq_error(item, "could not create cell: %s", cause);
return (CMD_RETURN_ERROR);
}
sc.item = item;
sc.s = s;

140
layout.c
View File

@@ -1152,6 +1152,7 @@ layout_close_pane(struct window_pane *wp)
notify_window("window-layout-changed", w);
}
/* Spread out cells inside a parent cell. */
int
layout_spread_cell(struct window *w, struct layout_cell *parent)
{
@@ -1180,6 +1181,7 @@ layout_spread_cell(struct window *w, struct layout_cell *parent)
each = (size - (number - 1)) / number;
if (each == 0)
return (0);
/*
* Remaining space after assigning that which can be evenly
* distributed.
@@ -1214,6 +1216,7 @@ layout_spread_cell(struct window *w, struct layout_cell *parent)
return (changed);
}
/* Spread out cells evenly. */
void
layout_spread_out(struct window_pane *wp)
{
@@ -1232,3 +1235,140 @@ layout_spread_out(struct window_pane *wp)
}
} while ((parent = parent->parent) != NULL);
}
/* Get a new tiled cell. */
struct layout_cell *
layout_get_tiled_cell(struct cmdq_item *item, struct args *args,
struct window *w, struct window_pane *wp, int flags, char **cause)
{
struct layout_cell *lc;
enum layout_type type;
u_int curval;
int size = -1;
if (window_pane_is_floating(wp)) {
*cause = xstrdup("can't split a floating pane");
return (NULL);
}
type = LAYOUT_TOPBOTTOM;
if (args_has(args, 'h'))
type = LAYOUT_LEFTRIGHT;
if (args_has(args, 'l') || args_has(args, 'p')) {
if (args_has(args, 'f')) {
if (type == LAYOUT_TOPBOTTOM)
curval = w->sy;
else
curval = w->sx;
} else {
if (type == LAYOUT_TOPBOTTOM)
curval = wp->sy;
else
curval = wp->sx;
}
}
if (args_has(args, 'l')) {
size = args_percentage_and_expand(args, 'l', 0, INT_MAX, curval,
item, cause);
} else if (args_has(args, 'p')) {
size = args_strtonum_and_expand(args, 'p', 0, 100, item,
cause);
if (*cause == NULL)
size = curval * size / 100;
}
if (*cause != NULL) {
*cause = xstrdup("invalid tiled geometry");
return (NULL);
}
if (args_has(args, 'b'))
flags |= SPAWN_BEFORE;
if (args_has(args, 'f'))
flags |= SPAWN_FULLSIZE;
window_push_zoom(wp->window, 1, args_has(args, 'Z'));
lc = layout_split_pane(wp, type, size, flags);
if (lc == NULL)
*cause = xstrdup("no space for a new pane");
return (lc);
}
/* Get a new floating cell. */
struct layout_cell *
layout_get_floating_cell(struct cmdq_item *item, struct args *args,
struct window *w, __unused struct window_pane *wp, struct layout_cell *lc,
char **cause)
{
u_int sx, sy, ox, oy;
int new = 0;
if (lc == NULL) {
lc = layout_create_cell(NULL);
new = 1;
}
sx = lc->sx; sy = lc->sy;
ox = lc->xoff; oy = lc->yoff;
if (args_has(args, 'x')) {
sx = args_percentage_and_expand(args, 'x', 0, USHRT_MAX, w->sx,
item, cause);
if (*cause != NULL)
goto error;
}
if (args_has(args, 'y')) {
sy = args_percentage_and_expand(args, 'y', 0, USHRT_MAX, w->sy,
item, cause);
if (*cause != NULL)
goto error;
}
if (args_has(args, 'X')) {
ox = args_percentage_and_expand(args, 'X', 0, USHRT_MAX, w->sx,
item, cause);
if (*cause != NULL)
goto error;
}
if (args_has(args, 'Y')) {
oy = args_percentage_and_expand(args, 'Y', 0, USHRT_MAX, w->sy,
item, cause);
if (*cause != NULL)
goto error;
}
if (sx == UINT_MAX)
sx = w->sx / 2;
if (sy == UINT_MAX)
sy = w->sy / 4;
if (ox == INT_MAX) {
if (w->last_new_pane_x == 0)
ox = 4;
else {
ox = w->last_new_pane_x + 4;
if (w->last_new_pane_x > w->sx)
ox = 4;
}
w->last_new_pane_x = ox;
}
if (oy == INT_MAX) {
if (w->last_new_pane_y == 0)
oy = 2;
else {
oy = w->last_new_pane_y + 2;
if (w->last_new_pane_y > w->sy)
oy = 2;
}
w->last_new_pane_y = oy;
}
layout_set_size(lc, sx, sy, ox, oy);
lc->flags |= LAYOUT_CELL_FLOATING;
return (lc);
error:
if (new)
layout_destroy_cell(w, lc, &w->layout_root);
return (NULL);
}

11
tmux.h
View File

@@ -3504,12 +3504,6 @@ void window_pane_send_theme_update(struct window_pane *);
struct style_range *window_pane_border_status_get_range(struct window_pane *,
u_int, u_int);
int window_pane_is_floating(struct window_pane *);
int window_pane_tiled_geometry(struct window *,
struct window_pane *, int *, int *, enum layout_type *,
struct cmdq_item *, struct args *, char **);
int window_pane_floating_geometry(struct window *,
struct window_pane *, u_int *, u_int *, u_int *, u_int *,
struct cmdq_item *, struct args *, char **);
/* layout.c */
u_int layout_count_cells(struct layout_cell *);
@@ -3543,6 +3537,11 @@ struct layout_cell *layout_split_pane(struct window_pane *, enum layout_type,
void layout_close_pane(struct window_pane *);
int layout_spread_cell(struct window *, struct layout_cell *);
void layout_spread_out(struct window_pane *);
struct layout_cell *layout_get_floating_cell(struct cmdq_item *, struct args *,
struct window *, struct window_pane *, struct layout_cell *,
char **);
struct layout_cell *layout_get_tiled_cell(struct cmdq_item *, struct args *,
struct window *, struct window_pane *, int, char **);
/* layout-custom.c */
char *layout_dump(struct window *, struct layout_cell *);

118
window.c
View File

@@ -2094,124 +2094,6 @@ window_pane_border_status_get_range(struct window_pane *wp, u_int x, u_int y)
return (style_ranges_get_range(srs, x - wp->xoff - 2));
}
/* Work out geometry for tiled panes. */
int
window_pane_tiled_geometry(struct window *w, struct window_pane *wp,
int *out_size, int *out_flags, enum layout_type *out_type,
struct cmdq_item *item, struct args *args, char **cause)
{
int size = -1, flags = *out_flags;
enum layout_type type;
u_int curval = 0;
type = LAYOUT_TOPBOTTOM;
if (args_has(args, 'h'))
type = LAYOUT_LEFTRIGHT;
if (args_has(args, 'l') || args_has(args, 'p')) {
if (args_has(args, 'f')) {
if (type == LAYOUT_TOPBOTTOM)
curval = w->sy;
else
curval = w->sx;
} else {
if (type == LAYOUT_TOPBOTTOM)
curval = wp->sy;
else
curval = wp->sx;
}
}
if (args_has(args, 'l')) {
size = args_percentage_and_expand(args, 'l', 0, INT_MAX, curval,
item, cause);
} else if (args_has(args, 'p')) {
size = args_strtonum_and_expand(args, 'p', 0, 100, item,
cause);
if (*cause == NULL)
size = curval * size / 100;
}
if (*cause != NULL)
return (-1);
if (args_has(args, 'b'))
flags |= SPAWN_BEFORE;
if (args_has(args, 'f'))
flags |= SPAWN_FULLSIZE;
*out_size = size;
*out_flags = flags;
*out_type = type;
return (0);
}
/* Work out geometry for floating panes. */
int
window_pane_floating_geometry(struct window *w, __unused struct window_pane *wp,
u_int *out_x, u_int *out_y, u_int *out_sx, u_int *out_sy,
struct cmdq_item *item, struct args *args, char **cause)
{
u_int x, y, sx = w->sx / 2, sy = w->sy / 4;
if (args_has(args, 'x')) {
sx = args_percentage_and_expand(args, 'x', 0, USHRT_MAX, w->sx,
item, cause);
if (*cause != NULL)
return (-1);
}
if (args_has(args, 'y')) {
sy = args_percentage_and_expand(args, 'y', 0, USHRT_MAX, w->sy,
item, cause);
if (*cause != NULL)
return (-1);
}
if (args_has(args, 'X')) {
x = args_percentage_and_expand(args, 'X', 0, USHRT_MAX, w->sx,
item, cause);
if (*cause != NULL)
return (-1);
} else {
if (w->last_new_pane_x == 0)
x = 4;
else {
x = w->last_new_pane_x + 4;
if (x + sx >= w->sx) {
w->last_new_pane_x = 0;
w->last_new_pane_y = 0;
x = 4;
y = 2;
}
}
w->last_new_pane_x = x;
}
if (args_has(args, 'Y')) {
y = args_percentage_and_expand(args, 'Y', 0, USHRT_MAX, w->sy,
item, cause);
if (*cause != NULL)
return (-1);
} else {
if (w->last_new_pane_y == 0)
y = 2;
else {
y = w->last_new_pane_y + 2;
if (y + sy >= w->sy) {
w->last_new_pane_x = 0;
w->last_new_pane_y = 0;
x = 4;
y = 2;
}
}
w->last_new_pane_y = y;
}
*out_x = x;
*out_y = y;
*out_sx = sx;
*out_sy = sy;
return (0);
}
int
window_pane_is_floating(struct window_pane *wp)
{