From 03f8690f9cbbd1814e91e80bcfb365542531240e Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 18 Feb 2026 09:10:31 +0000 Subject: [PATCH] Pass which clipboard is set through to the terminal, from Axel Lindskog in GitHub issue 4858. --- input.c | 43 +++++++++++++++++++++++-------------------- screen-write.c | 4 ++-- tmux.h | 3 ++- tty-keys.c | 12 ++++++++++-- tty.c | 4 ++-- 5 files changed, 39 insertions(+), 27 deletions(-) diff --git a/input.c b/input.c index ee92a7cf..53bcb8bd 100644 --- a/input.c +++ b/input.c @@ -1139,11 +1139,9 @@ input_get(struct input_ctx *ictx, u_int validx, int minval, int defval) static void input_send_reply(struct input_ctx *ictx, const char *reply) { - struct bufferevent *bev = ictx->event; - - if (bev != NULL) { + if (ictx->event != NULL) { log_debug("%s: %s", __func__, reply); - bufferevent_write(bev, reply, strlen(reply)); + bufferevent_write(ictx->event, reply, strlen(reply)); } } @@ -3052,8 +3050,9 @@ input_osc_133(struct input_ctx *ictx, const char *p) /* Handle OSC 52 reply. */ static void -input_osc_52_reply(struct input_ctx *ictx) +input_osc_52_reply(struct input_ctx *ictx, char clip) { + struct bufferevent *ev = ictx->event; struct paste_buffer *pb; int state; const char *buf; @@ -3067,9 +3066,9 @@ input_osc_52_reply(struct input_ctx *ictx) return; buf = paste_buffer_data(pb, &len); if (ictx->input_end == INPUT_END_BEL) - input_reply_clipboard(ictx->event, buf, len, "\007"); + input_reply_clipboard(ev, buf, len, "\007", clip); else - input_reply_clipboard(ictx->event, buf, len, "\033\\"); + input_reply_clipboard(ev, buf, len, "\033\\", clip); return; } input_add_request(ictx, INPUT_REQUEST_CLIPBOARD, ictx->input_end); @@ -3082,7 +3081,7 @@ input_osc_52_reply(struct input_ctx *ictx) */ static int input_osc_52_parse(struct input_ctx *ictx, const char *p, u_char **out, - int *outlen, char *flags) + int *outlen, char *clip) { char *end; size_t len; @@ -3100,13 +3099,13 @@ input_osc_52_parse(struct input_ctx *ictx, const char *p, u_char **out, log_debug("%s: %s", __func__, end); for (i = 0; p + i != end; i++) { - if (strchr(allow, p[i]) != NULL && strchr(flags, p[i]) == NULL) - flags[j++] = p[i]; + if (strchr(allow, p[i]) != NULL && strchr(clip, p[i]) == NULL) + clip[j++] = p[i]; } - log_debug("%s: %.*s %s", __func__, (int)(end - p - 1), p, flags); + log_debug("%s: %.*s %s", __func__, (int)(end - p - 1), p, clip); if (strcmp(end, "?") == 0) { - input_osc_52_reply(ictx); + input_osc_52_reply(ictx, *clip); return (0); } @@ -3132,9 +3131,9 @@ input_osc_52(struct input_ctx *ictx, const char *p) struct screen_write_ctx ctx; u_char *out; int outlen; - char flags[sizeof "cpqs01234567"] = ""; + char clip[sizeof "cpqs01234567"] = ""; - if (!input_osc_52_parse(ictx, p, &out, &outlen, flags)) + if (!input_osc_52_parse(ictx, p, &out, &outlen, clip)) return; if (wp == NULL) { @@ -3143,12 +3142,12 @@ input_osc_52(struct input_ctx *ictx, const char *p) free(out); return; } - tty_set_selection(&ictx->c->tty, flags, out, outlen); + tty_set_selection(&ictx->c->tty, clip, out, outlen); paste_add(NULL, out, outlen); } else { /* Normal window. */ screen_write_start_pane(&ctx, wp, NULL); - screen_write_setselection(&ctx, flags, out, outlen); + screen_write_setselection(&ctx, clip, out, outlen); screen_write_stop(&ctx); notify_pane("pane-set-clipboard", wp); paste_add(NULL, out, outlen); @@ -3196,7 +3195,7 @@ input_osc_104(struct input_ctx *ictx, const char *p) /* Send a clipboard reply. */ void input_reply_clipboard(struct bufferevent *bev, const char *buf, size_t len, - const char *end) + const char *end, char clip) { char *out = NULL; int outlen = 0; @@ -3212,7 +3211,10 @@ input_reply_clipboard(struct bufferevent *bev, const char *buf, size_t len, } } - bufferevent_write(bev, "\033]52;;", 6); + bufferevent_write(bev, "\033]52;", 5); + if (clip != 0) + bufferevent_write(bev, &clip, 1); + bufferevent_write(bev, ";", 1); if (outlen != 0) bufferevent_write(bev, out, outlen); bufferevent_write(bev, end, strlen(end)); @@ -3354,6 +3356,7 @@ static void input_request_clipboard_reply(struct input_request *ir, void *data) { struct input_ctx *ictx = ir->ictx; + struct bufferevent *ev = ictx->event; struct input_request_clipboard_data *cd = data; int state; char *copy; @@ -3368,9 +3371,9 @@ input_request_clipboard_reply(struct input_request *ir, void *data) } if (ir->idx == INPUT_END_BEL) - input_reply_clipboard(ictx->event, cd->buf, cd->len, "\007"); + input_reply_clipboard(ev, cd->buf, cd->len, "\007", cd->clip); else - input_reply_clipboard(ictx->event, cd->buf, cd->len, "\033\\"); + input_reply_clipboard(ev, cd->buf, cd->len, "\033\\", cd->clip); } /* Handle a reply to a request. */ diff --git a/screen-write.c b/screen-write.c index 0eee94bb..61b81ad3 100644 --- a/screen-write.c +++ b/screen-write.c @@ -2275,14 +2275,14 @@ screen_write_overwrite(struct screen_write_ctx *ctx, struct grid_cell *gc, /* Set external clipboard. */ void -screen_write_setselection(struct screen_write_ctx *ctx, const char *flags, +screen_write_setselection(struct screen_write_ctx *ctx, const char *clip, u_char *str, u_int len) { struct tty_ctx ttyctx; screen_write_initctx(ctx, &ttyctx, 0); ttyctx.ptr = str; - ttyctx.ptr2 = (void *)flags; + ttyctx.ptr2 = (void *)clip; ttyctx.num = len; tty_write(tty_cmd_setselection, &ttyctx); diff --git a/tmux.h b/tmux.h index 4c40cf83..2c62bd52 100644 --- a/tmux.h +++ b/tmux.h @@ -1114,6 +1114,7 @@ struct input_request_palette_data { struct input_request_clipboard_data { char *buf; size_t len; + char clip; }; /* Request sent to client on behalf of pane. */ @@ -3021,7 +3022,7 @@ void input_parse_buffer(struct window_pane *, u_char *, size_t); void input_parse_screen(struct input_ctx *, struct screen *, screen_write_init_ctx_cb, void *, u_char *, size_t); void input_reply_clipboard(struct bufferevent *, const char *, size_t, - const char *); + const char *, char); void input_set_buffer_size(size_t); void input_request_reply(struct client *, enum input_request_type, void *); void input_cancel_requests(struct client *); diff --git a/tty-keys.c b/tty-keys.c index 361de3df..7f9e8352 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -1310,7 +1310,7 @@ tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size) { struct client *c = tty->client; size_t end, terminator = 0, needed; - char *copy, *out; + char *copy, *out, clip = 0; int outlen; struct input_request_clipboard_data cd; @@ -1360,7 +1360,14 @@ tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size) /* Adjust end so that it points to the start of the terminator. */ end -= terminator - 1; - /* Get the second argument. */ + /* + * Save which clipboard was used from the second argument. If more than + * one is specified (should not happen), ignore the argument. + */ + if (end >= 2 && buf[0] != ';' && buf[1] == ';') + clip = buf[0]; + + /* Skip the second argument. */ while (end != 0 && *buf != ';') { buf++; end--; @@ -1393,6 +1400,7 @@ tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size) /* Set reply if any. */ cd.buf = out; cd.len = outlen; + cd.clip = clip; input_request_reply(c, INPUT_REQUEST_CLIPBOARD, &cd); /* Create a buffer if requested. */ diff --git a/tty.c b/tty.c index 29369598..d05d2dc2 100644 --- a/tty.c +++ b/tty.c @@ -1993,7 +1993,7 @@ tty_cmd_setselection(struct tty *tty, const struct tty_ctx *ctx) } void -tty_set_selection(struct tty *tty, const char *flags, const char *buf, +tty_set_selection(struct tty *tty, const char *clip, const char *buf, size_t len) { char *encoded; @@ -2009,7 +2009,7 @@ tty_set_selection(struct tty *tty, const char *flags, const char *buf, b64_ntop(buf, len, encoded, size); tty->flags |= TTY_NOBLOCK; - tty_putcode_ss(tty, TTYC_MS, flags, encoded); + tty_putcode_ss(tty, TTYC_MS, clip, encoded); free(encoded); }