summaryrefslogtreecommitdiff
path: root/usr.bin/tmux
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2024-10-01 06:15:48 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2024-10-01 06:15:48 +0000
commit6c2a6b8206877f2f701d369d7d41c80e581f12b4 (patch)
tree3e08eba40c2d6914183fac6f5b3625470cd6bb63 /usr.bin/tmux
parente7f809a1aea24e1152e5a02419b561da9c11c85f (diff)
Change pasting to bypass the output key processing entirely and write
what was originally received. Fixes problems with pasted text being interpreted as extended keys reported by Mark Kelly.
Diffstat (limited to 'usr.bin/tmux')
-rw-r--r--usr.bin/tmux/cmd-send-keys.c8
-rw-r--r--usr.bin/tmux/input-keys.c9
-rw-r--r--usr.bin/tmux/server-client.c64
-rw-r--r--usr.bin/tmux/session.c9
-rw-r--r--usr.bin/tmux/tmux.h15
-rw-r--r--usr.bin/tmux/tty-keys.c19
-rw-r--r--usr.bin/tmux/window.c36
7 files changed, 113 insertions, 47 deletions
diff --git a/usr.bin/tmux/cmd-send-keys.c b/usr.bin/tmux/cmd-send-keys.c
index b49fd82dd03..8ea5d92badb 100644
--- a/usr.bin/tmux/cmd-send-keys.c
+++ b/usr.bin/tmux/cmd-send-keys.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-send-keys.c,v 1.75 2023/01/16 11:26:14 nicm Exp $ */
+/* $OpenBSD: cmd-send-keys.c,v 1.76 2024/10/01 06:15:47 nicm Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -73,11 +73,13 @@ cmd_send_keys_inject_key(struct cmdq_item *item, struct cmdq_item *after,
if (args_has(args, 'K')) {
if (tc == NULL)
return (item);
- event = xmalloc(sizeof *event);
+ event = xcalloc(1, sizeof *event);
event->key = key|KEYC_SENT;
memset(&event->m, 0, sizeof event->m);
- if (server_client_handle_key(tc, event) == 0)
+ if (server_client_handle_key(tc, event) == 0) {
+ free(event->buf);
free(event);
+ }
return (item);
}
diff --git a/usr.bin/tmux/input-keys.c b/usr.bin/tmux/input-keys.c
index 42b5b235ee0..db37bdf171a 100644
--- a/usr.bin/tmux/input-keys.c
+++ b/usr.bin/tmux/input-keys.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: input-keys.c,v 1.98 2024/08/26 07:45:05 nicm Exp $ */
+/* $OpenBSD: input-keys.c,v 1.99 2024/10/01 06:15:47 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -499,9 +499,12 @@ input_key_vt10x(struct bufferevent *bev, key_code key)
return (0);
}
- /* Prevent TAB and RET from being swallowed by C0 remapping logic. */
+ /*
+ * Prevent TAB, CR and LF from being swallowed by the C0 remapping
+ * logic.
+ */
onlykey = key & KEYC_MASK_KEY;
- if (onlykey == '\r' || onlykey == '\t')
+ if (onlykey == '\r' || onlykey == '\n' || onlykey == '\t')
key &= ~KEYC_CTRL;
/*
diff --git a/usr.bin/tmux/server-client.c b/usr.bin/tmux/server-client.c
index b929c2002c8..6e63416e9cd 100644
--- a/usr.bin/tmux/server-client.c
+++ b/usr.bin/tmux/server-client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server-client.c,v 1.409 2024/09/16 20:28:22 nicm Exp $ */
+/* $OpenBSD: server-client.c,v 1.410 2024/10/01 06:15:47 nicm Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -46,8 +46,6 @@ static void server_client_check_modes(struct client *);
static void server_client_set_title(struct client *);
static void server_client_set_path(struct client *);
static void server_client_reset_state(struct client *);
-static int server_client_is_bracket_pasting(struct client *, key_code);
-static int server_client_assume_paste(struct session *);
static void server_client_update_latest(struct client *);
static void server_client_dispatch(struct imsg *, void *);
@@ -1801,18 +1799,18 @@ out:
/* Is this a bracket paste key? */
static int
-server_client_is_bracket_pasting(struct client *c, key_code key)
+server_client_is_bracket_paste(struct client *c, key_code key)
{
if (key == KEYC_PASTE_START) {
c->flags |= CLIENT_BRACKETPASTING;
log_debug("%s: bracket paste on", c->name);
- return (1);
+ return (0);
}
if (key == KEYC_PASTE_END) {
- c->flags &= ~CLIENT_BRACKETPASTING;
+ c->flags &= ~CLIENT_BRACKETPASTING;
log_debug("%s: bracket paste off", c->name);
- return (1);
+ return (0);
}
return !!(c->flags & CLIENT_BRACKETPASTING);
@@ -1820,25 +1818,29 @@ server_client_is_bracket_pasting(struct client *c, key_code key)
/* Is this fast enough to probably be a paste? */
static int
-server_client_assume_paste(struct session *s)
+server_client_is_assume_paste(struct client *c)
{
- struct timeval tv;
- int t;
+ struct session *s = c->session;
+ struct timeval tv;
+ int t;
+ if (c->flags & CLIENT_BRACKETPASTING)
+ return (0);
if ((t = options_get_number(s->options, "assume-paste-time")) == 0)
return (0);
- timersub(&s->activity_time, &s->last_activity_time, &tv);
+ timersub(&c->activity_time, &c->last_activity_time, &tv);
if (tv.tv_sec == 0 && tv.tv_usec < t * 1000) {
- log_debug("session %s pasting (flag %d)", s->name,
- !!(s->flags & SESSION_PASTING));
- if (s->flags & SESSION_PASTING)
+ if (c->flags & CLIENT_ASSUMEPASTING)
return (1);
- s->flags |= SESSION_PASTING;
+ c->flags |= CLIENT_ASSUMEPASTING;
+ log_debug("%s: assume paste on", c->name);
return (0);
}
- log_debug("session %s not pasting", s->name);
- s->flags &= ~SESSION_PASTING;
+ if (c->flags & CLIENT_ASSUMEPASTING) {
+ c->flags &= ~CLIENT_ASSUMEPASTING;
+ log_debug("%s: assume paste off", c->name);
+ }
return (0);
}
@@ -1891,6 +1893,8 @@ server_client_key_callback(struct cmdq_item *item, void *data)
wl = s->curw;
/* Update the activity timer. */
+ memcpy(&c->last_activity_time, &c->activity_time,
+ sizeof c->last_activity_time);
if (gettimeofday(&c->activity_time, NULL) != 0)
fatal("gettimeofday failed");
session_update_activity(s, &c->activity_time);
@@ -1928,14 +1932,16 @@ server_client_key_callback(struct cmdq_item *item, void *data)
goto forward_key;
/* Forward if bracket pasting. */
- if (server_client_is_bracket_pasting(c, key))
- goto forward_key;
+ if (server_client_is_bracket_paste (c, key))
+ goto paste_key;
/* Treat everything as a regular key when pasting is detected. */
if (!KEYC_IS_MOUSE(key) &&
+ key != KEYC_FOCUS_IN &&
+ key != KEYC_FOCUS_OUT &&
(~key & KEYC_SENT) &&
- server_client_assume_paste(s))
- goto forward_key;
+ server_client_is_assume_paste(c))
+ goto paste_key;
/*
* Work out the current key table. If the pane is in a mode, use
@@ -2104,10 +2110,20 @@ forward_key:
goto out;
if (wp != NULL)
window_pane_key(wp, c, s, wl, key, m);
+ goto out;
+
+paste_key:
+ if (c->flags & CLIENT_READONLY)
+ goto out;
+ if (event->buf != NULL)
+ window_pane_paste(wp, event->buf, event->len);
+ key = KEYC_NONE;
+ goto out;
out:
if (s != NULL && key != KEYC_FOCUS_OUT)
server_client_update_latest(c);
+ free(event->buf);
free(event);
return (CMD_RETURN_NORMAL);
}
@@ -2521,11 +2537,13 @@ server_client_click_timer(__unused int fd, __unused short events, void *data)
* Waiting for a third click that hasn't happened, so this must
* have been a double click.
*/
- event = xmalloc(sizeof *event);
+ event = xcalloc(1, sizeof *event);
event->key = KEYC_DOUBLECLICK;
memcpy(&event->m, &c->click_event, sizeof event->m);
- if (!server_client_handle_key(c, event))
+ if (!server_client_handle_key(c, event)) {
+ free(event->buf);
free(event);
+ }
}
c->flags &= ~(CLIENT_DOUBLECLICK|CLIENT_TRIPLECLICK);
}
diff --git a/usr.bin/tmux/session.c b/usr.bin/tmux/session.c
index 548d11c83ef..7777b4843af 100644
--- a/usr.bin/tmux/session.c
+++ b/usr.bin/tmux/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.96 2023/09/02 08:38:37 nicm Exp $ */
+/* $OpenBSD: session.c,v 1.97 2024/10/01 06:15:47 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -272,19 +272,16 @@ session_lock_timer(__unused int fd, __unused short events, void *arg)
void
session_update_activity(struct session *s, struct timeval *from)
{
- struct timeval *last = &s->last_activity_time;
struct timeval tv;
- memcpy(last, &s->activity_time, sizeof *last);
if (from == NULL)
gettimeofday(&s->activity_time, NULL);
else
memcpy(&s->activity_time, from, sizeof s->activity_time);
- log_debug("session $%u %s activity %lld.%06d (last %lld.%06d)", s->id,
+ log_debug("session $%u %s activity %lld.%06d", s->id,
s->name, (long long)s->activity_time.tv_sec,
- (int)s->activity_time.tv_usec, (long long)last->tv_sec,
- (int)last->tv_usec);
+ (int)s->activity_time.tv_usec);
if (evtimer_initialized(&s->lock_timer))
evtimer_del(&s->lock_timer);
diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h
index 606c23cfe0b..19b429d0f44 100644
--- a/usr.bin/tmux/tmux.h
+++ b/usr.bin/tmux/tmux.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.1229 2024/09/30 08:10:20 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.1230 2024/10/01 06:15:47 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -1311,8 +1311,7 @@ struct session {
struct options *options;
-#define SESSION_PASTING 0x1
-#define SESSION_ALERTED 0x2
+#define SESSION_ALERTED 0x1
int flags;
u_int attached;
@@ -1390,8 +1389,11 @@ struct mouse_event {
/* Key event. */
struct key_event {
- key_code key;
- struct mouse_event m;
+ key_code key;
+ struct mouse_event m;
+
+ char *buf;
+ size_t len;
};
/* Terminal definition. */
@@ -1806,6 +1808,7 @@ struct client {
struct timeval creation_time;
struct timeval activity_time;
+ struct timeval last_activity_time;
struct environ *environ;
struct format_job_tree *jobs;
@@ -1872,6 +1875,7 @@ struct client {
#define CLIENT_WINDOWSIZECHANGED 0x400000000ULL
#define CLIENT_CLIPBOARDBUFFER 0x800000000ULL
#define CLIENT_BRACKETPASTING 0x1000000000ULL
+#define CLIENT_ASSUMEPASTING 0x2000000000ULL
#define CLIENT_ALLREDRAWFLAGS \
(CLIENT_REDRAWWINDOW| \
CLIENT_REDRAWSTATUS| \
@@ -3097,6 +3101,7 @@ void window_pane_reset_mode_all(struct window_pane *);
int window_pane_key(struct window_pane *, struct client *,
struct session *, struct winlink *, key_code,
struct mouse_event *);
+void window_pane_paste(struct window_pane *, char *, size_t);
int window_pane_visible(struct window_pane *);
int window_pane_exited(struct window_pane *);
u_int window_pane_search(struct window_pane *, const char *, int,
diff --git a/usr.bin/tmux/tty-keys.c b/usr.bin/tmux/tty-keys.c
index 5109b880d02..e01f52ac53a 100644
--- a/usr.bin/tmux/tty-keys.c
+++ b/usr.bin/tmux/tty-keys.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tty-keys.c,v 1.179 2024/09/30 08:10:20 nicm Exp $ */
+/* $OpenBSD: tty-keys.c,v 1.180 2024/10/01 06:15:47 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -944,9 +944,6 @@ complete_key:
if (bspace != _POSIX_VDISABLE && (key & KEYC_MASK_KEY) == bspace)
key = (key & KEYC_MASK_MODIFIERS)|KEYC_BSPACE;
- /* Remove data from buffer. */
- evbuffer_drain(tty->in, size);
-
/* Remove key timer. */
if (event_initialized(&tty->key_timer))
evtimer_del(&tty->key_timer);
@@ -965,13 +962,23 @@ complete_key:
/* Fire the key. */
if (key != KEYC_UNKNOWN) {
- event = xmalloc(sizeof *event);
+ event = xcalloc(1, sizeof *event);
event->key = key;
memcpy(&event->m, &m, sizeof event->m);
- if (!server_client_handle_key(c, event))
+
+ event->buf = xmalloc(size);
+ event->len = size;
+ memcpy (event->buf, buf, event->len);
+
+ if (!server_client_handle_key(c, event)) {
+ free(event->buf);
free(event);
+ }
}
+ /* Remove data from buffer. */
+ evbuffer_drain(tty->in, size);
+
return (1);
discard_key:
diff --git a/usr.bin/tmux/window.c b/usr.bin/tmux/window.c
index 1a085966a34..dd2f1f8b0e6 100644
--- a/usr.bin/tmux/window.c
+++ b/usr.bin/tmux/window.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: window.c,v 1.292 2024/08/26 07:14:40 nicm Exp $ */
+/* $OpenBSD: window.c,v 1.293 2024/10/01 06:15:47 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -1155,6 +1155,24 @@ window_pane_reset_mode_all(struct window_pane *wp)
}
static void
+window_pane_copy_paste(struct window_pane *wp, char *buf, size_t len)
+{
+ struct window_pane *loop;
+
+ TAILQ_FOREACH(loop, &wp->window->panes, entry) {
+ if (loop != wp &&
+ TAILQ_EMPTY(&loop->modes) &&
+ loop->fd != -1 &&
+ (~loop->flags & PANE_INPUTOFF) &&
+ window_pane_visible(loop) &&
+ options_get_number(loop->options, "synchronize-panes")) {
+ log_debug("%s: %.*s", __func__, (int)len, buf);
+ bufferevent_write(loop->event, buf, len);
+ }
+ }
+}
+
+static void
window_pane_copy_key(struct window_pane *wp, key_code key)
{
struct window_pane *loop;
@@ -1170,6 +1188,22 @@ window_pane_copy_key(struct window_pane *wp, key_code key)
}
}
+void
+window_pane_paste(struct window_pane *wp, char *buf, size_t len)
+{
+ if (!TAILQ_EMPTY(&wp->modes))
+ return;
+
+ if (wp->fd == -1 || wp->flags & PANE_INPUTOFF)
+ return;
+
+ log_debug("%s: %.*s", __func__, (int)len, buf);
+ bufferevent_write(wp->event, buf, len);
+
+ if (options_get_number(wp->options, "synchronize-panes"))
+ window_pane_copy_paste(wp, buf, len);
+}
+
int
window_pane_key(struct window_pane *wp, struct client *c, struct session *s,
struct winlink *wl, key_code key, struct mouse_event *m)