diff --git a/CHANGES b/CHANGES index 58c320d99..40c45e2d0 100644 --- a/CHANGES +++ b/CHANGES @@ -115,8 +115,8 @@ CHANGES FROM 3.7c TO 3.8 * Change show-options and show-hooks to use formats and add a -F flag to each. * Add support for the Kitty keyboard protocol. When extended-keys is on, - tmux uses it with terminals which support it, detected when a client - attaches or set with a new kittykeys terminal feature, and standard + tmux uses it with terminals which support it, detected by querying the + terminal or set with a new kittykeys terminal feature, and standard extended keys or VT10x keys with other terminals, so terminals with different capabilities may be attached at the same time. Programs inside tmux may ask for either the Kitty protocol or modifyOtherKeys and get keys diff --git a/options.c b/options.c index 3b4ef41b2..4e5d57eaa 100644 --- a/options.c +++ b/options.c @@ -1401,10 +1401,8 @@ options_push_changes(const char *name) server_client_set_key_table(loop, NULL); } if (strcmp(name, "extended-keys") == 0) { - TAILQ_FOREACH(loop, &clients, entry) { - if (loop->tty.flags & TTY_STARTED) - tty_update_features(&loop->tty); - } + TAILQ_FOREACH(loop, &clients, entry) + tty_extended_keys_changed(&loop->tty); } if (strcmp(name, "user-keys") == 0) { TAILQ_FOREACH(loop, &clients, entry) { diff --git a/regress/kitty-keys-clients.sh b/regress/kitty-keys-clients.sh index 17321da79..7b007bfe7 100644 --- a/regress/kitty-keys-clients.sh +++ b/regress/kitty-keys-clients.sh @@ -10,7 +10,7 @@ KCONF=$(mktemp) LCONF=$(mktemp) OUT=$(mktemp) TMP=$(mktemp) -SOCKETS="testKmc$$ testKka$$ testKua$$ testKrt$$ testKru$$ testKlq$$ testKlu$$" +SOCKETS="testKmc$$ testKka$$ testKua$$ testKrt$$ testKru$$ testKlq$$ testKlu$$ testKpo$$ testKpi$$" printf '%s\n' 'set -g extended-keys on' >"$KCONF" printf '%s\n' 'set -g extended-keys off' >"$LCONF" @@ -142,5 +142,22 @@ wait_for_client_mode "$LQ" '' 'VT10x' || exit 1 $LU send-keys C-a wait_for_output "$TMP" || exit 1 [ "$(tr -d ' \n' <"$TMP")" = '1b5b39373b3575' ] || exit 1 +$LU kill-server 2>/dev/null +$LQ kill-server 2>/dev/null + +# The Kitty query must not be sent while extended-keys is off, but must be sent +# and answered once it is turned on. +: >"$OUT" +PO="$TEST_TMUX -LtestKpo$$ -f$KCONF" +PI="$TEST_TMUX -LtestKpi$$ -f$LCONF" +$PI new-session -d -x80 -y24 -s q || exit 1 +$PO new-session -d -x80 -y24 "sleep 1; $PI attach-session -t q" || exit 1 +$PO pipe-pane -O -t: "cat >>'$OUT'" +wait_for_client_mode "$PI" '' 'VT10x' || exit 1 +sleep 1 +od -An -v -t x1 <"$OUT" | tr -d ' \n' | grep -q 1b5b3f75 && exit 1 +$PI set-option -g extended-keys on +wait_for_client_mode "$PI" '' 'Kitty 1' || exit 1 +od -An -v -t x1 <"$OUT" | tr -d ' \n' | grep -q 1b5b3f75 || exit 1 exit 0 diff --git a/tmux.1 b/tmux.1 index eabb02153..db16793f1 100644 --- a/tmux.1 +++ b/tmux.1 @@ -4955,7 +4955,8 @@ this feature is disabled and only standard keys are reported. .Pp .Nm will always request extended keys itself if the terminal supports them. -Support for the Kitty keyboard protocol is detected when a client attaches. +When enabled, support for the Kitty keyboard protocol is detected by asking the +terminal when a client attaches or the option is changed. See also the .Ic kittykeys and diff --git a/tmux.h b/tmux.h index 70c089cf8..6acdf1dc0 100644 --- a/tmux.h +++ b/tmux.h @@ -3037,6 +3037,7 @@ void tty_invalidate(struct tty *); void tty_start_tty(struct tty *); void tty_send_requests(struct tty *); void tty_repeat_requests(struct tty *, int); +void tty_extended_keys_changed(struct tty *); void tty_stop_tty(struct tty *); void tty_set_title(struct tty *, const char *); void tty_set_path(struct tty *, const char *); diff --git a/tty-keys.c b/tty-keys.c index b5e93798d..13c1c3471 100644 --- a/tty-keys.c +++ b/tty-keys.c @@ -1562,7 +1562,7 @@ tty_keys_device_attributes(struct tty *tty, const char *buf, size_t len, } log_debug("%s: received primary DA %.*s", c->name, (int)*size, buf); - /* A DA response without a preceding keyboard response means no support. */ + /* The keyboard query, if sent, is answered first; else nothing is due. */ tty->flags |= TTY_HAVEKKB; tty_update_features(tty); tty->flags |= TTY_HAVEDA; diff --git a/tty.c b/tty.c index 6e8dfa881..fbde2ce5c 100644 --- a/tty.c +++ b/tty.c @@ -404,11 +404,14 @@ tty_start_tty(struct tty *tty) void tty_send_requests(struct tty *tty) { + int ek; + if (~tty->flags & TTY_STARTED) return; if (tty->term->flags & TERM_VT100LIKE) { - if (~tty->flags & TTY_HAVEKKB) + ek = options_get_number(global_options, "extended-keys"); + if (ek != 0 && (~tty->flags & TTY_HAVEKKB)) tty_puts(tty, "\033[?u"); if (~tty->flags & TTY_HAVEDA) tty_puts(tty, "\033[c"); @@ -451,6 +454,25 @@ tty_repeat_requests(struct tty *tty, int force) tty_start_start_timer(tty); } +/* Ask about Kitty keyboard support if extended-keys was turned on later. */ +void +tty_extended_keys_changed(struct tty *tty) +{ + if (~tty->flags & TTY_STARTED) + return; + tty_update_features(tty); + + if (options_get_number(global_options, "extended-keys") == 0) + return; + if (~tty->term->flags & TERM_VT100LIKE) + return; + if (tty->term->flags & TERM_KITTYKEYS) + return; + tty->flags &= ~TTY_HAVEKKB; + tty_puts(tty, "\033[?u"); + tty_start_start_timer(tty); +} + void tty_stop_tty(struct tty *tty) {