From f95d055e04f129b015a46deb702081b8b87636ca Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 30 Sep 2024 07:54:51 +0000 Subject: [PATCH 1/2] Only use default-shell for popups, return to /bin/sh for run-shell, if-shell and #() - these have been documented as using /bin/sh for a long time and scripts rely on it. Pointed out by Gregory Pakosz. --- job.c | 23 +++++++++++++++-------- popup.c | 2 +- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/job.c b/job.c index 94ae342ef..943eef2c1 100644 --- a/job.c +++ b/job.c @@ -71,9 +71,10 @@ static LIST_HEAD(joblist, job) all_jobs = LIST_HEAD_INITIALIZER(all_jobs); /* Start a job running. */ struct job * -job_run(const char *cmd, int argc, char **argv, struct environ *e, struct session *s, - const char *cwd, job_update_cb updatecb, job_complete_cb completecb, - job_free_cb freecb, void *data, int flags, int sx, int sy) +job_run(const char *cmd, int argc, char **argv, struct environ *e, + struct session *s, const char *cwd, job_update_cb updatecb, + job_complete_cb completecb, job_free_cb freecb, void *data, int flags, + int sx, int sy) { struct job *job; struct environ *env; @@ -83,6 +84,7 @@ job_run(const char *cmd, int argc, char **argv, struct environ *e, struct sessio sigset_t set, oldset; struct winsize ws; char **argvp, tty[TTY_NAME_MAX], *argv0; + struct options *oo; /* * Do not set TERM during .tmux.conf (second argument here), it is nice @@ -93,12 +95,17 @@ job_run(const char *cmd, int argc, char **argv, struct environ *e, struct sessio if (e != NULL) environ_copy(e, env); - if (s != NULL) - shell = options_get_string(s->options, "default-shell"); - else - shell = options_get_string(global_s_options, "default-shell"); - if (!checkshell(shell)) + if (~flags & JOB_DEFAULTSHELL) shell = _PATH_BSHELL; + else { + if (s != NULL) + oo = s->options; + else + oo = global_s_options; + shell = options_get_string(oo, "default-shell"); + if (!checkshell(shell)) + shell = _PATH_BSHELL; + } argv0 = shell_argv0(shell, 0); sigfillset(&set); diff --git a/popup.c b/popup.c index 6d126cf49..b753e4a18 100644 --- a/popup.c +++ b/popup.c @@ -718,7 +718,7 @@ popup_display(int flags, enum box_lines lines, struct cmdq_item *item, u_int px, pd->job = job_run(shellcmd, argc, argv, env, s, cwd, popup_job_update_cb, popup_job_complete_cb, NULL, pd, - JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE, jx, jy); + JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE|JOB_DEFAULTSHELL, jx, jy); pd->ictx = input_init(NULL, job_get_event(pd->job), &pd->palette); server_client_set_overlay(c, 0, popup_check_cb, popup_mode_cb, From 89adec0ca5f3cf7510b3854967b33b399871da7e Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 30 Sep 2024 08:10:20 +0000 Subject: [PATCH 2/2] On some Windows terminals, if TIOCWINSZ does not return xpixel and ypixel (they are zero), if this is the case then try the query escape sequences. From Dmitry Galchinsky in GitHub issue 4099. --- tmux.h | 3 +++ tty-keys.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tty.c | 11 ++++++-- 3 files changed, 91 insertions(+), 2 deletions(-) diff --git a/tmux.h b/tmux.h index 6fc3bdbb0..2414db175 100644 --- a/tmux.h +++ b/tmux.h @@ -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; @@ -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); @@ -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 *); diff --git a/tty-keys.c b/tty-keys.c index 3debeea12..3c08db116 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -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) @@ -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); diff --git a/tty.c b/tty.c index e65a33d12..f1fd47bcd 100644 --- a/tty.c +++ b/tty.c @@ -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 *); @@ -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; @@ -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);