diff --git a/layout-custom.c b/layout-custom.c index b2871f0d..2942720c 100644 --- a/layout-custom.c +++ b/layout-custom.c @@ -335,7 +335,7 @@ layout_assign(struct window_pane **wp, struct layout_cell *lc, int flags) case LAYOUT_TOPBOTTOM: case LAYOUT_FLOATING: TAILQ_FOREACH(lcchild, &lc->cells, entry) - layout_assign(wp, lcchild, PANE_FLOATING); + layout_assign(wp, lcchild, flags); return; } } diff --git a/screen-redraw.c b/screen-redraw.c index dc96c517..4ea49176 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -702,7 +702,7 @@ screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx) /* Left not visible. */ l = ctx->ox - xoff; x = 0; - width = size - i; + width = size - l; } else { /* Right not visible. */ l = 0; @@ -710,7 +710,8 @@ screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx) width = size - x; } - r = screen_redraw_get_visible_ranges(wp, x, yoff, width, NULL); + r = tty_check_overlay_range(tty, x, yoff, width); + r = screen_redraw_get_visible_ranges(wp, x, yoff, width, r); if (ctx->statustop) yoff += ctx->statuslines; for (i = 0; i < r->used; i++) { @@ -1273,15 +1274,42 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp) struct screen *s = wp->screen; struct colour_palette *palette = &wp->palette; struct grid_cell defaults; - u_int i, j, woy, wx, wy, py, width; + u_int j, k, woy, wx, wy, py, width; struct visible_ranges *r; struct visible_range *ri; + /* + * There are 3 coordinate spaces: + * + * window: (0 to w->sx-1, 0 to w->sy-1) + * tty: (0 to tty->sx-1, 0 to tty->sy-1) + * pane: (0 to wp->sx-1, 0 to wp->sy-1) + * + * Transformations: + * window <-> tty (x-axis): + * window_x = tty_x + ctx->ox + * tty_x = window_x - ctx->ox + * + * window <-> tty (y-axis): + * woy = (ctx->statustop) ? ctx->statuslines : 0 + * window_y = tty_y + ctx->oy - woy + * tty_y = woy + window_y - ctx->oy + * + * window <-> pane (x-axis): + * window_x = pane_x + wp->xoff + * pane_x = window_x - wp->xoff + * + * window <-> pane (y-axis): + * window_y = pane_y + wp->yoff + * pane_y = window_y - wp->yoff + */ + if (wp->base.mode & MODE_SYNC) screen_write_stop_sync(wp); log_debug("%s: %s @%u %%%u", __func__, c->name, w->id, wp->id); + /* Check if pane completely not visible. */ if (wp->xoff + (int)wp->sx <= ctx->ox || wp->xoff >= (int)ctx->ox + (int)ctx->sx) return; @@ -1303,37 +1331,36 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp) if (wp->xoff >= (int)ctx->ox && wp->xoff + (int)wp->sx <= (int)ctx->ox + (int)ctx->sx) { /* All visible. */ - i = 0; wx = (u_int)(wp->xoff - (int)ctx->ox); width = wp->sx; } else if (wp->xoff < (int)ctx->ox && wp->xoff + (int)wp->sx > (int)ctx->ox + (int)ctx->sx) { /* Both left and right not visible. */ - i = ctx->ox; wx = 0; width = ctx->sx; } else if (wp->xoff < (int)ctx->ox) { /* Left not visible. */ - i = (u_int)((int)ctx->ox - wp->xoff); wx = 0; - width = wp->sx - i; + width = wp->sx - ((u_int)((int)ctx->ox - wp->xoff)); } else { /* Right not visible. */ - i = 0; wx = (u_int)(wp->xoff - (int)ctx->ox); width = ctx->sx - wx; } - log_debug("%s: %s %%%u line %u,%u at %u,%u, width %u", - __func__, c->name, wp->id, i, j, wx, wy, width); /* Get visible ranges of line before we draw it. */ - r = screen_redraw_get_visible_ranges(wp, wx, wy, width, NULL); + r = tty_check_overlay_range(tty, wx, wy, width); + r = screen_redraw_get_visible_ranges(wp, wx, wy, width, r); tty_default_colours(&defaults, wp); - for (i = 0; i < r->used; i++) { - ri = &r->ranges[i]; + for (k = 0; k < r->used; k++) { + ri = &r->ranges[k]; if (ri->nx == 0) continue; - tty_draw_line(tty, s, ri->px - wp->xoff, j, ri->nx, + log_debug("%s: %s %%%u range pane (%u,%u) width %u, tty (%u,%u) width %u", + __func__, c->name, wp->id, + ri->px + (int)ctx->ox - wp->xoff, j, ri->nx, + ri->px, py, ri->nx); + tty_draw_line(tty, s, ri->px + (int)ctx->ox - wp->xoff, j, ri->nx, ri->px, py, &defaults, palette); } } @@ -1494,13 +1521,13 @@ screen_redraw_draw_scrollbar(struct screen_redraw_ctx *ctx, } for (j = jmin; j < jmax; j++) { - wy = sb_y + j; /* window y coordinate */ - py = sb_tty_y + j;/* tty y coordinate */ + wy = sb_y + j; /* window y coordinate */ + py = sb_tty_y + j; /* tty y coordinate */ r = tty_check_overlay_range(tty, sb_x, wy, imax); r = screen_redraw_get_visible_ranges(wp, sb_x, wy, imax, r); for (i = imin; i < imax; i++) { px = sb_x + ox + i; /* tty x coordinate */ - wx = sb_x + i; /* window x coordinate */ + wx = sb_x + i; /* window x coordinate */ if (wx < xoff - (int)sb_w - (int)sb_pad || px >= sx || px < 0 || wy < yoff - 1 || diff --git a/tty-draw.c b/tty-draw.c index 865fff60..24d8b711 100644 --- a/tty-draw.c +++ b/tty-draw.c @@ -46,10 +46,6 @@ static void tty_draw_line_clear(struct tty *tty, u_int px, u_int py, u_int nx, const struct grid_cell *defaults, u_int bg, int wrapped) { - struct visible_ranges *r; - struct visible_range *rr; - u_int i; - /* Nothing to clear. */ if (nx == 0) return; @@ -82,20 +78,14 @@ tty_draw_line_clear(struct tty *tty, u_int px, u_int py, u_int nx, } /* Couldn't use an escape sequence, use spaces. */ - r = tty_check_overlay_range(tty, px, py, nx); - for (i = 0; i < r->used; i++) { - rr = &r->ranges[i]; - if (rr->nx != 0) { - if (rr->px != 0 || !wrapped) - tty_cursor(tty, rr->px, py); - if (rr->nx == 1) - tty_putc(tty, ' '); - else if (rr->nx == 2) - tty_putn(tty, " ", 2, 2); - else - tty_repeat_space(tty, rr->nx); - } - } + if (px != 0 || !wrapped) + tty_cursor(tty, px, py); + if (nx == 1) + tty_putc(tty, ' '); + else if (nx == 2) + tty_putn(tty, " ", 2, 2); + else + tty_repeat_space(tty, nx); } /* Draw a line from screen to tty. */ diff --git a/tty.c b/tty.c index ea1705d3..39f79c22 100644 --- a/tty.c +++ b/tty.c @@ -108,6 +108,7 @@ tty_init(struct tty *tty, struct client *c) tty->cstyle = SCREEN_CURSOR_DEFAULT; tty->ccolour = -1; tty->fg = tty->bg = -1; + tty->mouse_last_pane = -1; if (tcgetattr(c->fd, &tty->tio) != 0) return (-1); @@ -1092,12 +1093,14 @@ tty_redraw_region(struct tty *tty, const struct tty_ctx *ctx) * If region is large, schedule a redraw. In most cases this is likely * to be followed by some more scrolling. */ - if (tty_large_region(tty, ctx)) { - log_debug("%s: %s large redraw", __func__, c->name); + if (tty_large_region(tty, ctx) && ~ctx->flags & TTY_CTX_PANE_OBSCURED) { + log_debug("%s: %s large region redraw", __func__, c->name); ctx->redraw_cb(ctx); return; } + log_debug("%s: %s small region redraw (%u-%u)", __func__, c->name, + ctx->orupper, ctx->orlower); for (i = ctx->orupper; i <= ctx->orlower; i++) tty_draw_pane(tty, ctx, i); } @@ -1123,23 +1126,23 @@ static int tty_clamp_line(struct tty *tty, const struct tty_ctx *ctx, u_int px, u_int py, u_int nx, u_int *i, u_int *x, u_int *rx, u_int *ry) { - u_int xoff = ctx->rxoff + px; + int xoff = ctx->rxoff + px; if (!tty_is_visible(tty, ctx, px, py, nx, 1)) return (0); *ry = ctx->yoff + py - ctx->woy; - if (xoff >= ctx->wox && xoff + nx <= ctx->wox + ctx->wsx) { + if (xoff >= (int)ctx->wox && xoff + nx <= ctx->wox + ctx->wsx) { /* All visible. */ *i = 0; *x = ctx->xoff + px - ctx->wox; *rx = nx; - } else if (xoff < ctx->wox && xoff + nx > ctx->wox + ctx->wsx) { + } else if (xoff < (int)ctx->wox && xoff + nx > ctx->wox + ctx->wsx) { /* Both left and right not visible. */ *i = ctx->wox; *x = 0; *rx = ctx->wsx; - } else if (xoff < ctx->wox) { + } else if (xoff < (int)ctx->wox) { /* Left not visible. */ *i = ctx->wox - (ctx->xoff + px); *x = 0; @@ -1215,13 +1218,23 @@ static void tty_clear_pane_line(struct tty *tty, const struct tty_ctx *ctx, u_int py, u_int px, u_int nx, u_int bg) { - struct client *c = tty->client; - u_int i, x, rx, ry; + struct client *c = tty->client; + struct visible_ranges *r; + struct visible_range *ri; + u_int i, l, x, rx, ry; log_debug("%s: %s, %u at %u,%u", __func__, c->name, nx, px, py); - if (tty_clamp_line(tty, ctx, px, py, nx, &i, &x, &rx, &ry)) - tty_clear_line(tty, &ctx->defaults, ry, x, rx, bg); + if (tty_clamp_line(tty, ctx, px, py, nx, &l, &x, &rx, &ry)) { + r = tty_check_overlay_range(tty, x, ry, rx); + for (i = 0; i < r->used; i++) { + ri = &r->ranges[i]; + if (ri->nx == 0) + continue; + tty_clear_line(tty, &ctx->defaults, ry, ri->px, ri->nx, + bg); + } + } } /* Clamp area position to visible part of pane. */ @@ -1288,12 +1301,13 @@ tty_clamp_area(struct tty *tty, const struct tty_ctx *ctx, u_int px, u_int py, /* Clear an area, adjusting to visible part of pane. */ static void -tty_clear_area(struct tty *tty, const struct grid_cell *defaults, u_int py, +tty_clear_area(struct tty *tty, const struct tty_ctx *ctx, u_int py, u_int ny, u_int px, u_int nx, u_int bg) { - struct client *c = tty->client; - u_int yy; - char tmp[64]; + struct client *c = tty->client; + const struct grid_cell *defaults = &ctx->defaults; + u_int yy; + char tmp[64]; log_debug("%s: %s, %u,%u at %u,%u", __func__, c->name, nx, ny, px, py); @@ -1301,7 +1315,10 @@ tty_clear_area(struct tty *tty, const struct grid_cell *defaults, u_int py, if (nx == 0 || ny == 0) return; - /* If genuine BCE is available, can try escape sequences. */ + /* + * If there is an overlay or BCE is not available, cannot clear as a + * region. + */ if (c->overlay_check == NULL && !tty_fake_bce(tty, defaults, bg)) { /* Use ED if clearing off the bottom of the terminal. */ if (px == 0 && @@ -1366,9 +1383,10 @@ tty_clear_pane_area(struct tty *tty, const struct tty_ctx *ctx, u_int py, u_int i, j, x, y, rx, ry; if (tty_clamp_area(tty, ctx, px, py, nx, ny, &i, &j, &x, &y, &rx, &ry)) - tty_clear_area(tty, &ctx->defaults, y, ry, x, rx, bg); + tty_clear_area(tty, ctx, y, ry, x, rx, bg); } +/* Redraw a line of a screen at py. */ static void tty_draw_pane(struct tty *tty, const struct tty_ctx *ctx, u_int py) { @@ -1404,6 +1422,7 @@ tty_draw_pane(struct tty *tty, const struct tty_ctx *ctx, u_int py) } } +/* Check if character needs to be mapped for codeset. */ const struct grid_cell * tty_check_codeset(struct tty *tty, const struct grid_cell *gc) { @@ -1612,7 +1631,7 @@ tty_cmd_insertcharacter(struct tty *tty, const struct tty_ctx *ctx) { struct client *c = tty->client; - if ((ctx->flags & TTY_CTX_WINDOW_BIGGER) || + if ((ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED)) || !tty_full_width(tty, ctx) || tty_fake_bce(tty, &ctx->defaults, ctx->bg) || (!tty_term_has(tty->term, TTYC_ICH) && @@ -1635,7 +1654,7 @@ tty_cmd_deletecharacter(struct tty *tty, const struct tty_ctx *ctx) { struct client *c = tty->client; - if ((ctx->flags & TTY_CTX_WINDOW_BIGGER) || + if (ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED) || !tty_full_width(tty, ctx) || tty_fake_bce(tty, &ctx->defaults, ctx->bg) || (!tty_term_has(tty->term, TTYC_DCH) && @@ -1667,7 +1686,7 @@ tty_cmd_insertline(struct tty *tty, const struct tty_ctx *ctx) { struct client *c = tty->client; - if ((ctx->flags & TTY_CTX_WINDOW_BIGGER) || + if ((ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED)) || !tty_full_width(tty, ctx) || tty_fake_bce(tty, &ctx->defaults, ctx->bg) || !tty_term_has(tty->term, TTYC_CSR) || @@ -1695,7 +1714,7 @@ tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx) { struct client *c = tty->client; - if ((ctx->flags & TTY_CTX_WINDOW_BIGGER) || + if (ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED) || !tty_full_width(tty, ctx) || tty_fake_bce(tty, &ctx->defaults, ctx->bg) || !tty_term_has(tty->term, TTYC_CSR) || @@ -1755,7 +1774,7 @@ tty_cmd_reverseindex(struct tty *tty, const struct tty_ctx *ctx) if (ctx->ocy != ctx->orupper) return; - if ((ctx->flags & TTY_CTX_WINDOW_BIGGER) || + if (ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED) || (!tty_full_width(tty, ctx) && !tty_use_margin(tty)) || tty_fake_bce(tty, &ctx->defaults, 8) || !tty_term_has(tty->term, TTYC_CSR) || @@ -1827,10 +1846,10 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx) { - struct client *c = tty->client; - u_int i; + struct client *c = tty->client; + u_int i; - if ((ctx->flags & TTY_CTX_WINDOW_BIGGER) || + if (ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED) || (!tty_full_width(tty, ctx) && !tty_use_margin(tty)) || tty_fake_bce(tty, &ctx->defaults, 8) || !tty_term_has(tty->term, TTYC_CSR) || @@ -1869,7 +1888,7 @@ tty_cmd_scrolldown(struct tty *tty, const struct tty_ctx *ctx) u_int i; struct client *c = tty->client; - if ((ctx->flags & TTY_CTX_WINDOW_BIGGER) || + if (ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED) || (!tty_full_width(tty, ctx) && !tty_use_margin(tty)) || tty_fake_bce(tty, &ctx->defaults, 8) || !tty_term_has(tty->term, TTYC_CSR) || @@ -1969,9 +1988,11 @@ tty_cmd_clearscreen(struct tty *tty, const struct tty_ctx *ctx) void tty_cmd_alignmenttest(struct tty *tty, const struct tty_ctx *ctx) { - u_int i, j; + struct client *c = tty->client; + u_int i, j; - if (ctx->flags & TTY_CTX_WINDOW_BIGGER) { + if (ctx->flags & (TTY_CTX_WINDOW_BIGGER|TTY_CTX_PANE_OBSCURED) || + c->overlay_check != NULL) { ctx->redraw_cb(ctx); return; } @@ -2040,7 +2061,7 @@ void tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx) { struct visible_ranges *r; - struct visible_range *rr; + struct visible_range *ri; u_int i, px, py, cx; const char *cp = ctx->data.data; size_t n = ctx->data.size; @@ -2075,11 +2096,11 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx) r = tty_check_overlay_range(tty, px, py, n); for (i = 0; i < r->used; i++) { - rr = &r->ranges[i]; - if (rr->nx != 0) { - cx = rr->px - ctx->xoff + ctx->wox; + ri = &r->ranges[i]; + if (ri->nx != 0) { + cx = ri->px - ctx->xoff + ctx->wox; tty_cursor_pane_unless_wrap(tty, ctx, cx, ctx->ocy); - tty_putn(tty, cp + rr->px - px, rr->nx, rr->nx); + tty_putn(tty, cp + ri->px - px, ri->nx, ri->nx); } } } @@ -2211,6 +2232,10 @@ tty_cell(struct tty *tty, const struct grid_cell *gc, if (gc->flags & GRID_FLAG_PADDING) return; + /* Check if character is covered by overlay or floating pane. */ + if (!tty_check_overlay(tty, tty->cx, tty->cy)) + return; + /* Check the output codeset and apply attributes. */ gcp = tty_check_codeset(tty, gc); tty_attributes(tty, gcp, defaults, palette, hl); @@ -2324,8 +2349,21 @@ tty_margin_off(struct tty *tty) static void tty_margin_pane(struct tty *tty, const struct tty_ctx *ctx) { - tty_margin(tty, ctx->xoff - ctx->wox, - ctx->xoff + ctx->sx - 1 - ctx->wox); + int l, r; + + l = ctx->xoff - ctx->wox; + r = ctx->xoff + ctx->sx - 1 - ctx->wox; + + if (l < 0) + l = 0; + if (l > (int)ctx->wsx) + l = ctx->wsx; + if (r < 0) + r = 0; + if (r > (int)ctx->wsx) + r = ctx->wsx; + + tty_margin(tty, l, r); } /* Set margin at absolute position. */