-/* $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>
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);
}
-/* $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>
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;
/*
-/* $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>
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 *);
/* 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);
/* 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);
}
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);
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
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);
}
* 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);
}
-/* $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>
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);
-/* $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>
struct options *options;
-#define SESSION_PASTING 0x1
-#define SESSION_ALERTED 0x2
+#define SESSION_ALERTED 0x1
int flags;
u_int attached;
/* 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. */
struct timeval creation_time;
struct timeval activity_time;
+ struct timeval last_activity_time;
struct environ *environ;
struct format_job_tree *jobs;
#define CLIENT_WINDOWSIZECHANGED 0x400000000ULL
#define CLIENT_CLIPBOARDBUFFER 0x800000000ULL
#define CLIENT_BRACKETPASTING 0x1000000000ULL
+#define CLIENT_ASSUMEPASTING 0x2000000000ULL
#define CLIENT_ALLREDRAWFLAGS \
(CLIENT_REDRAWWINDOW| \
CLIENT_REDRAWSTATUS| \
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,
-/* $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>
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);
/* 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:
-/* $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>
window_pane_reset_mode(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)
{
}
}
+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)