Skip to content

Commit

Permalink
On some Windows terminals, if TIOCWINSZ does not return xpixel and
Browse files Browse the repository at this point in the history
ypixel (they are zero), if this is the case then try the query escape
sequences. From Dmitry Galchinsky in GitHub issue 4099.
  • Loading branch information
nicm committed Sep 30, 2024
1 parent f95d055 commit 89adec0
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 2 deletions.
3 changes: 3 additions & 0 deletions tmux.h
Original file line number Diff line number Diff line change
Expand Up @@ -1474,6 +1474,7 @@ struct tty {
#define TTY_HAVEXDA 0x200
#define TTY_SYNCING 0x400
#define TTY_HAVEDA2 0x800 /* Secondary DA. */
#define TTY_WINSIZEQUERY 0x1000
#define TTY_ALL_REQUEST_FLAGS \
(TTY_HAVEDA|TTY_HAVEDA2|TTY_HAVEXDA)
int flags;
Expand Down Expand Up @@ -2307,6 +2308,7 @@ typedef void (*job_free_cb) (void *);
#define JOB_NOWAIT 0x1
#define JOB_KEEPWRITE 0x2
#define JOB_PTY 0x4
#define JOB_DEFAULTSHELL 0x8
struct job *job_run(const char *, int, char **, struct environ *,
struct session *, const char *, job_update_cb,
job_complete_cb, job_free_cb, void *, int, int, int);
Expand Down Expand Up @@ -2369,6 +2371,7 @@ void tty_cell(struct tty *, const struct grid_cell *,
int tty_init(struct tty *, struct client *);
void tty_resize(struct tty *);
void tty_set_size(struct tty *, u_int, u_int, u_int, u_int);
void tty_invalidate(struct tty *);
void tty_start_tty(struct tty *);
void tty_send_requests(struct tty *);
void tty_repeat_requests(struct tty *);
Expand Down
79 changes: 79 additions & 0 deletions tty-keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,74 @@ tty_keys_next1(struct tty *tty, const char *buf, size_t len, key_code *key,
return (-1);
}

/* Process window size change escape sequences. */
static int
tty_keys_winsz(struct tty *tty, const char *buf, size_t len, size_t *size)
{
struct client *c = tty->client;
size_t end;
char tmp[64];
u_int sx, sy, xpixel, ypixel, char_x, char_y;

*size = 0;

/* If we did not request this, ignore it. */
if (!(tty->flags & TTY_WINSIZEQUERY))
return (-1);

/* First two bytes are always \033[. */
if (buf[0] != '\033')
return (-1);
if (len == 1)
return (1);
if (buf[1] != '[')
return (-1);
if (len == 2)
return (1);

/*
* 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;
if (!isdigit((u_char)buf[end]) && buf[end] != ';')
break;
}
if (end == len)
return (1);
if (end == sizeof tmp || buf[end] != 't')
return (-1);

/* Copy to the buffer. */
memcpy(tmp, buf + 2, end - 2);
tmp[end - 2] = '\0';

/* Try to parse the window size sequence. */
if (sscanf(tmp, "8;%u;%u", &sy, &sx) == 2) {
/* Window size in characters. */
tty_set_size(tty, sx, sy, tty->xpixel, tty->ypixel);

*size = end + 1;
return (0);
} else if (sscanf(tmp, "4;%u;%u", &ypixel, &xpixel) == 2) {
/* Window size in pixels. */
char_x = (xpixel && tty->sx) ? xpixel / tty->sx : 0;
char_y = (ypixel && tty->sy) ? ypixel / tty->sy : 0;
tty_set_size(tty, tty->sx, tty->sy, char_x, char_y);
tty_invalidate(tty);

tty->flags &= ~TTY_WINSIZEQUERY;
*size = end + 1;
return (0);
}

log_debug("%s: unrecognized window size sequence: %s", c->name, tmp);
return (-1);
}


/* Process at least one key in the buffer. Return 0 if no keys present. */
int
tty_keys_next(struct tty *tty)
Expand Down Expand Up @@ -754,6 +822,17 @@ tty_keys_next(struct tty *tty)
goto partial_key;
}

/* Check for window size query */
switch (tty_keys_winsz(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;
}

first_key:
/* Try to lookup complete key. */
n = tty_keys_next1(tty, buf, len, &key, &size, expired);
Expand Down
11 changes: 9 additions & 2 deletions tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ static void tty_cursor_pane(struct tty *, const struct tty_ctx *, u_int,
u_int);
static void tty_cursor_pane_unless_wrap(struct tty *,
const struct tty_ctx *, u_int, u_int);
static void tty_invalidate(struct tty *);
static void tty_colours(struct tty *, const struct grid_cell *);
static void tty_check_fg(struct tty *, struct colour_palette *,
struct grid_cell *);
Expand Down Expand Up @@ -135,6 +134,14 @@ tty_resize(struct tty *tty)
ypixel = 0;
} else
ypixel = ws.ws_ypixel / sy;

if ((xpixel == 0 || ypixel == 0) &&
tty->out != NULL &&
!(tty->flags & TTY_WINSIZEQUERY) &&
(tty->term->flags & TERM_VT100LIKE)) {
tty_puts(tty, "\033[18t\033[14t");
tty->flags |= TTY_WINSIZEQUERY;
}
} else {
sx = 80;
sy = 24;
Expand Down Expand Up @@ -2247,7 +2254,7 @@ tty_reset(struct tty *tty)
memcpy(&tty->last_cell, &grid_default_cell, sizeof tty->last_cell);
}

static void
void
tty_invalidate(struct tty *tty)
{
memcpy(&tty->cell, &grid_default_cell, sizeof tty->cell);
Expand Down

0 comments on commit 89adec0

Please sign in to comment.