diff --git a/cmd-join-pane.c b/cmd-join-pane.c index 9802083d..904d2c29 100644 --- a/cmd-join-pane.c +++ b/cmd-join-pane.c @@ -160,7 +160,7 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item) server_status_session(dst_s); if (window_count_panes(src_w) == 0) - server_kill_window(src_w); + server_kill_window(src_w, 1); else notify_window("window-layout-changed", src_w); notify_window("window-layout-changed", dst_w); diff --git a/cmd-kill-window.c b/cmd-kill-window.c index 68139faa..430f667e 100644 --- a/cmd-kill-window.c +++ b/cmd-kill-window.c @@ -57,9 +57,10 @@ cmd_kill_window_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); struct cmd_find_state *target = cmdq_get_target(item); - struct winlink *wl = target->wl, *wl2, *wl3; + struct winlink *wl = target->wl, *loop; struct window *w = wl->window; struct session *s = target->s; + u_int found; if (cmd_get_entry(self) == &cmd_unlink_window_entry) { if (!args_has(args, 'k') && !session_is_linked(s, w)) { @@ -67,16 +68,43 @@ cmd_kill_window_exec(struct cmd *self, struct cmdq_item *item) return (CMD_RETURN_ERROR); } server_unlink_window(s, wl); - } else { - if (args_has(args, 'a')) { - RB_FOREACH_SAFE(wl2, winlinks, &s->windows, wl3) { - if (wl != wl2) - server_kill_window(wl2->window); - } - } else - server_kill_window(wl->window); + recalculate_sizes(); + return (CMD_RETURN_NORMAL); } - recalculate_sizes(); + if (args_has(args, 'a')) { + if (RB_PREV(winlinks, &s->windows, wl) == NULL && + RB_NEXT(winlinks, &s->windows, wl) == NULL) + return (CMD_RETURN_NORMAL); + + /* Kill all windows except the current one. */ + do { + found = 0; + RB_FOREACH(loop, winlinks, &s->windows) { + if (loop->window != wl->window) { + server_kill_window(loop->window, 0); + found++; + break; + } + } + } while (found != 0); + + /* + * If the current window appears in the session more than once, + * kill it as well. + */ + found = 0; + RB_FOREACH(loop, winlinks, &s->windows) { + if (loop->window == wl->window) + found++; + } + if (found > 1) + server_kill_window(wl->window, 0); + + server_renumber_all(); + return (CMD_RETURN_NORMAL); + } + + server_kill_window(wl->window, 1); return (CMD_RETURN_NORMAL); } diff --git a/server-fn.c b/server-fn.c index d66aed0b..84ec4123 100644 --- a/server-fn.c +++ b/server-fn.c @@ -183,7 +183,7 @@ server_kill_pane(struct window_pane *wp) struct window *w = wp->window; if (window_count_panes(w) == 1) { - server_kill_window(w); + server_kill_window(w, 1); recalculate_sizes(); } else { server_unzoom_window(w); @@ -195,19 +195,15 @@ server_kill_pane(struct window_pane *wp) } void -server_kill_window(struct window *w) +server_kill_window(struct window *w, int renumber) { - struct session *s, *next_s, *target_s; - struct session_group *sg; - struct winlink *wl; - - next_s = RB_MIN(sessions, &sessions); - while (next_s != NULL) { - s = next_s; - next_s = RB_NEXT(sessions, &sessions, s); + struct session *s, *s1; + struct winlink *wl; + RB_FOREACH_SAFE(s, sessions, &sessions, s1) { if (!session_has(s, w)) continue; + server_unzoom_window(w); while ((wl = winlink_find_by_window(&s->windows, w)) != NULL) { if (session_detach(s, wl)) { @@ -217,17 +213,35 @@ server_kill_window(struct window *w) server_redraw_session_group(s); } - if (options_get_number(s->options, "renumber-windows")) { - if ((sg = session_group_contains(s)) != NULL) { - TAILQ_FOREACH(target_s, &sg->sessions, gentry) - session_renumber_windows(target_s); - } else - session_renumber_windows(s); - } + if (renumber) + server_renumber_session(s); } recalculate_sizes(); } +void +server_renumber_session(struct session *s) +{ + struct session_group *sg; + + if (options_get_number(s->options, "renumber-windows")) { + if ((sg = session_group_contains(s)) != NULL) { + TAILQ_FOREACH(s, &sg->sessions, gentry) + session_renumber_windows(s); + } else + session_renumber_windows(s); + } +} + +void +server_renumber_all(void) +{ + struct session *s; + + RB_FOREACH(s, sessions, &sessions) + server_renumber_session(s); +} + int server_link_window(struct session *src, struct winlink *srcwl, struct session *dst, int dstidx, int killflag, int selectflag, @@ -354,7 +368,7 @@ server_destroy_pane(struct window_pane *wp, int notify) window_remove_pane(w, wp); if (TAILQ_EMPTY(&w->panes)) - server_kill_window(w); + server_kill_window(w, 1); else server_redraw_window(w); } diff --git a/tmux.h b/tmux.h index 0a1a740b..a8c67051 100644 --- a/tmux.h +++ b/tmux.h @@ -2420,7 +2420,9 @@ void server_lock(void); void server_lock_session(struct session *); void server_lock_client(struct client *); void server_kill_pane(struct window_pane *); -void server_kill_window(struct window *); +void server_kill_window(struct window *, int); +void server_renumber_session(struct session *); +void server_renumber_all(void); int server_link_window(struct session *, struct winlink *, struct session *, int, int, int, char **); void server_unlink_window(struct session *, struct winlink *); diff --git a/window-tree.c b/window-tree.c index 32b94e15..384cf392 100644 --- a/window-tree.c +++ b/window-tree.c @@ -1054,7 +1054,7 @@ window_tree_kill_each(__unused void *modedata, void *itemdata, break; case WINDOW_TREE_WINDOW: if (wl != NULL) - server_kill_window(wl->window); + server_kill_window(wl->window, 1); break; case WINDOW_TREE_PANE: if (wp != NULL)