Add argument to refresh-client -l to forward clipboard to a pane. GitHub
authornicm <nicm@openbsd.org>
Tue, 8 Mar 2022 12:01:19 +0000 (12:01 +0000)
committernicm <nicm@openbsd.org>
Tue, 8 Mar 2022 12:01:19 +0000 (12:01 +0000)
issue 3068.

usr.bin/tmux/cmd-refresh-client.c
usr.bin/tmux/input.c
usr.bin/tmux/server-client.c
usr.bin/tmux/tmux.1
usr.bin/tmux/tmux.h
usr.bin/tmux/tty-keys.c
usr.bin/tmux/tty.c

index 696d571..eb7db1e 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-refresh-client.c,v 1.46 2022/02/15 13:03:02 nicm Exp $ */
+/* $OpenBSD: cmd-refresh-client.c,v 1.47 2022/03/08 12:01:19 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -34,7 +34,7 @@ const struct cmd_entry cmd_refresh_client_entry = {
        .name = "refresh-client",
        .alias = "refresh",
 
-       .args = { "A:B:cC:Df:F:lLRSt:U", 0, 1, NULL },
+       .args = { "A:B:cC:Df:F:l::LRSt:U", 0, 1, NULL },
        .usage = "[-cDlLRSU] [-A pane:state] [-B name:what:format] "
                 "[-C XxY] [-f flags] " CMD_TARGET_CLIENT_USAGE " [adjustment]",
 
@@ -162,6 +162,37 @@ out:
        free(copy);
 }
 
+static enum cmd_retval
+cmd_refresh_client_clipboard(struct cmd *self, struct cmdq_item *item)
+{
+       struct args             *args = cmd_get_args(self);
+       struct client           *tc = cmdq_get_target_client(item);
+       const char              *p;
+       u_int                    i;
+       struct cmd_find_state    fs;
+
+       p = args_get(args, 'l');
+       if (p == NULL) {
+               if (tc->flags & CLIENT_CLIPBOARDBUFFER)
+                       return (CMD_RETURN_NORMAL);
+               tc->flags |= CLIENT_CLIPBOARDBUFFER;
+       } else {
+               if (cmd_find_target(&fs, item, p, CMD_FIND_PANE, 0) != 0)
+                       return (CMD_RETURN_ERROR);
+               for (i = 0; i < tc->clipboard_npanes; i++) {
+                       if (tc->clipboard_panes[i] == fs.wp->id)
+                               break;
+               }
+               if (i != tc->clipboard_npanes)
+                       return (CMD_RETURN_NORMAL);
+               tc->clipboard_panes = xreallocarray (tc->clipboard_panes,
+                   tc->clipboard_npanes + 1, sizeof *tc->clipboard_panes);
+               tc->clipboard_panes[tc->clipboard_npanes++] = fs.wp->id;
+       }
+       tty_clipboard_query(&tc->tty);
+       return (CMD_RETURN_NORMAL);
+}
+
 static enum cmd_retval
 cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
 {
@@ -224,10 +255,8 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
                return (CMD_RETURN_NORMAL);
        }
 
-       if (args_has(args, 'l')) {
-               tty_send_osc52_query(&tc->tty);
-               return (CMD_RETURN_NORMAL);
-       }
+       if (args_has(args, 'l'))
+               return (cmd_refresh_client_clipboard(self, item));
 
        if (args_has(args, 'F')) /* -F is an alias for -f */
                server_client_set_flags(tc, args_get(args, 'F'));
