kill-window -a cannot just walk the list of windows because if

renumber-windows is on, the window it wants to keep could be moved.
Change to renumber afterwards and also behave better if the window is
linked into the session twice. GitHub issue 2287.
This commit is contained in:
nicm 2020-07-04 14:24:02 +00:00
parent 43e1577b5d
commit 1e42689661
5 changed files with 75 additions and 31 deletions

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

4
tmux.h
View File

@ -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 *);

View File

@ -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)