diff --git a/grid-view.c b/grid-view.c index 5659d5763..8c9794114 100644 --- a/grid-view.c +++ b/grid-view.c @@ -74,6 +74,10 @@ grid_view_clear_history(struct grid *gd, u_int bg) gl = grid_get_line(gd, grid_view_y(gd, yy)); if (gl->cellused != 0) last = yy + 1; +#ifdef ENABLE_IMAGES + else if (image_grid_line_has_images(gl)) + last = yy + 1; +#endif } if (last == 0) { grid_view_clear(gd, 0, 0, gd->sx, gd->sy, bg); diff --git a/image-grid.c b/image-grid.c index 3c87505d2..0873e9170 100644 --- a/image-grid.c +++ b/image-grid.c @@ -380,3 +380,82 @@ image_grid_line_has_images(struct grid_line *gl) { return (gl->images != NULL && !TAILQ_EMPTY(&gl->images->spans)); } + +/* Check whether a grid area has any image spans. */ +int +image_grid_area_has_images(struct grid *gd, u_int x, u_int y, u_int sx, + u_int sy) +{ + struct image_line *line; + struct image_span *span; + u_int row, end; + + if (gd->images == NULL) + return (0); + if (sx == 0 || sy == 0 || y >= gd->hsize + gd->sy) + return (0); + + end = x + sx; + if (end < x) + end = UINT_MAX; + if (sy > gd->hsize + gd->sy - y) + sy = gd->hsize + gd->sy - y; + + for (row = y; row < y + sy; row++) { + line = gd->linedata[row].images; + if (line == NULL) + continue; + TAILQ_FOREACH(span, &line->spans, line_entry) { + if (span->x < end && span->x + span->sx > x) + return (1); + } + } + return (0); +} + +/* Record window damage when an area containing images changes. */ +void +image_redraw_area(struct screen_write_ctx *ctx, u_int x, u_int y, u_int sx, + u_int sy) +{ + struct window_pane *wp = ctx->wp; + struct grid *gd = ctx->s->grid; + + if (wp == NULL) + return; + if (!image_grid_area_has_images(gd, x, gd->hsize + y, sx, sy)) + return; + redraw_damage_window(wp->window, wp->xoff + x, wp->yoff + y, sx, sy); +} + +/* Record window damage for all visible images. */ +void +image_redraw_all(struct screen_write_ctx *ctx) +{ + struct screen *s = ctx->s; + u_int sx = screen_size_x(s), sy = screen_size_y(s); + + image_redraw_area(ctx, 0, 0, sx, sy); +} + +/* Record window damage for images in the scroll region. */ +void +image_redraw_scroll(struct screen_write_ctx *ctx) +{ + struct screen *s = ctx->s; + u_int sx = screen_size_x(s), sy = s->rlower - s->rupper + 1; + + image_redraw_area(ctx, 0, s->rupper, sx, sy); +} + +/* Redraw images under changed cells. */ +void +image_damage_screen(struct screen_write_ctx *ctx, u_int x, u_int y, u_int sx, + u_int sy) +{ + struct screen *s = ctx->s; + + image_redraw_area(ctx, x, y, sx, sy); + if (ctx->flags & SCREEN_WRITE_INPUT) + image_grid_remove(s->grid, x, s->grid->hsize + y, sx, sy); +} diff --git a/screen-write.c b/screen-write.c index 8fda18fa1..08e76cedb 100644 --- a/screen-write.c +++ b/screen-write.c @@ -1471,6 +1471,10 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx) memcpy(&gc, &grid_default_cell, sizeof gc); utf8_set(&gc.data, 'E'); +#ifdef ENABLE_IMAGES + image_damage_screen(ctx, 0, 0, screen_size_x(s), screen_size_y(s)); +#endif + for (yy = 0; yy < screen_size_y(s); yy++) { for (xx = 0; xx < screen_size_x(s); xx++) grid_view_set_cell(s->grid, xx, yy, &gc); @@ -1516,6 +1520,10 @@ screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg) screen_write_initctx(ctx, &ttyctx, 0, 1); ttyctx.bg = bg; +#ifdef ENABLE_IMAGES + image_redraw_area(ctx, 0, s->cy, screen_size_x(s), 1); +#endif + grid_view_insert_cells(s->grid, s->cx, s->cy, nx, bg); screen_write_collect_flush(ctx, 0, __func__); @@ -1552,6 +1560,10 @@ screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg) screen_write_initctx(ctx, &ttyctx, 0, 1); ttyctx.bg = bg; +#ifdef ENABLE_IMAGES + image_redraw_area(ctx, 0, s->cy, screen_size_x(s), 1); +#endif + grid_view_delete_cells(s->grid, s->cx, s->cy, nx, bg); screen_write_collect_flush(ctx, 0, __func__); @@ -1588,6 +1600,10 @@ screen_write_clearcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg) screen_write_initctx(ctx, &ttyctx, 0, 1); ttyctx.bg = bg; +#ifdef ENABLE_IMAGES + image_redraw_area(ctx, s->cx, s->cy, nx, 1); +#endif + grid_view_clear(s->grid, s->cx, s->cy, nx, 1, bg); screen_write_collect_flush(ctx, 0, __func__); @@ -1624,6 +1640,10 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny, u_int bg) screen_write_initctx(ctx, &ttyctx, 1, 1); ttyctx.bg = bg; +#ifdef ENABLE_IMAGES + image_redraw_area(ctx, 0, s->cy, screen_size_x(s), sy - s->cy); +#endif + grid_view_insert_lines(gd, s->cy, ny, bg); screen_write_collect_flush(ctx, 0, __func__); @@ -1648,6 +1668,11 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny, u_int bg) screen_write_initctx(ctx, &ttyctx, 1, 1); ttyctx.bg = bg; +#ifdef ENABLE_IMAGES + image_redraw_area(ctx, 0, s->cy, screen_size_x(s), + s->rlower + 1 - s->cy); +#endif + if (s->cy < s->rupper || s->cy > s->rlower) grid_view_insert_lines(gd, s->cy, ny, bg); else @@ -1687,6 +1712,10 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny, u_int bg) screen_write_initctx(ctx, &ttyctx, 1, 1); ttyctx.bg = bg; +#ifdef ENABLE_IMAGES + image_redraw_area(ctx, 0, s->cy, screen_size_x(s), sy - s->cy); +#endif + grid_view_delete_lines(gd, s->cy, ny, bg); screen_write_collect_flush(ctx, 0, __func__); @@ -1713,6 +1742,10 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny, u_int bg) screen_write_initctx(ctx, &ttyctx, 1, 1); ttyctx.bg = bg; +#ifdef ENABLE_IMAGES + image_redraw_area(ctx, 0, s->cy, screen_size_x(s), ry); +#endif + if (s->cy < s->rupper || s->cy > s->rlower) grid_view_delete_lines(gd, s->cy, ny, bg); else @@ -1743,8 +1776,18 @@ screen_write_clearline(struct screen_write_ctx *ctx, u_int bg) u_int flags; gl = grid_get_line(s->grid, s->grid->hsize + s->cy); - if (gl->cellsize == 0 && COLOUR_DEFAULT(bg)) + if (gl->cellsize == 0 && COLOUR_DEFAULT(bg)) { +#ifdef ENABLE_IMAGES + if (!image_grid_line_has_images(gl)) + return; +#else return; +#endif + } + +#ifdef ENABLE_IMAGES + image_redraw_area(ctx, 0, s->cy, sx, 1); +#endif flags = gl->flags & GRID_LINE_OSC133_FLAGS; memcpy(&od, &gl->osc133_data, sizeof od); @@ -1777,8 +1820,21 @@ screen_write_clearendofline(struct screen_write_ctx *ctx, u_int bg) } gl = grid_get_line(s->grid, s->grid->hsize + s->cy); - if (s->cx > sx - 1 || (s->cx >= gl->cellsize && COLOUR_DEFAULT(bg))) + if (s->cx > sx - 1) return; + if (s->cx >= gl->cellsize && COLOUR_DEFAULT(bg)) { +#ifdef ENABLE_IMAGES + if (!image_grid_area_has_images(s->grid, s->cx, + s->grid->hsize + s->cy, sx - s->cx, 1)) + return; +#else + return; +#endif + } + +#ifdef ENABLE_IMAGES + image_redraw_area(ctx, s->cx, s->cy, sx - s->cx, 1); +#endif grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1, bg); @@ -1802,6 +1858,10 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx, u_int bg) return; } +#ifdef ENABLE_IMAGES + image_redraw_area(ctx, 0, s->cy, s->cx + 1, 1); +#endif + if (s->cx > sx - 1) grid_view_clear(s->grid, 0, s->cy, sx, 1, bg); else @@ -1851,6 +1911,10 @@ screen_write_reverseindex(struct screen_write_ctx *ctx, u_int bg) return; } +#ifdef ENABLE_IMAGES + image_redraw_scroll(ctx); +#endif + grid_view_scroll_region_down(s->grid, s->rupper, s->rlower, bg); screen_write_collect_flush(ctx, 0, __func__); @@ -1918,6 +1982,10 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped, u_int bg) return; } +#ifdef ENABLE_IMAGES + image_redraw_scroll(ctx); +#endif + grid_view_scroll_region_up(gd, s->rupper, s->rlower, bg); screen_write_collect_scroll(ctx, bg); ctx->scrolled++; @@ -1941,6 +2009,10 @@ screen_write_scrollup(struct screen_write_ctx *ctx, u_int lines, u_int bg) ctx->bg = bg; } +#ifdef ENABLE_IMAGES + image_redraw_scroll(ctx); +#endif + for (i = 0; i < lines; i++) { grid_view_scroll_region_up(gd, s->rupper, s->rlower, bg); screen_write_collect_scroll(ctx, bg); @@ -1965,6 +2037,10 @@ 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; +#ifdef ENABLE_IMAGES + image_redraw_scroll(ctx); +#endif + for (i = 0; i < lines; i++) grid_view_scroll_region_down(gd, s->rupper, s->rlower, bg); @@ -2004,6 +2080,12 @@ screen_write_clearendofscreen(struct screen_write_ctx *ctx, u_int bg) screen_write_initctx(ctx, &ttyctx, 1, 1); ttyctx.bg = bg; +#ifdef ENABLE_IMAGES + if (s->cx < sx) + image_redraw_area(ctx, s->cx, s->cy, sx - s->cx, 1); + image_redraw_area(ctx, 0, s->cy + 1, sx, sy - (s->cy + 1)); +#endif + /* Scroll into history if it is enabled and clearing entire screen. */ if (s->cx == 0 && s->cy == 0 && @@ -2080,6 +2162,11 @@ screen_write_clearstartofscreen(struct screen_write_ctx *ctx, u_int bg) screen_write_initctx(ctx, &ttyctx, 1, 1); ttyctx.bg = bg; +#ifdef ENABLE_IMAGES + image_redraw_area(ctx, 0, 0, sx, s->cy); + image_redraw_area(ctx, 0, s->cy, s->cx + 1, 1); +#endif + if (s->cy > 0) grid_view_clear(s->grid, 0, 0, sx, s->cy, bg); if (s->cx > sx - 1) @@ -2148,6 +2235,10 @@ screen_write_clearscreen(struct screen_write_ctx *ctx, u_int bg) screen_write_initctx(ctx, &ttyctx, 1, 1); ttyctx.bg = bg; +#ifdef ENABLE_IMAGES + image_redraw_all(ctx); +#endif + /* Scroll into history if it is enabled. */ if ((s->grid->flags & GRID_HISTORY) && ctx->wp != NULL && @@ -2573,6 +2664,10 @@ screen_write_clear_cell(struct screen_write_ctx *ctx, u_int px, u_int py) grid_view_get_cell(gd, px, py, &gc); bg = gc.bg; +#ifdef ENABLE_IMAGES + image_damage_screen(ctx, px, py, 1, 1); +#endif + memcpy(&gc, &grid_default_cell, sizeof gc); gc.bg = bg; grid_view_set_cell(gd, px, py, &gc); @@ -2649,6 +2744,10 @@ screen_write_collect_end(struct screen_write_ctx *ctx) } } +#ifdef ENABLE_IMAGES + image_damage_screen(ctx, s->cx, s->cy, ci->used, 1); +#endif + grid_view_set_cells(s->grid, s->cx, s->cy, &ci->gc, cl->data + ci->x, ci->used); if (bnx != 0) @@ -2781,6 +2880,11 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc) return; screen_write_initctx(ctx, &ttyctx, 0, 0); +#ifdef ENABLE_IMAGES + /* Mark images as damaged. */ + image_damage_screen(ctx, s->cx, s->cy, width, 1); +#endif + /* Handle overwriting of UTF-8 characters. */ gl = grid_get_line(s->grid, s->grid->hsize + s->cy); if (gl->flags & GRID_LINE_EXTENDED) { @@ -3012,6 +3116,11 @@ screen_write_combine(struct screen_write_ctx *ctx, const struct grid_cell *gc) } else force_wide = 0; +#ifdef ENABLE_IMAGES + /* Mark images as damaged. */ + image_damage_screen(ctx, cx - n, cy, n, 1); +#endif + /* Set the new cell. */ grid_view_set_cell(gd, cx - n, cy, &last); if (force_wide) diff --git a/tmux-image.h b/tmux-image.h index 61fb5598b..685b006bf 100644 --- a/tmux-image.h +++ b/tmux-image.h @@ -81,6 +81,14 @@ void image_grid_move_cells(struct grid *, u_int, u_int, u_int, void image_grid_duplicate_lines(struct grid *, u_int, struct grid *, u_int, u_int); int image_grid_line_has_images(struct grid_line *); +int image_grid_area_has_images(struct grid *, u_int, u_int, u_int, + u_int); +void image_redraw_area(struct screen_write_ctx *, u_int, u_int, + u_int, u_int); +void image_redraw_all(struct screen_write_ctx *); +void image_redraw_scroll(struct screen_write_ctx *); +void image_damage_screen(struct screen_write_ctx *, u_int, u_int, + u_int, u_int); /* image-sixel.c */ #define SIXEL_COLOUR_REGISTERS 1024