index 14d8d57..86f6b60 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: input.c,v 1.199 2022/02/15 13:11:29 nicm Exp $ */
+/* $OpenBSD: input.c,v 1.200 2022/03/08 12:01:19 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -2682,8 +2682,8 @@ input_osc_52(struct input_ctx *ictx, const char *p)
 {
        struct window_pane      *wp = ictx->wp;
        char                    *end;
-       const char              *buf;
-       size_t                   len;
+       const char              *buf = NULL;
+       size_t                   len = 0;
        u_char                  *out;
        int                      outlen, state;
        struct screen_write_ctx  ctx;
@@ -2703,26 +2703,12 @@ input_osc_52(struct input_ctx *ictx, const char *p)
        log_debug("%s: %s", __func__, end);
 
        if (strcmp(end, "?") == 0) {
-               if ((pb = paste_get_top(NULL)) != NULL) {
+               if ((pb = paste_get_top(NULL)) != NULL)
                        buf = paste_buffer_data(pb, &len);
-                       outlen = 4 * ((len + 2) / 3) + 1;
-                       out = xmalloc(outlen);
-                       if ((outlen = b64_ntop(buf, len, out, outlen)) == -1) {
-                               free(out);
-                               return;
-                       }
-               } else {
-                       outlen = 0;
-                       out = NULL;
-               }
-               bufferevent_write(ictx->event, "\033]52;;", 6);
-               if (outlen != 0)
-                       bufferevent_write(ictx->event, out, outlen);
                if (ictx->input_end == INPUT_END_BEL)
-                       bufferevent_write(ictx->event, "\007", 1);
+                       input_reply_clipboard(ictx->event, buf, len, "\007");
                else
-                       bufferevent_write(ictx->event, "\033\\", 2);
-               free(out);
+                       input_reply_clipboard(ictx->event, buf, len, "\033\\");
                return;
        }
 
@@ -2780,3 +2766,26 @@ input_osc_104(struct input_ctx *ictx, const char *p)
                screen_write_fullredraw(&ictx->ctx);
        free(copy);
 }
+
+void
+input_reply_clipboard(struct bufferevent *bev, const char *buf, size_t len,
+    const char *end)
+{
+       char    *out = NULL;
+       size_t   outlen = 0;
+
+       if (buf != NULL && len != 0) {
+               outlen = 4 * ((len + 2) / 3) + 1;
+               out = xmalloc(outlen);
+               if ((outlen = b64_ntop(buf, len, out, outlen)) == -1) {
+                       free(out);
+                       return;
+               }
+       }
+
+       bufferevent_write(bev, "\033]52;;", 6);
+       if (outlen != 0)
+               bufferevent_write(bev, out, outlen);
+       bufferevent_write(bev, end, strlen(end));
+       free(out);
+}
index c6e9826..a3279a4 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: server-client.c,v 1.391 2022/02/16 18:55:05 nicm Exp $ */
+/* $OpenBSD: server-client.c,v 1.392 2022/03/08 12:01:19 nicm Exp $ */
 
 /*
  * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -425,6 +425,7 @@ server_client_lost(struct client *c)
        if (c->flags & CLIENT_TERMINAL)
                tty_free(&c->tty);
        free(c->ttyname);
+       free(c->clipboard_panes);
 
        free(c->term_name);
        free(c->term_type);
index 04f8dfe..743bd64 100644 (file)
@@ -1,4 +1,4 @@
-.\" $OpenBSD: tmux.1,v 1.880 2022/03/08 11:28:40 nicm Exp $
+.\" $OpenBSD: tmux.1,v 1.881 2022/03/08 12:01:19 nicm Exp $
 .\"
 .\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
 .\"
@@ -1338,11 +1338,12 @@ and sets an environment variable for the newly created session; it may be
 specified multiple times.
 .Tg refresh
 .It Xo Ic refresh-client
-.Op Fl cDlLRSU
+.Op Fl cDLRSU
 .Op Fl A Ar pane:state
 .Op Fl B Ar name:what:format
 .Op Fl C Ar size
 .Op Fl f Ar flags
+.Op Fl l Op Ar target-pane
 .Op Fl t Ar target-client
 .Op Ar adjustment
 .Xc
@@ -1456,7 +1457,11 @@ sets a comma-separated list of client flags, see
 .Fl l
 requests the clipboard from the client using the
 .Xr xterm 1
-escape sequence and stores it in a new paste buffer.
+escape sequence.
+If
+Ar target-pane
+is given, the clipboard is sent (in encoded form), otherwise it is stored in a
+new paste buffer.
 .Pp
 .Fl L ,
 .Fl R ,
index 22369b5..d88f9cb 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.1162 2022/03/08 11:28:40 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.1163 2022/03/08 12:01:19 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -1331,7 +1331,7 @@ LIST_HEAD(tty_terms, tty_term);
 struct tty {
        struct client   *client;
        struct event     start_timer;
-       struct event     query_timer;
+       struct event     clipboard_timer;
 
        u_int            sx;
        u_int            sy;
@@ -1764,6 +1764,7 @@ struct client {
 #define CLIENT_CONTROL_PAUSEAFTER 0x100000000ULL
 #define CLIENT_CONTROL_WAITEXIT 0x200000000ULL
 #define CLIENT_WINDOWSIZECHANGED 0x400000000ULL
+#define CLIENT_CLIPBOARDBUFFER 0x800000000ULL
 #define CLIENT_ALLREDRAWFLAGS          \
        (CLIENT_REDRAWWINDOW|           \
         CLIENT_REDRAWSTATUS|           \
@@ -1844,6 +1845,9 @@ struct client {
 
        struct client_files      files;
 
+       u_int                   *clipboard_panes;
+       u_int                    clipboard_npanes;
+
        TAILQ_ENTRY(client)      entry;
 };
 TAILQ_HEAD(clients, client);
@@ -2232,7 +2236,7 @@ void      tty_reset(struct tty *);
 void   tty_region_off(struct tty *);
 void   tty_margin_off(struct tty *);
 void   tty_cursor(struct tty *, u_int, u_int);
-void   tty_send_osc52_query(struct tty *);
+void   tty_clipboard_query(struct tty *);
 void   tty_putcode(struct tty *, enum tty_code_code);
 void   tty_putcode1(struct tty *, enum tty_code_code, int);
 void   tty_putcode2(struct tty *, enum tty_code_code, int, int);
@@ -2678,6 +2682,8 @@ void       input_parse_pane(struct window_pane *);
 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 *);
 
 /* input-key.c */
 void    input_key_build(void);
