diff --git a/options-table.c b/options-table.c index eacf0947..a42d41c1 100644 --- a/options-table.c +++ b/options-table.c @@ -86,7 +86,7 @@ static const char *options_table_remain_on_exit_list[] = { "off", "on", "failed", NULL }; static const char *options_table_detach_on_destroy_list[] = { - "off", "on", "no-detached", NULL + "off", "on", "no-detached", "previous", "next", NULL }; static const char *options_table_extended_keys_list[] = { "off", "on", "always", NULL diff --git a/server-fn.c b/server-fn.c index 2e9665f5..3c14c733 100644 --- a/server-fn.c +++ b/server-fn.c @@ -29,8 +29,7 @@ #include "tmux.h" -static struct session *server_next_session(struct session *); -static void server_destroy_session_group(struct session *); +static void server_destroy_session_group(struct session *); void server_redraw_client(struct client *c) @@ -209,8 +208,8 @@ server_kill_window(struct window *w, int renumber) if (session_detach(s, wl)) { server_destroy_session_group(s); break; - } else - server_redraw_session_group(s); + } + server_redraw_session_group(s); } if (renumber) @@ -384,9 +383,10 @@ server_destroy_session_group(struct session *s) struct session_group *sg; struct session *s1; - if ((sg = session_group_contains(s)) == NULL) + if ((sg = session_group_contains(s)) == NULL) { server_destroy_session(s); - else { + session_destroy(s, 1, __func__); + } else { TAILQ_FOREACH_SAFE(s, &sg->sessions, gentry, s1) { server_destroy_session(s); session_destroy(s, 1, __func__); @@ -395,52 +395,55 @@ server_destroy_session_group(struct session *s) } static struct session * -server_next_session(struct session *s) +server_find_session(struct session *s, + int (*f)(struct session *, struct session *)) { struct session *s_loop, *s_out = NULL; RB_FOREACH(s_loop, sessions, &sessions) { - if (s_loop == s) - continue; - if (s_out == NULL || - timercmp(&s_loop->activity_time, &s_out->activity_time, <)) + if (s_loop != s && (s_out == NULL || f(s_loop, s_out))) s_out = s_loop; } return (s_out); } -static struct session * -server_next_detached_session(struct session *s) +static int +server_newer_session(struct session *s_loop, struct session *s_out) { - struct session *s_loop, *s_out = NULL; + return (timercmp(&s_loop->activity_time, &s_out->activity_time, <)); +} - RB_FOREACH(s_loop, sessions, &sessions) { - if (s_loop == s || s_loop->attached) - continue; - if (s_out == NULL || - timercmp(&s_loop->activity_time, &s_out->activity_time, <)) - s_out = s_loop; - } - return (s_out); +static int +server_newer_detached_session(struct session *s_loop, struct session *s_out) +{ + if (s_loop->attached) + return (0); + return (server_newer_session(s_loop, s_out)); } void server_destroy_session(struct session *s) { struct client *c; - struct session *s_new; + struct session *s_new = NULL; int detach_on_destroy; detach_on_destroy = options_get_number(s->options, "detach-on-destroy"); if (detach_on_destroy == 0) - s_new = server_next_session(s); + s_new = server_find_session(s, server_newer_session); else if (detach_on_destroy == 2) - s_new = server_next_detached_session(s); - else + s_new = server_find_session(s, server_newer_detached_session); + else if (detach_on_destroy == 3) + s_new = session_previous_session(s); + else if (detach_on_destroy == 4) + s_new = session_next_session(s); + if (s_new == s) s_new = NULL; TAILQ_FOREACH(c, &clients, entry) { if (c->session != s) continue; + c->session = NULL; + c->last_session = NULL; server_client_set_session(c, s_new); if (s_new == NULL) c->flags |= CLIENT_EXIT; diff --git a/session.c b/session.c index de3f336f..688b23f4 100644 --- a/session.c +++ b/session.c @@ -367,11 +367,9 @@ session_detach(struct session *s, struct winlink *wl) session_group_synchronize_from(s); - if (RB_EMPTY(&s->windows)) { - session_destroy(s, 1, __func__); + if (RB_EMPTY(&s->windows)) return (1); - } - return (0); + return (0); } /* Return if session has window. */ diff --git a/tmux.1 b/tmux.1 index 3228556c..6306e12a 100644 --- a/tmux.1 +++ b/tmux.1 @@ -4039,16 +4039,25 @@ The default is 80x24. If enabled and the session is no longer attached to any clients, it is destroyed. .It Xo Ic detach-on-destroy -.Op Ic off | on | no-detached +.Op Ic off | on | no-detached | previous | next .Xc -If on (the default), the client is detached when the session it is attached to +If +.Ic on +(the default), the client is detached when the session it is attached to is destroyed. -If off, the client is switched to the most recently active of the remaining +If +.Ic off , +the client is switched to the most recently active of the remaining sessions. If .Ic no-detached , the client is detached only if there are no detached sessions; if detached sessions exist, the client is switched to the most recently active. +If +.Ic previous +or +.Ic next , +the client is switched to the previous or next session in alphabetical order. .It Ic display-panes-active-colour Ar colour Set the colour used by the .Ic display-panes