mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	It is annoying that the copy mode key table (or any other key table)
will suppress root key table bindings. So change to always check the root table if no binding is found in the current table (whether it be the prefix table from pressing the prefix or the copy mode table from a pane). A root key binding can be blocked by binding the key to a command that does nothing (like send-keys with no arguments). Problem reported by Thomas Sattler.
This commit is contained in:
		| @@ -138,11 +138,11 @@ server_client_get_key_table(struct client *c) | |||||||
| 	return (name); | 	return (name); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Is this client using the default key table? */ | /* Is this table the default key table? */ | ||||||
| int | static int | ||||||
| server_client_is_default_key_table(struct client *c) | server_client_is_default_key_table(struct client *c, struct key_table *table) | ||||||
| { | { | ||||||
| 	return (strcmp(c->keytable->name, server_client_get_key_table(c)) == 0); | 	return (strcmp(table->name, server_client_get_key_table(c)) == 0); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Create a new client. */ | /* Create a new client. */ | ||||||
| @@ -793,8 +793,7 @@ server_client_handle_key(struct client *c, key_code key) | |||||||
| 	struct window		*w; | 	struct window		*w; | ||||||
| 	struct window_pane	*wp; | 	struct window_pane	*wp; | ||||||
| 	struct timeval		 tv; | 	struct timeval		 tv; | ||||||
| 	const char		*name; | 	struct key_table	*table, *first; | ||||||
| 	struct key_table	*table; |  | ||||||
| 	struct key_binding	 bd_find, *bd; | 	struct key_binding	 bd_find, *bd; | ||||||
| 	int			 xtimeout; | 	int			 xtimeout; | ||||||
| 	struct cmd_find_state	 fs; | 	struct cmd_find_state	 fs; | ||||||
| @@ -870,22 +869,18 @@ server_client_handle_key(struct client *c, key_code key) | |||||||
| 	if (!KEYC_IS_MOUSE(key) && server_client_assume_paste(s)) | 	if (!KEYC_IS_MOUSE(key) && server_client_assume_paste(s)) | ||||||
| 		goto forward; | 		goto forward; | ||||||
|  |  | ||||||
| retry: |  | ||||||
| 	/* | 	/* | ||||||
| 	 * Work out the current key table. If the pane is in a mode, use | 	 * Work out the current key table. If the pane is in a mode, use | ||||||
| 	 * the mode table instead of the default key table. | 	 * the mode table instead of the default key table. | ||||||
| 	 */ | 	 */ | ||||||
| 	name = NULL; | 	if (server_client_is_default_key_table(c, c->keytable) && | ||||||
| 	if (wp != NULL && wp->mode != NULL && wp->mode->key_table != NULL) | 	    wp != NULL && | ||||||
| 		name = wp->mode->key_table(wp); | 	    wp->mode != NULL && | ||||||
| 	if (name == NULL || !server_client_is_default_key_table(c)) | 	    wp->mode->key_table != NULL) | ||||||
|  | 		table = key_bindings_get_table(wp->mode->key_table(wp), 1); | ||||||
|  | 	else | ||||||
| 		table = c->keytable; | 		table = c->keytable; | ||||||
| 	else | 	first = table; | ||||||
| 		table = key_bindings_get_table(name, 1); |  | ||||||
| 	if (wp == NULL) |  | ||||||
| 		log_debug("key table %s (no pane)", table->name); |  | ||||||
| 	else |  | ||||||
| 		log_debug("key table %s (pane %%%u)", table->name, wp->id); |  | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 	 * The prefix always takes precedence and forces a switch to the prefix | 	 * The prefix always takes precedence and forces a switch to the prefix | ||||||
| @@ -899,6 +894,13 @@ retry: | |||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | retry: | ||||||
|  | 	/* Log key table. */ | ||||||
|  | 	if (wp == NULL) | ||||||
|  | 		log_debug("key table %s (no pane)", table->name); | ||||||
|  | 	else | ||||||
|  | 		log_debug("key table %s (pane %%%u)", table->name, wp->id); | ||||||
|  |  | ||||||
| 	/* Try to see if there is a key binding in the current table. */ | 	/* Try to see if there is a key binding in the current table. */ | ||||||
| 	bd_find.key = key; | 	bd_find.key = key; | ||||||
| 	bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find); | 	bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find); | ||||||
| @@ -913,8 +915,10 @@ retry: | |||||||
| 			server_client_set_key_table(c, NULL); | 			server_client_set_key_table(c, NULL); | ||||||
| 			c->flags &= ~CLIENT_REPEAT; | 			c->flags &= ~CLIENT_REPEAT; | ||||||
| 			server_status_client(c); | 			server_status_client(c); | ||||||
|  | 			table = c->keytable; | ||||||
| 			goto retry; | 			goto retry; | ||||||
| 		} | 		} | ||||||
|  | 		log_debug("found in key table %s", table->name); | ||||||
|  |  | ||||||
| 		/* | 		/* | ||||||
| 		 * Take a reference to this table to make sure the key binding | 		 * Take a reference to this table to make sure the key binding | ||||||
| @@ -959,19 +963,24 @@ retry: | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* | 	/* | ||||||
| 	 * No match in this table. If repeating, switch the client back to the | 	 * No match in this table. If not in the root table or if repeating, | ||||||
| 	 * root table and try again. | 	 * switch the client back to the root table and try again. | ||||||
| 	 */ | 	 */ | ||||||
| 	if (c->flags & CLIENT_REPEAT) { | 	log_debug("not found in key table %s", table->name); | ||||||
|  | 	if (!server_client_is_default_key_table(c, table) || | ||||||
|  | 	    (c->flags & CLIENT_REPEAT)) { | ||||||
| 		server_client_set_key_table(c, NULL); | 		server_client_set_key_table(c, NULL); | ||||||
| 		c->flags &= ~CLIENT_REPEAT; | 		c->flags &= ~CLIENT_REPEAT; | ||||||
| 		server_status_client(c); | 		server_status_client(c); | ||||||
|  | 		table = c->keytable; | ||||||
| 		goto retry; | 		goto retry; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* If no match and we're not in the root table, that's it. */ | 	/* | ||||||
| 	if (name == NULL && !server_client_is_default_key_table(c)) { | 	 * No match in the root table either. If this wasn't the first table | ||||||
| 		log_debug("no key in key table %s", table->name); | 	 * tried, don't pass the key to the pane. | ||||||
|  | 	 */ | ||||||
|  | 	if (first != table) { | ||||||
| 		server_client_set_key_table(c, NULL); | 		server_client_set_key_table(c, NULL); | ||||||
| 		server_status_client(c); | 		server_status_client(c); | ||||||
| 		return; | 		return; | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								tmux.h
									
									
									
									
									
								
							| @@ -1847,7 +1847,6 @@ void	 server_client_set_identify(struct client *); | |||||||
| void	 server_client_clear_identify(struct client *, struct window_pane *); | void	 server_client_clear_identify(struct client *, struct window_pane *); | ||||||
| void	 server_client_set_key_table(struct client *, const char *); | void	 server_client_set_key_table(struct client *, const char *); | ||||||
| const char *server_client_get_key_table(struct client *); | const char *server_client_get_key_table(struct client *); | ||||||
| int	 server_client_is_default_key_table(struct client *); |  | ||||||
| int	 server_client_check_nested(struct client *); | int	 server_client_check_nested(struct client *); | ||||||
| void	 server_client_handle_key(struct client *, key_code); | void	 server_client_handle_key(struct client *, key_code); | ||||||
| void	 server_client_create(int); | void	 server_client_create(int); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 nicm
					nicm