index 3fcad31..70ac1b4 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tty-keys.c,v 1.153 2022/02/16 18:55:05 nicm Exp $ */
+/* $OpenBSD: tty-keys.c,v 1.154 2022/03/08 12:01:19 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -1154,12 +1154,14 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size,
  * partial.
  */
 static int
-tty_keys_clipboard(__unused struct tty *tty, const char *buf, size_t len,
-    size_t *size)
+tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size)
 {
-       size_t   end, terminator, needed;
-       char    *copy, *out;
-       int      outlen;
+       struct client           *c = tty->client;
+       struct window_pane      *wp;
+       size_t                   end, terminator, needed;
+       char                    *copy, *out;
+       int                      outlen;
+       u_int                    i;
 
        *size = 0;
 
@@ -1221,6 +1223,7 @@ tty_keys_clipboard(__unused struct tty *tty, const char *buf, size_t len,
        if (~tty->flags & TTY_OSC52QUERY)
                return (0);
        tty->flags &= ~TTY_OSC52QUERY;
+       evtimer_del(&tty->clipboard_timer);
 
        /* It has to be a string so copy it. */
        copy = xmalloc(end + 1);
@@ -1237,9 +1240,20 @@ tty_keys_clipboard(__unused struct tty *tty, const char *buf, size_t len,
        }
        free(copy);
 
-       /* Create a new paste buffer. */
+       /* Create a new paste buffer and forward to panes. */
        log_debug("%s: %.*s", __func__, outlen, out);
-       paste_add(NULL, out, outlen);
+       if (c->flags & CLIENT_CLIPBOARDBUFFER) {
+               paste_add(NULL, out, outlen);
+               c->flags &= ~CLIENT_CLIPBOARDBUFFER;
+       }
+       for (i = 0; i < c->clipboard_npanes; i++) {
+               wp = window_pane_find_by_id(c->clipboard_panes[i]);
+               if (wp != NULL)
+                       input_reply_clipboard(wp->event, out, outlen, "\033\\");
+       }
+       free(c->clipboard_panes);
+       c->clipboard_panes = NULL;
+       c->clipboard_npanes = 0;
 
        return (0);
 }
index 253fc10..da7bd19 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tty.c,v 1.416 2022/02/15 13:03:02 nicm Exp $ */
+/* $OpenBSD: tty.c,v 1.417 2022/03/08 12:01:19 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -2921,24 +2921,29 @@ tty_default_attributes(struct tty *tty, const struct grid_cell *defaults,
 }
 
 static void
-tty_query_timer_callback(__unused int fd, __unused short events, void *data)
+tty_clipboard_query_callback(__unused int fd, __unused short events, void *data)
 {
        struct tty      *tty = data;
+       struct client   *c = tty->client;
+
+       c->flags &= ~CLIENT_CLIPBOARDBUFFER;
+       free(c->clipboard_panes);
+       c->clipboard_panes = NULL;
+       c->clipboard_npanes = 0;
 
        tty->flags &= ~TTY_OSC52QUERY;
 }
 
 void
-tty_send_osc52_query(struct tty *tty)
+tty_clipboard_query(struct tty *tty)
 {
        struct timeval   tv = { .tv_sec = TTY_QUERY_TIMEOUT };
 
        if ((~tty->flags & TTY_STARTED) || (tty->flags & TTY_OSC52QUERY))
                return;
        tty_putcode_ptr2(tty, TTYC_MS, "", "?");
-       tty->flags |= TTY_OSC52QUERY;
 
-       evtimer_set(&tty->query_timer, tty_query_timer_callback, tty);
-       evtimer_add(&tty->query_timer, &tv);
+       tty->flags |= TTY_OSC52QUERY;
+       evtimer_set(&tty->clipboard_timer, tty_clipboard_query_callback, tty);
+       evtimer_add(&tty->clipboard_timer, &tv);
 }
-