From b642eac4503cc89cde01103f7bacca57cc9c1a2b Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Thu, 5 Dec 2019 09:11:24 +0000 Subject: [PATCH] Redraw and scroll images and part of invalidating them. --- input.c | 2 +- screen-redraw.c | 5 ++-- screen-write.c | 70 ++++++++++++++++++++++++++++++++++++++++++++----- tmux.h | 4 ++- tty.c | 32 ++++++++++++++++++++++ 5 files changed, 102 insertions(+), 11 deletions(-) diff --git a/input.c b/input.c index 0cf614ff..2f6c6006 100644 --- a/input.c +++ b/input.c @@ -2172,7 +2172,7 @@ input_dcs_dispatch(struct input_ctx *ictx) si = sixel_parse(buf, len, w->xpixel, w->ypixel); if (si != NULL) { sixel_log(si); - screen_write_sixelimage(sctx, si); + screen_write_sixelimage(sctx, si, ictx->cell.cell.bg); } } diff --git a/screen-redraw.c b/screen-redraw.c index e7f4f077..03b784b1 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -578,7 +578,7 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp) struct client *c = ctx->c; struct window *w = c->session->curw->window; struct tty *tty = &c->tty; - struct screen *s; + struct screen *s = wp->screen; u_int i, j, top, x, y, width; log_debug("%s: %s @%u %%%u", __func__, c->name, w->id, wp->id); @@ -590,7 +590,6 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp) else top = 0; - s = wp->screen; for (j = 0; j < wp->sy; j++) { if (wp->yoff + j < ctx->oy || wp->yoff + j >= ctx->oy + ctx->sy) continue; @@ -624,4 +623,6 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp) tty_draw_line(tty, wp, s, i, j, width, x, y); } + + tty_draw_images(tty, wp, s); } diff --git a/screen-write.c b/screen-write.c index 2d376e66..d9a06473 100644 --- a/screen-write.c +++ b/screen-write.c @@ -1044,6 +1044,8 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped, u_int bg) struct screen *s = ctx->s; struct grid *gd = s->grid; struct grid_line *gl; + int redraw; + u_int rupper = s->rupper, rlower = s->rlower; gl = grid_get_line(gd, gd->hsize + s->cy); if (wrapped) @@ -1052,15 +1054,21 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped, u_int bg) gl->flags &= ~GRID_LINE_WRAPPED; log_debug("%s: at %u,%u (region %u-%u)", __func__, s->cx, s->cy, - s->rupper, s->rlower); + rupper, rlower); if (bg != ctx->bg) { screen_write_collect_flush(ctx, 1); ctx->bg = bg; } - if (s->cy == s->rlower) { - grid_view_scroll_region_up(gd, s->rupper, s->rlower, bg); + if (s->cy == rlower) { + if (rlower == screen_size_y(s) - 1) + redraw = image_scroll_up(s, 1); + else + redraw = image_check_line(s, rupper, rlower - rupper); + if (redraw && ctx->wp != NULL) + ctx->wp->flags |= PANE_REDRAW; + grid_view_scroll_region_up(gd, rupper, rlower, bg); screen_write_collect_scroll(ctx); ctx->scrolled++; } else if (s->cy < screen_size_y(s) - 1) @@ -1085,6 +1093,9 @@ screen_write_scrollup(struct screen_write_ctx *ctx, u_int lines, u_int bg) ctx->bg = bg; } + if (image_scroll_up(s, lines) && ctx->wp != NULL) + ctx->wp->flags |= PANE_REDRAW; + for (i = 0; i < lines; i++) { grid_view_scroll_region_up(gd, s->rupper, s->rlower, bg); screen_write_collect_scroll(ctx); @@ -1109,6 +1120,9 @@ screen_write_scrolldown(struct screen_write_ctx *ctx, u_int lines, u_int bg) else if (lines > s->rlower - s->rupper + 1) lines = s->rlower - s->rupper + 1; + if (image_free_all(s) && ctx->wp != NULL) + ctx->wp->flags |= PANE_REDRAW; + for (i = 0; i < lines; i++) grid_view_scroll_region_down(gd, s->rupper, s->rlower, bg); @@ -1326,6 +1340,9 @@ screen_write_collect_end(struct screen_write_ctx *ctx) } } + if (image_check_area(s, s->cx, s->cy, ci->used, 1) && ctx->wp != NULL) + ctx->wp->flags |= PANE_REDRAW; + grid_view_set_cells(s->grid, s->cx, s->cy, &ci->gc, ci->data, ci->used); screen_write_set_cursor(ctx, s->cx + ci->used, -1); @@ -1674,16 +1691,55 @@ screen_write_rawstring(struct screen_write_ctx *ctx, u_char *str, u_int len) /* Write a SIXEL image. */ void -screen_write_sixelimage(struct screen_write_ctx *ctx, struct sixel_image *si) +screen_write_sixelimage(struct screen_write_ctx *ctx, struct sixel_image *si, + u_int bg) { - struct screen *s = ctx->s; - struct tty_ctx ttyctx; + struct screen *s = ctx->s; + struct grid *gd = s->grid; + struct tty_ctx ttyctx; + u_int x, y, sx, sy, cx = s->cx, cy = s->cy, i, lines; + struct sixel_image *new; + + sixel_size_in_cells(si, &x, &y); + if (x > screen_size_x(s) || y > screen_size_y(s)) { + if (x > screen_size_x(s) - cx) + sx = screen_size_x(s) - cx; + else + sx = x; + if (y > screen_size_y(s) - 1) + sy = screen_size_y(s) - 1; + else + sy = y; + new = sixel_scale(si, 0, 0, 0, y - sy, sx, sy, 1); + sixel_free(si); + si = new; + sixel_size_in_cells(si, &x, &y); + } + + sy = screen_size_y(s) - cy; + if (sy < y) { + lines = y - sy + 1; + if (image_scroll_up(s, lines) && ctx->wp != NULL) + ctx->wp->flags |= PANE_REDRAW; + for (i = 0; i < lines; i++) { + grid_view_scroll_region_up(gd, 0, screen_size_y(s) - 1, + bg); + screen_write_collect_scroll(ctx); + } + ctx->scrolled += lines; + if (lines > cy) + screen_write_cursormove(ctx, -1, 0, 0); + else + screen_write_cursormove(ctx, -1, cy - lines, 0); + } + screen_write_collect_flush(ctx, 0); image_store(s, si); screen_write_initctx(ctx, &ttyctx); ttyctx.ptr = si; - screen_write_collect_flush(ctx, 0); tty_write(tty_cmd_sixelimage, &ttyctx); + + screen_write_cursormove(ctx, 0, cy + y, 0); } diff --git a/tmux.h b/tmux.h index 48b36354..79c08491 100644 --- a/tmux.h +++ b/tmux.h @@ -1963,6 +1963,7 @@ void tty_set_title(struct tty *, const char *); void tty_update_mode(struct tty *, int, struct screen *); void tty_draw_line(struct tty *, struct window_pane *, struct screen *, u_int, u_int, u_int, u_int, u_int); +void tty_draw_images(struct tty *, struct window_pane *, struct screen *); int tty_open(struct tty *, char **); void tty_close(struct tty *); void tty_free(struct tty *); @@ -2377,7 +2378,8 @@ void screen_write_collect_add(struct screen_write_ctx *, void screen_write_cell(struct screen_write_ctx *, const struct grid_cell *); void screen_write_setselection(struct screen_write_ctx *, u_char *, u_int); void screen_write_rawstring(struct screen_write_ctx *, u_char *, u_int); -void screen_write_sixelimage(struct screen_write_ctx *, struct sixel_image *); +void screen_write_sixelimage(struct screen_write_ctx *, + struct sixel_image *, u_int); /* screen-redraw.c */ void screen_redraw_screen(struct client *); diff --git a/tty.c b/tty.c index e5e7e78a..e69d9c38 100644 --- a/tty.c +++ b/tty.c @@ -1378,6 +1378,38 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s, tty_update_mode(tty, tty->mode, s); } +void +tty_draw_images(struct tty *tty, struct window_pane *wp, struct screen *s) +{ + struct client *c = tty->client; + struct image *im; + struct tty_ctx ttyctx; + + TAILQ_FOREACH(im, &s->images, entry) { + memset(&ttyctx, 0, sizeof ttyctx); + + ttyctx.wp = wp; + + ttyctx.ocx = im->px; + ttyctx.ocy = im->py; + + ttyctx.orlower = s->rlower; + ttyctx.orupper = s->rupper; + + ttyctx.bigger = tty_window_offset(&c->tty, &ttyctx.ox, + &ttyctx.oy, &ttyctx.sx, &ttyctx.sy); + + ttyctx.xoff = wp->xoff; + ttyctx.yoff = wp->yoff; + + if (status_at_line(c) == 0) + ttyctx.yoff += status_line_size(c); + + ttyctx.ptr = im->data; + tty_cmd_sixelimage(tty, &ttyctx); + } +} + static int tty_client_ready(struct client *c, struct window_pane *wp) {