floating panes, and use a more modern serialization format.
## Serialization
layout-custom.c now emits a canonical current format with:
- Pane syntax: %pane-id,z-index:geometry[:flags]
- Semicolons between child cells.
- X-style geometry: WxH+X+Y
- Every pane represented inside layout_root, including floating panes.
- No legacy <...> floating-pane wrapper.
- Z-index serialized for tiled and floating panes.
- Flags:
- f: floating
- h: hidden
- z: zoomed
- Hidden panes use their saved restoration geometry.
- Single-pane windows serialize as a pane root cell.
window_layout and list-windows continue emitting a four-digit checksum.
## Geometry
Current layouts accept:
- +N: absolute positive offset
- ++N: equivalent to +N
- +-N: absolute negative offset
- -N: right/bottom-relative offset for floating panes
- Omitted offsets: +0+0
- One offset: second defaults to +0
Relative offsets are resolved immediately. Output always contains canonical absolute
coordinates.
Widths and heights are restricted to 1..PANE_MAXIMUM; offsets and resolved offsets are
restricted to -PANE_MAXIMUM..PANE_MAXIMUM.
## Checksums and whitespace
- The outer checksum is optional on input for current and legacy layouts.
- If supplied, it must be correct.
- Output still includes it.
- Checksums cover all non-whitespace layout text.
- Whitespace and newlines may be inserted between tokens.
- Optional nested checksums are accepted and validated but not emitted.
## Legacy compatibility
Legacy comma-separated layouts remain accepted:
WxH,x,y{cell,cell,...}
WxH,x,y,pane-id
Additional compatibility behavior includes:
- The reported e6db,113x28,... layout works and resizes existing panes correctly.
- Older inconsistent root dimensions are corrected safely.
- Legacy layouts with surplus cells continue pruning cells until the target pane count
matches.
- Legacy panes remain assigned in tree order.
- Legacy input is re-emitted in the current canonical format.
Mixed legacy/current syntax is rejected.
## Pane matching and counts
For current layouts:
- Pane IDs must be unique.
- With matching pane counts:
- An exact ID set maps panes by identity.
- A completely disjoint ID set maps panes in tree order.
- A partial ID match is rejected as ambiguous.
- If the target has fewer panes:
- Cells are removed from the end of the tree.
- Remaining z-indexes are compacted while preserving order.
- Existing panes are assigned in tree order.
- No panes are killed or created.
- A target with more panes than layout cells is rejected.
Layouts are therefore snapshots that rearrange existing panes and windows, not complete
session-restoration data.
## Validation and safety
Parsing now constructs and validates a temporary tree before replacing the active layout:
- Maximum input length: 8192 bytes.
- Maximum nesting depth: 64.
- Checked signed and unsigned numeric parsing.
- Dimension and offset bounds.
- Container size consistency.
- Exact trailing-input checks.
- Unique, contiguous z-indexes starting at zero.
- Floating panes must precede tiled panes in z-order.
- Unknown and duplicate flags are rejected.
- Hidden and zoomed flags cannot be combined.
- Only one pane may be zoomed.
- Relative positioning is accepted only for floating panes.
- Overflow-safe size aggregation.
Invalid single-window layouts are validated before the window is unzoomed. Multi-window
layouts are all validated before any window is changed.
## Multi-window layouts
cmd-select-layout.c accepts:
@window-id:layout[@window-id:layout...]
Records may be adjacent or separated by whitespace/newlines. Unknown and duplicate window IDs
are rejected.
This allows direct reuse of:
tmux list-windows -F '#{window_id}:#{window_layout}'
## Supporting runtime changes
- tmux.h adds parsed pane IDs, z-indexes, hidden/zoomed/relative cell flags, and
layout_validate.
- layout.c initializes parsed metadata safely.
- window.c treats hidden cells, including saved cells, as non-visible.
## Documentation
tmux.1 now documents:
- Current and legacy grammars.
- Geometry and flags.
- Z-index and pane-ID rules.
- Optional checksums.
- Multi-window wrappers.
- Pane-count pruning.
- Snapshot versus session-restoration semantics.
The authoritative description is under select-layout; list-windows and list-panes reference
it.
## Tests
Added regress/layout-custom.sh covering serialization, compatibility, validation, geometry,
IDs, pruning, flags, zoom, checksums, whitespace, and multi-window application.
Updated regress/control-client-sanity.sh for canonical output.
Verified:
- Debug build
- Layout regression
- Floating-pane geometry regression
- Control-client regression
- Man-page rendering
- git diff --check
replaces the previous "modal" behaviour where the pane would be resized,
which tended to make a mess. Instead, the scrollbar appears when
scrolling or when hovered over with the mouse and disappears a
(configurable) short period later. From Michael Grant.
is generated and cached in the client: it holds positions and sizes of
panes, borders and so on. The scene is invalidated when a pane is moved
or resized or relevant option is changed. This scene is then drawn to
the client as needed and text and colours are filled in. With Michael
Grant.
pane-scrollbars turn them on or off, pane-scrollbars-position sets the
position (left or right), and pane-scrollbars-style to set the colours.
Mouse support will come later. From Michael Grant in GitHub issue 4221.
been a limitation for a long time.
There are two new options, window-size and default-size, and a new
command, resize-window. The force-width and force-height options and the
session_width and session_height formats have been removed.
The new window-size option tells tmux how to work out the size of
windows: largest means it picks the size of the largest session,
smallest the smallest session (similar to the old behaviour) and manual
means that it does not automatically resize windows. The default is
currently largest but this may change. aggressive-resize modifies the
choice of session for largest and smallest as it did before.
If a window is in a session attached to a client that is too small, only
part of the window is shown. tmux attempts to keep the cursor visible,
so the part of the window displayed is changed as the cursor moves (with
a small delay, to try and avoid excess redrawing when applications
redraw status lines or similar that are not currently visible). The
offset of the visible portion of the window is shown in status-right.
Drawing windows which are larger than the client is not as efficient as
those which fit, particularly when the cursor moves, so it is
recommended to avoid using this on slow machines or networks (set
window-size to smallest or manual).
The resize-window command can be used to resize a window manually. If it
is used, the window-size option is automatically set to manual for the
window (undo this with "setw -u window-size"). resize-window works in a
similar way to resize-pane (-U -D -L -R -x -y flags) but also has -a and
-A flags. -a sets the window to the size of the smallest client (what it
would be if window-size was smallest) and -A the largest.
For the same behaviour as force-width or force-height, use resize-window
-x or -y, and "setw -u window-size" to revert to automatic sizing..
If the global window-size option is set to manual, the default-size
option is used for new windows. If -x or -y is used with new-session,
that sets the default-size option for the new session.
The maximum size of a window is 10000x10000. But expect applications to
complain and much higher memory use if making a window excessively
big. The minimum size is the size required for the current layout
including borders.
The refresh-client command can be used to pan around a window, -U -D -L
-R moves up, down, left or right and -c returns to automatic cursor
tracking. The position is reset when the current window is changed.