diff options
author | Nicholas Marriott <nicholas.marriott@gmail.com> | 2020-05-14 11:18:19 +0100 |
---|---|---|
committer | Nicholas Marriott <nicholas.marriott@gmail.com> | 2020-05-14 11:18:19 +0100 |
commit | 0bdbf47ef946b3535cc32b45ea8d971de5baddb5 (patch) | |
tree | a44b650fc7eb232083f25e070f243899ed9cbedc /server-client.c | |
parent | 12eceaf2b3ef2b028a55d8ad11951be700be0446 (diff) | |
download | rtmux-0bdbf47ef946b3535cc32b45ea8d971de5baddb5.tar.gz rtmux-0bdbf47ef946b3535cc32b45ea8d971de5baddb5.tar.bz2 rtmux-0bdbf47ef946b3535cc32b45ea8d971de5baddb5.zip |
Add a client flag 'active-pane' which stores the active pane in the client and
allows it to be changed independently from the real active pane stored in the
window. This is can be used with session groups which allow an independent
current window (although it would be nice to have a flag for this too and
remove session groups). The client active pane is only really useful
interactively, many things (hooks, window-style, zooming) still use the window
active pane.
Diffstat (limited to 'server-client.c')
-rw-r--r-- | server-client.c | 91 |
1 files changed, 89 insertions, 2 deletions
diff --git a/server-client.c b/server-client.c index 2e9f15a6..c7bec010 100644 --- a/server-client.c +++ b/server-client.c @@ -54,6 +54,19 @@ static void server_client_dispatch_read_data(struct client *, 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) @@ -209,6 +222,7 @@ server_client_create(int fd) c->cwd = NULL; c->queue = cmdq_new(); + RB_INIT(&c->windows); c->tty.fd = -1; c->tty.sx = 80; @@ -270,6 +284,7 @@ void server_client_lost(struct client *c) { struct client_file *cf, *cf1; + struct client_window *cw, *cw1; c->flags |= CLIENT_DEAD; @@ -281,6 +296,10 @@ server_client_lost(struct client *c) 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); @@ -1124,7 +1143,7 @@ server_client_key_callback(struct cmdq_item *item, void *data) /* Find affected pane. */ if (!KEYC_IS_MOUSE(key) || cmd_find_from_mouse(&fs, m, 0) != 0) - cmd_find_from_session(&fs, s, 0); + cmd_find_from_client(&fs, c, 0); wp = fs.wp; /* Forward mouse keys if disabled. */ @@ -1533,7 +1552,7 @@ server_client_reset_state(struct client *c) { struct tty *tty = &c->tty; struct window *w = c->session->curw->window; - struct window_pane *wp = w->active, *loop; + 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; @@ -2238,6 +2257,8 @@ server_client_set_flags(struct client *c, const char *flags) 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; @@ -2268,6 +2289,8 @@ server_client_get_flags(struct client *c) 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) @@ -2276,3 +2299,67 @@ server_client_get_flags(struct client *c) 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); + } + } +} |