From 69440d19b783c72139f22c5c72b34b55d99e71de Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 7 May 2019 10:25:15 +0000 Subject: Do not use evbuffer_add_buffer because it is destructive and doesn't work in newer libevent. --- control-notify.c | 7 +------ input.c | 25 +++++++++++++------------ notify.c | 4 ++-- tmux.h | 5 +++-- window.c | 8 +++++--- 5 files changed, 24 insertions(+), 25 deletions(-) diff --git a/control-notify.c b/control-notify.c index 7b28e8f0..340dab73 100644 --- a/control-notify.c +++ b/control-notify.c @@ -28,19 +28,14 @@ void control_notify_input(struct client *c, struct window_pane *wp, - struct evbuffer *input) + const u_char *buf, size_t len) { - u_char *buf; - size_t len; struct evbuffer *message; u_int i; if (c->session == NULL) return; - buf = EVBUFFER_DATA(input); - len = EVBUFFER_LENGTH(input); - /* * Only write input if the window pane is linked to a window belonging * to the client's session. diff --git a/input.c b/input.c index 20272a62..285de2d2 100644 --- a/input.c +++ b/input.c @@ -873,19 +873,28 @@ input_set_state(struct window_pane *wp, const struct input_transition *itr) /* Parse input. */ void input_parse(struct window_pane *wp) +{ + struct evbuffer *evb = wp->event->input; + + input_parse_buffer(wp, EVBUFFER_DATA(evb), EVBUFFER_LENGTH(evb)); + evbuffer_drain(evb, EVBUFFER_LENGTH(evb)); +} + +/* Parse given input. */ +void +input_parse_buffer(struct window_pane *wp, u_char *buf, size_t len) { struct input_ctx *ictx = wp->ictx; struct screen_write_ctx *sctx = &ictx->ctx; const struct input_transition *itr; - struct evbuffer *evb = wp->event->input; - u_char *buf; - size_t len, off; + size_t off = 0; - if (EVBUFFER_LENGTH(evb) == 0) + if (len == 0) return; window_update_activity(wp->window); wp->flags |= PANE_CHANGED; + notify_input(wp, buf, len); /* * Open the screen. Use NULL wp if there is a mode set as don't want to @@ -897,12 +906,6 @@ input_parse(struct window_pane *wp) screen_write_start(sctx, NULL, &wp->base); ictx->wp = wp; - buf = EVBUFFER_DATA(evb); - len = EVBUFFER_LENGTH(evb); - off = 0; - - notify_input(wp, evb); - log_debug("%s: %%%u %s, %zu bytes: %.*s", __func__, wp->id, ictx->state->name, len, (int)len, buf); @@ -950,8 +953,6 @@ input_parse(struct window_pane *wp) /* Close the screen. */ screen_write_stop(sctx); - - evbuffer_drain(evb, len); } /* Split the parameter list (if any). */ diff --git a/notify.c b/notify.c index 088d7596..3079f0eb 100644 --- a/notify.c +++ b/notify.c @@ -199,13 +199,13 @@ notify_hook(struct cmdq_item *item, const char *name) } void -notify_input(struct window_pane *wp, struct evbuffer *input) +notify_input(struct window_pane *wp, const u_char *buf, size_t len) { struct client *c; TAILQ_FOREACH(c, &clients, entry) { if (c->flags & CLIENT_CONTROL) - control_notify_input(c, wp, input); + control_notify_input(c, wp, buf, len); } } diff --git a/tmux.h b/tmux.h index 31b03180..e6ed8c87 100644 --- a/tmux.h +++ b/tmux.h @@ -1699,7 +1699,7 @@ char *format_trim_right(const char *, u_int); /* notify.c */ void notify_hook(struct cmdq_item *, const char *); -void notify_input(struct window_pane *, struct evbuffer *); +void notify_input(struct window_pane *, const u_char *, size_t); void notify_client(const char *, struct client *); void notify_session(const char *, struct session *); void notify_winlink(const char *, struct winlink *); @@ -2087,6 +2087,7 @@ void input_free(struct window_pane *); void input_reset(struct window_pane *, int); struct evbuffer *input_pending(struct window_pane *); void input_parse(struct window_pane *); +void input_parse_buffer(struct window_pane *, u_char *, size_t); /* input-key.c */ void input_key(struct window_pane *, key_code, struct mouse_event *); @@ -2428,7 +2429,7 @@ void control_write_buffer(struct client *, struct evbuffer *); /* control-notify.c */ void control_notify_input(struct client *, struct window_pane *, - struct evbuffer *); + const u_char *, size_t); void control_notify_pane_mode_changed(int); void control_notify_window_layout_changed(struct window *); void control_notify_window_pane_changed(struct window *); diff --git a/window.c b/window.c index 62de5006..b08a5d35 100644 --- a/window.c +++ b/window.c @@ -1477,6 +1477,9 @@ window_pane_input_callback(struct client *c, int closed, void *data) { struct window_pane_input_data *cdata = data; struct window_pane *wp; + struct evbuffer *evb = c->stdin_data; + u_char *buf = EVBUFFER_DATA(evb); + size_t len = EVBUFFER_LENGTH(evb); wp = window_pane_find_by_id(cdata->wp); if (wp == NULL || closed || c->flags & CLIENT_DEAD) { @@ -1489,9 +1492,8 @@ window_pane_input_callback(struct client *c, int closed, void *data) return; } - if (evbuffer_add_buffer(wp->event->input, c->stdin_data) != 0) - evbuffer_drain(c->stdin_data, EVBUFFER_LENGTH(c->stdin_data)); - input_parse(wp); + input_parse_buffer(wp, buf, len); + evbuffer_drain(evb, len); } int -- cgit v1.2.3 From 85a9c2f52b8855560fa9fdaa033d1c7bca738429 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 7 May 2019 11:24:03 +0000 Subject: Treat keys in identify mode (display-panes) specially and handle them immediately rather than queuing them (the command can block the queue which means they were not being seen until it finished which was too late). Reported by denis@ and solene@, ok solene@. --- cmd-copy-mode.c | 8 ++++---- server-client.c | 40 +++++++++++++++++++++++++++++++++++++++- tmux.h | 2 +- tty-keys.c | 6 ++---- 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c index bd05f8a2..b35d0af1 100644 --- a/cmd-copy-mode.c +++ b/cmd-copy-mode.c @@ -73,10 +73,10 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item) return (CMD_RETURN_NORMAL); } - if (window_pane_set_mode(wp, &window_copy_mode, NULL, args) != 0) - return (CMD_RETURN_NORMAL); - if (args_has(args, 'M')) - window_copy_start_drag(c, &shared->mouse); + if (!window_pane_set_mode(wp, &window_copy_mode, NULL, args)) { + if (args_has(args, 'M')) + window_copy_start_drag(c, &shared->mouse); + } if (args_has(self->args, 'u')) window_copy_pageup(wp, 0); diff --git a/server-client.c b/server-client.c index 13a589ef..2840ba60 100644 --- a/server-client.c +++ b/server-client.c @@ -986,7 +986,7 @@ server_client_assume_paste(struct session *s) * Handle data key input from client. This owns and can modify the key event it * is given and is responsible for freeing it. */ -enum cmd_retval +static enum cmd_retval server_client_key_callback(struct cmdq_item *item, void *data) { struct client *c = item->client; @@ -1206,6 +1206,44 @@ out: return (CMD_RETURN_NORMAL); } +/* Handle a key event. */ +int +server_client_handle_key(struct client *c, struct key_event *event) +{ + struct session *s = c->session; + struct window *w; + struct window_pane *wp = NULL; + struct cmdq_item *item; + + /* Check the client is good to accept input. */ + if (s == NULL || (c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED)) != 0) + return (0); + w = s->curw->window; + + /* + * Key presses in identify mode are a special case. The queue might be + * blocked so they need to be processed immediately rather than queued. + */ + if (c->flags & CLIENT_IDENTIFY) { + if (c->flags & CLIENT_READONLY) + return (0); + if (event->key >= '0' && event->key <= '9') { + window_unzoom(w); + wp = window_pane_at_index(w, event->key - '0'); + } + server_client_clear_identify(c, wp); + return (0); + } + + /* + * Add the key to the queue so it happens after any commands queued by + * previous keys. + */ + item = cmdq_get_callback(server_client_key_callback, event); + cmdq_append(c, item); + return (1); +} + /* Client functions that need to happen every loop. */ void server_client_loop(void) diff --git a/tmux.h b/tmux.h index e6ed8c87..55c24531 100644 --- a/tmux.h +++ b/tmux.h @@ -2012,7 +2012,7 @@ void server_client_set_identify(struct client *, u_int); 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 *); -enum cmd_retval server_client_key_callback(struct cmdq_item *, void *); +int server_client_handle_key(struct client *, struct key_event *); struct client *server_client_create(int); int server_client_open(struct client *, char **); void server_client_unref(struct client *); diff --git a/tty-keys.c b/tty-keys.c index 90f34877..3ab7f184 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -573,7 +573,6 @@ tty_keys_next(struct tty *tty) cc_t bspace; int delay, expired = 0, n; key_code key; - struct cmdq_item *item; struct mouse_event m = { 0 }; struct key_event *event; @@ -732,9 +731,8 @@ complete_key: event = xmalloc(sizeof *event); event->key = key; memcpy(&event->m, &m, sizeof event->m); - - item = cmdq_get_callback(server_client_key_callback, event); - cmdq_append(c, item); + if (!server_client_handle_key(c, event)) + free(event); } return (1); -- cgit v1.2.3