Adjust latest client when a client detaches, GitHub issue 2657.
authornicm <nicm@openbsd.org>
Thu, 10 Jun 2021 07:21:46 +0000 (07:21 +0000)
committernicm <nicm@openbsd.org>
Thu, 10 Jun 2021 07:21:46 +0000 (07:21 +0000)
usr.bin/tmux/server-client.c

index ddb09ac..03b622e 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: server-client.c,v 1.372 2021/04/12 09:36:12 nicm Exp $ */
+/* $OpenBSD: server-client.c,v 1.373 2021/06/10 07:21:46 nicm Exp $ */
 
 /*
  * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -46,6 +46,7 @@ static void   server_client_check_modes(struct client *);
 static void    server_client_set_title(struct client *);
 static void    server_client_reset_state(struct client *);
 static int     server_client_assume_paste(struct session *);
+static void    server_client_update_latest(struct client *);
 
 static void    server_client_dispatch(struct imsg *, void *);
 static void    server_client_dispatch_command(struct client *, struct imsg *);
@@ -274,6 +275,40 @@ server_client_open(struct client *c, char **cause)
        return (0);
 }
 
+/* Lost an attached client. */
+static void
+server_client_attached_lost(struct client *c)
+{
+       struct session  *s = c->session;
+       struct window   *w;
+       struct client   *loop;
+       struct client   *found;
+
+       log_debug("lost attached client %p", c);
+
+       /*
+        * By this point the session in the client has been cleared so walk all
+        * windows to find any with this client as the latest.
+        */
+       RB_FOREACH(w, windows, &windows) {
+               if (w->latest != c)
+                       continue;
+
+               found = NULL;
+               TAILQ_FOREACH(loop, &clients, entry) {
+                       s = loop->session;
+                       if (loop == c || s == NULL || s->curw->window != w)
+                               continue;
+                       if (found == NULL ||
+                           timercmp(&loop->activity_time, &found->activity_time,
+                           >))
+                               found = loop;
+               }
+               if (found != NULL)
+                       server_client_update_latest(found);
+       }
+}
+
 /* Lost a client. */
 void
 server_client_lost(struct client *c)
@@ -299,8 +334,10 @@ server_client_lost(struct client *c)
        TAILQ_REMOVE(&clients, c, entry);
        log_debug("lost client %p", c);
 
-       if (c->flags & CLIENT_ATTACHED)
+       if (c->flags & CLIENT_ATTACHED) {
+               server_client_attached_lost(c);
                notify_client("client-detached", c);
+       }
 
        if (c->flags & CLIENT_CONTROL)
                control_stop(c);