diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index c1bd088f7..556dfedcf 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -63,7 +63,7 @@ tmux -vv -Ltest -f/dev/null new Or if you need your configuration: -~~~base +~~~bash tmux kill-server tmux -vv new ~~~ diff --git a/cmd-send-keys.c b/cmd-send-keys.c index 86e7daedc..6be3f2ead 100644 --- a/cmd-send-keys.c +++ b/cmd-send-keys.c @@ -70,6 +70,7 @@ cmd_send_keys_inject_key(struct cmdq_item *item, struct cmdq_item *after, struct key_table *table = NULL; struct key_binding *bd; struct key_event *event; + struct cmdq_item *new_after = after; if (args_has(args, 'K')) { if (tc == NULL) @@ -77,10 +78,16 @@ cmd_send_keys_inject_key(struct cmdq_item *item, struct cmdq_item *after, event = xcalloc(1, sizeof *event); event->key = key|KEYC_SENT; memset(&event->m, 0, sizeof event->m); - if (server_client_handle_key(tc, event) == 0) { - free(event->buf); - free(event); + if (after == NULL) { + if (server_client_handle_key(tc, event) != 0) + return (item); + } else { + if (server_client_handle_key_after(tc, event, after, + &new_after) != 0) + return (new_after); } + free(event->buf); + free(event); return (item); } @@ -229,8 +236,10 @@ cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item) if (count == 0) { if (args_has(args, 'N') || args_has(args, 'R')) return (CMD_RETURN_NORMAL); + after = args_has(args, 'K') ? item : NULL; for (; np != 0; np--) - cmd_send_keys_inject_key(item, NULL, args, event->key); + after = cmd_send_keys_inject_key(item, after, args, + event->key); return (CMD_RETURN_NORMAL); } diff --git a/screen-write.c b/screen-write.c index df7ea0f9b..55244ce71 100644 --- a/screen-write.c +++ b/screen-write.c @@ -1161,7 +1161,8 @@ screen_write_redraw_line(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx, ttyctx->ocx = cx; ttyctx->ocy = yy; - tty_write(tty_cmd_cell, ttyctx); + if (~s->mode & MODE_SYNC) + tty_write(tty_cmd_cell, ttyctx); } } } @@ -1208,6 +1209,8 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx) screen_write_initctx(ctx, &ttyctx, 1, 1); + if (s->mode & MODE_SYNC) + return; if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { tty_write(tty_cmd_alignmenttest, &ttyctx); return; @@ -1247,6 +1250,8 @@ screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = nx; + if (s->mode & MODE_SYNC) + return; if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { tty_write(tty_cmd_insertcharacter, &ttyctx); return; @@ -1286,6 +1291,8 @@ screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = nx; + if (s->mode & MODE_SYNC) + return; if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { tty_write(tty_cmd_deletecharacter, &ttyctx); return; @@ -1325,6 +1332,8 @@ screen_write_clearcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = nx; + if (s->mode & MODE_SYNC) + return; if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { tty_write(tty_cmd_clearcharacter, &ttyctx); return; @@ -1364,6 +1373,8 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = ny; + if (s->mode & MODE_SYNC) + return; if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { tty_write(tty_cmd_insertline, &ttyctx); return; @@ -1389,6 +1400,8 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = ny; + if (s->mode & MODE_SYNC) + return; if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { tty_write(tty_cmd_insertline, &ttyctx); return; @@ -1428,6 +1441,8 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = ny; + if (s->mode & MODE_SYNC) + return; if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { tty_write(tty_cmd_deleteline, &ttyctx); return; @@ -1453,6 +1468,8 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = ny; + if (s->mode & MODE_SYNC) + return; if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { tty_write(tty_cmd_deleteline, &ttyctx); return; @@ -1594,6 +1611,8 @@ screen_write_reverseindex(struct screen_write_ctx *ctx, u_int bg) screen_write_initctx(ctx, &ttyctx, 1, 1); ttyctx.bg = bg; + if (s->mode & MODE_SYNC) + return; if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { tty_write(tty_cmd_reverseindex, &ttyctx); return; @@ -1725,6 +1744,8 @@ screen_write_scrolldown(struct screen_write_ctx *ctx, u_int lines, u_int bg) screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = lines; + if (s->mode & MODE_SYNC) + return; if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED || ctx->wp == NULL) { tty_write(tty_cmd_scrolldown, &ttyctx); return; @@ -1776,6 +1797,8 @@ screen_write_clearendofscreen(struct screen_write_ctx *ctx, u_int bg) screen_write_collect_clear(ctx, s->cy + 1, sy - (s->cy + 1)); screen_write_collect_flush(ctx, 0, __func__); + if (s->mode & MODE_SYNC) + return; if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED) { tty_write(tty_cmd_clearendofscreen, &ttyctx); return; @@ -1850,6 +1873,8 @@ screen_write_clearstartofscreen(struct screen_write_ctx *ctx, u_int bg) screen_write_collect_clear(ctx, 0, s->cy); screen_write_collect_flush(ctx, 0, __func__); + if (s->mode & MODE_SYNC) + return; if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED) { tty_write(tty_cmd_clearstartofscreen, &ttyctx); return; @@ -1923,6 +1948,8 @@ screen_write_clearscreen(struct screen_write_ctx *ctx, u_int bg) screen_write_collect_clear(ctx, 0, sy); + if (s->mode & MODE_SYNC) + return; if (~ttyctx.flags & TTY_CTX_PANE_OBSCURED) { tty_write(tty_cmd_clearscreen, &ttyctx); return; @@ -2579,7 +2606,8 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc) if (s->mode & MODE_INSERT) { screen_write_collect_flush(ctx, 0, __func__); ttyctx.n = width; - tty_write(tty_cmd_insertcharacter, &ttyctx); + if (~s->mode & MODE_SYNC) + tty_write(tty_cmd_insertcharacter, &ttyctx); } /* If not writing, done now. */ @@ -2603,7 +2631,8 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc) for (i = 0, vis = 0; i < r->used; i++) vis += r->ranges[i].nx; if (vis >= width) { - tty_write(tty_cmd_cell, &ttyctx); + if (~s->mode & MODE_SYNC) + tty_write(tty_cmd_cell, &ttyctx); return; } @@ -2612,6 +2641,8 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc) * spaces in the visible regions. */ utf8_set(&tmp_gc.data, ' '); + if (s->mode & MODE_SYNC) + return; for (i = 0; i < r->used; i++) { ri = &r->ranges[i]; if (ri->nx == 0) @@ -2753,7 +2784,8 @@ screen_write_combine(struct screen_write_ctx *ctx, const struct grid_cell *gc) ttyctx.cell = &last; if (force_wide) ttyctx.flags |= TTY_CTX_CELL_INVALIDATE; - tty_write(tty_cmd_cell, &ttyctx); + if (~s->mode & MODE_SYNC) + tty_write(tty_cmd_cell, &ttyctx); screen_write_set_cursor(ctx, cx, cy); return (1); diff --git a/server-client.c b/server-client.c index 9838ca1a6..0d47a2944 100644 --- a/server-client.c +++ b/server-client.c @@ -1164,11 +1164,11 @@ server_client_repeat_time(struct client *c, struct key_binding *bd) static enum cmd_retval server_client_key_callback(struct cmdq_item *item, void *data) { - struct client *c = cmdq_get_client(item); struct key_event *event = data; + struct client *c, *ec = event->client; key_code key = event->key; struct mouse_event *m = &event->m; - struct session *s = c->session; + struct session *s; struct winlink *wl; struct window_pane *wp; struct window_mode_entry *wme; @@ -1180,6 +1180,12 @@ server_client_key_callback(struct cmdq_item *item, void *data) struct cmd_find_state fs; key_code key0, prefix, prefix2; + if (ec != NULL) + c = ec; + else + c = cmdq_get_client(item); + s = c->session; + /* Check the client is good to accept input. */ if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS)) goto out; @@ -1426,14 +1432,17 @@ paste_key: out: if (s != NULL && key != KEYC_FOCUS_OUT) server_client_update_latest(c); + if (ec != NULL) + server_client_unref(ec); free(event->buf); free(event); return (CMD_RETURN_NORMAL); } /* Handle a key event. */ -int -server_client_handle_key(struct client *c, struct key_event *event) +static int +server_client_handle_key0(struct client *c, struct key_event *event, + struct cmdq_item *after, struct cmdq_item **next) { struct session *s = c->session; struct cmdq_item *item; @@ -1487,10 +1496,31 @@ server_client_handle_key(struct client *c, struct key_event *event) * previous keys. */ item = cmdq_get_callback(server_client_key_callback, event); + if (after != NULL) { + event->client = c; + c->references++; + item = cmdq_insert_after(after, item); + if (next != NULL) + *next = item; + return (1); + } cmdq_append(c, item); return (1); } +int +server_client_handle_key(struct client *c, struct key_event *event) +{ + return (server_client_handle_key0(c, event, NULL, NULL)); +} + +int +server_client_handle_key_after(struct client *c, struct key_event *event, + struct cmdq_item *after, struct cmdq_item **next) +{ + return (server_client_handle_key0(c, event, after, next)); +} + /* Client functions that need to happen every loop. */ void server_client_loop(void) @@ -1782,7 +1812,7 @@ server_client_reset_state(struct client *c) struct window_pane *wp = server_client_get_pane(c), *loop; struct screen *s = NULL; struct options *oo = c->session->options; - int mode = 0, cursor, flags; + int mode = 0, cursor, flags, pane_mode = 0; u_int cx = 0, cy = 0, ox, oy, sx, sy, n; struct visible_ranges *r; @@ -1827,6 +1857,8 @@ server_client_reset_state(struct client *c) cx = c->prompt_cursor; } else if (wp != NULL && c->overlay_draw == NULL) { cursor = 0; + pane_mode = wp->base.mode; + tty_window_offset(tty, &ox, &oy, &sx, &sy); if (wp->xoff + (int)s->cx >= (int)ox && wp->xoff + (int)s->cx <= (int)ox + (int)sx && @@ -1845,13 +1877,14 @@ server_client_reset_state(struct client *c) cy += status_line_size(c); } - if (!cursor) + if ((pane_mode & MODE_SYNC) || !cursor) mode &= ~MODE_CURSOR; } else if (c->overlay_mode == NULL || s == NULL) mode &= ~MODE_CURSOR; - - log_debug("%s: cursor to %u,%u", __func__, cx, cy); - tty_cursor(tty, cx, cy); + if (~pane_mode & MODE_SYNC) { + log_debug("%s: cursor to %u,%u", __func__, cx, cy); + tty_cursor(tty, cx, cy); + } /* * Set mouse mode if requested. To support dragging, always use button diff --git a/sort.c b/sort.c index fda6a90ba..212da22ea 100644 --- a/sort.c +++ b/sort.c @@ -65,7 +65,12 @@ sort_buffer_cmp(const void *a0, const void *b0) result = strcmp(pa->name, pb->name); break; case SORT_CREATION: - result = pa->order - pb->order; + if (pa->order > pb->order) + result = -1; + else if (pa->order < pb->order) + result = 1; + else + result = 0; break; case SORT_SIZE: result = pa->size - pb->size; @@ -251,11 +256,11 @@ sort_winlink_cmp(const void *a0, const void *b0) break; case SORT_CREATION: if (timercmp(&wa->creation_time, &wb->creation_time, >)) { - result = -1; + result = 1; break; } if (timercmp(&wa->creation_time, &wb->creation_time, <)) { - result = 1; + result = -1; break; } break; diff --git a/tmux.h b/tmux.h index d2179cf3b..4e21f6133 100644 --- a/tmux.h +++ b/tmux.h @@ -1629,6 +1629,8 @@ struct mouse_event { /* Key event. */ struct key_event { + struct client *client; + key_code key; struct mouse_event m; @@ -3091,6 +3093,8 @@ 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 *); int server_client_handle_key(struct client *, struct key_event *); +int server_client_handle_key_after(struct client *, struct key_event *, + struct cmdq_item *, struct cmdq_item **); struct client *server_client_create(int); int server_client_open(struct client *, char **); void server_client_unref(struct client *); diff --git a/tty-draw.c b/tty-draw.c index a2868aa4c..ec96409da 100644 --- a/tty-draw.c +++ b/tty-draw.c @@ -181,7 +181,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, bg = ngc.bg; } } - tty_attributes(tty, &last, style_ctx); + tty_attributes(tty, &last, style_ctx); log_debug("%s: clearing %u padding cells", __func__, cx); tty_draw_line_clear(tty, atx, aty, cx, style_ctx->defaults, bg, 0); if (cx == ex)