Add hidden panes and a "show desktop" button to the pane list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Michael Grant
2026-10-01 08:24:16 +01:00
parent 291c043080
commit d6cf5e0e4d
14 changed files with 281 additions and 48 deletions

View File

@@ -65,13 +65,15 @@ cmd_break_pane_float(struct cmdq_item *item, struct args *args,
free(cause);
return (CMD_RETURN_ERROR);
}
layout_remove_tile(w, lc);
/* A hidden pane has already given up its space. */
if (~wp->flags & PANE_HIDDEN)
layout_remove_tile(w, lc);
layout_set_size(lc, fg->sx, fg->sy, fg->xoff, fg->yoff);
lc->flags |= LAYOUT_CELL_FLOATING;
window_raise_pane(wp);
if (!args_has(args, 'd'))
if (!args_has(args, 'd') && (~wp->flags & PANE_HIDDEN))
window_set_active_pane(w, wp, 1);
layout_fix_offsets(w);
layout_fix_panes(w, NULL);
@@ -149,6 +151,7 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
window_lost_pane(w, wp);
layout_close_pane(wp);
wp->flags &= ~(PANE_HIDDEN|PANE_HIDDENALL);
w = wp->window = window_create(w->sx, w->sy, w->xpixel, w->ypixel);
window_add_ref(w, __func__);
options_set_parent(wp->options, w->options);

View File

@@ -429,7 +429,12 @@ cmd_join_pane_tile(struct cmdq_item *item, struct args *args, struct window *w,
lc->fg.xoff = lc->g.xoff;
lc->fg.yoff = lc->g.yoff;
if (layout_insert_tile(w, lc) != 0) {
if (wp->flags & PANE_HIDDEN) {
/* It takes its space when it is shown. */
if (lc->parent != NULL)
layout_set_size(lc, 0, 0, 0, 0);
lc->tg.sx = UINT_MAX;
} else if (layout_insert_tile(w, lc) != 0) {
cmdq_error(item, "no space for a new pane");
return (CMD_RETURN_ERROR);
}
@@ -440,7 +445,7 @@ cmd_join_pane_tile(struct cmdq_item *item, struct args *args, struct window *w,
TAILQ_INSERT_TAIL(&w->z_index, wp, zentry);
}
if (!args_has(args, 'd'))
if (!args_has(args, 'd') && (~wp->flags & PANE_HIDDEN))
window_set_active_pane(w, wp, 1);
layout_fix_offsets(w);
layout_fix_panes(w, NULL);
@@ -545,6 +550,7 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
TAILQ_REMOVE(&src_w->z_index, src_wp, zentry);
src_wp->window = dst_w;
src_wp->flags &= ~(PANE_HIDDEN|PANE_HIDDENALL);
options_set_parent(src_wp->options, dst_w->options);
src_wp->flags |= (PANE_STYLECHANGED|PANE_THEMECHANGED);
if (flags & SPAWN_BEFORE)

View File

@@ -41,8 +41,8 @@ const struct cmd_entry cmd_resize_pane_entry = {
.name = "resize-pane",
.alias = "resizep",
.args = { "aD::L::MR::Tt:U::x:y:Z", 0, 1, NULL },
.usage = "[-aMTZ] [-D lines] [-L columns] [-R columns] [-U lines] "
.args = { "aD::HL::MR::Tt:U::x:y:Z", 0, 1, NULL },
.usage = "[-aHMTZ] [-D lines] [-L columns] [-R columns] [-U lines] "
"[-x width] [-y height] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 },
@@ -51,6 +51,35 @@ const struct cmd_entry cmd_resize_pane_entry = {
.exec = cmd_resize_pane_exec
};
/*
* Show the desktop: hide every pane above the layout, remembering which, or if
* any were hidden like that show just those again.
*/
static void
cmd_resize_pane_desktop(struct window *w)
{
struct window_pane *wp;
int marked = 0;
TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->flags & PANE_HIDDENALL)
marked = 1;
}
TAILQ_FOREACH(wp, &w->panes, entry) {
if (marked) {
if (wp->flags & PANE_HIDDENALL)
window_show_pane(wp);
continue;
}
if (wp == w->modal || (wp->flags & PANE_HIDDEN))
continue;
if (!window_pane_is_raised(wp))
continue;
window_hide_pane(wp);
wp->flags |= PANE_HIDDENALL;
}
}
static enum cmd_retval
cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
{
@@ -83,6 +112,16 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
if (args_has(args, 'M'))
return (cmd_resize_pane_mouse_update(self, item));
if (args_has(args, 'H')) {
if (args_has(args, 'a'))
cmd_resize_pane_desktop(w);
else if (wp->flags & PANE_HIDDEN)
window_set_active_pane(w, wp, 1);
else
window_hide_pane(wp);
server_redraw_window(w);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'Z')) {
if (args_has(args, 'a'))
window_unzoom(w, 1);
@@ -93,6 +132,8 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
server_redraw_window(w);
return (CMD_RETURN_NORMAL);
}
if ((wp->flags & PANE_HIDDEN) && !window_pane_is_floating(wp))
window_show_pane(wp);
if (wp->flags & PANE_ZOOMED)
window_unzoom_pane(wp, 1);

View File

@@ -264,7 +264,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
}
if (wp == w->active)
if (wp == w->active && (~wp->flags & PANE_HIDDEN))
return (CMD_RETURN_NORMAL);
if (w->modal != NULL && wp != w->modal)
visible = 1;

