diff --git a/server-client.c b/server-client.c index 241e1bed..89a4faa6 100644 --- a/server-client.c +++ b/server-client.c @@ -491,6 +491,8 @@ server_client_loop(void) struct window_pane *wp; u_int i; + int tmate_should_sync_layout = 0; + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); if (c == NULL) @@ -513,7 +515,7 @@ server_client_loop(void) continue; if (w->flags & WINDOW_REDRAW) - tmate_sync_window(w); + tmate_should_sync_layout = 1; w->flags &= ~WINDOW_REDRAW; TAILQ_FOREACH(wp, &w->panes, entry) { @@ -522,6 +524,9 @@ server_client_loop(void) wp->flags &= ~PANE_REDRAW; } } + + if (tmate_should_sync_layout) + tmate_sync_layout(); } /* Check if pane should be resized. */ diff --git a/session.c b/session.c index d3d82ea2..ebe1178d 100644 --- a/session.c +++ b/session.c @@ -91,10 +91,12 @@ session_create(const char *name, const char *cmd, const char *cwd, { struct session *s; +#ifdef TMATE if (next_session_id != 0) { xasprintf(cause, "multi sessions is not supported with tmate"); return NULL; } +#endif s = xmalloc(sizeof *s); s->references = 0; @@ -270,6 +272,11 @@ session_new(struct session *s, options_set_number(&w->options, "remain-on-exit", 1); session_group_synchronize_from(s); + +#ifdef TMATE + tmate_sync_layout(); +#endif + return (wl); } @@ -423,6 +430,11 @@ session_set_current(struct session *s, struct winlink *wl) winlink_stack_push(&s->lastw, s->curw); s->curw = wl; winlink_clear_flags(wl); + +#ifdef TMATE + tmate_sync_layout(); +#endif + return (0); } diff --git a/tmate-encoder.c b/tmate-encoder.c index 976edc36..57f6c110 100644 --- a/tmate-encoder.c +++ b/tmate-encoder.c @@ -35,36 +35,81 @@ void tmate_write_header(void) pack(int, TMATE_PROTOCOL_VERSION); } -void tmate_sync_window(struct window *w) +void tmate_sync_layout(void) { + struct session *s; + struct winlink *wl; + struct window *w; struct window_pane *wp; int num_panes = 0; + int num_windows = 0; int active_pane_id = -1; + int active_window_id = -1; - pack(array, 7); - pack(int, TMATE_SYNC_WINDOW); + /* + * We only allow one session, it makes our lives easier. + * Especially when the HTML5 client will come along. + * We make no distinction between a winlink and its window. + * TODO send the winlink in the current session stack order. + */ - pack(int, w->id); - pack(string, w->name); - pack(int, w->sx); - pack(int, w->sy); + s = RB_MIN(sessions, &sessions); + if (!s) + return; - TAILQ_FOREACH(wp, &w->panes, entry) - num_panes++; - - pack(array, num_panes); - TAILQ_FOREACH(wp, &w->panes, entry) { - pack(array, 5); - pack(int, wp->id); - pack(int, wp->sx); - pack(int, wp->sy); - pack(int, wp->xoff); - pack(int, wp->yoff); - - if (wp == w->active) - active_pane_id = wp->id; + num_windows = 0; + RB_FOREACH(wl, winlinks, &s->windows) { + if (wl->window) + num_windows++; } - pack(int, active_pane_id); + + if (!num_windows) + return; + + pack(array, 5); + pack(int, TMATE_SYNC_LAYOUT); + + pack(int, s->sx); + pack(int, s->sy); + + pack(array, num_windows); + RB_FOREACH(wl, winlinks, &s->windows) { + w = wl->window; + if (!w) + continue; + + pack(array, 4); + pack(int, w->id); + pack(string, w->name); + + num_panes = 0; + TAILQ_FOREACH(wp, &w->panes, entry) + num_panes++; + + pack(array, num_panes); + TAILQ_FOREACH(wp, &w->panes, entry) { + pack(array, 5); + pack(int, wp->id); + pack(int, wp->sx); + pack(int, wp->sy); + pack(int, wp->xoff); + pack(int, wp->yoff); + + if (wp == w->active) + active_pane_id = wp->id; + } + pack(int, active_pane_id); + + if (wl == s->curw) + active_window_id = w->id; + } + + if (active_window_id == -1) { + wl = RB_MIN(winlinks, &s->windows); + active_window_id = wl->window->id; + } + + pack(int, active_window_id); } void tmate_pty_data(struct window_pane *wp, const char *buf, size_t len) diff --git a/tmate.h b/tmate.h index 3acabed4..7a07facd 100644 --- a/tmate.h +++ b/tmate.h @@ -20,7 +20,7 @@ enum tmate_commands { TMATE_HEADER, - TMATE_SYNC_WINDOW, + TMATE_SYNC_LAYOUT, TMATE_PTY_DATA, TMATE_CMD, TMATE_STATUS, @@ -35,7 +35,7 @@ struct tmate_encoder { extern void tmate_encoder_init(struct tmate_encoder *encoder); extern void tmate_write_header(void); -extern void tmate_sync_window(struct window *w); +extern void tmate_sync_layout(void); extern void tmate_pty_data(struct window_pane *wp, const char *buf, size_t len); extern int tmate_should_replicate_cmd(const struct cmd_entry *cmd); extern void tmate_cmd(const char *cmd); diff --git a/window.c b/window.c index f4bccadb..10629042 100644 --- a/window.c +++ b/window.c @@ -329,8 +329,6 @@ window_create(const char *name, const char *cmd, const char *shell, } else w->name = default_window_name(w); - tmate_sync_window(w); - return (w); } @@ -377,7 +375,7 @@ window_set_name(struct window *w, const char *new_name) free(w->name); w->name = xstrdup(new_name); notify_window_renamed(w); - tmate_sync_window(w); + tmate_sync_layout(); } void