From cbd419c4832975e3c8a83e9ead22d67f528bbc2b Mon Sep 17 00:00:00 2001 From: nicm Date: Sun, 29 Sep 2024 20:05:42 +0000 Subject: [PATCH 01/19] Fix grey colour, from Magnus Gross. --- colour.c | 2 +- tmux.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/colour.c b/colour.c index 0b787acb..5fd91c9c 100644 --- a/colour.c +++ b/colour.c @@ -948,7 +948,7 @@ colour_byname(const char *name) if (strncmp(name, "grey", 4) == 0 || strncmp(name, "gray", 4) == 0) { if (name[4] == '\0') - return (-1); + return (0xbebebe|COLOUR_FLAG_RGB); c = strtonum(name + 4, 0, 100, &errstr); if (errstr != NULL) return (-1); diff --git a/tmux.c b/tmux.c index a9619baf..30960245 100644 --- a/tmux.c +++ b/tmux.c @@ -408,9 +408,9 @@ main(int argc, char **argv) cfg_files[cfg_nfiles++] = xstrdup(optarg); cfg_quiet = 0; break; - case 'V': + case 'V': printf("tmux %s\n", getversion()); - exit(0); + exit(0); case 'l': flags |= CLIENT_LOGIN; break; From a1b7a3bcb32066a36367fbcd4ebbfedbd6ad8ec1 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 30 Sep 2024 07:54:51 +0000 Subject: [PATCH 02/19] 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 cab91d2c..eeb90f42 100644 --- a/job.c +++ b/job.c @@ -69,9 +69,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; @@ -81,6 +82,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 @@ -91,12 +93,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 706295fe..97f532c0 100644 --- a/popup.c +++ b/popup.c @@ -717,7 +717,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 868ddf5d38584c3d67ae32a23aeafc415d3d287f Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Mon, 30 Sep 2024 13:09:50 +0100 Subject: [PATCH 03/19] 3.5a bits. --- CHANGES | 7 +++++++ configure.ac | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index d88d4024..6185ddc6 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,10 @@ +CHANGES FROM 3.5 TO 3.5a + +* Revert to using /bin/sh for #() and run-shell and if-shell; the change to use + default-shell only applies now to popups. + +* Fix grey colour without a number suffix in styles. + CHANGES FROM 3.4 TO 3.5 * Revamp extended keys support to more closely match xterm and support mode 2 diff --git a/configure.ac b/configure.ac index 2a834037..97e5ca50 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ # configure.ac -AC_INIT([tmux], 3.5) +AC_INIT([tmux], 3.5a) AC_PREREQ([2.60]) AC_CONFIG_AUX_DIR(etc) From 834ec91b445721211d3eb3e21b780607b78453a8 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 2 Oct 2024 08:06:45 +0000 Subject: [PATCH 04/19] Report shifted keys like S-A as A not as S-A in mode 1 extended keys, from Stanislav Kljuhhin. --- input-keys.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/input-keys.c b/input-keys.c index 4dd42e1b..05971dae 100644 --- a/input-keys.c +++ b/input-keys.c @@ -553,6 +553,10 @@ input_key_mode1(struct bufferevent *bev, key_code key) (onlykey >= '@' && onlykey <= '~'))) return (input_key_vt10x(bev, key)); + /* Avoid reporting A as Shift-A, which is not expected in mode 1. */ + if ((key & KEYC_MASK_MODIFIERS) == KEYC_SHIFT) + return (input_key_vt10x(bev, key)); + /* * A regular key + Meta. In the absence of a standard to back this, we * mimic what iTerm 2 does. From 356887bca27b48e895eca261e0989319f432de73 Mon Sep 17 00:00:00 2001 From: nicm Date: Thu, 3 Oct 2024 05:41:59 +0000 Subject: [PATCH 05/19] Improve fix for shifted keys so it works for all the keys it should, Stanislav Kljuhhin in GitHub issue 4146. --- input-keys.c | 4 ---- tty-keys.c | 30 ++++++++++++++++++++++-------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/input-keys.c b/input-keys.c index 05971dae..4dd42e1b 100644 --- a/input-keys.c +++ b/input-keys.c @@ -553,10 +553,6 @@ input_key_mode1(struct bufferevent *bev, key_code key) (onlykey >= '@' && onlykey <= '~'))) return (input_key_vt10x(bev, key)); - /* Avoid reporting A as Shift-A, which is not expected in mode 1. */ - if ((key & KEYC_MASK_MODIFIERS) == KEYC_SHIFT) - return (input_key_vt10x(bev, key)); - /* * A regular key + Meta. In the absence of a standard to back this, we * mimic what iTerm 2 does. diff --git a/tty-keys.c b/tty-keys.c index 3debeea1..76e26a8b 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -930,7 +930,7 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len, u_int number, modifiers; char tmp[64]; cc_t bspace; - key_code nkey; + key_code nkey, onlykey; struct utf8_data ud; utf8_char uc; @@ -994,13 +994,7 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len, /* Update the modifiers. */ if (modifiers > 0) { modifiers--; - /* - * The Shift modifier may not be reported in some input modes, - * which is unfortunate, as in general case determining if a - * character is shifted or not requires knowing the input - * keyboard layout. So we only fix up the trivial case. - */ - if (modifiers & 1 || (nkey >= 'A' && nkey <= 'Z')) + if (modifiers & 1) nkey |= KEYC_SHIFT; if (modifiers & 2) nkey |= (KEYC_META|KEYC_IMPLIED_META); /* Alt */ @@ -1014,6 +1008,26 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len, if ((nkey & KEYC_MASK_KEY) == '\011' && (nkey & KEYC_SHIFT)) nkey = KEYC_BTAB | (nkey & ~KEYC_MASK_KEY & ~KEYC_SHIFT); + /* + * Deal with the Shift modifier when present alone. The problem is that + * in mode 2 some terminals would report shifted keys, like S-a, as + * just A, and some as S-A. + * + * Because we need an unambiguous internal representation, and because + * restoring the Shift modifier when it's missing would require knowing + * the keyboard layout, and because S-A would cause a lot of issues + * downstream, we choose to lose the Shift for all printable + * characters. + * + * That still leaves some ambiguity, such as C-S-A vs. C-A, but that's + * OK, and applications can handle that. + */ + onlykey = nkey & KEYC_MASK_KEY; + if (((onlykey > 0x20 && onlykey < 0x7f) || + KEYC_IS_UNICODE(nkey)) && + (nkey & KEYC_MASK_MODIFIERS) == KEYC_SHIFT) + nkey &= ~KEYC_SHIFT; + if (log_get_level() != 0) { log_debug("%s: extended key %.*s is %llx (%s)", c->name, (int)*size, buf, nkey, key_string_lookup_key(nkey, 1)); From 048db82041a9866e52306ea88169b8e5352ef386 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 4 Oct 2024 14:55:17 +0000 Subject: [PATCH 06/19] Do not translate BSpace as Unicode, GitHub issue 4156. --- tty-keys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tty-keys.c b/tty-keys.c index 76e26a8b..5416c78b 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -983,7 +983,7 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len, nkey = number; /* Convert UTF-32 codepoint into internal representation. */ - if (nkey & ~0x7f) { + if (nkey != KEYC_BSPACE && nkey & ~0x7f) { if (utf8_fromwc(nkey, &ud) == UTF8_DONE && utf8_from_data(&ud, &uc) == UTF8_DONE) nkey = uc; From 7997fd315279a15e86cc1ee2649e74603007bb1b Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Fri, 4 Oct 2024 18:59:53 +0100 Subject: [PATCH 07/19] Missing define. --- tmux.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tmux.h b/tmux.h index 0b14ccd0..071d9d29 100644 --- a/tmux.h +++ b/tmux.h @@ -2341,6 +2341,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); From 42959db0a487ee655f53eaaf9d5d9920fca5a9e1 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Sat, 5 Oct 2024 07:00:22 +0100 Subject: [PATCH 08/19] Update CHANGES. --- CHANGES | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES b/CHANGES index 6185ddc6..344a1ccc 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,9 @@ CHANGES FROM 3.5 TO 3.5a +* Do not translate BSpace as Unicode with extended keys. + +* Fix so that keys with Shift are represented correctly with extended keys. + * Revert to using /bin/sh for #() and run-shell and if-shell; the change to use default-shell only applies now to popups. From 549c35b06165f6ae023115eb76f83f2cbf945395 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Sat, 5 Oct 2024 07:01:16 +0100 Subject: [PATCH 09/19] Update regression tests. --- regress/capture-pane-sgr0.sh | 4 +-- regress/combine-test.result | 2 +- regress/format-strings.sh | 2 +- regress/input-keys.sh | 23 +++++++------ regress/tty-keys.sh | 62 ++++++++++++++++++------------------ 5 files changed, 48 insertions(+), 45 deletions(-) diff --git a/regress/capture-pane-sgr0.sh b/regress/capture-pane-sgr0.sh index 6a19ac8a..5d21ccc4 100644 --- a/regress/capture-pane-sgr0.sh +++ b/regress/capture-pane-sgr0.sh @@ -22,8 +22,8 @@ $TMUX -f/dev/null new -d " sleep 1 ( - printf '\033[1m\033[31m\033[42mabc\033[0m\033[31m\033[49mdef\n' - printf '\033[39m\033[100m bright bg\n' + printf '\033[1m\033[31m\033[42mabc\033[0m\033[31mdef\033[39m\n' + printf '\033[100m bright bg \033[49m\n' ) | cmp - $TMP || exit 1 $TMUX has 2>/dev/null && exit 1 diff --git a/regress/combine-test.result b/regress/combine-test.result index 8fb411ba..0d2afb5e 100644 --- a/regress/combine-test.result +++ b/regress/combine-test.result @@ -6,7 +6,7 @@ 👍🏻3 👍🏻 👍🏻4 🤷‍♂️5 -♂️ 7 +♂️7 🤷‍♂️8 🤷‍♂️9 🤷‍♂️10 diff --git a/regress/format-strings.sh b/regress/format-strings.sh index 0ae27386..bc4b00f7 100644 --- a/regress/format-strings.sh +++ b/regress/format-strings.sh @@ -172,7 +172,7 @@ test_format "#{l:#{pane_in_mode}}" "#{pane_in_mode}" test_format "#{l:#{?pane_in_mode,#{?#{==:#{session_name},Summer},ABC,XYZ},xyz}}" "#{?pane_in_mode,#{?#{==:#{session_name},Summer},ABC,XYZ},xyz}" # With escapes (which escape but are returned literally) -test_format "#{l:##{}" "##{" +test_format "#{l:##{}" "#{" test_format "#{l:#{#}}}" "#{#}}" # Invalid formats: diff --git a/regress/input-keys.sh b/regress/input-keys.sh index 262d12a6..d3b90995 100644 --- a/regress/input-keys.sh +++ b/regress/input-keys.sh @@ -6,10 +6,10 @@ TERM=screen [ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux) TMUX="$TEST_TMUX -Ltest" $TMUX kill-server 2>/dev/null - +sleep 1 $TMUX -f/dev/null new -x20 -y2 -d || exit 1 - -sleep 0.1 +sleep 1 +$TMUX set -g escape-time 0 exit_status=0 @@ -17,11 +17,14 @@ assert_key () { key=$1 expected_code=$2 - $TMUX new-window -- sh -c 'stty raw -echo && cat -tv' - $TMUX send-keys "$key" $ + W=$($TMUX new-window -P -- sh -c 'stty raw -echo && cat -tv') + $TMUX send-keys -t$W "$key" 'EOL' || exit 1 + sleep 0.2 - actual_code=$($TMUX capturep -p | head -1 | sed -e 's/\$$//') - $TMUX kill-window + actual_code=$($TMUX capturep -pt$W | \ + head -1 | \ + sed -e 's/EOL.*$//') + $TMUX kill-window -t$W || exit 1 if [ "$actual_code" = "$expected_code" ]; then if [ -n "$VERBOSE" ]; then @@ -205,7 +208,7 @@ assert_key 'PageUp' '^[[5~' assert_key 'PgUp' '^[[5~' assert_key 'BTab' '^[[Z' -assert_key 'C-S-Tab' '^[[Z' +assert_key 'C-S-Tab' '^I' assert_key 'Up' '^[[A' assert_key 'Down' '^[[B' @@ -291,8 +294,8 @@ assert_extended_key 'Insert' '^[[2;_~' assert_extended_key 'DC' '^[[3;_~' assert_extended_key 'Delete' '^[[3;_~' -assert_key 'C-Tab' "^[[9;5u" -assert_key 'C-S-Tab' "^[[1;5Z" +assert_key 'C-Tab' "^[[27;5;9~" +assert_key 'C-S-Tab' "^[[27;6;9~" $TMUX kill-server 2>/dev/null diff --git a/regress/tty-keys.sh b/regress/tty-keys.sh index 1fcc3657..0a1fe6bf 100644 --- a/regress/tty-keys.sh +++ b/regress/tty-keys.sh @@ -14,7 +14,7 @@ trap "rm -f $TMP" 0 1 15 $TMUX2 -f/dev/null new -d || exit 1 $TMUX -f/dev/null new -d "$TMUX2 attach" || exit 1 -sleep 0.1 +sleep 1 exit_status=0 @@ -60,38 +60,38 @@ assert_key () { } -assert_key 0x00 'C-Space' # -- 'Escape 0x00' 'M-C-Space' -assert_key 0x01 'C-a' -- 'Escape 0x01' 'M-C-a' -assert_key 0x02 'C-b' -- 'Escape 0x02' 'M-C-b' -assert_key 0x03 'C-c' -- 'Escape 0x03' 'M-C-c' -assert_key 0x04 'C-d' -- 'Escape 0x04' 'M-C-d' -assert_key 0x05 'C-e' -- 'Escape 0x05' 'M-C-e' -assert_key 0x06 'C-f' -- 'Escape 0x06' 'M-C-f' -assert_key 0x07 'C-g' -- 'Escape 0x07' 'M-C-g' -assert_key 0x08 'C-h' -- 'Escape 0x08' 'M-C-h' +assert_key 0x00 'C-Space' # -- 'Escape 0x00' 'C-M-Space' +assert_key 0x01 'C-a' -- 'Escape 0x01' 'C-M-a' +assert_key 0x02 'C-b' -- 'Escape 0x02' 'C-M-b' +assert_key 0x03 'C-c' -- 'Escape 0x03' 'C-M-c' +assert_key 0x04 'C-d' -- 'Escape 0x04' 'C-M-d' +assert_key 0x05 'C-e' -- 'Escape 0x05' 'C-M-e' +assert_key 0x06 'C-f' -- 'Escape 0x06' 'C-M-f' +assert_key 0x07 'C-g' -- 'Escape 0x07' 'C-M-g' +assert_key 0x08 'C-h' -- 'Escape 0x08' 'C-M-h' assert_key 0x09 'Tab' -- 'Escape 0x09' 'M-Tab' -assert_key 0x0A 'C-j' -- 'Escape 0x0A' 'M-C-j' -assert_key 0x0B 'C-k' -- 'Escape 0x0B' 'M-C-k' -assert_key 0x0C 'C-l' -- 'Escape 0x0C' 'M-C-l' +assert_key 0x0A 'C-j' -- 'Escape 0x0A' 'C-M-j' +assert_key 0x0B 'C-k' -- 'Escape 0x0B' 'C-M-k' +assert_key 0x0C 'C-l' -- 'Escape 0x0C' 'C-M-l' assert_key 0x0D 'Enter' -- 'Escape 0x0D' 'M-Enter' -assert_key 0x0E 'C-n' -- 'Escape 0x0E' 'M-C-n' -assert_key 0x0F 'C-o' -- 'Escape 0x0F' 'M-C-o' -assert_key 0x10 'C-p' -- 'Escape 0x10' 'M-C-p' -assert_key 0x11 'C-q' -- 'Escape 0x11' 'M-C-q' -assert_key 0x12 'C-r' -- 'Escape 0x12' 'M-C-r' -assert_key 0x13 'C-s' -- 'Escape 0x13' 'M-C-s' -assert_key 0x14 'C-t' -- 'Escape 0x14' 'M-C-t' -assert_key 0x15 'C-u' -- 'Escape 0x15' 'M-C-u' -assert_key 0x16 'C-v' -- 'Escape 0x16' 'M-C-v' -assert_key 0x17 'C-w' -- 'Escape 0x17' 'M-C-w' -assert_key 0x18 'C-x' -- 'Escape 0x18' 'M-C-x' -assert_key 0x19 'C-y' -- 'Escape 0x19' 'M-C-y' -assert_key 0x1A 'C-z' -- 'Escape 0x1A' 'M-C-z' +assert_key 0x0E 'C-n' -- 'Escape 0x0E' 'C-M-n' +assert_key 0x0F 'C-o' -- 'Escape 0x0F' 'C-M-o' +assert_key 0x10 'C-p' -- 'Escape 0x10' 'C-M-p' +assert_key 0x11 'C-q' -- 'Escape 0x11' 'C-M-q' +assert_key 0x12 'C-r' -- 'Escape 0x12' 'C-M-r' +assert_key 0x13 'C-s' -- 'Escape 0x13' 'C-M-s' +assert_key 0x14 'C-t' -- 'Escape 0x14' 'C-M-t' +assert_key 0x15 'C-u' -- 'Escape 0x15' 'C-M-u' +assert_key 0x16 'C-v' -- 'Escape 0x16' 'C-M-v' +assert_key 0x17 'C-w' -- 'Escape 0x17' 'C-M-w' +assert_key 0x18 'C-x' -- 'Escape 0x18' 'C-M-x' +assert_key 0x19 'C-y' -- 'Escape 0x19' 'C-M-y' +assert_key 0x1A 'C-z' -- 'Escape 0x1A' 'C-M-z' assert_key 0x1B 'Escape' -- 'Escape 0x1B' 'M-Escape' -assert_key 0x1C "C-\\" -- 'Escape 0x1C' "M-C-\\" -assert_key 0x1D 'C-]' -- 'Escape 0x1D' 'M-C-]' -assert_key 0x1E 'C-^' -- 'Escape 0x1E' 'M-C-^' -assert_key 0x1F 'C-_' -- 'Escape 0x1F' 'M-C-_' +assert_key 0x1C "C-\\" -- 'Escape 0x1C' "C-M-\\" +assert_key 0x1D 'C-]' -- 'Escape 0x1D' 'C-M-]' +assert_key 0x1E 'C-^' -- 'Escape 0x1E' 'C-M-^' +assert_key 0x1F 'C-_' -- 'Escape 0x1F' 'C-M-_' assert_key 0x20 'Space' -- 'Escape 0x20' 'M-Space' assert_key 0x21 '!' -- 'Escape 0x21' 'M-!' assert_key 0x22 '"' -- 'Escape 0x22' 'M-"' @@ -304,7 +304,7 @@ assert_extended_key () { key_name=$2 assert_key "Escape [${code};5u" "C-$key_name" - assert_key "Escape [${code};7u" "M-C-$key_name" + assert_key "Escape [${code};7u" "C-M-$key_name" } # Extended keys From 1d89233047c68e5f16f302416436fbf478f9f8b2 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 25 Nov 2025 20:27:23 +0000 Subject: [PATCH 10/19] Add a resize callback for menus so that they are correctly moved on resize. From m-einfalt at gmx dot de in GitHub issue 4696. --- menu.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/menu.c b/menu.c index fd3a9fe4..7449d88d 100644 --- a/menu.c +++ b/menu.c @@ -438,6 +438,38 @@ chosen: return (1); } +static void +menu_resize_cb(struct client *c, void *data) +{ + struct menu_data *md = data; + u_int nx, ny, w, h; + + if (md == NULL) + return; + + nx = md->px; + ny = md->py; + + w = md->menu->width + 4; + h = md->menu->count + 2; + + if (nx + w > c->tty.sx) { + if (c->tty.sx <= w) + nx = 0; + else + nx = c->tty.sx - w; + } + + if (ny + h > c->tty.sy) { + if (c->tty.sy <= h) + ny = 0; + else + ny = c->tty.sy - h; + } + md->px = nx; + md->py = ny; +} + static void menu_set_style(struct client *c, struct grid_cell *gc, const char *style, const char *option) @@ -551,6 +583,6 @@ menu_display(struct menu *menu, int flags, int starting_choice, if (md == NULL) return (-1); server_client_set_overlay(c, 0, NULL, menu_mode_cb, menu_draw_cb, - menu_key_cb, menu_free_cb, NULL, md); + menu_key_cb, menu_free_cb, menu_resize_cb, md); return (0); } From ca74fa1db0d631dcdcf8741f7fb6b470a1130750 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Tue, 25 Nov 2025 21:21:59 +0000 Subject: [PATCH 11/19] Update version and CHANGES. --- CHANGES | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++- configure.ac | 2 +- 2 files changed, 199 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index e1334c81..0cec4881 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,200 @@ +CHANGES FROM 3.5a TO 3.6 + +* Make -v to source-file pass through to subsequent source-file commands (issue + 4216). + +* If display-popup is used inside a popup, modify that popup (issue 4678). + +* Add selection-mode command to expilcitly set the selection mode in copy mode + (issue 3842). + +* Save and restore images in alternate screen (issue 3732). + +* Ignore Hangul filler character (issue 3998). + +* Improve handling of regional indicators and emoji modifiers (issue 3998). + +* Preserve marked pane with swap-window and move-window (issue 3443). + +* Set and check COLORTERM as a hint for RGB colour. + +* If tmux receives a palette request (OSC 4) in a pane and the palette entry + has not been set, send a request to the most recently used client and + forward any response instead (based on change from Tim Culverhouse, issue + 4665). + +* Add -l flag to command-prompt to disable splitting into multiple prompts + (issue 4483). + +* Don't enter copy mode on mouse wheel in alternate screen (issue 3705). + +* Add commands to centre the cursor in copy mode (issue 4662). + +* Support case insensitive search in modes in the same way as copy mode + (like emacs, so all-lowercase means case insensitive) (issue 4396). + +* Fix the logic of the no-detached case for the detach-on-destroy option (from + Martin Louazel, issue 4649). + +* Add buffer_full format variable (from Mohammad AlSaleh, issue 4630). + +* Introduce a new window option, tiled-layout-max-columns, which configures the + maximum number of columns in the tiled layout. + +* Add support for DECRQSS SP q (report cursor style), DECRQM ?12 (report cursor + blink state) and DECRQM ?2004, ?1004, ?1006 (report mouse state) ( rom + Andrea Alberti, issue 4618). + +* Fix missing argument from OSC 4 reply (issue 4596). + +* Add -k flag to display-popup which allows any key to dismiss the popup once + the command has exited (from Meriel Luna Mittelbach, issue 4612). + +* Add nicer default second and third status lines (from Michael Grant, issue + 4490). + +* Add a pane-border-lines "spaces" value to use spaces for pane borders (issue + 4587). + +* Replace invalid UTF-8 characters with the placeholder instead of ignoring + them (issue 4514). + +* Fix incorrect handling of Korean Hangul Jamo characters (from Roy Jung, issue + 4546). + +* Allow uppercase letters in gray/grey color names (from Pavel Roskin, issue + 4560). + +* Add sorting to W, P, L loop operators (from Michael Grant, issue 4516). + +* Detect support for OSC 52 using the device attributes report (from James + Holderness, issue 4539). + +* Add noattr for styles and use in mode-style to allow whether attributes are + ignored or used to be configured (issue 4498). + +* Add a set-default style attribute which replaces the current default colours + and attributes completely. + +* Add -E to run-shell to forward stderr as well as stdout (issue 4246). + +* Add an option variation-selector-always-wide to instruct tmux not to + always interpret VS16 as a wide character and assume the terminal does + likewise. + +* Switch to getopt_long from OpenSSH (from Koichi Murase, issue 4492). + +* Add more features for boolean expressions in formats: 1) extend && and || to + support arbitrarily many arguments and 2) add ! and !! for not and not-not + (from David Mandelberg). + +* Do not mistake other DCS sequences for SIXEL sequences (from James + Holderness, issue 4488). + +* Improve #? conditional expression in formats: add support for else if and + default empty string if no else value (from David Mandelberg, issue 4451). + +* Add default-client-command to set the command used if tmux is run without a + command; the default stays new-session (from David Mandelberg, issue + 4422). + +* Add S-Up and S-Down to move windows in tree mode (from David Mandelberg, + issue 4415). + +* Add mode 2031 support to automatically report dark or light theme. tmux will + guess the theme from the background colour on terminals which do not + themselves support the escape sequence (from Jonathan Slenders, issue 4353). + +* Add -M flag to capture-pane to use the copy mode screen (issue 4358). + +* Align index numbers in trees (from David Mandelberg, issue 4360). + +* Add display-message -C flag to update pane while message is displayed (from + Vitaly Ostrosablin, issue 4363). + +* Make list-commands command show only one command if an argument is given + (from Ilya Grigoriev, issue 4352). + +* Count line numbers correctly inside strings in configuration files (reported + by Pedro Navarro, issue 4325). + +* Map bright black (colour 8) to white (7) if the background is black on + terminals with only eight colours so the text is not invisible (from Dmytro + Bagrii, issue 4322). + +* New codepoint-widths option allowing users to override the width of + individual Unicode codepoints. + +* Add a nesting limit to source-file (from Fadi Afani, issue 4223). + +* Add copy-mode-position-style and copy-mode-selection-style options for copy + mode. + +* Add no-detach-on-destroy client option (issue 4242). + +* Add input-buffer-size option (from Ken Lau). + +* Add support for a scrollbar at the side of each pane. New options + pane-scrollbars turn them on or off, pane-scrollbars-position sets the + position (left or right), and pane-scrollbars-style to set the colours (from + Michael Grant, issue 4221). + +* Allow control characters to be entered at the command prompt by prefixing + with C-v (from Alexander Arch, issue 4206). + +* Do not attempt to search for zero length strings (from Alexander Arch, issue + 4209). + +* Preserve tabs for copying and capture-pane (from Alexander Arch, issue + 4201). + +* Increase the maximum for repeat-time. + +* Adjust how Ctrl and Meta keys are sent to use standard representation if + available in mode 1 (from Stanislav Kljuhhin, issue 4188). + +* Allow attributes in menu style (from Japin Li, issue 4194). + +* Add a sixel_support format variable which is 1 if SIXEL is supported, always + 0 on OpenBSD (requested by Misaki Masa, issue 4177). + +* Add prompt-cursor-colour and prompt-cursor-style to set the style of the + cursor in the command prompt and remove the emulated cursor (from Alexander + Arch, issue 4170). + +* Add initial-repeat-time option to allow the first repeat time to be increased + and later reduced (from David le Blanc, issue 4164). + +* Send focus events to pane when entering or leaving popup (issue 3991). + +* Add copy-mode-position-format to configure the position indicator. + +* Add -y flag to disable confirmation prompts in modes (issue 4152). + +* Add -C and -P flags to the copy commands in copy mode: -C prevents the + commands from sending the text to the clipboard and -P prevents them from + adding the text as a paste buffer (issue 4153). + +* Preserve transparency and raster attribute dimensions when sending a SIXEL + image, and avoid collapsing empty lines (issue 4149). + +* Bypass permission check for Cygwin (based on a change by Yuya Adachi via + Rafael Kitover, issue 4148). + +* Add MSYSTEM to default update-environment (for Cgywin). + +* Set client stdout file descriptor also for Cgywin (from Michael Wild via Rafael + Kitover, issue 4148). + +* Use global cursor style and colour options for modes instead of default + (issue 4117). + +* Fix pasting so it does not interpret keys but instead copies the input + without interpretation (reported by Mark Kelly). + +* Try to query window pixel size from the outside terminal if the values + returned by TIOCGWINSZ are zero (Dmitry Galchinsky, issue 4099). + CHANGES FROM 3.5 TO 3.5a * Do not translate BSpace as Unicode with extended keys. @@ -8,7 +205,7 @@ CHANGES FROM 3.5 TO 3.5a default-shell only applies now to popups. * Fix grey colour without a number suffix in styles. - + CHANGES FROM 3.4 TO 3.5 * Revamp extended keys support to more closely match xterm and support mode 2 diff --git a/configure.ac b/configure.ac index e6d4b548..4be9e03a 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ # configure.ac -AC_INIT([tmux], next-3.7) +AC_INIT([tmux], 3.6) AC_PREREQ([2.60]) AC_CONFIG_AUX_DIR(etc) From f0dec832b893f23829a01edaba6733db1f9d3f5a Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 25 Nov 2025 21:24:27 +0000 Subject: [PATCH 12/19] Add seconds options for clock mode, from augustus7613 dot mail at pm dot me in GitHub issue 4697. --- options-table.c | 2 +- tmux.1 | 2 +- window-clock.c | 24 +++++++++++++++++------- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/options-table.c b/options-table.c index e31178fa..980f8684 100644 --- a/options-table.c +++ b/options-table.c @@ -37,7 +37,7 @@ static const char *options_table_mode_keys_list[] = { "emacs", "vi", NULL }; static const char *options_table_clock_mode_style_list[] = { - "12", "24", NULL + "12", "24", "12-with-seconds", "24-with-seconds", NULL }; static const char *options_table_status_list[] = { "off", "on", "2", "3", "4", "5", NULL diff --git a/tmux.1 b/tmux.1 index 9a602927..51fb4002 100644 --- a/tmux.1 +++ b/tmux.1 @@ -4925,7 +4925,7 @@ option is enabled. Set clock colour. .Pp .It Xo Ic clock-mode-style -.Op Ic 12 | 24 +.Op Ic 12 | 24 | 12-with-seconds | 24-with-seconds .Xc Set clock hour format. .Pp diff --git a/window-clock.c b/window-clock.c index 8cef3f9a..51620d4a 100644 --- a/window-clock.c +++ b/window-clock.c @@ -45,7 +45,7 @@ const struct window_mode window_clock_mode = { }; struct window_clock_mode_data { - struct screen screen; + struct screen screen; time_t tim; struct event timer; }; @@ -142,7 +142,7 @@ window_clock_timer_callback(__unused int fd, __unused short events, void *arg) t = time(NULL); gmtime_r(&t, &now); gmtime_r(&data->tim, &then); - if (now.tm_min == then.tm_min) + if (now.tm_sec == then.tm_sec) return; data->tim = t; @@ -207,11 +207,12 @@ window_clock_draw_screen(struct window_mode_entry *wme) { struct window_pane *wp = wme->wp; struct window_clock_mode_data *data = wme->data; - struct screen_write_ctx ctx; + struct screen_write_ctx ctx; int colour, style; struct screen *s = &data->screen; struct grid_cell gc; char tim[64], *ptr; + const char *timeformat; time_t t; struct tm *tm; u_int i, j, x, y, idx; @@ -223,14 +224,23 @@ window_clock_draw_screen(struct window_mode_entry *wme) t = time(NULL); tm = localtime(&t); - if (style == 0) { - strftime(tim, sizeof tim, "%l:%M ", localtime(&t)); + if (style == 0 || style == 2) { + if (style == 2) + timeformat = "%l:%M:%S "; + else + timeformat = "%l:%M "; + strftime(tim, sizeof tim, timeformat, localtime(&t)); if (tm->tm_hour >= 12) strlcat(tim, "PM", sizeof tim); else strlcat(tim, "AM", sizeof tim); - } else - strftime(tim, sizeof tim, "%H:%M", tm); + } else { + if (style == 3) + timeformat = "%H:%M:%S"; + else + timeformat = "%H:%M"; + strftime(tim, sizeof tim, timeformat, tm); + } screen_write_clearscreen(&ctx, 8); From 00cef3e6be2f6ca7bf4ae9dffe467b6bb7d71014 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Tue, 25 Nov 2025 22:07:09 +0000 Subject: [PATCH 13/19] Add to CHANGES. --- CHANGES | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES b/CHANGES index 0cec4881..886d1673 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,8 @@ CHANGES FROM 3.5a TO 3.6 +* Add a resize callback for menus so that they are correctly moved on resize + (issue 4696). + * Make -v to source-file pass through to subsequent source-file commands (issue 4216). From a6690032adfaa20e307321f31bb51f308a90059d Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 25 Nov 2025 21:24:27 +0000 Subject: [PATCH 14/19] Add seconds options for clock mode, from augustus7613 dot mail at pm dot me in GitHub issue 4697. --- options-table.c | 2 +- tmux.1 | 2 +- window-clock.c | 24 +++++++++++++++++------- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/options-table.c b/options-table.c index 6946a085..8989c264 100644 --- a/options-table.c +++ b/options-table.c @@ -36,7 +36,7 @@ static const char *options_table_mode_keys_list[] = { "emacs", "vi", NULL }; static const char *options_table_clock_mode_style_list[] = { - "12", "24", NULL + "12", "24", "12-with-seconds", "24-with-seconds", NULL }; static const char *options_table_status_list[] = { "off", "on", "2", "3", "4", "5", NULL diff --git a/tmux.1 b/tmux.1 index a25da1fb..5a17095d 100644 --- a/tmux.1 +++ b/tmux.1 @@ -4927,7 +4927,7 @@ option is enabled. Set clock colour. .Pp .It Xo Ic clock-mode-style -.Op Ic 12 | 24 +.Op Ic 12 | 24 | 12-with-seconds | 24-with-seconds .Xc Set clock hour format. .Pp diff --git a/window-clock.c b/window-clock.c index 8cef3f9a..51620d4a 100644 --- a/window-clock.c +++ b/window-clock.c @@ -45,7 +45,7 @@ const struct window_mode window_clock_mode = { }; struct window_clock_mode_data { - struct screen screen; + struct screen screen; time_t tim; struct event timer; }; @@ -142,7 +142,7 @@ window_clock_timer_callback(__unused int fd, __unused short events, void *arg) t = time(NULL); gmtime_r(&t, &now); gmtime_r(&data->tim, &then); - if (now.tm_min == then.tm_min) + if (now.tm_sec == then.tm_sec) return; data->tim = t; @@ -207,11 +207,12 @@ window_clock_draw_screen(struct window_mode_entry *wme) { struct window_pane *wp = wme->wp; struct window_clock_mode_data *data = wme->data; - struct screen_write_ctx ctx; + struct screen_write_ctx ctx; int colour, style; struct screen *s = &data->screen; struct grid_cell gc; char tim[64], *ptr; + const char *timeformat; time_t t; struct tm *tm; u_int i, j, x, y, idx; @@ -223,14 +224,23 @@ window_clock_draw_screen(struct window_mode_entry *wme) t = time(NULL); tm = localtime(&t); - if (style == 0) { - strftime(tim, sizeof tim, "%l:%M ", localtime(&t)); + if (style == 0 || style == 2) { + if (style == 2) + timeformat = "%l:%M:%S "; + else + timeformat = "%l:%M "; + strftime(tim, sizeof tim, timeformat, localtime(&t)); if (tm->tm_hour >= 12) strlcat(tim, "PM", sizeof tim); else strlcat(tim, "AM", sizeof tim); - } else - strftime(tim, sizeof tim, "%H:%M", tm); + } else { + if (style == 3) + timeformat = "%H:%M:%S"; + else + timeformat = "%H:%M"; + strftime(tim, sizeof tim, timeformat, tm); + } screen_write_clearscreen(&ctx, 8); From 0dac7fe434d029a4f0b819cba8eb7963df291990 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Wed, 26 Nov 2025 08:34:33 +0000 Subject: [PATCH 15/19] Add to CHANGES. --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index 886d1673..eb0080ec 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,7 @@ CHANGES FROM 3.5a TO 3.6 +* Add seconds options for clock mode (issue 4697). + * Add a resize callback for menus so that they are correctly moved on resize (issue 4696). From 1decccace71b17a19dd3ec2355c73116e0812aa9 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Wed, 26 Nov 2025 08:44:41 +0000 Subject: [PATCH 16/19] Update version. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 4be9e03a..e6d4b548 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ # configure.ac -AC_INIT([tmux], 3.6) +AC_INIT([tmux], next-3.7) AC_PREREQ([2.60]) AC_CONFIG_AUX_DIR(etc) From bfa2f733351da5b2ee2674408eac744b067622fb Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Wed, 26 Nov 2025 10:41:17 +0000 Subject: [PATCH 17/19] Need signal.h for utempter, from Yasuhiro Kimura. --- server-fn.c | 1 + 1 file changed, 1 insertion(+) diff --git a/server-fn.c b/server-fn.c index 6ab7fa48..29802a60 100644 --- a/server-fn.c +++ b/server-fn.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include From a0dfef3b04ee446610ea5f5e85927216213221f8 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 26 Nov 2025 18:57:18 +0000 Subject: [PATCH 18/19] Place cursor on correct line if message-line is not 0, reported by Alexis Hildebrandt. --- server-client.c | 14 +++++++------- status.c | 13 +++++++++---- tmux.h | 1 + 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/server-client.c b/server-client.c index 14ebe5fb..184717a4 100644 --- a/server-client.c +++ b/server-client.c @@ -2905,8 +2905,8 @@ server_client_reset_state(struct client *c) struct window_pane *wp = server_client_get_pane(c), *loop; struct screen *s = NULL; struct options *oo = c->session->options; - int mode = 0, cursor, flags, n; - u_int cx = 0, cy = 0, ox, oy, sx, sy; + int mode = 0, cursor, flags; + u_int cx = 0, cy = 0, ox, oy, sx, sy, n; if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED)) return; @@ -2938,13 +2938,13 @@ server_client_reset_state(struct client *c) if (c->prompt_string != NULL) { n = options_get_number(oo, "status-position"); if (n == 0) - cy = 0; + cy = status_prompt_line_at(c); else { - n = status_line_size(c); - if (n == 0) - cy = tty->sy - 1; - else + n = status_line_size(c) - status_prompt_line_at(c); + if (n <= tty->sy) cy = tty->sy - n; + else + cy = tty->sy - 1; } cx = c->prompt_cursor; } else if (c->overlay_draw == NULL) { diff --git a/status.c b/status.c index 2786db7e..0551b547 100644 --- a/status.c +++ b/status.c @@ -264,14 +264,19 @@ status_line_size(struct client *c) } /* Get the prompt line number for client's session. 1 means at the bottom. */ -static u_int +u_int status_prompt_line_at(struct client *c) { struct session *s = c->session; + u_int line, lines; - if (c->flags & (CLIENT_STATUSOFF|CLIENT_CONTROL)) - return (1); - return (options_get_number(s->options, "message-line")); + lines = status_line_size(c); + if (lines == 0) + return (0); + line = options_get_number(s->options, "message-line"); + if (line >= lines) + return (lines - 1); + return (line); } /* Get window at window list position. */ diff --git a/tmux.h b/tmux.h index 99b80c68..20d3678a 100644 --- a/tmux.h +++ b/tmux.h @@ -2898,6 +2898,7 @@ extern u_int status_prompt_hsize[]; void status_timer_start(struct client *); void status_timer_start_all(void); void status_update_cache(struct session *); +u_int status_prompt_line_at(struct client *); int status_at_line(struct client *); u_int status_line_size(struct client *); struct style_range *status_get_range(struct client *, u_int, u_int); From e3a54ed0f46a4ac65c0abcdc445b291388fcdbdc Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 26 Nov 2025 19:02:03 +0000 Subject: [PATCH 19/19] Newer libevents do not allow event_del on a zero'd event. --- tty.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tty.c b/tty.c index bd0c6b37..cfff58c4 100644 --- a/tty.c +++ b/tty.c @@ -35,6 +35,8 @@ static int tty_log_fd = -1; +static void tty_start_timer_callback(int, short, void *); +static void tty_clipboard_query_callback(int, short, void *); 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); @@ -291,6 +293,8 @@ tty_open(struct tty *tty, char **cause) if (tty->out == NULL) fatal("out of memory"); + evtimer_set(&tty->clipboard_timer, tty_clipboard_query_callback, tty); + evtimer_set(&tty->start_timer, tty_start_timer_callback, tty); evtimer_set(&tty->timer, tty_timer_callback, tty); tty_start_tty(tty); @@ -322,7 +326,6 @@ tty_start_start_timer(struct tty *tty) log_debug("%s: start timer started", c->name); evtimer_del(&tty->start_timer); - evtimer_set(&tty->start_timer, tty_start_timer_callback, tty); evtimer_add(&tty->start_timer, &tv); } @@ -440,6 +443,7 @@ tty_stop_tty(struct tty *tty) tty->flags &= ~TTY_STARTED; evtimer_del(&tty->start_timer); + evtimer_del(&tty->clipboard_timer); event_del(&tty->timer); tty->flags &= ~TTY_BLOCK; @@ -3106,6 +3110,5 @@ tty_clipboard_query(struct tty *tty) tty_putcode_ss(tty, TTYC_MS, "", "?"); tty->flags |= TTY_OSC52QUERY; - evtimer_set(&tty->clipboard_timer, tty_clipboard_query_callback, tty); evtimer_add(&tty->clipboard_timer, &tv); }