View File

@@ -101,6 +101,8 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
else {
is_floating = window_pane_is_floating(wp);
flags |= SPAWN_SPLIT;
if (!is_floating && (wp->flags & PANE_HIDDEN))
window_show_pane(wp);
}
if (args_has(args, 'O')) {

View File

@@ -75,7 +75,8 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
struct window_pane *tmp_wp, *src_wp, *dst_wp;
struct layout_cell *src_lc, *dst_lc;
u_int sx, sy, xoff, yoff;
int src_idx, dst_idx, src_zoomed, dst_zoomed;
int src_idx, dst_idx, flags;
int src_zoomed, dst_zoomed;
dst_w = target->wl->window;
dst_wp = target->wp;
@@ -119,7 +120,7 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
src_zoomed = (args_has(args, 'Z') && (src_w->flags & WINDOW_ZOOMED));
if (src_wp == dst_wp)
if (src_wp == NULL || src_wp == dst_wp)
goto out;
server_client_remove_pane(src_wp);
@@ -145,11 +146,11 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
else
TAILQ_INSERT_AFTER(&dst_w->z_index, tmp_wp, src_wp, zentry);
/* Zoom belongs to the position in the window, like the cell. */
if ((src_wp->flags ^ dst_wp->flags) & PANE_ZOOMED) {
src_wp->flags ^= PANE_ZOOMED;
dst_wp->flags ^= PANE_ZOOMED;
}
/* Zoom and being hidden belong to the position, like the cell. */
flags = (src_wp->flags ^ dst_wp->flags) &
(PANE_ZOOMED|PANE_HIDDEN|PANE_HIDDENALL);
src_wp->flags ^= flags;
dst_wp->flags ^= flags;
src_lc = src_wp->layout_cell;
dst_lc = dst_wp->layout_cell;

View File

@@ -1110,6 +1110,20 @@ format_cb_pane_floating_flag(struct format_tree *ft)
return (NULL);
}
/* Callback for pane_hidden_flag. */
static void *
format_cb_pane_hidden_flag(struct format_tree *ft)
{
struct window_pane *wp = ft->wp;
if (wp != NULL) {
if (wp->flags & PANE_HIDDEN)
return (xstrdup("1"));
return (xstrdup("0"));
}
return (NULL);
}
/* Callback for pane_modal_flag. */
static void *
format_cb_pane_modal_flag(struct format_tree *ft)
@@ -3831,6 +3845,9 @@ static const struct format_table_entry format_table[] = {
{ "pane_height", FORMAT_TABLE_STRING,
format_cb_pane_height
},
{ "pane_hidden_flag", FORMAT_TABLE_STRING,
format_cb_pane_hidden_flag
},
{ "pane_id", FORMAT_TABLE_STRING,
format_cb_pane_id
},

View File

@@ -80,6 +80,7 @@
" 'Respawn' 'R' {respawn-pane -k}" \
" '#{?pane_marked,Unmark,Mark}' 'm' {select-pane -m}" \
" '#{?#{>:#{window_panes},1},,-}#{?pane_zoomed_flag,Unzoom,Zoom}' 'z' {resize-pane -Z}" \
" 'Hide' 'H' {resize-pane -H}" \
" '#{?#{||:#{pane_floating_flag},#{pane_zoomed_flag}},Bring To Front,}' 'F' {move-pane -P front}"
#define DEFAULT_MOVE_MENU \
" 'Centre' 'c' {move-pane -P centre}" \
@@ -397,6 +398,7 @@ key_bindings_init(void)
"bind -N 'Kill current window' & { confirm-before -p\"kill-window #W? (y/n)\" kill-window }",
"bind -N 'Prompt for window index to select' \"'\" { command-prompt -pindex { select-window -t ':%%' } }",
"bind -N 'New floating pane' * { new-pane }",
"bind -N 'Hide pane' _ { resize-pane -H }",
"bind -N 'Toggle pane between floating and tiled' @ { if -F '#{pane_floating_flag}' { join-pane } { break-pane -W } }",
"bind -N 'Switch to previous client' ( { switch-client -p }",
"bind -N 'Switch to next client' ) { switch-client -n }",
@@ -531,7 +533,7 @@ key_bindings_init(void)
"bind -n M-MouseDrag1Border { move-pane -M }",
/* Mouse button 1 down on status line. */
"bind -n MouseDown1Status { switch-client -t= }",
"bind -n MouseDown1Status { if -F '#{==:#{mouse_status_range},desktop}' { resize-pane -a -H } { if -Ft= '#{&&:#{==:#{mouse_status_range},pane},#{&&:#{pane_active},#{!:#{pane_hidden_flag}}}}' { resize-pane -H -t= } { switch-client -t= } } }",
"bind -n C-MouseDown1Status { swap-window -t@ }",
/* Mouse button 1 down on default pane-border-format */

View File

@@ -75,6 +75,7 @@ struct layout_parse_cell_ctx {
int index;
int zindex;
int zoomed;
int hidden;
};
/* Layout parse context. */
@@ -221,7 +222,7 @@ layout_parse_free_ctx(struct layout_parse_ctx *pctx)
/* Add a cell context to the parse context. */
static void
layout_parse_add_cctx(struct layout_parse_ctx *pctx, struct layout_cell *lc,
int active, int last, int index, int zindex, int zoomed)
int active, int last, int index, int zindex, int zoomed, int hidden)
{
struct layout_parse_cell_ctx *cctx;
@@ -238,6 +239,7 @@ layout_parse_add_cctx(struct layout_parse_ctx *pctx, struct layout_cell *lc,
cctx->index = index;
cctx->zindex = zindex;
cctx->zoomed = zoomed;
cctx->hidden = hidden;
}
/* Remove a cell context from the parse context. Does not preserve ordering. */
@@ -429,6 +431,8 @@ layout_append_v2(struct layout_cell *lc, struct layout_string *ls)
layout_string_write(ls, ",\"i\":%u", i);
if (wp->flags & PANE_ZOOMED)
layout_string_write(ls, ",\"Z\":true");
if (wp->flags & PANE_HIDDEN)
layout_string_write(ls, ",\"H\":true");
if (lc->flags & LAYOUT_CELL_FLOATING) {
z = layout_cell_zindex(lc);
layout_string_write(ls, ",\"z\":%u", z);
@@ -481,18 +485,23 @@ layout_append_v1(struct layout_cell *lc, struct layout_string *ls)
}
/*
* Copies the tiled part of a layout. Only populates what is necessary to dump a
* V1 layout string.
* Copies the part of a layout that is shown, which leaves out hidden tiled
* panes and, unless asked to keep them, floating panes. Only populates what is
* necessary to dump a layout string.
*/
static struct layout_cell *
layout_custom_copy_layout(struct layout_cell *lc)
layout_custom_copy_layout(struct layout_cell *lc, int keep_floating)
{
struct layout_cell *lcchild, *lcnewchild, *lconly;
struct layout_cell *lcnew;
if (lc->type == LAYOUT_WINDOWPANE &&
(lc->flags & LAYOUT_CELL_FLOATING))
return (NULL);
if (lc->type == LAYOUT_WINDOWPANE) {
if (lc->flags & LAYOUT_CELL_FLOATING) {
if (!keep_floating)
return (NULL);
} else if (lc->wp != NULL && (lc->wp->flags & PANE_HIDDEN))
return (NULL);
}
lcnew = layout_create_cell(NULL);
@@ -508,7 +517,8 @@ layout_custom_copy_layout(struct layout_cell *lc)
case LAYOUT_TOPBOTTOM:
case LAYOUT_LEFTRIGHT:
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
lcnewchild = layout_custom_copy_layout(lcchild);
lcnewchild = layout_custom_copy_layout(lcchild,
keep_floating);
if (lcnewchild == NULL)
continue;
TAILQ_INSERT_TAIL(&lcnew->cells, lcnewchild, entry);
@@ -534,11 +544,11 @@ layout_custom_copy_layout(struct layout_cell *lc)
/* Create a compatibility layout for dumping a V1 layout string. */
static struct layout_cell *
layout_custom_create_compat(struct layout_cell *lcroot)
layout_custom_create_compat(struct layout_cell *lcroot, int keep_floating)
{
struct layout_cell *lccompat;
lccompat = layout_custom_copy_layout(lcroot);
lccompat = layout_custom_copy_layout(lcroot, keep_floating);
if (lccompat != NULL && layout_cell_is_tiled(lccompat)) {
lccompat->g.xoff = 0;
lccompat->g.yoff = 0;
@@ -586,11 +596,18 @@ layout_append(struct layout_cell *lcroot, struct layout_string *ls, int flags)
if (!layout_cell_is_tiled(lcroot) &&
!layout_cell_has_tiled_child(lcroot))
return (-1);
lccompat = layout_custom_create_compat(lcroot);
lccompat = layout_custom_create_compat(lcroot, 0);
result = layout_append_v1(lccompat, ls);
layout_custom_free_compat(lccompat);
} else
result = layout_append_v2(lcroot, ls);
} else {
lccompat = layout_custom_create_compat(lcroot, 1);
if (lccompat == NULL)
result = layout_append_v2(lcroot, ls);
else {
result = layout_append_v2(lccompat, ls);
layout_custom_free_compat(lccompat);
}
}
return (result);
}
@@ -743,6 +760,12 @@ layout_parse(struct window *w, const char *input, char **cause)
}
}
/* Hidden tiled panes are in the new layout like the rest. */
TAILQ_FOREACH(wp, &w->panes, entry) {
if (!window_pane_is_floating(wp))
wp->flags &= ~(PANE_HIDDEN|PANE_HIDDENALL);
}
/* Destroy the old layout and swap to the new. */
layout_free_cell(w->layout_root, 0);
w->layout_root = lc;
@@ -1018,7 +1041,7 @@ layout_parse_json_layout(struct json_node *node, struct layout_cell *lcparent,
int64_t num;
char **cause = pctx->cause;
int boolean, index, zindex, active = -1;
int last = -1, zoomed = 0;
int last = -1, zoomed, hidden;
if (json_find_string(node, "t", &str, cause) != 0)
goto fail;
@@ -1108,14 +1131,20 @@ layout_parse_json_layout(struct json_node *node, struct layout_cell *lcparent,
} else
zindex = INT_MAX;
zoomed = hidden = 0;
if (json_find(node, "Z") != NULL) {
if (json_find_boolean(node, "Z", &boolean, cause) != 0)
goto fail;
zoomed = boolean;
}
if (json_find(node, "H") != NULL) {
if (json_find_boolean(node, "H", &boolean, cause) != 0)
goto fail;
hidden = boolean;
}
layout_parse_add_cctx(pctx, lc, active, last, index, zindex,
zoomed);
zoomed, hidden);
} else {
if (json_find_array(node, "c", &array, cause) != 0)
goto fail;
@@ -1225,11 +1254,18 @@ layout_parse_apply_ctx(struct window *w, struct layout_parse_ctx *pctx)
TAILQ_INSERT_HEAD(&w->z_index, wp, zentry);
}
/* Zoom panes. */
/* Zoom and hide panes. */
for (i = 0; i < pctx->size; i++) {
cctx = &pctx->cctxs[i];
wp = cctx->lc->wp;
if (cctx->zoomed)
window_zoom(cctx->lc->wp);
window_zoom(wp);
}
for (i = 0; i < pctx->size; i++) {
cctx = &pctx->cctxs[i];
wp = cctx->lc->wp;
if (cctx->hidden && window_pane_is_floating(wp))
window_hide_pane(wp);
}
/* Set the active pane. */

