mirror of
https://github.com/tmux/tmux.git
synced 2026-10-28 10:04:33 +08:00
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:
1 parent
50f751b12d
commit
f295f6a5b1
6 files changed
+113
-34
No files matched your search
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user