From 63b4fd5cacc1a53b93e92ef007d5a7249f5cac38 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Thu, 21 Mar 2013 16:14:09 +0000 Subject: Add a format client_prefix which is 1 if prefix key has been pressed, used for example #{?client_prefix,X,Y}. Also a few extra server_client_status needed. --- server-client.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'server-client.c') diff --git a/server-client.c b/server-client.c index 82189a5c..1cae4733 100644 --- a/server-client.c +++ b/server-client.c @@ -418,6 +418,7 @@ server_client_handle_key(struct client *c, int key) if (!(c->flags & CLIENT_PREFIX)) { if (isprefix) { c->flags |= CLIENT_PREFIX; + server_status_client(c); return; } @@ -432,6 +433,7 @@ server_client_handle_key(struct client *c, int key) /* Prefix key already pressed. Reset prefix and lookup key. */ c->flags &= ~CLIENT_PREFIX; + server_status_client(c); if ((bd = key_bindings_lookup(key | KEYC_PREFIX)) == NULL) { /* If repeating, treat this as a key, else ignore. */ if (c->flags & CLIENT_REPEAT) { @@ -587,8 +589,11 @@ server_client_repeat_timer(unused int fd, unused short events, void *data) { struct client *c = data; - if (c->flags & CLIENT_REPEAT) + if (c->flags & CLIENT_REPEAT) { + if (c->flags & CLIENT_PREFIX) + server_status_client(c); c->flags &= ~(CLIENT_PREFIX|CLIENT_REPEAT); + } } /* Check if client should be exited. */ -- cgit From c5504af4a685707389888db475fb7451ff5d8d86 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Thu, 21 Mar 2013 18:47:01 +0000 Subject: Add various checks to turn off bits that can't work in control mode (such as lock). --- server-client.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'server-client.c') diff --git a/server-client.c b/server-client.c index 1cae4733..b88b134e 100644 --- a/server-client.c +++ b/server-client.c @@ -356,6 +356,7 @@ server_client_handle_key(struct client *c, int key) /* Check the client is good to accept input. */ if ((c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED)) != 0) return; + if (c->session == NULL) return; s = c->session; @@ -529,6 +530,9 @@ server_client_reset_state(struct client *c) if (c->flags & CLIENT_SUSPENDED) return; + if (c->flags & CLIENT_CONTROL) + return; + tty_region(&c->tty, 0, c->tty.sy - 1); status = options_get_number(oo, "status"); @@ -626,7 +630,7 @@ server_client_check_redraw(struct client *c) struct window_pane *wp; int flags, redraw; - if (c->flags & CLIENT_SUSPENDED) + if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED)) return; flags = c->tty.flags & TTY_FREEZE; @@ -756,6 +760,8 @@ server_client_msg_dispatch(struct client *c) if (datalen != 0) fatalx("bad MSG_RESIZE size"); + if (c->flags & CLIENT_CONTROL) + break; if (tty_resize(&c->tty)) { recalculate_sizes(); server_redraw_client(c); @@ -925,7 +931,7 @@ server_client_msg_identify( if (data->flags & IDENTIFY_CONTROL) { c->stdin_callback = control_callback; - c->flags |= (CLIENT_CONTROL|CLIENT_SUSPENDED); + c->flags |= CLIENT_CONTROL; server_write_client(c, MSG_STDIN, NULL, 0); c->tty.fd = -1; @@ -950,7 +956,8 @@ server_client_msg_identify( tty_resize(&c->tty); - c->flags |= CLIENT_TERMINAL; + if (!(data->flags & IDENTIFY_CONTROL)) + c->flags |= CLIENT_TERMINAL; } /* Handle shell message. */ -- cgit From 8d59b189cc9e83ac0049fc3108de1b822fa7b4ce Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Fri, 22 Mar 2013 10:31:22 +0000 Subject: No more lint means no more ARGSUSED. --- server-client.c | 1 - 1 file changed, 1 deletion(-) (limited to 'server-client.c') diff --git a/server-client.c b/server-client.c index b88b134e..fc3989d9 100644 --- a/server-client.c +++ b/server-client.c @@ -587,7 +587,6 @@ server_client_reset_state(struct client *c) } /* Repeat time callback. */ -/* ARGSUSED */ void server_client_repeat_timer(unused int fd, unused short events, void *data) { -- cgit From a1722d5c2e545e4cce376848aab8a39465d3a036 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Fri, 22 Mar 2013 15:50:42 +0000 Subject: Remove unnecessary initializers of cmd_ctx. --- server-client.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'server-client.c') diff --git a/server-client.c b/server-client.c index fc3989d9..0feaa8b2 100644 --- a/server-client.c +++ b/server-client.c @@ -865,24 +865,22 @@ server_client_msg_info(struct cmd_ctx *ctx, const char *fmt, ...) void server_client_msg_command(struct client *c, struct msg_command_data *data) { - struct cmd_ctx ctx; + struct cmd_ctx *ctx; struct cmd_list *cmdlist = NULL; int argc; char **argv, *cause; - ctx.error = server_client_msg_error; - ctx.print = server_client_msg_print; - ctx.info = server_client_msg_info; - - ctx.msgdata = data; - ctx.curclient = NULL; - - ctx.cmdclient = c; + ctx = cmd_get_ctx(); + ctx->msgdata = data; + ctx->cmdclient = c; + ctx->error = server_client_msg_error; + ctx->print = server_client_msg_print; + ctx->info = server_client_msg_info; argc = data->argc; data->argv[(sizeof data->argv) - 1] = '\0'; if (cmd_unpack_argv(data->argv, sizeof data->argv, argc, &argv) != 0) { - server_client_msg_error(&ctx, "command too long"); + server_client_msg_error(ctx, "command too long"); goto error; } @@ -893,13 +891,13 @@ server_client_msg_command(struct client *c, struct msg_command_data *data) } if ((cmdlist = cmd_list_parse(argc, argv, &cause)) == NULL) { - server_client_msg_error(&ctx, "%s", cause); + server_client_msg_error(ctx, "%s", cause); cmd_free_argv(argc, argv); goto error; } cmd_free_argv(argc, argv); - switch (cmd_list_exec(cmdlist, &ctx)) + switch (cmd_list_exec(cmdlist, ctx)) { case CMD_RETURN_ERROR: case CMD_RETURN_NORMAL: @@ -910,11 +908,14 @@ server_client_msg_command(struct client *c, struct msg_command_data *data) break; } cmd_list_free(cmdlist); + cmd_free_ctx(ctx); return; error: if (cmdlist != NULL) cmd_list_free(cmdlist); + cmd_free_ctx(ctx); + c->flags |= CLIENT_EXIT; } -- cgit From 2243cfbe7559e6cf48194ff95dcd7eb6df5fe41d Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Fri, 22 Mar 2013 15:54:29 +0000 Subject: Need to set clients in context before changing their reference count. --- server-client.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'server-client.c') diff --git a/server-client.c b/server-client.c index 0feaa8b2..492d6b22 100644 --- a/server-client.c +++ b/server-client.c @@ -870,9 +870,8 @@ server_client_msg_command(struct client *c, struct msg_command_data *data) int argc; char **argv, *cause; - ctx = cmd_get_ctx(); + ctx = cmd_get_ctx(c, NULL); ctx->msgdata = data; - ctx->cmdclient = c; ctx->error = server_client_msg_error; ctx->print = server_client_msg_print; ctx->info = server_client_msg_info; -- cgit From a60687f9ba924abcb2934f1e7b603e3885dcd2ef Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Sun, 24 Mar 2013 09:28:59 +0000 Subject: Handle focus events from the terminal, from Aaron Jensen. --- server-client.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 2 deletions(-) (limited to 'server-client.c') diff --git a/server-client.c b/server-client.c index 492d6b22..ef4936fc 100644 --- a/server-client.c +++ b/server-client.c @@ -17,6 +17,7 @@ */ #include +#include #include #include @@ -28,6 +29,8 @@ #include "tmux.h" +void server_client_check_focus(struct window_pane *); +void server_client_check_resize(struct window_pane *); void server_client_check_mouse(struct client *, struct window_pane *); void server_client_repeat_timer(int, short, void *); void server_client_check_exit(struct client *); @@ -94,6 +97,8 @@ server_client_create(int fd) c->tty.mouse.event = MOUSE_EVENT_UP; c->tty.mouse.flags = 0; + c->flags |= CLIENT_FOCUSED; + evtimer_set(&c->repeat_timer, server_client_repeat_timer, c); for (i = 0; i < ARRAY_LENGTH(&clients); i++) { @@ -495,7 +500,7 @@ server_client_loop(void) /* * Any windows will have been redrawn as part of clients, so clear - * their flags now. + * their flags now. Also check pane focus and resize. */ for (i = 0; i < ARRAY_LENGTH(&windows); i++) { w = ARRAY_ITEM(&windows, i); @@ -503,9 +508,90 @@ server_client_loop(void) continue; w->flags &= ~WINDOW_REDRAW; - TAILQ_FOREACH(wp, &w->panes, entry) + TAILQ_FOREACH(wp, &w->panes, entry) { + server_client_check_focus(wp); + server_client_check_resize(wp); wp->flags &= ~PANE_REDRAW; + } + } +} + +/* Check if pane should be resized. */ +void +server_client_check_resize(struct window_pane *wp) +{ + struct winsize ws; + + if (wp->fd == -1 || !(wp->flags & PANE_RESIZE)) + return; + + memset(&ws, 0, sizeof ws); + ws.ws_col = wp->sx; + ws.ws_row = wp->sy; + + if (ioctl(wp->fd, TIOCSWINSZ, &ws) == -1) { +#ifdef __sun + /* + * Some versions of Solaris apparently can return an error when + * resizing; don't know why this happens, can't reproduce on + * other platforms and ignoring it doesn't seem to cause any + * issues. + */ + if (errno != EINVAL) +#endif + fatal("ioctl failed"); + } + + wp->flags &= ~PANE_RESIZE; +} + +/* Check whether pane should be focused. */ +void +server_client_check_focus(struct window_pane *wp) +{ + u_int i; + struct client *c; + + /* If we don't care about focus, forget it. */ + if (!(wp->base.mode & MODE_FOCUSON)) + return; + + /* If we're not the active pane in our window, we're not focused. */ + if (wp->window->active != wp) + goto not_focused; + + /* If we're in a mode, we're not focused. */ + if (wp->screen != &wp->base) + goto not_focused; + + /* + * If our window is the current window in any focused clients with an + * attached session, we're focused. + */ + for (i = 0; i < ARRAY_LENGTH(&clients); i++) { + c = ARRAY_ITEM(&clients, i); + if (c == NULL || c->session == NULL) + continue; + + if (!(c->flags & CLIENT_FOCUSED)) + continue; + if (c->session->flags & SESSION_UNATTACHED) + continue; + + if (c->session->curw->window == wp->window) + goto focused; } + +not_focused: + if (wp->flags & PANE_FOCUSED) + bufferevent_write(wp->event, "\033[O", 3); + wp->flags &= ~PANE_FOCUSED; + return; + +focused: + if (!(wp->flags & PANE_FOCUSED)) + bufferevent_write(wp->event, "\033[I", 3); + wp->flags |= PANE_FOCUSED; } /* -- cgit From 20636d956dd36c1f14152569a4d44a50eea9083d Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Sun, 24 Mar 2013 09:54:10 +0000 Subject: Add a command queue to standardize and simplify commands that call other commands and allow a command to block execution of subsequent commands. This allows run-shell and if-shell to be synchronous which has been much requested. Each client has a default command queue and commands are consumed one at a time from it. A command may suspend execution from the queue by returning CMD_RETURN_WAIT and then resume it by calling cmd_continue() - for example run-shell does this from the callback that is fired after the job is freed. When the command queue becomes empty, command clients are automatically exited (unless attaching). A callback is also fired - this is used for nested commands in, for example, if-shell which can block execution of the client's cmdq until a new cmdq becomes empty. Also merge all the old error/info/print functions together and lose the old curclient/cmdclient distinction - a cmdq is bound to one client (or none if in the configuration file), this is a command client if c->session is NULL otherwise an attached client. --- server-client.c | 83 ++++++++------------------------------------------------- 1 file changed, 11 insertions(+), 72 deletions(-) (limited to 'server-client.c') diff --git a/server-client.c b/server-client.c index ef4936fc..6f29000b 100644 --- a/server-client.c +++ b/server-client.c @@ -45,10 +45,6 @@ void server_client_msg_identify( struct client *, struct msg_identify_data *, int); void server_client_msg_shell(struct client *); -void printflike2 server_client_msg_error(struct cmd_ctx *, const char *, ...); -void printflike2 server_client_msg_print(struct cmd_ctx *, const char *, ...); -void printflike2 server_client_msg_info(struct cmd_ctx *, const char *, ...); - /* Create a new client. */ void server_client_create(int fd) @@ -67,6 +63,9 @@ server_client_create(int fd) fatal("gettimeofday failed"); memcpy(&c->activity_time, &c->creation_time, sizeof c->activity_time); + c->cmdq = cmdq_new(c); + c->cmdq->client_exit = 1; + c->stdin_data = evbuffer_new (); c->stdout_data = evbuffer_new (); c->stderr_data = evbuffer_new (); @@ -181,6 +180,10 @@ server_client_lost(struct client *c) free(c->prompt_buffer); free(c->cwd); + c->cmdq->dead = 1; + cmdq_free(c->cmdq); + c->cmdq = NULL; + environ_free(&c->environ); close(c->ibuf.fd); @@ -901,71 +904,18 @@ server_client_msg_dispatch(struct client *c) } } -/* Callback to send error message to client. */ -void printflike2 -server_client_msg_error(struct cmd_ctx *ctx, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - evbuffer_add_vprintf(ctx->cmdclient->stderr_data, fmt, ap); - va_end(ap); - - evbuffer_add(ctx->cmdclient->stderr_data, "\n", 1); - server_push_stderr(ctx->cmdclient); - ctx->cmdclient->retcode = 1; -} - -/* Callback to send print message to client. */ -void printflike2 -server_client_msg_print(struct cmd_ctx *ctx, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - evbuffer_add_vprintf(ctx->cmdclient->stdout_data, fmt, ap); - va_end(ap); - - evbuffer_add(ctx->cmdclient->stdout_data, "\n", 1); - server_push_stdout(ctx->cmdclient); -} - -/* Callback to send print message to client, if not quiet. */ -void printflike2 -server_client_msg_info(struct cmd_ctx *ctx, const char *fmt, ...) -{ - va_list ap; - - if (options_get_number(&global_options, "quiet")) - return; - - va_start(ap, fmt); - evbuffer_add_vprintf(ctx->cmdclient->stdout_data, fmt, ap); - va_end(ap); - - evbuffer_add(ctx->cmdclient->stdout_data, "\n", 1); - server_push_stdout(ctx->cmdclient); -} - /* Handle command message. */ void server_client_msg_command(struct client *c, struct msg_command_data *data) { - struct cmd_ctx *ctx; struct cmd_list *cmdlist = NULL; int argc; char **argv, *cause; - ctx = cmd_get_ctx(c, NULL); - ctx->msgdata = data; - ctx->error = server_client_msg_error; - ctx->print = server_client_msg_print; - ctx->info = server_client_msg_info; - argc = data->argc; data->argv[(sizeof data->argv) - 1] = '\0'; if (cmd_unpack_argv(data->argv, sizeof data->argv, argc, &argv) != 0) { - server_client_msg_error(ctx, "command too long"); + cmdq_error(c->cmdq, "command too long"); goto error; } @@ -975,31 +925,20 @@ server_client_msg_command(struct client *c, struct msg_command_data *data) *argv = xstrdup("new-session"); } - if ((cmdlist = cmd_list_parse(argc, argv, &cause)) == NULL) { - server_client_msg_error(ctx, "%s", cause); + if ((cmdlist = cmd_list_parse(argc, argv, NULL, 0, &cause)) == NULL) { + cmdq_error(c->cmdq, "%s", cause); cmd_free_argv(argc, argv); goto error; } cmd_free_argv(argc, argv); - switch (cmd_list_exec(cmdlist, ctx)) - { - case CMD_RETURN_ERROR: - case CMD_RETURN_NORMAL: - c->flags |= CLIENT_EXIT; - break; - case CMD_RETURN_ATTACH: - case CMD_RETURN_YIELD: - break; - } + cmdq_run(c->cmdq, cmdlist); cmd_list_free(cmdlist); - cmd_free_ctx(ctx); return; error: if (cmdlist != NULL) cmd_list_free(cmdlist); - cmd_free_ctx(ctx); c->flags |= CLIENT_EXIT; } -- cgit From c71844de631186f3df7ff5a6e3aab613da1e4853 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Sun, 24 Mar 2013 09:57:59 +0000 Subject: Add resize-pane -Z to temporary zoom the active pane to occupy the full window or unzoom (restored to the normal layout) if it already zoomed, bound to C-b z by default. The pane is unzoomed on pretty much any excuse whatsoever. We considered making this a new layout but the requirements are quite different from layouts so decided it is better as a special case. Each current layout cell is saved, a temporary one-cell layout generated and all except the active pane set to NULL. Prompted by suggestions and scripts from several. Thanks to Aaron Jensen and Thiago Padilha for testing an earlier version. --- server-client.c | 1 + 1 file changed, 1 insertion(+) (limited to 'server-client.c') diff --git a/server-client.c b/server-client.c index 6f29000b..64af442a 100644 --- a/server-client.c +++ b/server-client.c @@ -384,6 +384,7 @@ server_client_handle_key(struct client *c, int key) if (c->flags & CLIENT_IDENTIFY && key >= '0' && key <= '9') { if (c->flags & CLIENT_READONLY) return; + window_unzoom(w); wp = window_pane_at_index(w, key - '0'); if (wp != NULL && window_pane_visible(wp)) window_set_active_pane(w, wp); -- cgit From 62db3c8efe70020e2555e3f34e8c07d0b2106077 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Mon, 25 Mar 2013 10:03:24 +0000 Subject: Send DSC 1000p at the beginning of a -CC client's lifetime and ST and the end, from George Nachman. --- server-client.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'server-client.c') diff --git a/server-client.c b/server-client.c index 64af442a..e590d219 100644 --- a/server-client.c +++ b/server-client.c @@ -957,6 +957,8 @@ server_client_msg_identify( if (data->flags & IDENTIFY_CONTROL) { c->stdin_callback = control_callback; c->flags |= CLIENT_CONTROL; + if (data->flags & IDENTIFY_TERMIOS) + evbuffer_add_printf(c->stdout_data, "\033P1000p"); server_write_client(c, MSG_STDIN, NULL, 0); c->tty.fd = -1; -- cgit From e4c0730bf1e13ac256a58db7ee7a58c36c8980f4 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Mon, 25 Mar 2013 11:36:59 +0000 Subject: Use single stdout and stderr for control clients. --- server-client.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'server-client.c') diff --git a/server-client.c b/server-client.c index e590d219..13c037d8 100644 --- a/server-client.c +++ b/server-client.c @@ -154,7 +154,8 @@ server_client_lost(struct client *c) evbuffer_free (c->stdin_data); evbuffer_free (c->stdout_data); - evbuffer_free (c->stderr_data); + if (c->stderr_data != c->stdout_data) + evbuffer_free (c->stderr_data); status_free_jobs(&c->status_new); status_free_jobs(&c->status_old); @@ -956,6 +957,8 @@ server_client_msg_identify( if (data->flags & IDENTIFY_CONTROL) { c->stdin_callback = control_callback; + evbuffer_free(c->stderr_data); + c->stderr_data = c->stdout_data; c->flags |= CLIENT_CONTROL; if (data->flags & IDENTIFY_TERMIOS) evbuffer_add_printf(c->stdout_data, "\033P1000p"); -- cgit From 673eb160d428b294cea1ed5ca2a2c3cb3760b00f Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Mon, 25 Mar 2013 11:53:54 +0000 Subject: Sort includes and fix spaces. --- server-client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'server-client.c') diff --git a/server-client.c b/server-client.c index 13c037d8..f61912bc 100644 --- a/server-client.c +++ b/server-client.c @@ -21,10 +21,10 @@ #include #include -#include -#include #include #include +#include +#include #include #include "tmux.h" -- cgit