From b34111b3da1e4b1769a976cd40486144f7b4f5a2 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Thu, 28 Nov 2019 12:35:18 +0000 Subject: [PATCH] Pass through SIXEL DCS sequences (treat similarly to the passthrough escape sequence) if it appears the terminal outside supports them. --- input.c | 18 +++++++++++++----- screen-write.c | 15 +++++++++++++++ tmux.1 | 2 ++ tmux.h | 7 ++++++- tty-keys.c | 9 ++++++--- tty-term.c | 1 + tty.c | 15 ++++++++++++++- 7 files changed, 57 insertions(+), 10 deletions(-) diff --git a/input.c b/input.c index 452eac7f..b8d2f102 100644 --- a/input.c +++ b/input.c @@ -1305,8 +1305,8 @@ input_csi_dispatch(struct input_ctx *ictx) if (ictx->flags & INPUT_DISCARD) return (0); - log_debug("%s: '%c' \"%s\" \"%s\"", - __func__, ictx->ch, ictx->interm_buf, ictx->param_buf); + log_debug("%s: '%c' \"%s\" \"%s\"", __func__, ictx->ch, + ictx->interm_buf, ictx->param_buf); if (input_split(ictx) != 0) return (0); @@ -2151,19 +2151,27 @@ static int input_dcs_dispatch(struct input_ctx *ictx) { struct screen_write_ctx *sctx = &ictx->ctx; - u_char *buf = ictx->input_buf; - size_t len = ictx->input_len; + u_char *buf = ictx->input_buf, *pbuf = ictx->param_buf; + size_t len = ictx->input_len, plen = ictx->param_len; const char prefix[] = "tmux;"; const u_int prefixlen = (sizeof prefix) - 1; if (ictx->flags & INPUT_DISCARD) return (0); - log_debug("%s: \"%s\"", __func__, buf); + log_debug("%s: \"%s\" \"%s\" \"%s\"", __func__, buf, ictx->interm_buf, + ictx->param_buf); if (len >= prefixlen && strncmp(buf, prefix, prefixlen) == 0) screen_write_rawstring(sctx, buf + prefixlen, len - prefixlen); + if (buf[0] == 'q') { + screen_write_rawsixel(sctx, (char *)"\033P", 2, 1); + screen_write_rawsixel(sctx, pbuf, plen, 1); + screen_write_rawsixel(sctx, buf, len, 1); + screen_write_rawsixel(sctx, (char *)"\033\\", 2, 0); + } + return (0); } diff --git a/screen-write.c b/screen-write.c index 43cb42b4..9bd28836 100644 --- a/screen-write.c +++ b/screen-write.c @@ -1671,3 +1671,18 @@ screen_write_rawstring(struct screen_write_ctx *ctx, u_char *str, u_int len) tty_write(tty_cmd_rawstring, &ttyctx); } + +/* Write unmodified SIXEL data. */ +void +screen_write_rawsixel(struct screen_write_ctx *ctx, u_char *str, u_int len, + int more) +{ + struct tty_ctx ttyctx; + + screen_write_initctx(ctx, &ttyctx); + ttyctx.ptr = str; + ttyctx.num = len; + ttyctx.more = more; + + tty_write(tty_cmd_rawsixel, &ttyctx); +} diff --git a/tmux.1 b/tmux.1 index 9513bd79..aac4625c 100644 --- a/tmux.1 +++ b/tmux.1 @@ -5200,6 +5200,8 @@ $ printf '\e033[4 q' If .Em Se is not set, \&Ss with argument 0 will be used to reset the cursor style instead. +.It Em \&Sxl +Indicates that the terminal supports SIXEL. .It Em \&Tc Indicate that the terminal supports the .Ql direct colour diff --git a/tmux.h b/tmux.h index b7220b88..7c901b9d 100644 --- a/tmux.h +++ b/tmux.h @@ -446,6 +446,7 @@ enum tty_code_code { TTYC_SMULX, TTYC_SMUL, TTYC_SMXX, + TTYC_SXL, TTYC_SS, TTYC_TC, TTYC_TSL, @@ -1145,6 +1146,7 @@ struct tty_term { #define TERM_256COLOURS 0x1 #define TERM_EARLYWRAP 0x2 +#define TERM_SIXEL 0x4 int flags; LIST_ENTRY(tty_term) entry; @@ -1248,6 +1250,7 @@ struct tty_ctx { u_int num; void *ptr; + int more; /* * Cursor and region position before the screen was updated - this is @@ -1947,7 +1950,7 @@ void tty_draw_line(struct tty *, struct window_pane *, struct screen *, int tty_open(struct tty *, char **); void tty_close(struct tty *); void tty_free(struct tty *); -void tty_set_type(struct tty *, int); +void tty_set_type(struct tty *, int, int); void tty_write(void (*)(struct tty *, const struct tty_ctx *), struct tty_ctx *); void tty_cmd_alignmenttest(struct tty *, const struct tty_ctx *); @@ -1971,6 +1974,7 @@ void tty_cmd_scrolldown(struct tty *, const struct tty_ctx *); void tty_cmd_reverseindex(struct tty *, const struct tty_ctx *); void tty_cmd_setselection(struct tty *, const struct tty_ctx *); void tty_cmd_rawstring(struct tty *, const struct tty_ctx *); +void tty_cmd_rawsixel(struct tty *, const struct tty_ctx *); /* tty-term.c */ extern struct tty_terms tty_terms; @@ -2357,6 +2361,7 @@ 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_rawsixel(struct screen_write_ctx *, u_char *, u_int, int); /* screen-redraw.c */ void screen_redraw_screen(struct client *); diff --git a/tty-keys.c b/tty-keys.c index 6be40d0e..e644addb 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -1005,7 +1005,7 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len, u_int i, n = 0; char tmp[64], *endptr, p[32] = { 0 }, *cp, *next; static const char *types[] = TTY_TYPES; - int type; + int type, flags = 0; *size = 0; @@ -1068,9 +1068,12 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len, type = TTY_VT520; break; } - for (i = 2; i < n; i++) + for (i = 2; i < n; i++) { log_debug("%s: DA feature: %d", c->name, p[i]); - tty_set_type(tty, type); + if (p[i] == 4) + flags |= TERM_SIXEL; + } + tty_set_type(tty, type, flags); log_debug("%s: received DA %.*s (%s)", c->name, (int)*size, buf, types[type]); diff --git a/tty-term.c b/tty-term.c index 3ac9bc6c..ce3d690a 100644 --- a/tty-term.c +++ b/tty-term.c @@ -252,6 +252,7 @@ static const struct tty_term_code_entry tty_term_codes[] = { [TTYC_SETRGBF] = { TTYCODE_STRING, "setrgbf" }, [TTYC_SETULC] = { TTYCODE_STRING, "Setulc" }, [TTYC_SE] = { TTYCODE_STRING, "Se" }, + [TTYC_SXL] = { TTYCODE_FLAG, "Sxl" }, [TTYC_SGR0] = { TTYCODE_STRING, "sgr0" }, [TTYC_SITM] = { TTYCODE_STRING, "sitm" }, [TTYC_SMACS] = { TTYCODE_STRING, "smacs" }, diff --git a/tty.c b/tty.c index 594f02fa..cae2fd24 100644 --- a/tty.c +++ b/tty.c @@ -436,9 +436,10 @@ tty_free(struct tty *tty) } void -tty_set_type(struct tty *tty, int type) +tty_set_type(struct tty *tty, int type, int flags) { tty->term_type = type; + tty->term_flags |= flags; if (tty_use_margin(tty)) tty_puts(tty, "\033[?69h"); /* DECLRMM */ @@ -1865,6 +1866,18 @@ tty_cmd_rawstring(struct tty *tty, const struct tty_ctx *ctx) tty_invalidate(tty); } +void +tty_cmd_rawsixel(struct tty *tty, const struct tty_ctx *ctx) +{ + int flags = (tty->term->flags|tty->term_flags); + + if ((flags & TERM_SIXEL) || tty_term_has(tty->term, TTYC_SXL)) { + tty_add(tty, ctx->ptr, ctx->num); + if (!ctx->more) + tty_invalidate(tty); + } +} + static void tty_cell(struct tty *tty, const struct grid_cell *gc, struct window_pane *wp) {