From 9dc6946ebf359ec811cc4bb8b68ea9862b496369 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 10 May 2017 16:47:03 +0000 Subject: [PATCH 1/2] We can use ECH to clear sections of lines, so use it for internal panes (that don't touch an edge). Move all the tty clear code into two common functions rather than having the same bunch of checks everywhere. --- tty.c | 238 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 116 insertions(+), 122 deletions(-) diff --git a/tty.c b/tty.c index ba7a5158..a1219069 100644 --- a/tty.c +++ b/tty.c @@ -754,6 +754,73 @@ tty_redraw_region(struct tty *tty, const struct tty_ctx *ctx) } } +static void +tty_clear_line(struct tty *tty, const struct window_pane *wp, u_int py, + u_int px, u_int nx, u_int bg) +{ + log_debug("%s: %u at %u,%u", __func__, nx, px, py); + + /* Nothing to clear. */ + if (nx == 0) + return; + + /* If genuine BCE is available, can try escape sequences. */ + if (!tty_fake_bce(tty, wp, bg)) { + /* Off the end of the line, use EL if available. */ + if (px + nx >= tty->sx && tty_term_has(tty->term, TTYC_EL)) { + tty_cursor(tty, px, py); + tty_putcode(tty, TTYC_EL); + return; + } + + /* At the start of the line. Use EL1. */ + if (px == 0 && tty_term_has(tty->term, TTYC_EL1)) { + tty_cursor(tty, px + nx - 1, py); + tty_putcode(tty, TTYC_EL1); + return; + } + + /* Section of line. Use ECH if possible. */ + if (tty_term_has(tty->term, TTYC_ECH)) { + tty_cursor(tty, px, py); + tty_putcode1(tty, TTYC_ECH, nx); + return; + } + } + + /* Couldn't use an escape sequence, use spaces. */ + tty_repeat_space(tty, nx); +} + +static void +tty_clear_area(struct tty *tty, const struct window_pane *wp, u_int py, + u_int ny, u_int px, u_int nx, u_int bg) +{ + u_int yy; + + log_debug("%s: %u,%u at %u,%u", __func__, nx, ny, px, py); + + /* Nothing to clear. */ + if (nx == 0 || ny == 0) + return; + + /* If genuine BCE is available, can try escape sequences. */ + if (!tty_fake_bce(tty, wp, bg)) { + if (px == 0 && + px + nx >= tty->sx && + py + ny >= tty->sy && + tty_term_has(tty->term, TTYC_ED)) { + tty_cursor(tty, 0, py); + tty_putcode(tty, TTYC_ED); + return; + } + } + + /* Couldn't use an escape sequence, loop over the lines. */ + for (yy = py; yy < py + ny; yy++) + tty_clear_line(tty, wp, yy, px, nx, bg); +} + void tty_draw_pane(struct tty *tty, const struct window_pane *wp, u_int py, u_int ox, u_int oy) @@ -766,7 +833,7 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp, struct screen *s, u_int py, u_int ox, u_int oy) { struct grid_cell gc, last; - u_int i, j, sx, width; + u_int i, j, sx, nx, width; int flags, cleared = 0; char buf[512]; size_t len; @@ -857,16 +924,10 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp, tty_putn(tty, buf, len, width); } - if (!cleared && sx < tty->sx) { + nx = screen_size_x(s) - sx; + if (!cleared && sx < tty->sx && nx != 0) { tty_default_attributes(tty, wp, 8); - tty_cursor(tty, ox + sx, oy + py); - if (sx != screen_size_x(s) && - ox + screen_size_x(s) >= tty->sx && - tty_term_has(tty->term, TTYC_EL) && - !tty_fake_bce(tty, wp, 8)) - tty_putcode(tty, TTYC_EL); - else - tty_repeat_space(tty, screen_size_x(s) - sx); + tty_clear_line(tty, wp, oy + py, ox + sx, nx, 8); } tty->flags = (tty->flags & ~TTY_NOCURSOR) | flags; @@ -1012,56 +1073,36 @@ void tty_cmd_clearline(struct tty *tty, const struct tty_ctx *ctx) { struct window_pane *wp = ctx->wp; - struct screen *s = wp->screen; - u_int sx = screen_size_x(s); + u_int nx, py = ctx->yoff + ctx->ocy; tty_default_attributes(tty, wp, ctx->bg); - tty_cursor_pane(tty, ctx, 0, ctx->ocy); - - if (tty_pane_full_width(tty, ctx) && - !tty_fake_bce(tty, wp, ctx->bg) && - tty_term_has(tty->term, TTYC_EL)) - tty_putcode(tty, TTYC_EL); - else - tty_repeat_space(tty, sx); + nx = screen_size_x(wp->screen); + tty_clear_line(tty, wp, py, ctx->xoff, nx, ctx->bg); } void tty_cmd_clearendofline(struct tty *tty, const struct tty_ctx *ctx) { struct window_pane *wp = ctx->wp; - struct screen *s = wp->screen; - u_int sx = screen_size_x(s); + u_int nx, py = ctx->yoff + ctx->ocy; tty_default_attributes(tty, wp, ctx->bg); - tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); - - if (tty_pane_full_width(tty, ctx) && - tty_term_has(tty->term, TTYC_EL) && - !tty_fake_bce(tty, wp, ctx->bg)) - tty_putcode(tty, TTYC_EL); - else - tty_repeat_space(tty, sx - ctx->ocx); + nx = screen_size_x(wp->screen) - ctx->ocx; + tty_clear_line(tty, wp, py, ctx->xoff + ctx->ocx, nx, ctx->bg); } void tty_cmd_clearstartofline(struct tty *tty, const struct tty_ctx *ctx) { struct window_pane *wp = ctx->wp; + u_int nx, py = ctx->yoff + ctx->ocy; tty_default_attributes(tty, wp, ctx->bg); - if (ctx->xoff == 0 && - tty_term_has(tty->term, TTYC_EL1) && - !tty_fake_bce(tty, ctx->wp, ctx->bg)) { - tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); - tty_putcode(tty, TTYC_EL1); - } else { - tty_cursor_pane(tty, ctx, 0, ctx->ocy); - tty_repeat_space(tty, ctx->ocx + 1); - } + nx = screen_size_x(wp->screen) - ctx->ocx; + tty_clear_line(tty, wp, py, ctx->xoff, ctx->ocx + 1, ctx->bg); } void @@ -1159,116 +1200,69 @@ void tty_cmd_clearendofscreen(struct tty *tty, const struct tty_ctx *ctx) { struct window_pane *wp = ctx->wp; - struct screen *s = wp->screen; - u_int i, j; - u_int sx = screen_size_x(s), sy = screen_size_y(s); + u_int px, py, nx, ny; tty_default_attributes(tty, wp, ctx->bg); - tty_region_pane(tty, ctx, 0, sy - 1); + tty_region_pane(tty, ctx, 0, screen_size_y(wp->screen) - 1); tty_margin_off(tty); - if (tty_pane_full_width(tty, ctx) && - ctx->yoff + wp->sy >= tty->sy - 1 && - status_at_line(tty->client) <= 0 && - tty_term_has(tty->term, TTYC_ED)) { - tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); - tty_putcode(tty, TTYC_ED); - } else if (tty_pane_full_width(tty, ctx) && - tty_term_has(tty->term, TTYC_EL) && - !tty_fake_bce(tty, wp, ctx->bg)) { - tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); - tty_putcode(tty, TTYC_EL); - if (ctx->ocy != sy - 1) { - tty_cursor_pane(tty, ctx, 0, ctx->ocy + 1); - for (i = ctx->ocy + 1; i < sy; i++) { - tty_putcode(tty, TTYC_EL); - if (i == sy - 1) - continue; - tty_emulate_repeat(tty, TTYC_CUD, TTYC_CUD1, 1); - tty->cy++; - } - } - } else { - tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy); - tty_repeat_space(tty, sx - ctx->ocx); - for (j = ctx->ocy + 1; j < sy; j++) { - tty_cursor_pane(tty, ctx, 0, j); - tty_repeat_space(tty, sx); - } - } + px = ctx->xoff; + nx = screen_size_x(wp->screen); + py = ctx->yoff + ctx->ocy + 1; + ny = screen_size_y(wp->screen) - ctx->ocy - 1; + + tty_clear_area(tty, wp, py, ny, px, nx, ctx->bg); + + px = ctx->xoff + ctx->ocx; + nx = screen_size_x(wp->screen) - ctx->ocx; + py = ctx->yoff + ctx->ocy; + + tty_clear_line(tty, wp, py, px, nx, ctx->bg); } void tty_cmd_clearstartofscreen(struct tty *tty, const struct tty_ctx *ctx) { struct window_pane *wp = ctx->wp; - struct screen *s = wp->screen; - u_int i, j; - u_int sx = screen_size_x(s), sy = screen_size_y(s); + u_int px, py, nx, ny; tty_default_attributes(tty, wp, ctx->bg); - tty_region_pane(tty, ctx, 0, sy - 1); + tty_region_pane(tty, ctx, 0, screen_size_y(wp->screen) - 1); tty_margin_off(tty); - if (tty_pane_full_width(tty, ctx) && - tty_term_has(tty->term, TTYC_EL) && - !tty_fake_bce(tty, wp, ctx->bg)) { - tty_cursor_pane(tty, ctx, 0, 0); - for (i = 0; i < ctx->ocy; i++) { - tty_putcode(tty, TTYC_EL); - tty_emulate_repeat(tty, TTYC_CUD, TTYC_CUD1, 1); - tty->cy++; - } - } else { - tty_cursor_pane(tty, ctx, 0, 0); - for (j = 0; j < ctx->ocy; j++) { - tty_cursor_pane(tty, ctx, 0, j); - tty_repeat_space(tty, sx); - } - } - tty_cursor_pane(tty, ctx, 0, ctx->ocy); - tty_repeat_space(tty, ctx->ocx + 1); + px = ctx->xoff; + nx = screen_size_x(wp->screen); + py = ctx->yoff; + ny = ctx->ocy - 1; + + tty_clear_area(tty, wp, py, ny, px, nx, ctx->bg); + + px = ctx->xoff; + nx = ctx->ocx + 1; + py = ctx->yoff + ctx->ocy; + + tty_clear_line(tty, wp, py, px, nx, ctx->bg); } void tty_cmd_clearscreen(struct tty *tty, const struct tty_ctx *ctx) { struct window_pane *wp = ctx->wp; - struct screen *s = wp->screen; - u_int i, j; - u_int sx = screen_size_x(s), sy = screen_size_y(s); + u_int px, py, nx, ny; tty_default_attributes(tty, wp, ctx->bg); - tty_region_pane(tty, ctx, 0, sy - 1); + tty_region_pane(tty, ctx, 0, screen_size_y(wp->screen) - 1); tty_margin_off(tty); - if (tty_pane_full_width(tty, ctx) && - ctx->yoff + wp->sy >= tty->sy - 1 && - status_at_line(tty->client) <= 0 && - tty_term_has(tty->term, TTYC_ED)) { - tty_cursor_pane(tty, ctx, 0, 0); - tty_putcode(tty, TTYC_ED); - } else if (tty_pane_full_width(tty, ctx) && - tty_term_has(tty->term, TTYC_EL) && - !tty_fake_bce(tty, wp, ctx->bg)) { - tty_cursor_pane(tty, ctx, 0, 0); - for (i = 0; i < sy; i++) { - tty_putcode(tty, TTYC_EL); - if (i != sy - 1) { - tty_emulate_repeat(tty, TTYC_CUD, TTYC_CUD1, 1); - tty->cy++; - } - } - } else { - tty_cursor_pane(tty, ctx, 0, 0); - for (j = 0; j < sy; j++) { - tty_cursor_pane(tty, ctx, 0, j); - tty_repeat_space(tty, sx); - } - } + px = ctx->xoff; + nx = screen_size_x(wp->screen); + py = ctx->yoff; + ny = screen_size_y(wp->screen); + + tty_clear_area(tty, wp, py, ny, px, nx, ctx->bg); } void From 2dc9bfd93afd26b76dfdbf4a22338a5ef85893bf Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 10 May 2017 16:48:36 +0000 Subject: [PATCH 2/2] Prevent control clients from affecting the session size until they have specified a size with refresh-client -C. Prompted by a different change with the same purpose from George Nachman. --- cmd-refresh-client.c | 4 +++- resize.c | 3 +++ tmux.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/cmd-refresh-client.c b/cmd-refresh-client.c index 5190df89..6af3362b 100644 --- a/cmd-refresh-client.c +++ b/cmd-refresh-client.c @@ -67,8 +67,10 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item) cmdq_error(item, "not a control client"); return (CMD_RETURN_ERROR); } - if (tty_set_size(&c->tty, w, h)) + if (tty_set_size(&c->tty, w, h)) { + c->flags |= CLIENT_SIZECHANGED; recalculate_sizes(); + } } else if (args_has(args, 'S')) { c->flags |= CLIENT_STATUSFORCE; server_status_client(c); diff --git a/resize.c b/resize.c index ff1c9eec..4c41f769 100644 --- a/resize.c +++ b/resize.c @@ -60,6 +60,9 @@ recalculate_sizes(void) TAILQ_FOREACH(c, &clients, entry) { if (c->flags & CLIENT_SUSPENDED) continue; + if ((c->flags & (CLIENT_CONTROL|CLIENT_SIZECHANGED)) == + CLIENT_CONTROL) + continue; if (c->session == s) { if (c->tty.sx < ssx) ssx = c->tty.sx; diff --git a/tmux.h b/tmux.h index 9d0cd960..5fd57ee4 100644 --- a/tmux.h +++ b/tmux.h @@ -1345,6 +1345,7 @@ struct client { #define CLIENT_STATUSFORCE 0x80000 #define CLIENT_DOUBLECLICK 0x100000 #define CLIENT_TRIPLECLICK 0x200000 +#define CLIENT_SIZECHANGED 0x400000 int flags; struct key_table *keytable;