=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/server-client.c,v retrieving revision 1.340 retrieving revision 1.341 diff -c -r1.340 -r1.341 *** src/usr.bin/tmux/server-client.c 2020/05/16 16:16:07 1.340 --- src/usr.bin/tmux/server-client.c 2020/05/16 16:20:59 1.341 *************** *** 1,4 **** ! /* $OpenBSD: server-client.c,v 1.340 2020/05/16 16:16:07 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott --- 1,4 ---- ! /* $OpenBSD: server-client.c,v 1.341 2020/05/16 16:20:59 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott *************** *** 56,61 **** --- 56,74 ---- static void server_client_dispatch_read_done(struct client *, struct imsg *); + /* Compare client windows. */ + static int + server_client_window_cmp(struct client_window *cw1, + struct client_window *cw2) + { + if (cw1->window < cw2->window) + return (-1); + if (cw1->window > cw2->window) + return (1); + return (0); + } + RB_GENERATE(client_windows, client_window, entry, server_client_window_cmp); + /* Number of attached clients. */ u_int server_client_how_many(void) *************** *** 211,216 **** --- 224,230 ---- c->cwd = NULL; c->queue = cmdq_new(); + RB_INIT(&c->windows); c->tty.fd = -1; c->tty.sx = 80; *************** *** 272,277 **** --- 286,292 ---- server_client_lost(struct client *c) { struct client_file *cf, *cf1; + struct client_window *cw, *cw1; c->flags |= CLIENT_DEAD; *************** *** 283,288 **** --- 298,307 ---- cf->error = EINTR; file_fire_done(cf); } + RB_FOREACH_SAFE(cw, client_windows, &c->windows, cw1) { + RB_REMOVE(client_windows, &c->windows, cw); + free(cw); + } TAILQ_REMOVE(&clients, c, entry); log_debug("lost client %p", c); *************** *** 1126,1132 **** /* Find affected pane. */ if (!KEYC_IS_MOUSE(key) || cmd_find_from_mouse(&fs, m, 0) != 0) ! cmd_find_from_session(&fs, s, 0); wp = fs.wp; /* Forward mouse keys if disabled. */ --- 1145,1151 ---- /* Find affected pane. */ if (!KEYC_IS_MOUSE(key) || cmd_find_from_mouse(&fs, m, 0) != 0) ! cmd_find_from_client(&fs, c, 0); wp = fs.wp; /* Forward mouse keys if disabled. */ *************** *** 1535,1541 **** { struct tty *tty = &c->tty; struct window *w = c->session->curw->window; ! struct window_pane *wp = w->active, *loop; struct screen *s = NULL; struct options *oo = c->session->options; int mode = 0, cursor, flags; --- 1554,1560 ---- { struct tty *tty = &c->tty; struct window *w = c->session->curw->window; ! struct window_pane *wp = server_client_get_pane(c), *loop; struct screen *s = NULL; struct options *oo = c->session->options; int mode = 0, cursor, flags; *************** *** 2236,2241 **** --- 2255,2262 ---- flag = CLIENT_READONLY; else if (strcmp(next, "ignore-size") == 0) flag = CLIENT_IGNORESIZE; + else if (strcmp(next, "active-pane") == 0) + flag = CLIENT_ACTIVEPANE; else continue; *************** *** 2266,2271 **** --- 2287,2294 ---- strlcat(s, "no-output,", sizeof s); if (c->flags & CLIENT_READONLY) strlcat(s, "read-only,", sizeof s); + if (c->flags & CLIENT_ACTIVEPANE) + strlcat(s, "active-pane,", sizeof s); if (c->flags & CLIENT_SUSPENDED) strlcat(s, "suspended,", sizeof s); if (c->flags & CLIENT_UTF8) *************** *** 2273,2276 **** --- 2296,2363 ---- if (*s != '\0') s[strlen(s) - 1] = '\0'; return (s); + } + + /* Get client window. */ + static struct client_window * + server_client_get_client_window(struct client *c, u_int id) + { + struct client_window cw = { .window = id }; + + return (RB_FIND(client_windows, &c->windows, &cw)); + } + + /* Get client active pane. */ + struct window_pane * + server_client_get_pane(struct client *c) + { + struct session *s = c->session; + struct client_window *cw; + + if (s == NULL) + return (NULL); + + if (~c->flags & CLIENT_ACTIVEPANE) + return (s->curw->window->active); + cw = server_client_get_client_window(c, s->curw->window->id); + if (cw == NULL) + return (s->curw->window->active); + return (cw->pane); + } + + /* Set client active pane. */ + void + server_client_set_pane(struct client *c, struct window_pane *wp) + { + struct session *s = c->session; + struct client_window *cw; + + if (s == NULL) + return; + + cw = server_client_get_client_window(c, s->curw->window->id); + if (cw == NULL) { + cw = xcalloc(1, sizeof *cw); + cw->window = s->curw->window->id; + RB_INSERT(client_windows, &c->windows, cw); + } + cw->pane = wp; + log_debug("%s pane now %%%u", c->name, wp->id); + } + + /* Remove pane from client lists. */ + void + server_client_remove_pane(struct window_pane *wp) + { + struct client *c; + struct window *w = wp->window; + struct client_window *cw; + + TAILQ_FOREACH(c, &clients, entry) { + cw = server_client_get_client_window(c, w->id); + if (cw != NULL && cw->pane == wp) { + RB_REMOVE(client_windows, &c->windows, cw); + free(cw); + } + } }