diff --git a/cmd-join-pane.c b/cmd-join-pane.c index d9bcaee8b..55fde2b7c 100644 --- a/cmd-join-pane.c +++ b/cmd-join-pane.c @@ -459,7 +459,7 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item) struct window_pane *src_wp, *dst_wp; const char *s; char *cause = NULL; - int flags = 0, dst_idx; + int flags = 0, dst_idx, raised; struct layout_cell *lc; dst_s = target->s; @@ -479,17 +479,22 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item) args_has(args, 'D') || args_has(args, 'L') || args_has(args, 'R')) { - if (!window_pane_is_floating(dst_wp)) { + s = args_get(args, 'P'); + if (args_has(args, 'z') || + (s != NULL && cmd_join_pane_is_stacking(s))) + raised = window_pane_is_raised(dst_wp); + else + raised = window_pane_is_floating(dst_wp); + if (!raised) { cmdq_error(item, "pane is not floating"); return (CMD_RETURN_ERROR); } /* Moving unzooms a zoomed pane; reordering does not. */ - s = args_get(args, 'P'); if ((dst_wp->flags & PANE_ZOOMED) && !args_has(args, 'z') && (s == NULL || !cmd_join_pane_is_stacking(s))) window_unzoom_pane(dst_wp, 1); - if ((s = args_get(args, 'P')) != NULL) + if (s != NULL) return (cmd_join_pane_place(item, dst_wl, dst_wp, s)); if ((s = args_get(args, 'z')) != NULL) return (cmd_join_pane_zindex(item, dst_wl, dst_wp, s)); diff --git a/key-bindings.c b/key-bindings.c index 786017407..55f016879 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -79,7 +79,8 @@ " 'Kill' 'X' {kill-pane}" \ " 'Respawn' 'R' {respawn-pane -k}" \ " '#{?pane_marked,Unmark,Mark}' 'm' {select-pane -m}" \ - " '#{?#{>:#{window_panes},1},,-}#{?window_zoomed_flag,Unzoom,Zoom}' 'z' {resize-pane -Z}" + " '#{?#{>:#{window_panes},1},,-}#{?pane_zoomed_flag,Unzoom,Zoom}' 'z' {resize-pane -Z}" \ + " '#{?#{||:#{pane_floating_flag},#{pane_zoomed_flag}},Bring To Front,}' 'F' {move-pane -P front}" #define DEFAULT_MOVE_MENU \ " 'Centre' 'c' {move-pane -P centre}" \ " ''" \ @@ -536,6 +537,8 @@ key_bindings_init(void) /* Mouse button 1 down on default pane-border-format */ "bind -n MouseDown1Control9 { display-menu -t= -xM -yM -O -T 'Kill pane #{pane_index}?' 'Yes' 'y' { kill-pane -t= } 'No' 'n' {}}", "bind -n MouseDown1Control8 { resize-pane -Z }", + "bind -n M-MouseDown1Control8 { move-pane -P front }", + "bind -n S-MouseDown1Control8 { move-pane -P front }", "bind -n MouseDown1Control7 { if -Ft= '#{pane_floating_flag}' { join-pane } { break-pane -W } }", /* Mouse wheel down on status line. */ diff --git a/layout-custom.c b/layout-custom.c index f903ddab8..8a03d022c 100644 --- a/layout-custom.c +++ b/layout-custom.c @@ -74,6 +74,7 @@ struct layout_parse_cell_ctx { int last; int index; int zindex; + int zoomed; }; /* Layout parse context. */ @@ -220,7 +221,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 active, int last, int index, int zindex, int zoomed) { struct layout_parse_cell_ctx *cctx; @@ -236,6 +237,7 @@ layout_parse_add_cctx(struct layout_parse_ctx *pctx, struct layout_cell *lc, cctx->last = last; cctx->index = index; cctx->zindex = zindex; + cctx->zoomed = zoomed; } /* Remove a cell context from the parse context. Does not preserve ordering. */ @@ -423,6 +425,8 @@ layout_append_v2(struct layout_cell *lc, struct layout_string *ls) if (window_pane_index(wp, &i) != 0) return (-1); layout_string_write(ls, ",\"i\":%u", i); + if (wp->flags & PANE_ZOOMED) + layout_string_write(ls, ",\"Z\":true"); if (lc->flags & LAYOUT_CELL_FLOATING) { z = layout_cell_zindex(lc); layout_string_write(ls, ",\"z\":%u", z); @@ -1012,7 +1016,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; + int last = -1, zoomed = 0; if (json_find_string(node, "t", &str, cause) != 0) goto fail; @@ -1102,7 +1106,14 @@ layout_parse_json_layout(struct json_node *node, struct layout_cell *lcparent, } else zindex = INT_MAX; - layout_parse_add_cctx(pctx, lc, active, last, index, zindex); + if (json_find(node, "Z") != NULL) { + if (json_find_boolean(node, "Z", &boolean, cause) != 0) + goto fail; + zoomed = boolean; + } + + layout_parse_add_cctx(pctx, lc, active, last, index, zindex, + zoomed); } else { if (json_find_array(node, "c", &array, cause) != 0) goto fail; @@ -1212,6 +1223,13 @@ layout_parse_apply_ctx(struct window *w, struct layout_parse_ctx *pctx) TAILQ_INSERT_HEAD(&w->z_index, wp, zentry); } + /* Zoom panes. */ + for (i = 0; i < pctx->size; i++) { + cctx = &pctx->cctxs[i]; + if (cctx->zoomed) + window_zoom(cctx->lc->wp); + } + /* Set the active pane. */ for (i = 0; i < pctx->size; i++) { cctx = &pctx->cctxs[i]; diff --git a/regress/layout-custom.sh b/regress/layout-custom.sh index d6e5ae664..be5f79bef 100644 --- a/regress/layout-custom.sh +++ b/regress/layout-custom.sh @@ -729,7 +729,8 @@ for flags in '' A mixed; do legacy=$(v1_layout L:zoom) check_ok resize-pane -Z -t "L:zoom.$pane" during=$(raw_layout L:zoom) - must_equal 'Layout while zoomed' "$during" "$before" + must_equal 'Layout while zoomed' \ + "$(echo "$during" | sed 's/"Z":true,//')" "$before" must_equal 'Legacy layout while zoomed' \ "$(v1_layout L:zoom)" "$legacy" must_equal 'Zoom after dumping layout' \ @@ -738,6 +739,9 @@ for flags in '' A mixed; do "$(visible_layout L:zoom)" "$(layout L:zoom)" check_ok select-layout -t L:zoom "$during" must_equal 'Round trip from zoomed layout' \ + "$(raw_layout L:zoom)" "$during" + check_ok resize-pane -a -Z -t L:zoom + must_equal 'Unzoomed after round trip' \ "$(raw_layout L:zoom)" "$before" done check_ok kill-window -t L:zoom diff --git a/tmux.1 b/tmux.1 index 88eb9e7f3..9492ea8a6 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1742,7 +1742,8 @@ or to change session, window and pane. In that case, .Fl Z -keeps the window zoomed if it was zoomed. +moves the zoom to the pane selected if it was covered by a zoomed pane, +instead of the window being unzoomed. If .Fl l , .Fl n @@ -2792,8 +2793,8 @@ options. If .Fl d is given, the active pane is not changed. -The pane must not already be floating or hidden, and the window must not -be zoomed. +The pane must not already be floating. +A zoomed pane stays zoomed. .Tg capturep .It Xo Ic capture\-pane .Op Fl aeFHILpPRqCJMN @@ -3348,7 +3349,8 @@ Only windows for which the filter is true are killed. .D1 Pq alias: Ic lastp Select the last (previously selected) pane. .Fl Z -keeps the window zoomed if it was zoomed. +moves the zoom to the pane selected if it was covered by a zoomed pane, +instead of the window being unzoomed. .Fl e enables or .Fl d @@ -3527,10 +3529,10 @@ which may be one of: .It Li "top-right-centre" Ta "Centre of top-right quadrant" .It Li "bottom-left-centre" Ta "Centre of bottom-left quadrant" .It Li "bottom-right-centre" Ta "Centre of bottom-right quadrant" -.It Li "front" Ta "Front of floating panes" -.It Li "back" Ta "Back of floating panes" -.It Li "forward" Ta "Forward one floating pane" -.It Li "backward" Ta "Backward one floating pane" +.It Li "front" Ta "Front of floating and zoomed panes" +.It Li "back" Ta "Back of floating and zoomed panes" +.It Li "forward" Ta "Forward one floating or zoomed pane" +.It Li "backward" Ta "Backward one floating or zoomed pane" .It Li "forward-loop" Ta "Forward but back if already at front" .It Li "backward-loop" Ta "Backward but front if already at back" .El @@ -3711,7 +3713,9 @@ sets the pane border lines for floating panes; see may be used when bound to a mouse drag key; the new floating pane is resized to follow the mouse drag. .Fl A -creates a floating pane which remains visible above a zoomed pane. +creates a floating pane which is always on top: it stays in front of other +floating and zoomed panes, apart from a modal pane, even when they are +selected or zoomed. .Fl O creates a modal pane. A modal pane is always the active pane and prevents interaction with any other @@ -3832,7 +3836,7 @@ if specified, to .Ar new\-name . .Tg resizep .It Xo Ic resize\-pane -.Op Fl MTZ +.Op Fl aMTZ .Op Fl D Ar lines .Op Fl L Ar columns .Op Fl R Ar columns @@ -3879,8 +3883,15 @@ and target their respective borders, and negative values may be given. With .Fl Z , -the active pane is toggled between zoomed (occupying the whole of the window) -and unzoomed (its normal position in the layout). +the target pane is toggled between zoomed (occupying the whole of the window +above the layout and above any panes behind it in the stacking order) and +unzoomed (its normal position). +Any number of panes may be zoomed and a zoomed pane may be floating or tiled; +floating panes in front of a zoomed pane stay visible above it. +.Fl a +with +.Fl Z +unzooms every pane in the window. .Pp .Fl M begins mouse resizing (only valid if bound to a mouse key binding, see @@ -3991,7 +4002,8 @@ lower) with .Fl U or downward (numerically higher). .Fl Z -keeps the window zoomed if it was zoomed. +moves the zoom to the pane selected if it was covered by a zoomed pane, +instead of the window being unzoomed. .Tg selectl .It Xo Ic select\-layout .Op Fl Enop @@ -4034,7 +4046,8 @@ or is used, respectively the pane below, to the left, to the right, or above the target pane is used. .Fl Z -keeps the window zoomed if it was zoomed. +moves the zoom to the pane selected if it was covered by a zoomed pane, +instead of the window being unzoomed. .Fl l is the same as using the .Ic last\-pane @@ -4226,7 +4239,8 @@ instructs .Nm not to change the active pane and .Fl Z -keeps the window zoomed if it was zoomed. +moves the zoom to the pane selected if it was covered by a zoomed pane, +instead of the window being unzoomed. .Pp If .Fl s @@ -6031,6 +6045,22 @@ see the section. Attributes are ignored. .Pp +.It Xo Ic pane\-raise\-on\-focus +.Op Ic floating | all | off +.Xc +Which panes are raised to the front when they are made active. +.Ic floating +raises floating panes, so that activating a floating pane brings it to the +front, but not zoomed panes, so that the active pane of a zoomed window can be +used without floating panes above it being covered. +.Ic all +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. +.Pp .It Xo Ic pane\-scrollbars .Op Ic off | modal | on | auto\-hide .Xc @@ -7536,7 +7566,7 @@ The following variables are available, where appropriate: .It Li "window_start_flag" Ta "" Ta "1 if window has the lowest index" .It Li "window_visible_layout" Ta "" Ta "Window layout description, respecting zoomed window panes" .It Li "window_width" Ta "" Ta "Width of window" -.It Li "window_zoomed_flag" Ta "" Ta "1 if window is zoomed" +.It Li "window_zoomed_flag" Ta "" Ta "1 if any pane in the window is zoomed" .It Li "wrap_flag" Ta "" Ta "Pane wrap flag" .El .Sh STYLES @@ -7946,7 +7976,7 @@ The flag is one of the following symbols appended to the window name: .Ic monitor\-silence interval. .It Li "M" Ta "The window contains the marked pane." -.It Li "Z" Ta "The window's active pane is zoomed." +.It Li "Z" Ta "A pane in the window is zoomed." .El .Pp The # symbol relates to the