Add refresh-client -q to query terminal size, useful for terminals which

do not respond to SIGWINCH (such as serial). GitHub issue 5766 from
Charlie Stanley.
This commit is contained in:
nicm authored and tmux update bot committed 2026-10-26 11:29:27 +00:00
1 parent 50f751b12d
commit f295f6a5b1
6 files changed
+113 -34

No files matched your search

+8 -3
View File
@@ -1,4 +1,4 @@
/* $OpenBSD: cmd-refresh-client.c,v 1.56 2026/10/09 13:12:14 nicm Exp $ */
/* $OpenBSD: cmd-refresh-client.c,v 1.57 2026/10/26 10:14:59 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -35,8 +35,8 @@ const struct cmd_entry cmd_refresh_client_entry = {
.description = "Refresh or resize a client.",
.alias = "refresh",
.args = { "A:B:cC:Df:r:F:lLRSt:U", 0, 1, NULL },
.usage = "[-cDlLRSU] [-A pane:state] [-B name:what:format] "
.args = { "A:B:cC:Df:r:F:lLqRSt:U", 0, 1, NULL },
.usage = "[-cDlLqRSU] [-A pane:state] [-B name:what:format] "
"[-C XxY] [-f flags] [-r pane:report] " CMD_TARGET_CLIENT_USAGE
" [adjustment]",
@@ -240,6 +240,11 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'q')) {
tty_size_query(&tc->tty);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'F')) /* -F is an alias for -f */
server_client_set_flags(tc, args_get(args, 'F'));
if (args_has(args, 'f'))
+32 -5
View File
@@ -1,4 +1,4 @@
/* $OpenBSD: server-client.c,v 1.527 2026/10/23 06:45:15 nicm Exp $ */
/* $OpenBSD: server-client.c,v 1.528 2026/10/26 10:14:59 nicm Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -338,6 +338,36 @@ server_client_fire_resized(struct client *c, u_int old_sx, u_int old_sy)
events_fire("client-resized", ep);
}
/* Recalculate sizes and notify a resized client. */
static void
server_client_apply_resize(struct client *c, u_int old_sx, u_int old_sy)
{
if (c->session != NULL) {
recalculate_sizes();
server_redraw_client(c);
server_client_fire_resized(c, old_sx, old_sy);
}
}
/* Apply a new reported size. */
void
server_client_size_changed(struct client *c, u_int sx, u_int sy)
{
u_int old_sx = c->tty.sx, old_sy = c->tty.sy;
if (c->flags & CLIENT_CONTROL)
return;
if (sx == 0 || sy == 0 || (sx == old_sx && sy == old_sy))
return;
log_debug("%s: reported size %ux%u (was %ux%u)", c->name, sx, sy,
old_sx, old_sy);
server_client_update_latest(c);
tty_set_size(&c->tty, sx, sy, c->tty.xpixel, c->tty.ypixel);
tty_invalidate(&c->tty);
server_client_apply_resize(c, old_sx, old_sy);
}
/* Set client session. */
void
server_client_set_session(struct client *c, struct session *s)
@@ -2699,10 +2729,7 @@ server_client_dispatch(struct imsg *imsg, void *arg)
old_sy = c->tty.sy;
tty_resize(&c->tty);
tty_repeat_requests(&c->tty, 0);
recalculate_sizes();
server_redraw_client(c);
if (c->session != NULL)
server_client_fire_resized(c, old_sx, old_sy);
server_client_apply_resize(c, old_sx, old_sy);
break;
case MSG_EXITING:
if (datalen != 0)
+6 -3
View File
@@ -1,4 +1,4 @@
.\" $OpenBSD: tmux.1,v 1.1191 2026/10/20 06:45:56 nicm Exp $
.\" $OpenBSD: tmux.1,v 1.1192 2026/10/26 10:14:59 nicm Exp $
.\"
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
.\"
@@ -14,7 +14,7 @@
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: October 20 2026 $
.Dd $Mdocdate: October 26 2026 $
.Dt TMUX 1
.Os
.Sh NAME
@@ -1448,7 +1448,7 @@ 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 cDlLqRSU
.Op Fl A Ar pane:state
.Op Fl B Ar name:what:format
.Op Fl C Ar size
@@ -1575,6 +1575,9 @@ requests the clipboard from the client using the
.Xr xterm 1
escape sequence and stores it in a new paste buffer.
.Pp
.Fl q
queries the client terminal for its size.
.Pp
.Fl L ,
.Fl R ,
.Fl U
+8 -1
View File
@@ -1,4 +1,4 @@
/* $OpenBSD: tmux.h,v 1.1470 2026/10/23 06:45:15 nicm Exp $ */
/* $OpenBSD: tmux.h,v 1.1471 2026/10/26 10:14:59 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -1759,6 +1759,9 @@ struct tty_style_ctx {
struct hyperlinks *hyperlinks;
};
/* Maximum reported terminal size. */
#define CLIENT_MAX_TERM_SIZE 10000
/* Client terminal. */
struct tty {
struct client *client;
@@ -1824,6 +1827,8 @@ struct tty {
#define TTY_BRACKETPASTE 0x8000
#define TTY_HAVESYNC 0x10000
#define TTY_HAVEKITTYGRAPHICS 0x20000
#define TTY_WINSZPIXELS 0x40000
#define TTY_WINSZAPPLY 0x80000
#define TTY_ALL_REQUEST_FLAGS \
(TTY_HAVEDA|TTY_HAVEDA2|TTY_HAVEXDA|TTY_HAVESYNC|TTY_HAVEKITTYGRAPHICS)
int flags;
@@ -2957,6 +2962,7 @@ void tty_cell(struct tty *, const struct grid_cell *,
int tty_init(struct tty *, struct client *);
void tty_resize(struct tty *);
int tty_set_size(struct tty *, u_int, u_int, u_int, u_int);
void tty_size_query(struct tty *);
void tty_invalidate(struct tty *);
void tty_start_tty(struct tty *);
void tty_send_requests(struct tty *);
@@ -3337,6 +3343,7 @@ void server_client_exec(struct client *, const char *);
void server_client_loop(void);
const char *server_client_get_cwd(struct client *, struct session *);
void server_client_set_flags(struct client *, const char *);
void server_client_size_changed(struct client *, u_int, u_int);
const char *server_client_get_flags(struct client *);
void server_client_remove_pane(struct window_pane *);
void server_client_print(struct client *, int, struct evbuffer *);
+25 -13
View File
@@ -1,4 +1,4 @@
/* $OpenBSD: tty-keys.c,v 1.221 2026/10/22 07:16:40 nicm Exp $ */
/* $OpenBSD: tty-keys.c,v 1.222 2026/10/26 10:14:59 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -937,8 +937,8 @@ partial_key:
if (delay < 500)
delay = 500;
}
if (tty->flags & (TTY_WAITFG|TTY_WAITBG) ||
tty->flags & (TTY_OSC52QUERY|TTY_WINSZQUERY) ||
if (tty->flags & (TTY_WAITFG|TTY_WAITBG|TTY_OSC52QUERY) ||
tty->flags & (TTY_WINSZQUERY|TTY_WINSZPIXELS) ||
(tty->flags & TTY_ALL_REQUEST_FLAGS) != TTY_ALL_REQUEST_FLAGS ||
!TAILQ_EMPTY(&c->input_requests)) {
log_debug("%s: increasing delay (active query)", c->name);
@@ -1875,11 +1875,12 @@ tty_keys_winsz(struct tty *tty, const char *buf, size_t len, size_t *size,
size_t end;
char tmp[64];
u_int sx, sy, xpixel, ypixel, char_x, char_y;
int resize;
*size = 0;
/* If we did not request this, ignore it. */
if (!(tty->flags & TTY_WINSZQUERY))
if (!(tty->flags & (TTY_WINSZQUERY|TTY_WINSZPIXELS)))
return (-1);
/* First two bytes are always \033[. */
@@ -1892,10 +1893,7 @@ tty_keys_winsz(struct tty *tty, const char *buf, size_t len, size_t *size,
if (len == 2)
return (1);
/*
* Stop at either 't' or anything that isn't a
* number or ';'.
*/
/* Stop at either 't' or anything that isn't a number or ';'. */
for (end = 2; end < len && end != sizeof tmp; end++) {
if (buf[end] == 't')
break;
@@ -1913,28 +1911,42 @@ tty_keys_winsz(struct tty *tty, const char *buf, size_t len, size_t *size,
/* Try to parse the window size sequence. */
if (sscanf(tmp, "8;%u;%u", &sy, &sx) == 2) {
if (!(tty->flags & TTY_WINSZQUERY))
return (-1);
*size = end + 1;
if (!apply)
return (0);
/* Window size in characters. */
if (tty_set_size(tty, sx, sy, tty->xpixel, tty->ypixel))
resize = (tty->flags & TTY_WINSZAPPLY);
tty->flags &= ~(TTY_WINSZQUERY|TTY_WINSZAPPLY);
if (sx == 0 ||
sy == 0 ||
sx > CLIENT_MAX_TERM_SIZE ||
sy > CLIENT_MAX_TERM_SIZE) {
log_debug("%s: ignoring reported size %ux%u",
c->name, sx, sy);
return (0);
}
if (resize)
server_client_size_changed(c, sx, sy);
else if (tty_set_size(tty, sx, sy, tty->xpixel, tty->ypixel))
server_redraw_client(c);
return (0);
} else if (sscanf(tmp, "4;%u;%u", &ypixel, &xpixel) == 2) {
if (!(tty->flags & TTY_WINSZPIXELS))
return (-1);
*size = end + 1;
if (!apply)
return (0);
tty->flags &= ~TTY_WINSZPIXELS;
/* Window size in pixels. */
char_x = (xpixel && tty->sx) ? xpixel / tty->sx : 0;
char_y = (ypixel && tty->sy) ? ypixel / tty->sy : 0;
if (tty_set_size(tty, tty->sx, tty->sy, char_x, char_y))
server_redraw_client(c);
tty_invalidate(tty);
recalculate_sizes();
tty->flags &= ~TTY_WINSZQUERY;
return (0);
}
+34 -9
View File
@@ -1,4 +1,4 @@
/* $OpenBSD: tty.c,v 1.496 2026/10/22 07:16:40 nicm Exp $ */
/* $OpenBSD: tty.c,v 1.497 2026/10/26 10:14:59 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -38,6 +38,7 @@ static int tty_log_fd = -1;
static void tty_start_timer_callback(int, short, void *);
static void tty_start_start_timer(struct tty *);
static void tty_clipboard_query_callback(int, short, void *);
static void tty_send_size_query(struct tty *, int);
static void tty_set_italics(struct tty *);
static int tty_try_colour(struct tty *, int, const char *);
static void tty_force_cursor_colour(struct tty *, int);
@@ -116,6 +117,16 @@ tty_init(struct tty *tty, struct client *c)
return (0);
}
static void
tty_send_size_query(struct tty *tty, int apply)
{
tty_puts(tty, "\033[18t\033[14t");
tty->flags |= (TTY_WINSZQUERY|TTY_WINSZPIXELS);
if (apply)
tty->flags |= TTY_WINSZAPPLY;
tty_start_start_timer(tty);
}
void
tty_resize(struct tty *tty)
{
@@ -139,12 +150,9 @@ tty_resize(struct tty *tty)
if ((xpixel == 0 || ypixel == 0) &&
(tty->flags & TTY_STARTED) &&
!(tty->flags & TTY_WINSZQUERY) &&
(tty->term->flags & TERM_VT100LIKE)) {
tty_puts(tty, "\033[18t\033[14t");
tty->flags |= TTY_WINSZQUERY;
tty_start_start_timer(tty);
}
!(tty->flags & (TTY_WINSZQUERY|TTY_WINSZPIXELS)) &&
(tty->term->flags & TERM_VT100LIKE))
tty_send_size_query(tty, 0);
} else {
sx = 80;
sy = 24;
@@ -322,7 +330,11 @@ tty_start_timer_callback(__unused int fd, __unused short events, void *data)
tty_update_features(tty);
tty->flags |= TTY_ALL_REQUEST_FLAGS;
tty->flags &= ~(TTY_WAITBG|TTY_WAITFG|TTY_WINSZQUERY);
if (tty->flags & TTY_WINSZQUERY)
log_debug("%s: size query timed out", c->name);
tty->flags &= ~(TTY_WAITBG|TTY_WAITFG);
tty->flags &= ~(TTY_WINSZQUERY|TTY_WINSZPIXELS|TTY_WINSZAPPLY);
}
static void
@@ -470,7 +482,7 @@ tty_stop_tty(struct tty *tty)
evtimer_del(&tty->start_timer);
evtimer_del(&tty->clipboard_timer);
tty->flags &= ~TTY_WINSZQUERY;
tty->flags &= ~(TTY_WINSZQUERY|TTY_WINSZPIXELS|TTY_WINSZAPPLY);
event_del(&tty->timer);
tty->flags &= ~TTY_BLOCK;
@@ -2990,6 +3002,19 @@ tty_clipboard_query(struct tty *tty)
}
}
void
tty_size_query(struct tty *tty)
{
if (!(tty->flags & TTY_STARTED) ||
tty->out == NULL ||
tty->client->flags & CLIENT_CONTROL ||
!(tty->term->flags & TERM_VT100LIKE) ||
tty->flags & (TTY_WINSZQUERY|TTY_WINSZPIXELS))
return;
log_debug("%s: querying terminal size", tty->client->name);
tty_send_size_query(tty, 1);
}
void
tty_set_progress_bar(struct tty *tty, struct progress_bar *pb)
{