Add new layout format which includes floating panes. The new format is

now a JSON subset which is less fragile and easier to handle than the
old custom format. The old (version 1) format is still supported for
control mode clients for now - they must set the new-layouts flag to
receive the new format. From Dane Jensen.
This commit is contained in:
nicm
2026-09-09 07:03:39 +00:00
committed by tmux update bot
parent c7102ebbe5
commit bf43fdc0c7
5 changed files with 959 additions and 187 deletions

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: cmd-select-layout.c,v 1.44 2026/09/08 10:20:08 nicm Exp $ */ /* $OpenBSD: cmd-select-layout.c,v 1.45 2026/09/09 07:03:39 nicm Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -73,12 +73,13 @@ cmd_select_layout_exec(struct cmd *self, struct cmdq_item *item)
{ {
struct args *args = cmd_get_args(self); struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item); struct cmd_find_state *target = cmdq_get_target(item);
struct client *c = cmdq_get_target_client(item);
struct winlink *wl = target->wl; struct winlink *wl = target->wl;
struct window *w = wl->window; struct window *w = wl->window;
struct window_pane *wp = target->wp; struct window_pane *wp = target->wp;
const char *layoutname; const char *layoutname;
char *oldlayout, *cause; char *oldlayout, *cause = NULL;
int next, previous, layout; int next, previous, layout, flags = 0;
server_unzoom_window(w); server_unzoom_window(w);
@@ -89,8 +90,12 @@ cmd_select_layout_exec(struct cmd *self, struct cmdq_item *item)
if (args_has(args, 'p')) if (args_has(args, 'p'))
previous = 1; previous = 1;
if (c != NULL &&
(c->flags & CLIENT_CONTROL) &&
(~c->flags & CLIENT_CONTROL_NEWLAYOUTS))
flags |= LAYOUT_CUSTOM_OLD_FORMAT;
oldlayout = w->old_layout; oldlayout = w->old_layout;
w->old_layout = layout_dump(w, w->layout_root, 0); w->old_layout = layout_dump(w, w->layout_root, flags);
if (next || previous) { if (next || previous) {
if (next) if (next)

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: layout.c,v 1.98 2026/08/25 18:38:05 nicm Exp $ */ /* $OpenBSD: layout.c,v 1.99 2026/09/09 07:03:39 nicm Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -106,7 +106,7 @@ layout_free_cell(struct layout_cell *lc, int only_nodes)
} }
break; break;
case LAYOUT_WINDOWPANE: case LAYOUT_WINDOWPANE:
if (lc->wp != NULL) { if (lc->wp != NULL && lc->wp->layout_cell != NULL) {
lc->wp->layout_cell->parent = NULL; lc->wp->layout_cell->parent = NULL;
lc->wp->layout_cell = NULL; lc->wp->layout_cell = NULL;
} }
@@ -233,29 +233,6 @@ layout_make_node(struct layout_cell *lc, enum layout_type type)
lc->wp = NULL; lc->wp = NULL;
} }
/* Fix z-indexes. */
void
layout_fix_zindexes(struct window *w, struct layout_cell *lc)
{
struct layout_cell *lcchild;
if (lc == NULL)
return;
switch (lc->type) {
case LAYOUT_WINDOWPANE:
TAILQ_INSERT_TAIL(&w->z_index, lc->wp, zentry);
break;
case LAYOUT_LEFTRIGHT:
case LAYOUT_TOPBOTTOM:
TAILQ_FOREACH(lcchild, &lc->cells, entry)
layout_fix_zindexes(w, lcchild);
return;
default:
fatalx("bad layout type");
}
}
int int
layout_cell_is_tiled(struct layout_cell *lc) layout_cell_is_tiled(struct layout_cell *lc)
{ {
@@ -265,7 +242,7 @@ layout_cell_is_tiled(struct layout_cell *lc)
return is_leaf && !is_floating; return is_leaf && !is_floating;
} }
static int int
layout_cell_has_tiled_child(struct layout_cell *lc) layout_cell_has_tiled_child(struct layout_cell *lc)
{ {
struct layout_cell *lcchild; struct layout_cell *lcchild;
@@ -509,18 +486,20 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
/* Count the number of available cells in a layout. */ /* Count the number of available cells in a layout. */
u_int u_int
layout_count_cells(struct layout_cell *lc) layout_count_cells(struct layout_cell *lc, int with_floating)
{ {
struct layout_cell *lcchild; struct layout_cell *lcchild;
u_int count = 0; u_int count = 0;
switch (lc->type) { switch (lc->type) {
case LAYOUT_WINDOWPANE: case LAYOUT_WINDOWPANE:
if (lc->flags & LAYOUT_CELL_FLOATING && !with_floating)
return 0;
return (1); return (1);
case LAYOUT_LEFTRIGHT: case LAYOUT_LEFTRIGHT:
case LAYOUT_TOPBOTTOM: case LAYOUT_TOPBOTTOM:
TAILQ_FOREACH(lcchild, &lc->cells, entry) TAILQ_FOREACH(lcchild, &lc->cells, entry)
count += layout_count_cells(lcchild); count += layout_count_cells(lcchild, with_floating);
return (count); return (count);
default: default:
fatalx("bad layout type"); fatalx("bad layout type");
@@ -721,7 +700,7 @@ layout_destroy_cell(struct window *w, struct layout_cell *lc,
/* 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;
if (lcparent == NULL) { if (lcparent == NULL) {
if (lc->wp != NULL) if (*lcroot == lc)
*lcroot = NULL; *lcroot = NULL;
layout_free_cell(lc, 0); layout_free_cell(lc, 0);
return; return;

23
tmux.1
View File

@@ -1,4 +1,4 @@
.\" $OpenBSD: tmux.1,v 1.1167 2026/09/08 10:20:08 nicm Exp $ .\" $OpenBSD: tmux.1,v 1.1168 2026/09/09 07:03:39 nicm Exp $
.\" .\"
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> .\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
.\" .\"
@@ -14,7 +14,7 @@
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: September 8 2026 $ .Dd $Mdocdate: September 9 2026 $
.Dt TMUX 1 .Dt TMUX 1
.Os .Os
.Sh NAME .Sh NAME
@@ -2699,8 +2699,8 @@ For example:
.Bd -literal -offset indent .Bd -literal -offset indent
$ tmux list\-windows $ tmux list\-windows
0: ksh [159x48] 0: ksh [159x48]
layout: bb62,159x48,0,0{79x48,0,0,79x48,80,0} layout: {"V":2,"L":{"t":"h","w":159,"h":48,"x":0,"y":0,"c":[{"t":"p","w":79,"h":48,"x":0,"y":0,"l":0,"i":0,"I":"%0"},{"t":"p","w":79,"h":48,"x":80,"y":0,"a":true,"i":1,"I":"%2"}]}}
$ tmux select\-layout \[aq]bb62,159x48,0,0{79x48,0,0,79x48,80,0}\[aq] $ tmux select\-layout \[aq]{"V":2,"L":{"t":"h","w":159,"h":48,"x":0,"y":0,"c":[{"t":"p","w":79,"h":48,"x":0,"y":0,"l":0,"i":0,"I":"%0"},{"t":"p","w":79,"h":48,"x":80,"y":0,"a":true,"i":1,"I":"%2"}]}}\[aq]
.Ed .Ed
.Pp .Pp
.Nm .Nm
@@ -9070,7 +9070,7 @@ and flags (currently not used).
For example: For example:
.Bd -literal -offset indent .Bd -literal -offset indent
%begin 1363006971 2 1 %begin 1363006971 2 1
0: ksh* (1 panes) [80x24] [layout b25f,80x24,0,0,2] @2 (active) 0: ksh* (1 panes) [80x24] [layout {"V":2,"L":{"t":"p","w":80,"h":24,"x":0,"y":0,"a":true,"i":0,"I":"%2"}}] @2 (active)
%end 1363006971 2 1 %end 1363006971 2 1
.Ed .Ed
.Pp .Pp
@@ -9131,10 +9131,15 @@ The layout of a window with ID
.Ar window\-id .Ar window\-id
changed. changed.
The new layout is The new layout is
.Ar window\-layout . .Ar window\-layout
The window's visible layout is and the window's visible layout is
.Ar window\-visible\-layout .Ar window\-visible\-layout .
and the window flags are If the
.Ar new\-layouts
flag is set, both layout fields use the new format string; see
.Ic refresh\-client
.Fl f .
The window flags are
.Ar window\-flags . .Ar window\-flags .
.It Ic %message Ar message .It Ic %message Ar message
A message sent with the A message sent with the

6
tmux.h
View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tmux.h,v 1.1436 2026/09/08 10:20:08 nicm Exp $ */ /* $OpenBSD: tmux.h,v 1.1437 2026/09/09 07:03:39 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -3800,7 +3800,7 @@ struct visible_ranges *window_visible_ranges(struct window_pane *, int, int,
u_int, struct visible_ranges *); u_int, struct visible_ranges *);
/* layout.c */ /* layout.c */
u_int layout_count_cells(struct layout_cell *); u_int layout_count_cells(struct layout_cell *, int);
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 *, int); 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);
@@ -3812,8 +3812,8 @@ struct layout_cell *layout_search_by_border(struct layout_cell *, u_int, u_int);
void layout_set_size(struct layout_cell *, u_int, u_int, int, int); 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 *);
int layout_cell_is_tiled(struct layout_cell *); int layout_cell_is_tiled(struct layout_cell *);
int layout_cell_has_tiled_child(struct layout_cell *);
int layout_add_horizontal_border(struct layout_cell *, int layout_add_horizontal_border(struct layout_cell *,
struct layout_cell *, int); struct layout_cell *, int);
void layout_fix_offsets(struct window *); void layout_fix_offsets(struct window *);