Or this which handles pane death better: diff --git a/cmd-break-pane.c b/cmd-break-pane.c index a4350fe..4f329e5 100644 --- a/cmd-break-pane.c +++ b/cmd-break-pane.c @@ -63,6 +63,8 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx) } w = wl->window; + server_unzoom_window(w); + TAILQ_REMOVE(&w->panes, wp, entry); if (wp == w->active) { w->active = w->last; diff --git a/cmd-join-pane.c b/cmd-join-pane.c index a2e7a2d..41b532c 100644 --- a/cmd-join-pane.c +++ b/cmd-join-pane.c @@ -91,11 +91,13 @@ join_pane(struct cmd *self, struct cmd_ctx *ctx, int not_same_window) return (CMD_RETURN_ERROR); dst_w = dst_wl->window; dst_idx = dst_wl->idx; + server_unzoom_window(dst_w); src_wl = cmd_find_pane(ctx, args_get(args, 's'), NULL, &src_wp); if (src_wl == NULL) return (CMD_RETURN_ERROR); src_w = src_wl->window; + server_unzoom_window(src_w); if (not_same_window && src_w == dst_w) { ctx->error(ctx, "can't join a pane to its own window"); diff --git a/cmd-kill-pane.c b/cmd-kill-pane.c index 4f7af2e..f0a17ad 100644 --- a/cmd-kill-pane.c +++ b/cmd-kill-pane.c @@ -47,6 +47,7 @@ cmd_kill_pane_exec(struct cmd *self, struct cmd_ctx *ctx) if ((wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp)) == NULL) return (CMD_RETURN_ERROR); + server_unzoom_window(wl->window); if (window_count_panes(wl->window) == 1) { /* Only one pane, kill the window. */ diff --git a/cmd-resize-pane.c b/cmd-resize-pane.c index 328e1b4..e5b85cb 100644 --- a/cmd-resize-pane.c +++ b/cmd-resize-pane.c @@ -31,8 +31,8 @@ enum cmd_retval cmd_resize_pane_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_resize_pane_entry = { "resize-pane", "resizep", - "DLRt:Ux:y:", 0, 1, - "[-DLRU] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " [adjustment]", + "DLRt:Ux:y:Z", 0, 1, + "[-DLRUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " [adjustment]", 0, cmd_resize_pane_key_binding, NULL, @@ -75,6 +75,10 @@ cmd_resize_pane_key_binding(struct cmd *self, int key) self->args = args_create(1, "5"); args_set(self->args, 'R', NULL); break; + case 'z': + self->args = args_create(0); + args_set(self->args, 'z', NULL); + break; default: self->args = args_create(0); break; @@ -86,6 +90,7 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx) { struct args *args = self->args; struct winlink *wl; + struct window *w; const char *errstr; char *cause; struct window_pane *wp; @@ -94,6 +99,18 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx) if ((wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp)) == NULL) return (CMD_RETURN_ERROR); + w = wl->window; + + if (args_has(args, 'z')) { + if (TAILQ_EMPTY(&w->saved_panes)) + window_zoom(wp); + else + window_unzoom(w); + server_redraw_window(w); + server_status_window(w); + return (CMD_RETURN_NORMAL); + } + server_unzoom_window(w); if (args->argc == 0) adjust = 1; diff --git a/cmd-select-layout.c b/cmd-select-layout.c index b2423e9..7e7e35e 100644 --- a/cmd-select-layout.c +++ b/cmd-select-layout.c @@ -92,6 +92,7 @@ cmd_select_layout_exec(struct cmd *self, struct cmd_ctx *ctx) if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) return (CMD_RETURN_ERROR); + server_unzoom_window(wl->window); next = self->entry == &cmd_next_layout_entry; if (args_has(self->args, 'n')) diff --git a/cmd-select-pane.c b/cmd-select-pane.c index 8ebae5f..71882e4 100644 --- a/cmd-select-pane.c +++ b/cmd-select-pane.c @@ -94,6 +94,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx) ctx->error(ctx, "pane not visible"); return (CMD_RETURN_ERROR); } + server_unzoom_window(wp->window); if (args_has(self->args, 'L')) wp = window_pane_find_left(wp); diff --git a/cmd-split-window.c b/cmd-split-window.c index cac8095..a21ff77 100644 --- a/cmd-split-window.c +++ b/cmd-split-window.c @@ -72,6 +72,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx) if ((wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp)) == NULL) return (CMD_RETURN_ERROR); w = wl->window; + server_unzoom_window(w); environ_init(&env); environ_copy(&global_environ, &env); diff --git a/cmd-swap-pane.c b/cmd-swap-pane.c index 42fe2fc..cc9e7df 100644 --- a/cmd-swap-pane.c +++ b/cmd-swap-pane.c @@ -63,6 +63,7 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx) if (dst_wl == NULL) return (CMD_RETURN_ERROR); dst_w = dst_wl->window; + server_unzoom_window(dst_w); if (!args_has(args, 's')) { src_w = dst_w; @@ -82,6 +83,7 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx) return (CMD_RETURN_ERROR); src_w = src_wl->window; } + server_unzoom_window(src_w); if (src_wp == dst_wp) return (CMD_RETURN_NORMAL); diff --git a/key-bindings.c b/key-bindings.c index 9e5a729..bf9ff31 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -150,6 +150,7 @@ key_bindings_init(void) { 't', 0, &cmd_clock_mode_entry }, { 'w', 0, &cmd_choose_window_entry }, { 'x', 0, &cmd_confirm_before_entry }, + { 'z', 0, &cmd_resize_pane_entry }, { '{', 0, &cmd_swap_pane_entry }, { '}', 0, &cmd_swap_pane_entry }, { '~', 0, &cmd_show_messages_entry }, diff --git a/server-fn.c b/server-fn.c index 26f93d9..f17c3b1 100644 --- a/server-fn.c +++ b/server-fn.c @@ -377,6 +377,7 @@ server_destroy_pane(struct window_pane *wp) return; } + server_unzoom_window(w); layout_close_pane(wp); window_remove_pane(w, wp); @@ -588,3 +589,11 @@ server_set_stdin_callback(struct client *c, void (*cb)(struct client *, int, return (0); } + +void +server_unzoom_window(struct window *w) +{ + window_unzoom(w); + server_redraw_window(w); + server_status_window(w); +} diff --git a/tmux.h b/tmux.h index 8c06197..9849a2a 100644 --- a/tmux.h +++ b/tmux.h @@ -978,6 +978,12 @@ struct window { struct window_pane *last; struct window_panes panes; + struct window_pane *saved_before; + struct window_pane *saved_last; + struct window_panes saved_panes; + struct layout_cell *saved_layout; + struct layout_cell *saved_cell; + int lastlayout; struct layout_cell *layout_root; @@ -1910,6 +1916,7 @@ void server_push_stdout(struct client *); void server_push_stderr(struct client *); int server_set_stdin_callback(struct client *, void (*)(struct client *, int, void *), void *, char **); +void server_unzoom_window(struct window *); /* status.c */ int status_out_cmp(struct status_out *, struct status_out *); @@ -2113,6 +2120,8 @@ struct window_pane *window_find_string(struct window *, const char *); void window_set_active_pane(struct window *, struct window_pane *); struct window_pane *window_add_pane(struct window *, u_int); void window_resize(struct window *, u_int, u_int); +int window_zoom(struct window_pane *); +int window_unzoom(struct window *); void window_remove_pane(struct window *, struct window_pane *); struct window_pane *window_pane_at_index(struct window *, u_int); struct window_pane *window_pane_next_by_number(struct window *, diff --git a/window.c b/window.c index 77f06f8..dd8a422 100644 --- a/window.c +++ b/window.c @@ -278,6 +278,7 @@ window_create1(u_int sx, u_int sy) w->name = NULL; w->flags = 0; + TAILQ_INIT(&w->saved_panes); TAILQ_INIT(&w->panes); w->active = NULL; @@ -333,6 +334,8 @@ window_destroy(struct window *w) { u_int i; + window_unzoom(w); + if (window_index(w, &i) != 0) fatalx("index not found"); ARRAY_SET(&windows, i, NULL); @@ -455,6 +458,71 @@ window_find_string(struct window *w, const char *s) return (window_get_active_at(w, x, y)); } +int +window_zoom(struct window_pane *wp) +{ + struct window *w = wp->window; + struct window_pane *wp1; + + if (!TAILQ_EMPTY(&w->saved_panes)) + return (-1); + + if (!window_pane_visible(wp)) + return (-1); + if (w->active != wp) + window_set_active_pane(w, wp); + + w->saved_before = TAILQ_NEXT(wp, entry); + TAILQ_REMOVE(&w->panes, wp, entry); + + w->saved_last = w->last; + w->last = NULL; + + memcpy(&w->saved_panes, &w->panes, sizeof w->saved_panes); + TAILQ_INIT(&w->panes); + TAILQ_INSERT_HEAD(&w->panes, wp, entry); + + TAILQ_FOREACH(wp1, &w->saved_panes, entry) + RB_REMOVE(window_pane_tree, &all_window_panes, wp1); + + w->saved_cell = wp->layout_cell; + w->saved_layout = w->layout_root; + layout_init(w); + + return (0); +} + +int +window_unzoom(struct window *w) +{ + struct window_pane *wp, *wp1; + + if (TAILQ_EMPTY(&w->saved_panes)) + return (-1); + wp = w->active; + + TAILQ_FOREACH(wp1, &w->saved_panes, entry) + RB_INSERT(window_pane_tree, &all_window_panes, wp1); + + TAILQ_REMOVE(&w->panes, wp, entry); + memcpy(&w->panes, &w->saved_panes, sizeof w->panes); + TAILQ_INIT(&w->saved_panes); + + if (w->saved_before == NULL) + TAILQ_INSERT_TAIL(&w->panes, wp, entry); + else + TAILQ_INSERT_BEFORE(w->saved_before, wp, entry); + + w->last = w->saved_last; + + layout_free(w); + wp->layout_cell = w->saved_cell; + w->layout_root = w->saved_layout; + layout_fix_panes(w, w->sx, w->sy); + + return (0); +} + struct window_pane * window_add_pane(struct window *w, u_int hlimit) { @@ -585,6 +653,8 @@ window_printable_flags(struct session *s, struct winlink *wl) flags[pos++] = '*'; if (wl == TAILQ_FIRST(&s->lastw)) flags[pos++] = '-'; + if (!TAILQ_EMPTY(&wl->window->saved_panes)) + flags[pos++] = 'Z'; if (pos == 0) flags[pos++] = ' '; flags[pos] = '\0';
On Fri, Feb 22, 2013 at 10:42:36AM +0000, Nicholas Marriott wrote: > Like this, but I am unsure if this is just an awful hack and we might be > better to properly support 'detached' panes which don't have a > cell. Then we could have layouts where some panes aren't present at all > but they would still appear in lsp etc. > > > diff --git a/cmd-break-pane.c b/cmd-break-pane.c > index a4350fe..069eb3e 100644 > --- a/cmd-break-pane.c > +++ b/cmd-break-pane.c > @@ -63,6 +63,8 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx) > } > > w = wl->window; > + window_unzoom(w); > + > TAILQ_REMOVE(&w->panes, wp, entry); > if (wp == w->active) { > w->active = w->last; > diff --git a/cmd-join-pane.c b/cmd-join-pane.c > index a2e7a2d..9a3a9fd 100644 > --- a/cmd-join-pane.c > +++ b/cmd-join-pane.c > @@ -91,11 +91,13 @@ join_pane(struct cmd *self, struct cmd_ctx *ctx, int > not_same_window) > return (CMD_RETURN_ERROR); > dst_w = dst_wl->window; > dst_idx = dst_wl->idx; > + window_unzoom(dst_w); > > src_wl = cmd_find_pane(ctx, args_get(args, 's'), NULL, &src_wp); > if (src_wl == NULL) > return (CMD_RETURN_ERROR); > src_w = src_wl->window; > + window_unzoom(src_w); > > if (not_same_window && src_w == dst_w) { > ctx->error(ctx, "can't join a pane to its own window"); > diff --git a/cmd-kill-pane.c b/cmd-kill-pane.c > index 4f7af2e..750faf0 100644 > --- a/cmd-kill-pane.c > +++ b/cmd-kill-pane.c > @@ -54,6 +54,7 @@ cmd_kill_pane_exec(struct cmd *self, struct cmd_ctx *ctx) > recalculate_sizes(); > return (CMD_RETURN_NORMAL); > } > + window_unzoom(wl->window); > > if (args_has(self->args, 'a')) { > TAILQ_FOREACH_SAFE(loopwp, &wl->window->panes, entry, tmpwp) { > diff --git a/cmd-resize-pane.c b/cmd-resize-pane.c > index 328e1b4..dc75494 100644 > --- a/cmd-resize-pane.c > +++ b/cmd-resize-pane.c > @@ -31,8 +31,8 @@ enum cmd_retval cmd_resize_pane_exec(struct cmd *, > struct cmd_ctx *); > > const struct cmd_entry cmd_resize_pane_entry = { > "resize-pane", "resizep", > - "DLRt:Ux:y:", 0, 1, > - "[-DLRU] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " [adjustment]", > + "DLRt:Ux:y:Z", 0, 1, > + "[-DLRUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " > [adjustment]", > 0, > cmd_resize_pane_key_binding, > NULL, > @@ -75,6 +75,10 @@ cmd_resize_pane_key_binding(struct cmd *self, int key) > self->args = args_create(1, "5"); > args_set(self->args, 'R', NULL); > break; > + case 'z': > + self->args = args_create(0); > + args_set(self->args, 'z', NULL); > + break; > default: > self->args = args_create(0); > break; > @@ -86,6 +90,7 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx) > { > struct args *args = self->args; > struct winlink *wl; > + struct window *w; > const char *errstr; > char *cause; > struct window_pane *wp; > @@ -94,6 +99,16 @@ cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx) > > if ((wl = cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp)) == NULL) > return (CMD_RETURN_ERROR); > + w = wl->window; > + > + if (args_has(args, 'z')) { > + if (TAILQ_EMPTY(&w->saved_panes)) > + window_zoom(wp); > + else > + window_unzoom(w); > + return (CMD_RETURN_NORMAL); > + } > + window_unzoom(w); > > if (args->argc == 0) > adjust = 1; > diff --git a/cmd-select-layout.c b/cmd-select-layout.c > index b2423e9..558661b 100644 > --- a/cmd-select-layout.c > +++ b/cmd-select-layout.c > @@ -92,6 +92,7 @@ cmd_select_layout_exec(struct cmd *self, struct cmd_ctx > *ctx) > > if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) > return (CMD_RETURN_ERROR); > + window_unzoom(wl->window); > > next = self->entry == &cmd_next_layout_entry; > if (args_has(self->args, 'n')) > diff --git a/cmd-select-pane.c b/cmd-select-pane.c > index 8ebae5f..2428b26 100644 > --- a/cmd-select-pane.c > +++ b/cmd-select-pane.c > @@ -94,6 +94,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx) > ctx->error(ctx, "pane not visible"); > return (CMD_RETURN_ERROR); > } > + window_unzoom(wp->window); > > if (args_has(self->args, 'L')) > wp = window_pane_find_left(wp); > diff --git a/cmd-split-window.c b/cmd-split-window.c > index cac8095..242db41 100644 > --- a/cmd-split-window.c > +++ b/cmd-split-window.c > @@ -72,6 +72,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx) > if ((wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp)) == NULL) > return (CMD_RETURN_ERROR); > w = wl->window; > + window_unzoom(w); > > environ_init(&env); > environ_copy(&global_environ, &env); > diff --git a/cmd-swap-pane.c b/cmd-swap-pane.c > index 42fe2fc..4d9044b 100644 > --- a/cmd-swap-pane.c > +++ b/cmd-swap-pane.c > @@ -63,6 +63,7 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx) > if (dst_wl == NULL) > return (CMD_RETURN_ERROR); > dst_w = dst_wl->window; > + window_unzoom(dst_w); > > if (!args_has(args, 's')) { > src_w = dst_w; > @@ -82,6 +83,7 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx) > return (CMD_RETURN_ERROR); > src_w = src_wl->window; > } > + window_unzoom(src_w); > > if (src_wp == dst_wp) > return (CMD_RETURN_NORMAL); > diff --git a/key-bindings.c b/key-bindings.c > index 9e5a729..bf9ff31 100644 > --- a/key-bindings.c > +++ b/key-bindings.c > @@ -150,6 +150,7 @@ key_bindings_init(void) > { 't', 0, &cmd_clock_mode_entry }, > { 'w', 0, &cmd_choose_window_entry }, > { 'x', 0, &cmd_confirm_before_entry }, > + { 'z', 0, &cmd_resize_pane_entry }, > { '{', 0, &cmd_swap_pane_entry }, > { '}', 0, &cmd_swap_pane_entry }, > { '~', 0, &cmd_show_messages_entry }, > diff --git a/tmux.h b/tmux.h > index 8c06197..fa226a1 100644 > --- a/tmux.h > +++ b/tmux.h > @@ -978,6 +978,12 @@ struct window { > struct window_pane *last; > struct window_panes panes; > > + struct window_pane *saved_before; > + struct window_pane *saved_last; > + struct window_panes saved_panes; > + struct layout_cell *saved_layout; > + struct layout_cell *saved_cell; > + > int lastlayout; > struct layout_cell *layout_root; > > @@ -2113,6 +2119,8 @@ struct window_pane *window_find_string(struct window *, > const char *); > void window_set_active_pane(struct window *, struct window_pane *); > struct window_pane *window_add_pane(struct window *, u_int); > void window_resize(struct window *, u_int, u_int); > +int window_zoom(struct window_pane *); > +int window_unzoom(struct window *); > void window_remove_pane(struct window *, struct window_pane *); > struct window_pane *window_pane_at_index(struct window *, u_int); > struct window_pane *window_pane_next_by_number(struct window *, > diff --git a/window.c b/window.c > index 77f06f8..f9a2888 100644 > --- a/window.c > +++ b/window.c > @@ -278,6 +278,7 @@ window_create1(u_int sx, u_int sy) > w->name = NULL; > w->flags = 0; > > + TAILQ_INIT(&w->saved_panes); > TAILQ_INIT(&w->panes); > w->active = NULL; > > @@ -455,6 +456,73 @@ window_find_string(struct window *w, const char *s) > return (window_get_active_at(w, x, y)); > } > > +int > +window_zoom(struct window_pane *wp) > +{ > + struct window *w = wp->window; > + struct window_pane *wp1; > + > + if (!TAILQ_EMPTY(&w->saved_panes)) > + return (-1); > + > + if (!window_pane_visible(wp)) > + return (-1); > + if (w->active != wp) > + window_set_active_pane(w, wp); > + > + w->saved_before = TAILQ_NEXT(wp, entry); > + TAILQ_REMOVE(&w->panes, wp, entry); > + > + w->saved_last = w->last; > + w->last = NULL; > + > + memcpy(&w->saved_panes, &w->panes, sizeof w->saved_panes); > + TAILQ_INIT(&w->panes); > + TAILQ_INSERT_HEAD(&w->panes, wp, entry); > + > + TAILQ_FOREACH(wp1, &w->saved_panes, entry) > + RB_REMOVE(window_pane_tree, &all_window_panes, wp1); > + > + w->saved_cell = wp->layout_cell; > + w->saved_layout = w->layout_root; > + layout_init(w); > + > + server_redraw_window(w); > + return (0); > +} > + > +int > +window_unzoom(struct window *w) > +{ > + struct window_pane *wp, *wp1; > + > + if (TAILQ_EMPTY(&w->saved_panes)) > + return (-1); > + wp = w->active; > + > + TAILQ_FOREACH(wp1, &w->saved_panes, entry) > + RB_INSERT(window_pane_tree, &all_window_panes, wp1); > + > + TAILQ_REMOVE(&w->panes, wp, entry); > + memcpy(&w->panes, &w->saved_panes, sizeof w->panes); > + TAILQ_INIT(&w->saved_panes); > + > + if (w->saved_before == NULL) > + TAILQ_INSERT_TAIL(&w->panes, wp, entry); > + else > + TAILQ_INSERT_BEFORE(w->saved_before, wp, entry); > + > + w->last = w->saved_last; > + > + layout_free(w); > + wp->layout_cell = w->saved_cell; > + w->layout_root = w->saved_layout; > + layout_fix_panes(w, w->sx, w->sy); > + > + server_redraw_window(w); > + return (0); > +} > + > struct window_pane * > window_add_pane(struct window *w, u_int hlimit) > { > > > > On Fri, Feb 22, 2013 at 07:58:16AM +0000, Thomas Adam wrote: > > Hi, > > > > On 22 February 2013 07:52, Nicholas Marriott > > <nicholas.marri...@gmail.com> wrote: > > > Hmm. Not sure I like scrambling all the other panes sizes but I don't > > > see offhand why it freezes. I take it you didn't do restore? > > > > I think I restored it by reapplying a different layout. The freeze > > most likely was due to closing a pane in a maximised state because the > > other pane(s) would then be marked as not visible and hence couldn't > > select anything thereafter... or something like that. > > > > > Thinking more a mode wouldn't do it because of course they are inside > > > the pane :-). > > > > > > I think rather than removing the old layout we should just save it off > > > and make a new temporary one, then restoring it is simple. The problem > > > is of course all the panes are still reachable via the window so might > > > need checks all over the place... maybe just a check in > > > window_pane_visible might get some of them. And a bunch of calls in > > > various places to restore the layout before doing things like kill > > > pane/select layout/etc etc etc. > > > > Hmm. That might work. I did originally think of just adding this > > ability to resize-pane instead since it's not strictly a layout; of > > course, this would be disruptive to other panes, so... maybe not. > > > > -- Thomas Adam ------------------------------------------------------------------------------ Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_feb _______________________________________________ tmux-users mailing list tmux-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tmux-users