summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd-attach-session.c2
-rw-r--r--cmd-bind-key.c2
-rw-r--r--cmd-new-session.c1
-rw-r--r--cmd-send-keys.c23
-rw-r--r--cmd-set-option.c7
-rw-r--r--cmd-switch-client.c2
-rw-r--r--cmd-unbind-key.c8
-rw-r--r--format.c4
-rw-r--r--input-keys.c4
-rw-r--r--key-string.c40
-rw-r--r--options-table.c6
-rw-r--r--server-client.c50
-rw-r--r--server-fn.c1
-rw-r--r--tmux.116
-rw-r--r--tmux.h3
-rw-r--r--tty-keys.c8
16 files changed, 122 insertions, 55 deletions
diff --git a/cmd-attach-session.c b/cmd-attach-session.c
index 73c82248..00ced9df 100644
--- a/cmd-attach-session.c
+++ b/cmd-attach-session.c
@@ -119,6 +119,7 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
}
c->session = s;
+ server_client_set_key_table(c, NULL);
status_timer_start(c);
notify_attached_session_changed(c);
session_update_activity(s, NULL);
@@ -150,6 +151,7 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
}
c->session = s;
+ server_client_set_key_table(c, NULL);
status_timer_start(c);
notify_attached_session_changed(c);
session_update_activity(s, NULL);
diff --git a/cmd-bind-key.c b/cmd-bind-key.c
index 1867e814..b13409cb 100644
--- a/cmd-bind-key.c
+++ b/cmd-bind-key.c
@@ -62,7 +62,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq)
}
key = key_string_lookup_string(args->argv[0]);
- if (key == KEYC_NONE) {
+ if (key == KEYC_NONE || key == KEYC_UNKNOWN) {
cmdq_error(cmdq, "unknown key: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
}
diff --git a/cmd-new-session.c b/cmd-new-session.c
index aee69e12..341399be 100644
--- a/cmd-new-session.c
+++ b/cmd-new-session.c
@@ -262,6 +262,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
} else if (c->session != NULL)
c->last_session = c->session;
c->session = s;
+ server_client_set_key_table(c, NULL);
status_timer_start(c);
notify_attached_session_changed(c);
session_update_activity(s, NULL);
diff --git a/cmd-send-keys.c b/cmd-send-keys.c
index 73a308ae..1461baa9 100644
--- a/cmd-send-keys.c
+++ b/cmd-send-keys.c
@@ -52,8 +52,8 @@ cmd_send_keys_exec(struct cmd *self, struct cmd_q *cmdq)
struct mouse_event *m = &cmdq->item->mouse;
struct window_pane *wp;
struct session *s;
- const u_char *str;
- int i;
+ int i, literal;
+ const u_char *keystr;
key_code key;
if (args_has(args, 'M')) {
@@ -82,14 +82,17 @@ cmd_send_keys_exec(struct cmd *self, struct cmd_q *cmdq)
input_reset(wp);
for (i = 0; i < args->argc; i++) {
- str = args->argv[i];
-
- if (!args_has(args, 'l') &&
- (key = key_string_lookup_string(str)) != KEYC_NONE) {
- window_pane_key(wp, NULL, s, key, NULL);
- } else {
- for (; *str != '\0'; str++)
- window_pane_key(wp, NULL, s, *str, NULL);
+ literal = args_has(args, 'l');
+ if (!literal) {
+ key = key_string_lookup_string(args->argv[i]);
+ if (key != KEYC_NONE && key != KEYC_UNKNOWN)
+ window_pane_key(wp, NULL, s, key, NULL);
+ else
+ literal = 1;
+ }
+ if (literal) {
+ for (keystr = args->argv[i]; *keystr != '\0'; keystr++)
+ window_pane_key(wp, NULL, s, *keystr, NULL);
}
}
diff --git a/cmd-set-option.c b/cmd-set-option.c
index 7de91aa2..daee62ac 100644
--- a/cmd-set-option.c
+++ b/cmd-set-option.c
@@ -183,6 +183,10 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
w->active->flags |= PANE_CHANGED;
}
}
+ if (strcmp(oe->name, "key-table") == 0) {
+ TAILQ_FOREACH(c, &clients, entry)
+ server_client_set_key_table(c, NULL);
+ }
if (strcmp(oe->name, "status") == 0 ||
strcmp(oe->name, "status-interval") == 0)
status_timer_start_all();
@@ -396,7 +400,8 @@ cmd_set_option_key(__unused struct cmd *self, struct cmd_q *cmdq,
{
key_code key;
- if ((key = key_string_lookup_string(value)) == KEYC_NONE) {
+ key = key_string_lookup_string(value);
+ if (key == KEYC_UNKNOWN) {
cmdq_error(cmdq, "bad key: %s", value);
return (NULL);
}
diff --git a/cmd-switch-client.c b/cmd-switch-client.c
index edc0fd69..4746b15a 100644
--- a/cmd-switch-client.c
+++ b/cmd-switch-client.c
@@ -65,6 +65,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
table->references++;
key_bindings_unref_table(c->keytable);
c->keytable = table;
+ return (CMD_RETURN_NORMAL);
}
tflag = args_get(args, 't');
@@ -123,6 +124,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq)
if (c->session != NULL && c->session != s)
c->last_session = c->session;
c->session = s;
+ server_client_set_key_table(c, NULL);
status_timer_start(c);
session_update_activity(s, NULL);
gettimeofday(&s->last_attached_time, NULL);
diff --git a/cmd-unbind-key.c b/cmd-unbind-key.c
index cec538c0..66a4525e 100644
--- a/cmd-unbind-key.c
+++ b/cmd-unbind-key.c
@@ -51,7 +51,7 @@ cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_ERROR);
}
key = key_string_lookup_string(args->argv[0]);
- if (key == KEYC_NONE) {
+ if (key == KEYC_NONE || key == KEYC_UNKNOWN) {
cmdq_error(cmdq, "unknown key: %s", args->argv[0]);
return (CMD_RETURN_ERROR);
}
@@ -60,13 +60,13 @@ cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
cmdq_error(cmdq, "key given with -a");
return (CMD_RETURN_ERROR);
}
- key = KEYC_NONE;
+ key = KEYC_UNKNOWN;
}
if (args_has(args, 't'))
return (cmd_unbind_key_mode_table(self, cmdq, key));
- if (key == KEYC_NONE) {
+ if (key == KEYC_UNKNOWN) {
tablename = args_get(args, 'T');
if (tablename == NULL) {
key_bindings_remove_table("root");
@@ -109,7 +109,7 @@ cmd_unbind_key_mode_table(struct cmd *self, struct cmd_q *cmdq, key_code key)
return (CMD_RETURN_ERROR);
}
- if (key == KEYC_NONE) {
+ if (key == KEYC_UNKNOWN) {
while (!RB_EMPTY(mtab->tree)) {
mbind = RB_ROOT(mtab->tree);
RB_REMOVE(mode_key_tree, mtab->tree, mbind);
diff --git a/format.c b/format.c
index 90f4c311..a2da1cc2 100644
--- a/format.c
+++ b/format.c
@@ -1052,6 +1052,7 @@ void
format_defaults_client(struct format_tree *ft, struct client *c)
{
struct session *s;
+ const char *name;
if (ft->s == NULL)
ft->s = c->session;
@@ -1069,7 +1070,8 @@ format_defaults_client(struct format_tree *ft, struct client *c)
format_add_tv(ft, "client_created", &c->creation_time);
format_add_tv(ft, "client_activity", &c->activity_time);
- if (strcmp(c->keytable->name, "root") == 0)
+ name = server_client_get_key_table(c);
+ if (strcmp(c->keytable->name, name) == 0)
format_add(ft, "client_prefix", "%d", 0);
else
format_add(ft, "client_prefix", "%d", 1);
diff --git a/input-keys.c b/input-keys.c
index 0a18f37e..1572b7e7 100644
--- a/input-keys.c
+++ b/input-keys.c
@@ -160,14 +160,14 @@ input_key(struct window_pane *wp, key_code key, struct mouse_event *m)
* if necessary. If it is a UTF-8 key, split it and send it.
*/
justkey = (key & ~KEYC_ESCAPE);
- if (key != KEYC_NONE && justkey <= 0x7f) {
+ if (justkey <= 0x7f) {
if (key & KEYC_ESCAPE)
bufferevent_write(wp->event, "\033", 1);
ud.data[0] = justkey;
bufferevent_write(wp->event, &ud.data[0], 1);
return;
}
- if (key != KEYC_NONE && justkey > 0x7f && justkey < KEYC_BASE) {
+ if (justkey > 0x7f && justkey < KEYC_BASE) {
if (utf8_split(justkey, &ud) != UTF8_DONE)
return;
if (key & KEYC_ESCAPE)
diff --git a/key-string.c b/key-string.c
index 9a44892d..1ff3ca30 100644
--- a/key-string.c
+++ b/key-string.c
@@ -22,8 +22,8 @@
#include "tmux.h"
-key_code key_string_search_table(const char *);
-key_code key_string_get_modifiers(const char **);
+static key_code key_string_search_table(const char *);
+static key_code key_string_get_modifiers(const char **);
const struct {
const char *string;
@@ -98,7 +98,7 @@ const struct {
};
/* Find key string in table. */
-key_code
+static key_code
key_string_search_table(const char *string)
{
u_int i;
@@ -107,11 +107,11 @@ key_string_search_table(const char *string)
if (strcasecmp(string, key_string_table[i].string) == 0)
return (key_string_table[i].key);
}
- return (KEYC_NONE);
+ return (KEYC_UNKNOWN);
}
/* Find modifiers. */
-key_code
+static key_code
key_string_get_modifiers(const char **string)
{
key_code modifiers;
@@ -150,10 +150,14 @@ key_string_lookup_string(const char *string)
u_int i;
enum utf8_state more;
+ /* Is this no key? */
+ if (strcasecmp(string, "None") == 0)
+ return (KEYC_NONE);
+
/* Is this a hexadecimal value? */
if (string[0] == '0' && string[1] == 'x') {
if (sscanf(string + 2, "%hx%n", &u, &size) != 1 || size > 4)
- return (KEYC_NONE);
+ return (KEYC_UNKNOWN);
return (u);
}
@@ -165,30 +169,30 @@ key_string_lookup_string(const char *string)
}
modifiers |= key_string_get_modifiers(&string);
if (string[0] == '\0')
- return (KEYC_NONE);
+ return (KEYC_UNKNOWN);
/* Is this a standard ASCII key? */
if (string[1] == '\0' && (u_char)string[0] <= 127) {
key = (u_char)string[0];
if (key < 32 || key == 127)
- return (KEYC_NONE);
+ return (KEYC_UNKNOWN);
} else {
/* Try as a UTF-8 key. */
if ((more = utf8_open(&ud, (u_char)*string)) == UTF8_MORE) {
if (strlen(string) != ud.size)
- return (KEYC_NONE);
+ return (KEYC_UNKNOWN);
for (i = 1; i < ud.size; i++)
more = utf8_append(&ud, (u_char)string[i]);
if (more != UTF8_DONE)
- return (KEYC_NONE);
+ return (KEYC_UNKNOWN);
key = utf8_combine(&ud);
return (key | modifiers);
}
/* Otherwise look the key up in the table. */
key = key_string_search_table(string);
- if (key == KEYC_NONE)
- return (KEYC_NONE);
+ if (key == KEYC_UNKNOWN)
+ return (KEYC_UNKNOWN);
}
/* Convert the standard control keys. */
@@ -202,7 +206,7 @@ key_string_lookup_string(const char *string)
else if (key == 63)
key = KEYC_BSPACE;
else
- return (KEYC_NONE);
+ return (KEYC_UNKNOWN);
modifiers &= ~KEYC_CTRL;
}
@@ -222,9 +226,13 @@ key_string_lookup_key(key_code key)
/* Handle no key. */
if (key == KEYC_NONE)
- return ("<NONE>");
+ return ("None");
+
+ /* Handle special keys. */
+ if (key == KEYC_UNKNOWN)
+ return ("Unknown");
if (key == KEYC_MOUSE)
- return ("<MOUSE>");
+ return ("Mouse");
/*
* Special case: display C-@ as C-Space. Could do this below in
@@ -265,7 +273,7 @@ key_string_lookup_key(key_code key)
/* Invalid keys are errors. */
if (key == 127 || key > 255) {
- snprintf(out, sizeof out, "<INVALID#%llx>", key);
+ snprintf(out, sizeof out, "Invalid#%llx", key);
return (out);
}
diff --git a/options-table.c b/options-table.c
index ab61ef79..2d904124 100644
--- a/options-table.c
+++ b/options-table.c
@@ -210,6 +210,12 @@ const struct options_table_entry options_table[] = {
.default_num = 2000
},
+ { .name = "key-table",
+ .type = OPTIONS_TABLE_STRING,
+ .scope = OPTIONS_TABLE_SESSION,
+ .default_str = "root"
+ },
+
{ .name = "lock-after-time",
.type = OPTIONS_TABLE_NUMBER,
.scope = OPTIONS_TABLE_SESSION,
diff --git a/server-client.c b/server-client.c
index eb4361f5..aa4d407b 100644
--- a/server-client.c
+++ b/server-client.c
@@ -30,7 +30,6 @@
#include "tmux.h"
-void server_client_key_table(struct client *, const char *);
void server_client_free(int, short, void *);
void server_client_check_focus(struct window_pane *);
void server_client_check_resize(struct window_pane *);
@@ -70,13 +69,32 @@ server_client_check_nested(struct client *c)
/* Set client key table. */
void
-server_client_key_table(struct client *c, const char *name)
+server_client_set_key_table(struct client *c, const char *name)
{
+ if (name == NULL)
+ name = server_client_get_key_table(c);
+
key_bindings_unref_table(c->keytable);
c->keytable = key_bindings_get_table(name, 1);
c->keytable->references++;
}
+/* Get default key table. */
+const char *
+server_client_get_key_table(struct client *c)
+{
+ struct session *s = c->session;
+ const char *name;
+
+ if (s == NULL)
+ return ("root");
+
+ name = options_get_string(s->options, "key-table");
+ if (*name == '\0')
+ return ("root");
+ return (name);
+}
+
/* Create a new client. */
void
server_client_create(int fd)
@@ -307,7 +325,7 @@ server_client_check_mouse(struct client *c)
log_debug("down at %u,%u", x, y);
}
if (type == NOTYPE)
- return (KEYC_NONE);
+ return (KEYC_UNKNOWN);
/* Always save the session. */
m->s = s->id;
@@ -317,7 +335,7 @@ server_client_check_mouse(struct client *c)
if (m->statusat != -1 && y == (u_int)m->statusat) {
w = status_get_window_at(c, x);
if (w == NULL)
- return (KEYC_NONE);
+ return (KEYC_UNKNOWN);
m->w = w->id;
where = STATUS;
} else
@@ -350,7 +368,7 @@ server_client_check_mouse(struct client *c)
}
}
if (where == NOWHERE)
- return (KEYC_NONE);
+ return (KEYC_UNKNOWN);
m->wp = wp->id;
m->w = wp->window->id;
} else
@@ -369,7 +387,7 @@ server_client_check_mouse(struct client *c)
}
/* Convert to a key binding. */
- key = KEYC_NONE;
+ key = KEYC_UNKNOWN;
switch (type) {
case NOTYPE:
break;
@@ -481,8 +499,8 @@ server_client_check_mouse(struct client *c)
}
break;
}
- if (key == KEYC_NONE)
- return (KEYC_NONE);
+ if (key == KEYC_UNKNOWN)
+ return (KEYC_UNKNOWN);
/* Apply modifiers if any. */
if (b & MOUSE_MASK_META)
@@ -570,7 +588,7 @@ server_client_handle_key(struct client *c, key_code key)
if (c->flags & CLIENT_READONLY)
return;
key = server_client_check_mouse(c);
- if (key == KEYC_NONE)
+ if (key == KEYC_UNKNOWN)
return;
m->valid = 1;
@@ -596,7 +614,7 @@ retry:
* again in the root table.
*/
if ((c->flags & CLIENT_REPEAT) && !bd->can_repeat) {
- server_client_key_table(c, "root");
+ server_client_set_key_table(c, NULL);
c->flags &= ~CLIENT_REPEAT;
server_status_client(c);
goto retry;
@@ -623,7 +641,7 @@ retry:
evtimer_add(&c->repeat_timer, &tv);
} else {
c->flags &= ~CLIENT_REPEAT;
- server_client_key_table(c, "root");
+ server_client_set_key_table(c, NULL);
}
server_status_client(c);
@@ -638,15 +656,15 @@ retry:
* root table and try again.
*/
if (c->flags & CLIENT_REPEAT) {
- server_client_key_table(c, "root");
+ server_client_set_key_table(c, NULL);
c->flags &= ~CLIENT_REPEAT;
server_status_client(c);
goto retry;
}
/* If no match and we're not in the root table, that's it. */
- if (strcmp(c->keytable->name, "root") != 0) {
- server_client_key_table(c, "root");
+ if (strcmp(c->keytable->name, server_client_get_key_table(c)) != 0) {
+ server_client_set_key_table(c, NULL);
server_status_client(c);
return;
}
@@ -657,7 +675,7 @@ retry:
*/
if (key == (key_code)options_get_number(s->options, "prefix") ||
key == (key_code)options_get_number(s->options, "prefix2")) {
- server_client_key_table(c, "prefix");
+ server_client_set_key_table(c, "prefix");
server_status_client(c);
return;
}
@@ -842,7 +860,7 @@ server_client_repeat_timer(__unused int fd, __unused short events, void *data)
struct client *c = data;
if (c->flags & CLIENT_REPEAT) {
- server_client_key_table(c, "root");
+ server_client_set_key_table(c, NULL);
c->flags &= ~CLIENT_REPEAT;
server_status_client(c);
}
diff --git a/server-fn.c b/server-fn.c
index b6619f2e..3afeb090 100644
--- a/server-fn.c
+++ b/server-fn.c
@@ -385,6 +385,7 @@ server_destroy_session(struct session *s)
} else {
c->last_session = NULL;
c->session = s_new;
+ server_client_set_key_table(c, NULL);
status_timer_start(c);
notify_attached_session_changed(c);
session_update_activity(s_new, NULL);
diff --git a/tmux.1 b/tmux.1
index 7a2d87d4..ac8a7394 100644
--- a/tmux.1
+++ b/tmux.1
@@ -2576,6 +2576,11 @@ is in milliseconds.
Set the maximum number of lines held in window history.
This setting applies only to new windows - existing window histories are not
resized and retain the limit at the point they were created.
+.It Ic key-table Ar key-table
+Set the default key table to
+.Ar key-table
+instead of
+.Em root .
.It Ic lock-after-time Ar number
Lock the session (like the
.Ic lock-session
@@ -2668,8 +2673,19 @@ See the
section for details.
.It Ic prefix Ar key
Set the key accepted as a prefix key.
+In addition to the standard keys described under
+.Sx KEY BINDINGS ,
+.Ic prefix
+can be set to the special key
+.Ql None
+to set no prefix.
.It Ic prefix2 Ar key
Set a secondary key accepted as a prefix key.
+Like
+.Ic prefix ,
+.Ic prefix2
+can be set to
+.Ql None .
.It Xo Ic renumber-windows
.Op Ic on | off
.Xc
diff --git a/tmux.h b/tmux.h
index 59bf9475..2670a05a 100644
--- a/tmux.h
+++ b/tmux.h
@@ -87,6 +87,7 @@ struct tmuxproc;
/* Special key codes. */
#define KEYC_NONE 0xffff00000000ULL
+#define KEYC_UNKNOWN 0xfffe00000000ULL
#define KEYC_BASE 0x100000000000ULL
/* Key modifier bits. */
@@ -1801,6 +1802,8 @@ void server_update_socket(void);
void server_add_accept(int);
/* server-client.c */
+void server_client_set_key_table(struct client *, const char *);
+const char *server_client_get_key_table(struct client *);
int server_client_check_nested(struct client *);
void server_client_handle_key(struct client *, key_code);
void server_client_create(int);
diff --git a/tty-keys.c b/tty-keys.c
index b5e36f8e..86839a17 100644
--- a/tty-keys.c
+++ b/tty-keys.c
@@ -344,7 +344,7 @@ tty_keys_add1(struct tty_key **tkp, const char *s, key_code key)
if (tk == NULL) {
tk = *tkp = xcalloc(1, sizeof *tk);
tk->ch = *s;
- tk->key = KEYC_NONE;
+ tk->key = KEYC_UNKNOWN;
}
/* Find the next entry. */
@@ -444,7 +444,7 @@ tty_keys_find1(struct tty_key *tk, const char *buf, size_t len, size_t *size)
(*size)++;
/* At the end of the string, return the current node. */
- if (len == 0 || (tk->next == NULL && tk->key != KEYC_NONE))
+ if (len == 0 || (tk->next == NULL && tk->key != KEYC_UNKNOWN))
return (tk);
/* Move into the next tree for the following character. */
@@ -534,7 +534,7 @@ first_key:
if (tk->next != NULL)
goto partial_key;
key = tk->key;
- if (key != KEYC_NONE)
+ if (key != KEYC_UNKNOWN)
key |= KEYC_ESCAPE;
goto complete_key;
}
@@ -620,7 +620,7 @@ complete_key:
}
/* Fire the key. */
- if (key != KEYC_NONE)
+ if (key != KEYC_UNKNOWN)
server_client_handle_key(tty->client, key);
return (1);