diff --git a/screen-redraw.c b/screen-redraw.c index abdc6f9bf..a20ac59eb 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -1127,7 +1127,7 @@ redraw_draw_pane_span(struct redraw_draw_ctx *dctx, tty_draw_line(tty, s, px, py, n, x, y, &style_ctx); #ifdef ENABLE_IMAGES if (tty->term->flags & TERM_KITTY) - kitty_draw_line(tty, s, px, py, n, x, y); + kitty_draw_line(tty, s, px, py, n, x, y, &style_ctx); else if ((tty->term->flags & TERM_SIXEL) && tty->xpixel != 0 && tty->ypixel != 0) sixel_draw_line(tty, s, px, py, n, x, y); diff --git a/tmux.h b/tmux.h index 78d831c48..9fc905cc6 100644 --- a/tmux.h +++ b/tmux.h @@ -4245,7 +4245,7 @@ struct image *kitty_parse_image(void **, const u_char *, size_t, u_int, u_int, u_int *, u_int *, char *, int *); void kitty_free_state(void *); void kitty_draw_line(struct tty *, struct screen *, u_int, u_int, - u_int, u_int, u_int); + u_int, u_int, u_int, const struct tty_style_ctx *); void kitty_images_free(struct tty *, int); void sixel_draw_line(struct tty *, struct screen *, u_int, u_int, u_int, u_int, u_int); diff --git a/tty-draw.c b/tty-draw.c index ca02d6fec..563a86dea 100644 --- a/tty-draw.c +++ b/tty-draw.c @@ -29,6 +29,7 @@ enum tty_draw_line_state { TTY_DRAW_LINE_NEW1, TTY_DRAW_LINE_NEW2, TTY_DRAW_LINE_EMPTY, + TTY_DRAW_LINE_IMAGE, TTY_DRAW_LINE_SAME, TTY_DRAW_LINE_DONE }; @@ -38,6 +39,7 @@ static const char* tty_draw_line_states[] = { "NEW1", "NEW2", "EMPTY", + "IMAGE", "SAME", "DONE" }; @@ -131,7 +133,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, struct grid_line *gl; u_int i, j, last_i, cx, ex, width; u_int cellsize, bg; - int flags, empty, wrapped = 0; + int flags, empty, skip, wrapped = 0; char buf[1000]; size_t len; enum tty_draw_line_state current_state, next_state; @@ -236,6 +238,8 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, width = 0; current_state = TTY_DRAW_LINE_FIRST; for (;;) { + skip = 0; + /* Work out the next state. */ if (i == nx) { /* @@ -266,13 +270,17 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, if ((tty->term->flags & TERM_KITTY) || ((tty->term->flags & TERM_SIXEL) && tty->xpixel != 0 && - tty->ypixel != 0)) + tty->ypixel != 0)) { ascii = " "; - else + skip = 1; + } else ascii = image_get_ascii(im, gc.image_x, gc.image_y); utf8_set(&image_gc.data, *ascii); image_gc.flags &= ~GRID_FLAG_IMAGE; + if (skip) + image_gc.flags &= + ~GRID_FLAG_SELECTED; gcp = &image_gc; } else gcp = &gc; @@ -281,9 +289,12 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, #endif /* Work out empty cells. */ - empty = tty_draw_line_get_empty(gcp, &last, - nx - i); - if (empty != 0) + if (skip) + empty = 0; + else + empty = tty_draw_line_get_empty(gcp, + &last, nx - i); + if (empty != 0 || skip) ; else { /* Update for codeset if needed. */ @@ -300,7 +311,9 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, } /* Work out the next state. */ - if (empty != 0) + if (skip) + next_state = TTY_DRAW_LINE_IMAGE; + else if (empty != 0) next_state = TTY_DRAW_LINE_EMPTY; else if (current_state == TTY_DRAW_LINE_FIRST) next_state = TTY_DRAW_LINE_SAME; @@ -347,7 +360,8 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx, } /* Append the cell if it is not empty and not padding. */ - if (next_state != TTY_DRAW_LINE_EMPTY) { + if (next_state != TTY_DRAW_LINE_EMPTY && + next_state != TTY_DRAW_LINE_IMAGE) { memcpy(buf + len, gcp->data.data, gcp->data.size); len += gcp->data.size; width += gcp->data.width; diff --git a/tty-features.c b/tty-features.c index 1c6a7eb3e..d52407c59 100644 --- a/tty-features.c +++ b/tty-features.c @@ -224,9 +224,11 @@ static const struct tty_feature tty_feature_strikethrough = { 0 }; +#define TTY_FEATURE_SYNC "Sync=\\E[?2026%?%p1%{1}%-%tl%eh%;" + /* Terminal supports synchronized updates. */ static const char *const tty_feature_sync_capabilities[] = { - "Sync=\\E[?2026%?%p1%{1}%-%tl%eh%;", + TTY_FEATURE_SYNC, NULL }; static const struct tty_feature tty_feature_sync = { @@ -349,6 +351,7 @@ static const struct tty_feature tty_feature_ignorefkeys = { /* Terminal has sixel capability. */ static const char *const tty_feature_sixel_capabilities[] = { "Sxl", + TTY_FEATURE_SYNC, NULL }; static const struct tty_feature tty_feature_sixel = { @@ -360,6 +363,7 @@ static const struct tty_feature tty_feature_sixel = { /* Terminal has Kitty graphics protocol capability. */ static const char *const tty_feature_kitty_capabilities[] = { "Kty", + TTY_FEATURE_SYNC, NULL }; static const struct tty_feature tty_feature_kitty = { diff --git a/tty.c b/tty.c index cabd0551e..1811dba62 100644 --- a/tty.c +++ b/tty.c @@ -2119,6 +2119,11 @@ tty_cell(struct tty *tty, const struct grid_cell *gc, const struct tty_style_ctx *style_ctx) { const struct grid_cell *gcp; +#ifdef ENABLE_IMAGES + struct grid_cell image_gc; + struct image *im; + const char *ascii; +#endif /* Skip last character if terminal is stupid. */ if ((tty->term->flags & TERM_NOAM) && @@ -2134,6 +2139,26 @@ tty_cell(struct tty *tty, const struct grid_cell *gc, if (!tty_check_overlay(tty, tty->cx, tty->cy)) return; +#ifdef ENABLE_IMAGES + /* + * Graphical image cells are drawn by the redraw scene. In particular, + * do not erase one with a selected space while copy mode is moving the + * selection; the unchanged image would then need to be drawn again. + */ + if (gc->flags & GRID_FLAG_IMAGE) { + if ((tty->term->flags & TERM_KITTY) || + ((tty->term->flags & TERM_SIXEL) && + tty->xpixel != 0 && tty->ypixel != 0)) + return; + memcpy(&image_gc, gc, sizeof image_gc); + im = image_find(gc->image_id); + ascii = image_get_ascii(im, gc->image_x, gc->image_y); + utf8_set(&image_gc.data, *ascii); + image_gc.flags &= ~GRID_FLAG_IMAGE; + gc = &image_gc; + } +#endif + /* Check the output codeset and apply attributes. */ gcp = tty_check_codeset(tty, gc); tty_attributes(tty, gcp, style_ctx);