View File

@@ -79,6 +79,7 @@ layout_create_cell(struct layout_cell *lcparent)
layout_geometry_init(&lc->g);
layout_geometry_init(&lc->fg);
layout_geometry_init(&lc->tg);
return (lc);
}
@@ -238,8 +239,9 @@ layout_cell_is_tiled(struct layout_cell *lc)
{
int is_leaf = lc->type == LAYOUT_WINDOWPANE;
int is_floating = lc->flags & LAYOUT_CELL_FLOATING;
int is_hidden = lc->wp != NULL && (lc->wp->flags & PANE_HIDDEN);
return is_leaf && !is_floating;
return is_leaf && !is_floating && !is_hidden;
}
int
@@ -499,6 +501,8 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->layout_cell == NULL || wp == skip)
continue;
if (wp->flags & PANE_HIDDEN)
continue;
old_xoff = wp->xoff;
old_yoff = wp->yoff;

View File

@@ -209,7 +209,10 @@ static const char *options_table_copy_mode_line_numbers_list[] = {
"#{T:window-pane-current-status-format}" \
"#[pop-default]" \
"#[norange list=on default] " \
"}"
"}" \
"#[nolist align=right range=user|desktop]" \
"[_]" \
"#[norange default]"
#define OPTIONS_TABLE_STATUS_FORMAT3 \
"#[align=left]#{R: ,#{n:#{session_name}}}S: " \
"#[norange default]" \

25
tmux.1
View File

@@ -364,6 +364,8 @@ Choose the current window interactively.
Kill the current pane.
.It z
Toggle zoom state of the current pane.
.It _
Hide the current pane.
.It Tab
Choose a new window and session by fuzzy matching.
.It {
@@ -2794,7 +2796,7 @@ If
.Fl d
is given, the active pane is not changed.
The pane must not already be floating.
A zoomed pane stays zoomed.
A hidden or zoomed pane stays hidden or zoomed.
.Tg capturep
.It Xo Ic capture\-pane
.Op Fl aeFHILpPRqCJMN
@@ -3836,7 +3838,7 @@ if specified, to
.Ar new\-name .
.Tg resizep
.It Xo Ic resize\-pane
.Op Fl aMTZ
.Op Fl aHMTZ
.Op Fl D Ar lines
.Op Fl L Ar columns
.Op Fl R Ar columns
@@ -3893,6 +3895,19 @@ with
.Fl Z
unzooms every pane in the window.
.Pp
.Fl H
hides the target pane, or shows it if it is hidden.
A hidden pane is not shown, cannot be selected with the mouse and is skipped
when moving to the next or previous pane, but it is otherwise unchanged: a
hidden tiled pane gives its space to a neighbour and takes it back when shown,
and a pane that is zoomed or floating is still zoomed or floating when shown.
Selecting a hidden pane shows it.
.Fl a
with
.Fl H
hides every floating or zoomed pane in the window, or, if any were hidden in
this way, shows just those again.
.Pp
.Fl M
begins mouse resizing (only valid if bound to a mouse key binding, see
.Sx MOUSE SUPPORT ) .
@@ -6058,8 +6073,9 @@ also raises zoomed panes and
.Ic off
raises none.
A floating or zoomed pane that is covered by a zoomed pane is always raised
when it is made active; a tiled pane that is covered unzooms every pane
instead.
when it is made active, and a hidden pane is shown; a tiled pane that is
covered hides the zoomed panes instead, as the desktop does, so that the tiled
panes are shown, and the desktop shows them again.
Moving the mouse onto a pane with
.Ic focus\-follows\-mouse
makes it active without raising it, so
@@ -7445,6 +7461,7 @@ The following variables are available, where appropriate:
.It Li "pane_floating_flag" Ta "" Ta "1 if pane is floating"
.It Li "pane_format" Ta "" Ta "1 if format is for a pane"
.It Li "pane_height" Ta "" Ta "Height of pane"
.It Li "pane_hidden_flag" Ta "" Ta "1 if pane is hidden"
.It Li "pane_id" Ta "#D" Ta "Unique pane ID"
.It Li "pane_in_mode" Ta "" Ta "Number of modes pane is in"
.It Li "pane_index" Ta "#P" Ta "Index of pane"

5
tmux.h
View File

@@ -1348,6 +1348,8 @@ struct window_pane {
#define PANE_CAPTUREALLKEYS 0x100000
#define PANE_FLOATOVERZOOM 0x200000
#define PANE_CLOSEONCANCEL 0x400000
#define PANE_HIDDEN 0x800000
#define PANE_HIDDENALL 0x1000000
bitstr_t *sync_dirty;
u_int sync_dirty_size;
@@ -1593,6 +1595,7 @@ struct layout_cell {
struct layout_geometry g;
struct layout_geometry fg; /* saved floating pane */
struct layout_geometry tg; /* saved tiled pane, when hidden */
struct window_pane *wp;
struct layout_cells cells;
@@ -3721,6 +3724,8 @@ struct window_pane *window_add_pane(struct window *, struct window_pane *,
u_int, int);
void window_resize(struct window *, u_int, u_int, int, int);
void window_pane_send_resize(struct window_pane *, u_int, u_int);
void window_hide_pane(struct window_pane *);
int window_show_pane(struct window_pane *);
void window_raise_pane(struct window_pane *);
void window_lower_pane(struct window_pane *);
int window_zoom(struct window_pane *);

116
window.c
View File

@@ -677,7 +677,7 @@ window_pane_floating_overlaps(struct window_pane *fwp, struct window_pane *wp)
int fxoff, fyoff, xoff, yoff, border = 0;
u_int fsx, fsy, sx, sy;
if (!window_pane_is_raised(fwp))
if (!window_pane_is_raised(fwp) || !window_pane_is_visible(fwp))
return (0);
window_pane_full_size_offset(fwp, &fxoff, &fyoff, &fsx, &fsy);
@@ -763,10 +763,12 @@ window_activate_pane(struct window *w, struct window_pane *wp, int notify,
log_debug("%s: pane %%%u", __func__, wp->id);
if (wp == w->active)
return (0);
if (w->modal != NULL && wp != w->modal)
return (0);
if (wp->flags & PANE_HIDDEN)
window_show_pane(wp);
if (wp == w->active)
return (0);
if (!window_pane_is_visible(wp)) {
/*
* The pane is covered by a zoomed pane. A tiled pane that is
@@ -1012,6 +1014,82 @@ window_raise_pane(struct window_pane *wp)
redraw_invalidate_scene(w);
}
/*
* Hide a pane. It keeps its place in the layout and in the stacking order and
* stays zoomed or floating, so showing it again puts it back as it was.
*/
void
window_hide_pane(struct window_pane *wp)
{
struct window *w = wp->window;
struct layout_cell *lc = wp->layout_cell;
struct window_pane *wp1;
if ((wp->flags & PANE_HIDDEN) || wp == w->modal || lc == NULL)
return;
/* A tiled pane gives its space to a neighbour. */
if (layout_cell_is_tiled(lc)) {
memcpy(&lc->tg, &lc->g, sizeof lc->tg);
layout_remove_tile(w, lc);
}
wp->flags |= PANE_HIDDEN;
layout_fix_offsets(w);
layout_fix_panes(w, NULL);
/* Move the focus to the last used pane or the top one that is seen. */
if (wp == w->active) {
TAILQ_FOREACH(wp1, &w->last_panes, sentry) {
if (wp1 != wp && window_pane_is_visible(wp1))
break;
}
if (wp1 == NULL) {
TAILQ_FOREACH(wp1, &w->z_index, zentry) {
if (wp1 != wp && window_pane_is_visible(wp1))
break;
}
}
if (wp1 != NULL)
window_set_active_pane(w, wp1, 1);
}
events_fire_window("window-layout-changed", w);
redraw_invalidate_scene(w);
server_redraw_window(w);
}
/* Show a hidden pane. Returns -1 if a tiled pane has no room. */
int
window_show_pane(struct window_pane *wp)
{
struct window *w = wp->window;
struct layout_cell *lc = wp->layout_cell;
int tiled;
if (~wp->flags & PANE_HIDDEN)
return (0);
tiled = (lc != NULL && !window_pane_is_floating(wp));
if (tiled && layout_insert_tile(w, lc) != 0)
return (-1);
wp->flags &= ~(PANE_HIDDEN|PANE_HIDDENALL);
/* Try to get back the size the pane had. */
if (tiled && lc->parent != NULL && lc->tg.sx != UINT_MAX) {
if (lc->parent->type == LAYOUT_LEFTRIGHT)
layout_resize_pane_to(wp, lc->parent->type, lc->tg.sx);
else
layout_resize_pane_to(wp, lc->parent->type, lc->tg.sy);
}
layout_fix_offsets(w);
layout_fix_panes(w, NULL);
events_fire_window("window-layout-changed", w);
redraw_invalidate_scene(w);
server_redraw_window(w);
return (0);
}
/* Move a pane to the back of the panes it is stacked with. */
void
window_lower_pane(struct window_pane *wp)
@@ -1150,7 +1228,7 @@ window_zoomed_pane(struct window *w)
if (~w->flags & WINDOW_ZOOMED)
return (NULL);
TAILQ_FOREACH(wp, &w->z_index, zentry) {
if (wp->flags & PANE_ZOOMED)
if ((wp->flags & PANE_ZOOMED) && (~wp->flags & PANE_HIDDEN))
return (wp);
}
return (NULL);
@@ -1296,9 +1374,14 @@ window_pane_at_index(struct window *w, u_int idx)
struct window_pane *
window_pane_next_by_number(struct window *w, struct window_pane *wp, u_int n)
{
struct window_pane *start;
for (; n > 0; n--) {
if ((wp = TAILQ_NEXT(wp, entry)) == NULL)
wp = TAILQ_FIRST(&w->panes);
start = wp;
do {
if ((wp = TAILQ_NEXT(wp, entry)) == NULL)
wp = TAILQ_FIRST(&w->panes);
} while ((wp->flags & PANE_HIDDEN) && wp != start);
}
return (wp);
@@ -1308,9 +1391,15 @@ struct window_pane *
window_pane_previous_by_number(struct window *w, struct window_pane *wp,
u_int n)
{
struct window_pane *start;
for (; n > 0; n--) {
if ((wp = TAILQ_PREV(wp, window_panes, entry)) == NULL)
wp = TAILQ_LAST(&w->panes, window_panes);
start = wp;
do {
wp = TAILQ_PREV(wp, window_panes, entry);
if (wp == NULL)
wp = TAILQ_LAST(&w->panes, window_panes);
} while ((wp->flags & PANE_HIDDEN) && wp != start);
}
return (wp);
@@ -1375,7 +1464,10 @@ window_count_panes(struct window *w, int with_floating)
u_int n = 0;
TAILQ_FOREACH(wp, &w->panes, entry) {
if (with_floating || !window_pane_is_floating(wp))
if (with_floating)
n++;
else if (!window_pane_is_floating(wp) &&
(~wp->flags & PANE_HIDDEN))
n++;
}
return (n);
@@ -1444,6 +1536,8 @@ window_pane_printable_flags(struct window_pane *wp)
flags[pos++] = 'Z';
if (window_pane_is_floating(wp))
flags[pos++] = 'F';
if (wp->flags & PANE_HIDDEN)
flags[pos++] = 'H';
if (wp->flags & PANE_FLOATOVERZOOM)
flags[pos++] = 'A';
if (wp == w->modal)
@@ -2155,6 +2249,8 @@ window_pane_is_visible(struct window_pane *wp)
struct window *w = wp->window;
struct window_pane *wp1;
if (wp->flags & PANE_HIDDEN)
return (0);
if (~w->flags & WINDOW_ZOOMED)
return (1);
@@ -2162,7 +2258,7 @@ window_pane_is_visible(struct window_pane *wp)
TAILQ_FOREACH(wp1, &w->z_index, zentry) {
if (wp1 == wp)
return (1);
if (wp1->flags & PANE_ZOOMED)
if ((wp1->flags & PANE_ZOOMED) && (~wp1->flags & PANE_HIDDEN))
return (0);
}
return (1);