From 195a9b357a440607c1ecc9bde2f5df08ce66ddf9 Mon Sep 17 00:00:00 2001 From: Dane Jensen Date: Wed, 10 Jun 2026 23:13:49 -0700 Subject: [PATCH] `hide-pane` and `show-pane` now use the new layout mechanics. --- cmd-hide-pane.c | 176 +++++++++++++++++++++++------------------------- format.c | 2 +- layout.c | 127 ++-------------------------------- screen-write.c | 2 +- tmux.h | 3 - window.c | 51 ++++++-------- 6 files changed, 111 insertions(+), 250 deletions(-) diff --git a/cmd-hide-pane.c b/cmd-hide-pane.c index e9a9fe1d..131efa48 100644 --- a/cmd-hide-pane.c +++ b/cmd-hide-pane.c @@ -27,12 +27,8 @@ * Hide or show panes. */ -static enum cmd_retval cmd_hide_pane_hide_exec(struct cmd *, struct cmdq_item *); -static enum cmd_retval cmd_hide_pane_show_exec(struct cmd *, struct cmdq_item *); - -static enum cmd_retval cmd_hide_pane_hide(struct window *, struct window_pane *, - struct cmdq_item *); -static enum cmd_retval cmd_hide_pane_show(struct window *, struct window_pane *); +static enum cmd_retval cmd_hide_pane_exec(struct cmd *, struct cmdq_item *); +static enum cmd_retval cmd_show_pane_exec(struct cmd *, struct cmdq_item *); const struct cmd_entry cmd_hide_pane_entry = { .name = "hide-pane", @@ -44,7 +40,7 @@ const struct cmd_entry cmd_hide_pane_entry = { .target = { 't', CMD_FIND_PANE, 0 }, .flags = CMD_AFTERHOOK, - .exec = cmd_hide_pane_hide_exec + .exec = cmd_hide_pane_exec }; const struct cmd_entry cmd_show_pane_entry = { @@ -57,12 +53,61 @@ const struct cmd_entry cmd_show_pane_entry = { .target = { 't', CMD_FIND_PANE, 0 }, .flags = CMD_AFTERHOOK, - .exec = cmd_hide_pane_show_exec + .exec = cmd_show_pane_exec }; +static enum cmd_retval +cmd_hide_pane_hide(struct window *w, struct window_pane *wp) +{ + struct window_pane *wpp = NULL; + struct layout_cell *lc = wp->layout_cell; + + if (window_pane_is_hidden(wp)) + return (CMD_RETURN_NORMAL); + + if (wp == w->active) { + /* Find previous active pane. */ + TAILQ_FOREACH(wpp, &w->last_panes, sentry) { + if (wpp != wp && window_pane_visible(wpp)) + break; + } + if (wpp == NULL) { + TAILQ_FOREACH(wpp, &w->z_index, zentry) { + if (wpp != wp && + window_pane_visible(wpp)) + break; + } + } + } + + lc->flags |= LAYOUT_CELL_HIDDEN; + + layout_remove_tile(w, lc); + layout_fix_offsets(w); + layout_fix_panes(w, NULL); + + window_pane_stack_remove(&w->last_panes, wp); + if (wpp != NULL) { + window_set_active_pane(w, wpp, 1); + } else if (wp == w->active) { + /* No visible previous active pane; null active pane + * to show dots background. */ + w->active = NULL; + if (options_get_number(global_options, "focus-events")) + window_pane_update_focus(wp); + notify_window("window-pane-changed", w); + notify_window("window-layout-changed", w); + server_redraw_window(w); + } else { + notify_window("window-layout-changed", w); + server_redraw_window(w); + } + + return (CMD_RETURN_NORMAL); +} static enum cmd_retval -cmd_hide_pane_hide_exec(struct cmd *self, struct cmdq_item *item) +cmd_hide_pane_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); struct cmd_find_state *target = cmdq_get_target(item); @@ -73,11 +118,13 @@ cmd_hide_pane_hide_exec(struct cmd *self, struct cmdq_item *item) char *cause = NULL; enum cmd_retval rv; + window_unzoom(w, 1); + if (args_has(args, 'a')) { TAILQ_FOREACH(wp, &w->z_index, zentry) { if (!window_pane_visible(wp) || wp == active_pane) continue; - rv = cmd_hide_pane_hide(w, wp, item); + rv = cmd_hide_pane_hide(w, wp); if (rv != CMD_RETURN_NORMAL) return (rv); } @@ -97,12 +144,34 @@ cmd_hide_pane_hide_exec(struct cmd *self, struct cmdq_item *item) cmdq_error(item, "No target pane to hide."); return (CMD_RETURN_ERROR); } - return (cmd_hide_pane_hide(w, wp, item)); + return (cmd_hide_pane_hide(w, wp)); } } static enum cmd_retval -cmd_hide_pane_show_exec(struct cmd *self, struct cmdq_item *item) +cmd_hide_pane_show(struct window *w, struct window_pane *wp) +{ + struct layout_cell *lc = wp->layout_cell; + + if (!window_pane_is_hidden(wp)) + return (CMD_RETURN_NORMAL); + + lc->flags &= ~LAYOUT_CELL_HIDDEN; + + layout_insert_tile(w, lc); + layout_fix_offsets(w); + layout_fix_panes(w, NULL); + + window_set_active_pane(w, wp, 1); + + notify_window("window-layout-changed", w); + server_redraw_window(w); + + return (CMD_RETURN_NORMAL); +} + +static enum cmd_retval +cmd_show_pane_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); struct cmd_find_state *target = cmdq_get_target(item); @@ -113,6 +182,8 @@ cmd_hide_pane_show_exec(struct cmd *self, struct cmdq_item *item) char *cause = NULL; enum cmd_retval rv; + window_unzoom(w, 1); + if (args_has(args, 'a')) { TAILQ_FOREACH(wp, &w->z_index, zentry) { if (!window_pane_visible(wp)) @@ -140,84 +211,3 @@ cmd_hide_pane_show_exec(struct cmd *self, struct cmdq_item *item) return (cmd_hide_pane_show(w, wp)); } } - -static enum cmd_retval -cmd_hide_pane_hide(struct window *w, struct window_pane *wp, - __unused struct cmdq_item *item) -{ - struct window_pane *pwp = NULL; - - if (wp->flags & PANE_HIDDEN) - return (CMD_RETURN_NORMAL); - - if (wp == w->active) { - /* - * Unzoom before searching: under zoom, window_pane_visible - * returns false for every non-active pane. - */ - if (w->flags & WINDOW_ZOOMED) - window_unzoom(w, 1); - /* Find previous active pane. */ - TAILQ_FOREACH(pwp, &w->last_panes, sentry) { - if (pwp != wp && window_pane_visible(pwp)) - break; - } - if (pwp == NULL) { - TAILQ_FOREACH(pwp, &w->z_index, zentry) { - if (pwp != wp && - window_pane_visible(pwp)) - break; - } - } - } - - wp->flags |= PANE_HIDDEN; - - if (w->layout_root != NULL) { - wp->saved_layout_cell = wp->layout_cell; - layout_hide_cell(w, wp->layout_cell); - layout_fix_offsets(w); - layout_fix_panes(w, NULL); - } - - window_pane_stack_remove(&w->last_panes, wp); - if (pwp != NULL) { - window_set_active_pane(w, pwp, 1); - } else if (wp == w->active) { - /* No visible previous active pane; null active pane - * to show dots background. */ - w->active = NULL; - if (options_get_number(global_options, "focus-events")) - window_pane_update_focus(wp); - notify_window("window-pane-changed", w); - notify_window("window-layout-changed", w); - server_redraw_window(w); - } else { - notify_window("window-layout-changed", w); - server_redraw_window(w); - } - - return (CMD_RETURN_NORMAL); -} - -static enum cmd_retval -cmd_hide_pane_show(struct window *w, struct window_pane *wp) -{ - wp->flags &= ~PANE_HIDDEN; - - /* Fix pane offsets and sizes. */ - if (w->layout_root != NULL && wp->saved_layout_cell != NULL) { - wp->layout_cell = wp->saved_layout_cell; - wp->saved_layout_cell = NULL; - layout_show_cell(w, wp->layout_cell); - layout_fix_offsets(w); - layout_fix_panes(w, NULL); - } - - window_set_active_pane(w, wp, 1); - - notify_window("window-layout-changed", w); - server_redraw_window(w); - - return (CMD_RETURN_NORMAL); -} diff --git a/format.c b/format.c index 898a2667..aa49ceb5 100644 --- a/format.c +++ b/format.c @@ -2155,7 +2155,7 @@ format_cb_pane_hidden_flag(struct format_tree *ft) struct window_pane *wp = ft->wp; if (wp != NULL) { - if (wp->flags & PANE_HIDDEN) + if (window_pane_is_hidden(wp)) return (xstrdup("1")); return (xstrdup("0")); } diff --git a/layout.c b/layout.c index 2658d30d..7af5b9ce 100644 --- a/layout.c +++ b/layout.c @@ -435,7 +435,8 @@ layout_fix_panes(struct window *w, struct window_pane *skip) sb_pos = options_get_number(w->options, "pane-scrollbars-position"); TAILQ_FOREACH(wp, &w->panes, entry) { - if ((lc = wp->layout_cell) == NULL || wp == skip) + if ((lc = wp->layout_cell) == NULL || wp == skip || + !window_pane_visible(wp)) continue; wp->xoff = lc->xoff; @@ -625,62 +626,6 @@ layout_resize_set_size(struct window *w, struct layout_cell *lc, layout_resize_adjust(w, lc, type, change); } -/* - * Redistribute space equally among all visible (non-hidden WINDOWPANE) - * children of lcparent in the given direction. Hidden WINDOWPANE leaves - * are skipped; their stored sizes are left untouched. Container children - * have their own children resized proportionally via layout_resize_child_cells. - * - * If all children happen to be hidden (n==0), nothing is done. - */ -void -layout_redistribute_cells(struct window *w, struct layout_cell *lcparent, - enum layout_type type) -{ - struct layout_cell *lc; - u_int n, total, each, rem, i, target; - - /* Count visible cells at this level. */ - n = 0; - TAILQ_FOREACH(lc, &lcparent->cells, entry) { - if (lc->type == LAYOUT_WINDOWPANE && - lc->wp != NULL && - (lc->wp->flags & PANE_HIDDEN)) - continue; - n++; - } - if (n == 0) - return; - - total = (type == LAYOUT_LEFTRIGHT) ? lcparent->sx : lcparent->sy; - if (total + 1 < n) /* can't fit even the minimum borders */ - return; - - /* - * each * n + (n-1) borders = total - * → each = (total - (n-1)) / n, rem = (total - (n-1)) % n - * The first `rem` visible cells get (each+1) to consume the remainder. - */ - each = (total - (n - 1)) / n; - rem = (total - (n - 1)) % n; - - i = 0; - TAILQ_FOREACH(lc, &lcparent->cells, entry) { - if (lc->type == LAYOUT_WINDOWPANE && - lc->wp != NULL && - (lc->wp->flags & PANE_HIDDEN)) - continue; - target = each + (i < rem ? 1 : 0); - if (type == LAYOUT_LEFTRIGHT) - lc->sx = target; - else - lc->sy = target; - if (lc->type != LAYOUT_WINDOWPANE) - layout_resize_child_cells(w, lc); - i++; - } -} - /* 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) @@ -790,71 +735,6 @@ out: } } - -/* Hide a cell. Space is redistributed to the nearest neighbour if the cell was - * tiled. - */ -void -layout_hide_cell(struct window *w, struct layout_cell *lc) -{ - struct layout_cell *lcother, *lcparent, *lcchild; - u_int shown_children = 0; - int val; - - if (lc == NULL) - return; - - lcparent = lc->parent; - lc->flags |= LAYOUT_CELL_HIDDEN; - - /* Merge the space into the nearest neighbour. */ - lcother = layout_cell_get_neighbour(lc); - - if (lcother != NULL) { - if (lcparent->type == LAYOUT_LEFTRIGHT) - val = lc->sx + 1; - else - val = lc->sy + 1; - layout_resize_adjust(w, lcother, lcparent->type, val); - } - - if (layout_cell_is_tiled(lc)) - layout_set_size(lc, 0, 0, 0, 0); - - /* If no children are tiled, hide the parent. */ - if (lcparent != NULL) { - TAILQ_FOREACH(lcchild, &lcparent->cells, entry) { - if (layout_cell_is_tiled(lcchild)) { - shown_children = 1; - break; - } - } - if (shown_children == 0) - layout_hide_cell(w, lcparent); - } -} - -/* Show a cell and redistribute the space in tiled cells. */ -void -layout_show_cell(struct window *w, struct layout_cell *lc) -{ - struct layout_cell *lcparent; - - if (lc == NULL) - return; - lcparent = lc->parent; - if (lcparent == NULL) - return; - - /* - * Redistribute the parent's space equally among all visible (non- - * hidden) children, including lc which has just been shown. - * This ensures every pane at this level gets an equal share rather - * than one pane losing most of its space to the restored pane. - */ - layout_redistribute_cells(w, lcparent, lcparent->type); -} - /* Initialize layout for pane. */ void layout_init(struct window *w, struct window_pane *wp) @@ -1866,6 +1746,9 @@ layout_insert_tile(struct window *w, struct layout_cell *lc) if (lc == NULL) fatalx("layout cell cannot be null when tiling"); + if (lc->flags & LAYOUT_CELL_FLOATING) + return (1); + if (lcparent == NULL) { /* Only pane in the layout. */ layout_set_size(lc, w->sx, w->sy, 0, 0); diff --git a/screen-write.c b/screen-write.c index 55244ce7..0b6db4e3 100644 --- a/screen-write.c +++ b/screen-write.c @@ -146,7 +146,7 @@ screen_write_set_client_cb(struct tty_ctx *ttyctx, struct client *c) if (wp->layout_cell == NULL) return (0); - if (wp->flags & PANE_HIDDEN) + if (window_pane_is_hidden(wp)) return (0); if (wp->flags & (PANE_REDRAW|PANE_DROP)) diff --git a/tmux.h b/tmux.h index ed131e9f..b4788b5e 100644 --- a/tmux.h +++ b/tmux.h @@ -1289,7 +1289,6 @@ struct window_pane { #define PANE_THEMECHANGED 0x2000 #define PANE_UNSEENCHANGES 0x4000 #define PANE_REDRAWSCROLLBAR 0x8000 -#define PANE_HIDDEN 0x20000 /* Last floating position/size, saved when the pane is tiled. */ int saved_float_xoff; @@ -3545,8 +3544,6 @@ void layout_destroy_cell(struct window *, struct layout_cell *, struct layout_cell **); void layout_hide_cell(struct window *, struct layout_cell *); void layout_show_cell(struct window *, struct layout_cell *); -void layout_redistribute_cells(struct window *, struct layout_cell *, - enum layout_type); void layout_resize_layout(struct window *, struct layout_cell *, enum layout_type, int, int); struct layout_cell *layout_search_by_border(struct layout_cell *, u_int, u_int); diff --git a/window.c b/window.c index 481cea82..6f6f42f9 100644 --- a/window.c +++ b/window.c @@ -543,7 +543,8 @@ window_pane_update_focus(struct window_pane *wp) int window_set_active_pane(struct window *w, struct window_pane *wp, int notify) { - struct window_pane *lastwp; + struct window_pane *lastwp; + struct layout_cell *lc; log_debug("%s: pane %%%u", __func__, wp->id); @@ -557,18 +558,15 @@ window_set_active_pane(struct window *w, struct window_pane *wp, int notify) window_pane_stack_push(&w->last_panes, lastwp); w->active = wp; - w->active->active_point = next_active_point++; - w->active->flags |= PANE_CHANGED; + wp->active_point = next_active_point++; + wp->flags |= PANE_CHANGED; + lc = wp->layout_cell; - if (wp->flags & PANE_HIDDEN) { - wp->flags &= ~PANE_HIDDEN; - if (w->layout_root != NULL && wp->saved_layout_cell != NULL) { - wp->layout_cell = wp->saved_layout_cell; - wp->saved_layout_cell = NULL; - layout_show_cell(w, wp->layout_cell); - layout_fix_offsets(w); - layout_fix_panes(w, NULL); - } + if (window_pane_is_hidden(wp)) { + lc->flags &= ~LAYOUT_CELL_HIDDEN; + layout_insert_tile(w, lc); + layout_fix_offsets(w); + layout_fix_panes(w, NULL); } notify_window("window-layout-changed", w); server_redraw_window(w); @@ -864,19 +862,19 @@ window_lost_pane(struct window *w, struct window_pane *wp) /* Try to find a good fit. */ wpp = TAILQ_FIRST(&w->last_panes); - if (wpp == NULL || wpp->flags & PANE_HIDDEN) { + if (wpp == NULL || window_pane_is_hidden(wpp)) { wpp = TAILQ_PREV(wp, window_panes, entry); - if (wpp == NULL || wpp->flags & PANE_HIDDEN) + if (wpp == NULL || window_pane_is_hidden(wpp)) wpp = TAILQ_NEXT(wp, entry); } /* Try to find any fit. */ - if (wpp == NULL || (wpp->flags & PANE_HIDDEN)) { + if (wpp == NULL || window_pane_is_hidden(wpp)) { TAILQ_FOREACH_SAFE(wpp, &w->panes, entry, twpp) { - if (wpp != wp && (~wpp->flags & PANE_HIDDEN)) + if (wpp != wp && !window_pane_is_hidden(wpp)) break; } } - if (wpp != NULL && (wpp->flags & PANE_HIDDEN)) + if (wpp != NULL && window_pane_is_hidden(wpp)) wpp = NULL; w->active = wpp; @@ -1046,7 +1044,7 @@ 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) + if (window_pane_is_hidden(wp)) flags[pos++] = 'm'; flags[pos] = '\0'; @@ -1463,8 +1461,9 @@ window_pane_key(struct window_pane *wp, struct client *c, struct session *s, int window_pane_visible(struct window_pane *wp) { - if (~wp->window->flags & WINDOW_ZOOMED && - ~wp->flags & PANE_HIDDEN) + if (window_pane_is_hidden(wp)) + return (0); + if (~wp->window->flags & WINDOW_ZOOMED) return (1); return (wp == wp->window->active); @@ -2202,19 +2201,11 @@ window_get_pane_status(struct window *w) int window_pane_is_floating(struct window_pane *wp) { - struct layout_cell *lc = wp->layout_cell; - - if (lc == NULL || (lc->flags & LAYOUT_CELL_FLOATING) == 0) - return (0); - return (1); + return (wp->layout_cell->flags & LAYOUT_CELL_FLOATING); } int window_pane_is_hidden(struct window_pane *wp) { - struct layout_cell *lc = wp->layout_cell; - - if ((lc->flags & LAYOUT_CELL_HIDDEN) == 0) - return (0); - return (1); + return (wp->layout_cell->flags & LAYOUT_CELL_HIDDEN); }