diff --git a/tmux.h b/tmux.h index 26422b2e3..1241069ef 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.1426 2026/08/18 07:43:44 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.1427 2026/08/18 09:01:20 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -1811,8 +1811,9 @@ struct tty { #define TTY_WAITFG 0x2000 #define TTY_WAITBG 0x4000 #define TTY_BRACKETPASTE 0x8000 +#define TTY_HAVESYNC 0x10000 #define TTY_ALL_REQUEST_FLAGS \ - (TTY_HAVEDA|TTY_HAVEDA2|TTY_HAVEXDA) + (TTY_HAVEDA|TTY_HAVEDA2|TTY_HAVEXDA|TTY_HAVESYNC) int flags; struct tty_term *term; diff --git a/tty-keys.c b/tty-keys.c index 6c2289495..8462e0d9b 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty-keys.c,v 1.213 2026/08/17 14:47:41 nicm Exp $ */ +/* $OpenBSD: tty-keys.c,v 1.214 2026/08/18 09:01:20 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -59,6 +59,7 @@ static int tty_keys_device_attributes2(struct tty *, const char *, size_t, size_t *); static int tty_keys_extended_device_attributes(struct tty *, const char *, size_t, size_t *); +static int tty_keys_sync(struct tty *, const char *, size_t, size_t *); static int tty_keys_palette(struct tty *, const char *, size_t, size_t *); /* A key tree entry. */ @@ -771,6 +772,17 @@ tty_keys_next(struct tty *tty) goto partial_key; } + /* Is this a synchronized update mode response? */ + switch (tty_keys_sync(tty, buf, len, &size)) { + case 0: /* yes */ + key = KEYC_UNKNOWN; + goto complete_key; + case -1: /* no, or not valid */ + break; + case 1: /* partial */ + goto partial_key; + } + /* Is this a primary device attributes response? */ switch (tty_keys_device_attributes(tty, buf, len, &size)) { case 0: /* yes */ @@ -1521,6 +1533,54 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len, return (0); } +/* + * Handle a synchronized update mode response. Returns 0 for success, -1 for + * failure, 1 for partial. + */ +static int +tty_keys_sync(struct tty *tty, const char *buf, size_t len, size_t *size) +{ + struct client *c = tty->client; + static const char prefix[] = "\033[?2026;"; + size_t i; + int status; + + *size = 0; + if (tty->flags & TTY_HAVESYNC) + return (-1); + + /* The response is always \033[?2026;Ps$y. */ + for (i = 0; i < (sizeof prefix) - 1; i++) { + if (i == len) + return (1); + if (buf[i] != prefix[i]) + return (-1); + } + if (i == len) + return (1); + if (buf[i] < '0' || buf[i] > '4') + return (-1); + status = buf[i++] - '0'; + if (i == len) + return (1); + if (buf[i++] != '$') + return (-1); + if (i == len) + return (1); + if (buf[i++] != 'y') + return (-1); + *size = i; + + if (status == 1 || status == 2 || status == 3) { + tty_parse_client_features(c, "sync", ","); + tty_update_features(tty); + } + log_debug("%s: received DECRPM %.*s", c->name, (int)*size, buf); + tty->flags |= TTY_HAVESYNC; + + return (0); +} + /* * Handle secondary device attributes input. Returns 0 for success, -1 for * failure, 1 for partial. diff --git a/tty.c b/tty.c index e20796a23..e8a60c68d 100644 --- a/tty.c +++ b/tty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty.c,v 1.478 2026/08/17 14:47:41 nicm Exp $ */ +/* $OpenBSD: tty.c,v 1.479 2026/08/18 09:01:20 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -403,6 +403,8 @@ tty_send_requests(struct tty *tty) tty_puts(tty, "\033[>c"); if (~tty->flags & TTY_HAVEXDA) tty_puts(tty, "\033[>q"); + if (~tty->flags & TTY_HAVESYNC) + tty_puts(tty, "\033[?2026$p"); tty_puts(tty, "\033]10;?\033\\\033]11;?\033\\"); tty->flags |= (TTY_WAITBG|TTY_WAITFG); } else