From bb53c20c1882cbc909d4fe2ae3c6ad665da6abf6 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Sat, 6 Feb 2010 22:55:31 +0000 Subject: [PATCH] Support attaching a client read-only with a new -r flag to the attach-session command. --- cmd-attach-session.c | 7 +++++-- cmd-detach-client.c | 2 +- key-bindings.c | 14 +++++++++++++- server-client.c | 25 ++++++++++++++++--------- tmux.1 | 6 +++++- tmux.h | 2 ++ 6 files changed, 42 insertions(+), 14 deletions(-) diff --git a/cmd-attach-session.c b/cmd-attach-session.c index c8f01633..dbc43141 100644 --- a/cmd-attach-session.c +++ b/cmd-attach-session.c @@ -28,8 +28,8 @@ int cmd_attach_session_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_attach_session_entry = { "attach-session", "attach", - "[-d] " CMD_TARGET_SESSION_USAGE, - CMD_CANTNEST|CMD_STARTSERVER|CMD_SENDENVIRON, "d", + "[-dr] " CMD_TARGET_SESSION_USAGE, + CMD_CANTNEST|CMD_STARTSERVER|CMD_SENDENVIRON, "dr", cmd_target_init, cmd_target_parse, cmd_attach_session_exec, @@ -89,6 +89,9 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_ctx *ctx) return (-1); } + if (cmd_check_flag(data->chflags, 'r')) + ctx->cmdclient->flags |= CLIENT_READONLY; + if (cmd_check_flag(data->chflags, 'd')) server_write_session(s, MSG_DETACH, NULL, 0); diff --git a/cmd-detach-client.c b/cmd-detach-client.c index 4903281f..a2288036 100644 --- a/cmd-detach-client.c +++ b/cmd-detach-client.c @@ -29,7 +29,7 @@ int cmd_detach_client_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_detach_client_entry = { "detach-client", "detach", CMD_TARGET_CLIENT_USAGE, - 0, "", + CMD_READONLY, "", cmd_target_init, cmd_target_parse, cmd_detach_client_exec, diff --git a/key-bindings.c b/key-bindings.c index d536af11..c08ac942 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -239,7 +239,9 @@ key_bindings_info(struct cmd_ctx *ctx, const char *fmt, ...) void key_bindings_dispatch(struct key_binding *bd, struct client *c) { - struct cmd_ctx ctx; + struct cmd_ctx ctx; + struct cmd *cmd; + int readonly; ctx.msgdata = NULL; ctx.curclient = c; @@ -250,5 +252,15 @@ key_bindings_dispatch(struct key_binding *bd, struct client *c) ctx.cmdclient = NULL; + readonly = 1; + TAILQ_FOREACH(cmd, bd->cmdlist, qentry) { + if (!(cmd->entry->flags & CMD_READONLY)) + readonly = 0; + } + if (!readonly && c->flags & CLIENT_READONLY) { + key_bindings_info(&ctx, "Client is read-only"); + return; + } + cmd_list_exec(bd->cmdlist, &ctx); } diff --git a/server-client.c b/server-client.c index 03560c1c..03d5c84b 100644 --- a/server-client.c +++ b/server-client.c @@ -271,6 +271,8 @@ server_client_handle_key(int key, struct mouse_event *mouse, void *data) /* Special case: number keys jump to pane in identify mode. */ if (c->flags & CLIENT_IDENTIFY && key >= '0' && key <= '9') { + if (c->flags & CLIENT_READONLY) + return; wp = window_pane_at_index(w, key - '0'); if (wp != NULL && window_pane_visible(wp)) window_set_active_pane(w, wp); @@ -279,15 +281,20 @@ server_client_handle_key(int key, struct mouse_event *mouse, void *data) } /* Handle status line. */ - status_message_clear(c); - server_clear_identify(c); + if (!(c->flags & CLIENT_READONLY)) { + status_message_clear(c); + server_clear_identify(c); + } if (c->prompt_string != NULL) { - status_prompt_key(c, key); + if (!(c->flags & CLIENT_READONLY)) + status_prompt_key(c, key); return; } /* Check for mouse keys. */ if (key == KEYC_MOUSE) { + if (c->flags & CLIENT_READONLY) + return; if (options_get_number(oo, "mouse-select-pane")) { window_set_active_at(w, mouse->x, mouse->y); server_redraw_window_borders(w); @@ -313,9 +320,10 @@ server_client_handle_key(int key, struct mouse_event *mouse, void *data) c->flags |= CLIENT_PREFIX; else { /* Try as a non-prefix key binding. */ - if ((bd = key_bindings_lookup(key)) == NULL) - window_pane_key(wp, c, key); - else + if ((bd = key_bindings_lookup(key)) == NULL) { + if (!(c->flags & CLIENT_READONLY)) + window_pane_key(wp, c, key); + } else key_bindings_dispatch(bd, c); } return; @@ -329,7 +337,7 @@ server_client_handle_key(int key, struct mouse_event *mouse, void *data) c->flags &= ~CLIENT_REPEAT; if (isprefix) c->flags |= CLIENT_PREFIX; - else + else if (!(c->flags & CLIENT_READONLY)) window_pane_key(wp, c, key); } return; @@ -340,7 +348,7 @@ server_client_handle_key(int key, struct mouse_event *mouse, void *data) c->flags &= ~CLIENT_REPEAT; if (isprefix) c->flags |= CLIENT_PREFIX; - else + else if (!(c->flags & CLIENT_READONLY)) window_pane_key(wp, c, key); return; } @@ -660,7 +668,6 @@ server_client_msg_command(struct client *c, struct msg_command_data *data) { struct cmd_ctx ctx; struct cmd_list *cmdlist = NULL; - struct cmd *cmd; int argc; char **argv, *cause; diff --git a/tmux.1 b/tmux.1 index 67ce3bc4..360d53a2 100644 --- a/tmux.1 +++ b/tmux.1 @@ -364,7 +364,7 @@ new-window ; split-window -d The following commands are available: .Bl -tag -width Ds .It Xo Ic attach-session -.Op Fl d +.Op Fl dr .Op Fl t Ar target-session .Xc .D1 (alias: Ic attach ) @@ -376,6 +376,10 @@ If used from inside, switch the current client. If .Fl d is specified, any other clients attached to the session are detached. +.Fl r +signifies the client is read-only (only keys bound to the +.Ic detach-client +command have any effect) .Pp If no server is started, .Ic attach-session diff --git a/tmux.h b/tmux.h index 43cd8197..2afaf3cc 100644 --- a/tmux.h +++ b/tmux.h @@ -1094,6 +1094,7 @@ struct client { #define CLIENT_IDENTIFY 0x100 #define CLIENT_DEAD 0x200 #define CLIENT_BORDERS 0x400 +#define CLIENT_READONLY 0x800 int flags; struct event identify_timer; @@ -1172,6 +1173,7 @@ struct cmd_entry { #define CMD_ARG01 0x10 #define CMD_ARG2 0x20 #define CMD_ARG12 0x40 +#define CMD_READONLY 0x80 int flags; const char *chflags;