diff --git a/CHANGES b/CHANGES index 2aad808bf..7970f0aac 100644 --- a/CHANGES +++ b/CHANGES @@ -111,14 +111,14 @@ 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, selected with a new kitty - value for the extended-keys-format option. This can report the Super and - Hyper modifiers (key name prefixes s- and H-) as well as Control, Meta - and Shift. The protocol is negotiated separately with each client, so - terminals with different capabilities may be attached at the same time; - clients without it use standard extended keys, or VT10x keys if those - are also unavailable, and their input is translated for applications - which have asked for Kitty encoding. +* 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 + 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 + in the form they asked for. The Kitty protocol can report the Super and + Hyper modifiers (key name prefixes s- and H-). * Add a client_key_mode format giving the extended key reporting mode in use for a client, alongside the existing pane_key_mode for a pane. diff --git a/format.c b/format.c index a65d1b962..467deae87 100644 --- a/format.c +++ b/format.c @@ -1635,11 +1635,9 @@ format_cb_client_key_mode(struct format_tree *ft) } /* This mirrors the choice made in tty_update_features(). */ - kitty = ((c->tty.flags & (TTY_HAVEKKB|TTY_KKBSUPPORT)) == - (TTY_HAVEKKB|TTY_KKBSUPPORT)); + kitty = ((c->tty.term->flags & TERM_KITTYKEYS) != 0); eks = (options_get_number(global_options, "extended-keys") != 0); - if (kitty && options_get_number(global_options, - "extended-keys-format") == EXTENDED_KEYS_KITTY) + if (kitty) eks = 0; if (eks && tty_term_has(c->tty.term, TTYC_ENEKS)) mode = "Ext"; @@ -2527,10 +2525,7 @@ format_cb_pane_key_mode(struct format_tree *ft) char *s; if (ft->wp != NULL && ft->wp->screen != NULL) { - if (options_get_number(global_options, "extended-keys-format") == - EXTENDED_KEYS_KITTY) { - if (ft->wp->screen->kitty_keys.flags == 0) - return (xstrdup("VT10x")); + if (ft->wp->screen->kitty_keys.flags != 0) { xasprintf(&s, "Kitty %u", ft->wp->screen->kitty_keys.flags); return (s); diff --git a/input-keys.c b/input-keys.c index fbb7e1528..66936b9ac 100644 --- a/input-keys.c +++ b/input-keys.c @@ -395,8 +395,7 @@ input_key_build(void) /* Translate a key code into an output key sequence for a pane. */ int -input_key_pane(struct window_pane *wp, key_code key, struct mouse_event *m, - int extended_encoding) +input_key_pane(struct window_pane *wp, key_code key, struct mouse_event *m) { if (log_get_level() != 0) { log_debug("writing key 0x%llx (%s) to %%%u", key, @@ -408,20 +407,7 @@ input_key_pane(struct window_pane *wp, key_code key, struct mouse_event *m, input_key_mouse(wp, m); return (0); } - return (input_key(wp->screen, wp->event, key, extended_encoding)); -} - -/* Return whether a key may use the configured extended encoding. */ -int -input_key_client_supports_extended(struct client *c, key_code key) -{ - if (c == NULL || (key & KEYC_SENT)) - return (1); - if (options_get_number(global_options, "extended-keys") == 0) - return (0); - if (c->tty.flags & TTY_KKBPUSHED) - return (1); - return (tty_term_has(c->tty.term, TTYC_ENEKS)); + return (input_key(wp->screen, wp->event, key)); } static void @@ -586,8 +572,7 @@ input_key_mode1(struct bufferevent *bev, key_code key) /* Translate a key code into an output key sequence. */ int -input_key(struct screen *s, struct bufferevent *bev, key_code key, - int extended_encoding) +input_key(struct screen *s, struct bufferevent *bev, key_code key) { struct input_key_entry *ike = NULL; key_code newkey; @@ -604,9 +589,8 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key, return (0); } - if (extended_encoding && - options_get_number(global_options, "extended-keys-format") == - EXTENDED_KEYS_KITTY && input_key_kitty(s, bev, key) == 0) + /* Kitty keys take precedence if the application asked for them. */ + if (input_key_kitty(s, bev, key) == 0) return (0); /* Is this backspace? */ @@ -700,8 +684,7 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key, } if (key & (KEYC_SUPER|KEYC_HYPER)) return (input_key_vt10x(bev, key)); - if (options_get_number(global_options, "extended-keys-format") == - EXTENDED_KEYS_KITTY) + if (s->kitty_keys.flags & KITTY_KEY_SUPPORTED) return (input_key_vt10x(bev, key)); /* diff --git a/input-kitty.c b/input-kitty.c index 8879f8de9..912652f2d 100644 --- a/input-kitty.c +++ b/input-kitty.c @@ -145,21 +145,10 @@ static const struct input_kitty_key input_kitty_keys[] = { { KEYC_ISO_LEVEL5_SHIFT, 57454, 'u' } }; -static u_int -input_kitty_default_flags(void) -{ - if (options_get_number(global_options, "extended-keys") == 2 && - options_get_number(global_options, "extended-keys-format") == - EXTENDED_KEYS_KITTY) - return (KITTY_KEY_DISAMBIGUATE); - return (0); -} - void input_kitty_reset(struct screen *s) { memset(&s->kitty_keys, 0, sizeof s->kitty_keys); - s->kitty_keys.flags = input_kitty_default_flags(); } void @@ -186,7 +175,6 @@ input_kitty_set(struct screen *s, u_int flags, int mode) s->kitty_keys.flags &= ~flags; else s->kitty_keys.flags = flags; - s->kitty_keys.flags |= input_kitty_default_flags(); } void @@ -194,8 +182,7 @@ input_kitty_push(struct screen *s, u_int flags) { s->kitty_keys.saved_flags = s->kitty_keys.flags; s->kitty_keys.have_saved = 1; - s->kitty_keys.flags = (flags & KITTY_KEY_SUPPORTED)| - input_kitty_default_flags(); + s->kitty_keys.flags = flags & KITTY_KEY_SUPPORTED; } void @@ -206,9 +193,8 @@ input_kitty_pop(struct screen *s, u_int count) if (s->kitty_keys.have_saved && count == 1) s->kitty_keys.flags = s->kitty_keys.saved_flags; else - s->kitty_keys.flags = input_kitty_default_flags(); + s->kitty_keys.flags = 0; s->kitty_keys.have_saved = 0; - s->kitty_keys.flags |= input_kitty_default_flags(); } static u_int diff --git a/input.c b/input.c index 4e3652c9d..870ce7124 100644 --- a/input.c +++ b/input.c @@ -162,7 +162,6 @@ static void input_set_state(struct input_ctx *, const struct input_transition *); static void input_reset_cell(struct input_ctx *); static void input_report_current_theme(struct input_ctx *); -static int input_pane_supports_extended(struct window_pane *); static void input_osc_4(struct input_ctx *, const char *); static void input_osc_8(struct input_ctx *, const char *); static void input_osc_9(struct input_ctx *, const char *); @@ -1180,29 +1179,6 @@ input_send_reply(struct input_ctx *ictx, const char *reply) } } -/* Return whether attached tty clients can provide extended keys to a pane. */ -static int -input_pane_supports_extended(struct window_pane *wp) -{ - struct client *c; - - if (wp == NULL) - return (1); - TAILQ_FOREACH(c, &clients, entry) { - if ((c->flags & (CLIENT_TERMINAL|CLIENT_ATTACHED)) != - (CLIENT_TERMINAL|CLIENT_ATTACHED)) - continue; - if (c->flags & - (CLIENT_UNATTACHEDFLAGS|CLIENT_CONTROL|CLIENT_READONLY)) - continue; - if (c->session == NULL || !session_has(c->session, wp->window)) - continue; - if (!input_key_client_supports_extended(c, 0)) - return (0); - } - return (1); -} - /* Reply to terminal query. */ static void printflike(3, 4) input_reply(struct input_ctx *ictx, int add, const char *fmt, ...) @@ -1557,9 +1533,6 @@ input_csi_dispatch(struct input_ctx *ictx) screen_write_cursormove(sctx, m - 1, n - 1, 1); break; case INPUT_CSI_MODSET: - if (options_get_number(global_options, "extended-keys-format") == - EXTENDED_KEYS_KITTY) - break; n = input_get(ictx, 0, 0, 0); if (n != 4) break; @@ -1579,9 +1552,6 @@ input_csi_dispatch(struct input_ctx *ictx) screen_write_mode_set(sctx, MODE_KEYS_EXTENDED); break; case INPUT_CSI_MODOFF: - if (options_get_number(global_options, "extended-keys-format") == - EXTENDED_KEYS_KITTY) - break; n = input_get(ictx, 0, 0, 0); if (n != 4) break; @@ -1596,19 +1566,12 @@ input_csi_dispatch(struct input_ctx *ictx) screen_write_mode_set(sctx, MODE_KEYS_EXTENDED); break; case INPUT_CSI_KITTY_QUERY: - if (options_get_number(global_options, "extended-keys") == 0 || - options_get_number(global_options, "extended-keys-format") != - EXTENDED_KEYS_KITTY) + if (options_get_number(global_options, "extended-keys") == 0) break; - n = s->kitty_keys.flags; - if (!input_pane_supports_extended(ictx->wp)) - n = 0; - input_reply(ictx, 1, "\033[?%uu", n); + input_reply(ictx, 1, "\033[?%uu", s->kitty_keys.flags); break; case INPUT_CSI_KITTY_SET: - if (options_get_number(global_options, "extended-keys") == 0 || - options_get_number(global_options, "extended-keys-format") != - EXTENDED_KEYS_KITTY) + if (options_get_number(global_options, "extended-keys") == 0) break; n = input_get(ictx, 0, 0, 0); m = input_get(ictx, 1, 1, 1); @@ -1616,18 +1579,14 @@ input_csi_dispatch(struct input_ctx *ictx) input_kitty_set(s, n, m); break; case INPUT_CSI_KITTY_PUSH: - if (options_get_number(global_options, "extended-keys") == 0 || - options_get_number(global_options, "extended-keys-format") != - EXTENDED_KEYS_KITTY) + if (options_get_number(global_options, "extended-keys") == 0) break; n = input_get(ictx, 0, 0, 0); if (n >= 0) input_kitty_push(s, n); break; case INPUT_CSI_KITTY_POP: - if (options_get_number(global_options, "extended-keys") == 0 || - options_get_number(global_options, "extended-keys-format") != - EXTENDED_KEYS_KITTY) + if (options_get_number(global_options, "extended-keys") == 0) break; n = input_get(ictx, 0, 1, 1); if (n >= 0) diff --git a/options.c b/options.c index fa10d8a7d..3b4ef41b2 100644 --- a/options.c +++ b/options.c @@ -1400,6 +1400,12 @@ options_push_changes(const char *name) TAILQ_FOREACH(loop, &clients, entry) 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); + } + } if (strcmp(name, "user-keys") == 0) { TAILQ_FOREACH(loop, &clients, entry) { if (loop->tty.flags & TTY_OPENED) diff --git a/popup.c b/popup.c index c54a614e4..0345fa367 100644 --- a/popup.c +++ b/popup.c @@ -449,8 +449,7 @@ popup_key_cb(struct client *c, void *data, struct key_event *event) bufferevent_write(job_get_event(pd->job), buf, len); return (0); } - input_key(&pd->s, job_get_event(pd->job), event->key, - input_key_client_supports_extended(pd->c, event->key)); + input_key(&pd->s, job_get_event(pd->job), event->key); } return (0); diff --git a/regress/kitty-keys-clients.sh b/regress/kitty-keys-clients.sh index 504cafcd7..17321da79 100644 --- a/regress/kitty-keys-clients.sh +++ b/regress/kitty-keys-clients.sh @@ -1,27 +1,23 @@ #!/bin/sh -# Test per-client keyboard protocol negotiation and pane-side fallback. +# Test per-client keyboard protocol detection and pane-side encoding. PATH=/bin:/usr/bin TERM=screen [ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux) KCONF=$(mktemp) -UCONF=$(mktemp) LCONF=$(mktemp) OUT=$(mktemp) TMP=$(mktemp) SOCKETS="testKmc$$ testKka$$ testKua$$ testKrt$$ testKru$$ testKlq$$ testKlu$$" -printf '%s\n' 'set -g extended-keys on' \ - 'set -g extended-keys-format kitty' >"$KCONF" -printf '%s\n' 'set -g extended-keys on' \ - 'set -g extended-keys-format csi-u' >"$UCONF" +printf '%s\n' 'set -g extended-keys on' >"$KCONF" printf '%s\n' 'set -g extended-keys off' >"$LCONF" cleanup() { - rm -f "$KCONF" "$UCONF" "$LCONF" "$OUT" "$TMP" + rm -f "$KCONF" "$LCONF" "$OUT" "$TMP" for socket in $SOCKETS; do $TEST_TMUX -L"$socket" kill-server 2>/dev/null done @@ -78,16 +74,17 @@ wait_for_client_mode() [ "$(client_mode "$tmux" "$session")" = "$wanted" ] } -# A server preferring Kitty must negotiate each client independently. +# Each client must be negotiated independently. A tmux with extended-keys off +# stands in for a terminal without Kitty keys, since it does not answer the +# query. M="$TEST_TMUX -LtestKmc$$ -f$KCONF" KA="$TEST_TMUX -LtestKka$$ -f$KCONF" -UA="$TEST_TMUX -LtestKua$$ -f$UCONF" +UA="$TEST_TMUX -LtestKua$$ -f$LCONF" $M new-session -d -x80 -y24 -s kitty || exit 1 $M new-session -d -x80 -y24 -s csiu || exit 1 $KA new-session -d -x80 -y24 "$M attach-session -t kitty" || exit 1 $UA new-session -d -x80 -y24 "$M attach-session -t csiu" || exit 1 wait_for_mode "$KA" 'Kitty 1' || exit 1 -wait_for_mode "$UA" 'Ext 2' || exit 1 # Each client must report the protocol its own terminal negotiated. wait_for_client_mode "$M" kitty 'Kitty 1' || exit 1 @@ -99,7 +96,7 @@ uc=$($M list-clients -F '#{client_name} #{client_session}' | $M command-prompt -t"$uc" -k 'display-message -pl "%%"' >"$TMP" & pid=$! sleep 0.2 -$UA send-keys 'Escape [97;5u' +$UA send-keys Escape '[97;5u' wait "$pid" [ "$(tr -d '[:space:]' <"$TMP")" = 'C-a' ] || exit 1 @@ -117,11 +114,10 @@ $M kill-server 2>/dev/null # Standard extended input must be translated for a Kitty-requesting pane. : >"$OUT" R="$TEST_TMUX -LtestKrt$$ -f$KCONF" -RU="$TEST_TMUX -LtestKru$$ -f$UCONF" +RU="$TEST_TMUX -LtestKru$$ -f$LCONF" $R new-session -d -x80 -y24 \ "stty raw -echo; printf '\033[>1u'; dd bs=1 count=7 2>/dev/null | od -An -v -t x1 >'$OUT'; sleep 5" || exit 1 $RU new-session -d -x80 -y24 "$R attach-session" || exit 1 -wait_for_mode "$RU" 'Ext 2' || exit 1 wait_for_client_mode "$R" '' 'Ext' || exit 1 $RU send-keys C-a wait_for_output "$OUT" || exit 1 @@ -129,16 +125,22 @@ wait_for_output "$OUT" || exit 1 $RU kill-server 2>/dev/null $R kill-server 2>/dev/null -# Do not report Kitty active when an attached client only supports VT10x. +# An application is told the Kitty flags it asked for even when a client that +# only supports VT10x is attached, and keys from that client are encoded as it +# asked. : >"$OUT" +: >"$TMP" printf '%s\n' "set -as terminal-overrides ',*:Eneks@:Dseks@'" >>"$KCONF" LQ="$TEST_TMUX -LtestKlq$$ -f$KCONF" LU="$TEST_TMUX -LtestKlu$$ -f$LCONF" $LQ new-session -d -x80 -y24 \ - "stty raw -echo; sleep 2; printf '\033[>1u\033[?u'; dd bs=1 count=5 2>/dev/null | od -An -v -t x1 >'$OUT'; sleep 5" || exit 1 + "stty raw -echo; sleep 2; printf '\033[>1u\033[?u'; dd bs=1 count=5 2>/dev/null | od -An -v -t x1 >'$OUT'; dd bs=1 count=7 2>/dev/null | od -An -v -t x1 >'$TMP'; sleep 5" || exit 1 $LU new-session -d -x80 -y24 "$LQ attach-session" || exit 1 wait_for_output "$OUT" || exit 1 -[ "$(tr -d ' \n' <"$OUT")" = '1b5b3f3075' ] || exit 1 +[ "$(tr -d ' \n' <"$OUT")" = '1b5b3f3175' ] || exit 1 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 exit 0 diff --git a/regress/kitty-keys-input.sh b/regress/kitty-keys-input.sh index 58862c7d6..c00968393 100644 --- a/regress/kitty-keys-input.sh +++ b/regress/kitty-keys-input.sh @@ -12,8 +12,7 @@ TERM=screen CONF=$(mktemp) TMP=$(mktemp) -printf '%s\n' 'set -g extended-keys on' \ - 'set -g extended-keys-format kitty' >"$CONF" +printf '%s\n' 'set -g extended-keys on' >"$CONF" TMUX="$TEST_TMUX -LtestKIA$$ -f$CONF" TMUX2="$TEST_TMUX -LtestKIB$$ -f$CONF" @@ -44,7 +43,9 @@ assert_key() $TMUX2 command-prompt -k 'display-message -pl "%%"' >"$TMP" & sleep 0.15 - $TMUX send-keys $keys + # Send raw bytes so the outer tmux does not encode them itself. + raw=$(printf '%s' "$keys" | sed -e 's/Escape /\\033/g' -e 's/ //g') + $TMUX send-keys -H $(printf "$raw" | od -An -v -t x1) wait actual=$(tr -d '[:space:]' <"$TMP") @@ -62,10 +63,6 @@ if ! wait_for_mode 'Kitty 1'; then exit 1 fi -# The handshake is done, so stop the outer tmux encoding the raw sequences -# below as Kitty keys itself. -$TMUX set-option -g extended-keys-format csi-u - # Modifiers, including the Kitty-only Super and Hyper. assert_key 'Escape [97;2u' 'S-a' assert_key 'Escape [97;3u' 'M-a' diff --git a/regress/kitty-keys.sh b/regress/kitty-keys.sh index 7353c3af1..e273df12e 100644 --- a/regress/kitty-keys.sh +++ b/regress/kitty-keys.sh @@ -13,8 +13,7 @@ TMUX="$TEST_TMUX -LtestK$$ -f$CONF" trap 'rm -f "$CONF" "$OUT"; $TMUX kill-server 2>/dev/null' 0 1 15 -printf '%s\n' 'set -g extended-keys on' \ - 'set -g extended-keys-format kitty' >"$CONF" +printf '%s\n' 'set -g extended-keys on' >"$CONF" wait_for_output() { @@ -90,11 +89,13 @@ wait_for_output check_output 1b5b3f31751b5b3f3075 : >"$OUT" +# "always" forces modifyOtherKeys mode 1, not Kitty keys. $TMUX set-option -g extended-keys always $TMUX respawn-pane -k -t: \ "stty raw -echo; printf '\033[>0u\033[?u'; dd bs=1 count=5 2>/dev/null | od -An -v -t x1 >'$OUT'; sleep 5" wait_for_output -check_output 1b5b3f3175 +check_output 1b5b3f3075 +wait_for_mode 'Ext 1' $TMUX set-option -g extended-keys on : >"$OUT" diff --git a/screen-write.c b/screen-write.c index 44bfbc567..ad8fa6137 100644 --- a/screen-write.c +++ b/screen-write.c @@ -437,9 +437,7 @@ screen_write_reset(struct screen_write_ctx *ctx) s->mode = MODE_CURSOR|MODE_WRAP; - if (options_get_number(global_options, "extended-keys") == 2 && - options_get_number(global_options, "extended-keys-format") != - EXTENDED_KEYS_KITTY) + if (options_get_number(global_options, "extended-keys") == 2) s->mode = (s->mode & ~EXTENDED_KEY_MODES)|MODE_KEYS_EXTENDED; input_kitty_reset(s); diff --git a/screen.c b/screen.c index 4ec75dab7..767f17a34 100644 --- a/screen.c +++ b/screen.c @@ -118,9 +118,7 @@ screen_reinit(struct screen *s, int check) s->mode = MODE_CURSOR|MODE_WRAP|(s->mode & MODE_CRLF); - if (options_get_number(global_options, "extended-keys") == 2 && - options_get_number(global_options, "extended-keys-format") != - EXTENDED_KEYS_KITTY) + if (options_get_number(global_options, "extended-keys") == 2) s->mode = (s->mode & ~EXTENDED_KEY_MODES)|MODE_KEYS_EXTENDED; if (SCREEN_IS_ALTERNATE(s)) screen_alternate_off(s, NULL, 0); diff --git a/tmux.1 b/tmux.1 index 93ba2d797..b68c36c55 100644 --- a/tmux.1 +++ b/tmux.1 @@ -4908,19 +4908,29 @@ If enabled, the server will exit when there are no attached clients. .Op Ic on | off | always .Xc Controls how modified keys are reported. -For the -.Ic csi\-u -and -.Ic xterm -formats, this controls the +When enabled, +.Nm +uses the Kitty keyboard protocol with terminals which support it, and the .Ic modifyOtherKeys .Xr xterm 1 -resource. -For the -.Ic kitty -format, this controls the progressive keyboard protocol enhancements. +resource with other terminals which support extended keys. +Each client uses the best that its terminal supports, so clients with different +terminals may be attached at the same time. .Pp -When set to +Programs inside panes may request either the Kitty keyboard protocol or +.Ic modifyOtherKeys , +and keys are sent to each program in the form it requested, whichever client +they were typed on. +The Kitty keyboard protocol can report the Super and Hyper modifiers, whose key +name prefixes are +.Ql s- +and +.Ql H- ; +its disambiguate and report-all enhancements are supported. +.Pp +For +.Ic modifyOtherKeys , +when set to .Ic on , the program inside the pane can request one of two modes: mode 1 which changes the sequence for only keys which lack an existing well-known representation; or @@ -4929,7 +4939,8 @@ When set to .Ic always , modes 1 and 2 can still be requested by applications, but mode 1 will be forced instead of the standard mode. -This applies only to applications inside panes and does not change what +This applies only to applications inside panes; it does not force the Kitty +keyboard protocol or change what .Nm requests from the terminal. When set to @@ -4938,19 +4949,12 @@ this feature is disabled and only standard keys are reported. .Pp .Nm will always request extended keys itself if the terminal supports them. -When the -.Ic kitty -format is selected, it is preferred separately for each client; clients which -do not support it use standard extended keys if available, or standard VT10x -keys otherwise. -Input from standard extended-key clients is translated to Kitty encoding for -applications which have requested it. -A Kitty keyboard state query reflects the clients attached to the window at -the time of the query; if none are attached, the requested state is reported. -Applications are not notified if client support changes after the reply. +Support for the Kitty keyboard protocol is detected when a client attaches. See also the +.Ic kittykeys +and .Ic extkeys -feature for the +features for the .Ic terminal\-features option, the .Ic extended\-keys\-format @@ -4962,22 +4966,9 @@ variables. .It Xo Ic extended\-keys\-format .Op Ic csi\-u | xterm | kitty .Xc -Selects the format for reporting modified keys to applications. -The -.Ic kitty -format uses the Kitty keyboard protocol and supports the Super and Hyper -modifiers. -Their key name prefixes are -.Ql s- -and -.Ql H- . -The disambiguate and report-all enhancements are supported; event types, -alternate keys and associated text are not requested. -For the -.Ic csi\-u -and -.Ic xterm -formats, this is the equivalent of the +Selects the format for reporting modified keys to programs which request +.Ic modifyOtherKeys . +This is the equivalent of the .Ic formatOtherKeys .Xr xterm 1 resource. @@ -4989,10 +4980,11 @@ and as .Ql \[ha][[65;6u when set to .Ic csi\-u . -With -.Ic kitty , -it will be reported as -.Ql \[ha][[97;6u . +.Ic kitty +is accepted for compatibility and is the same as +.Ic csi\-u ; +programs which request the Kitty keyboard protocol receive it whatever this +option is set to. .It Xo Ic focus\-events .Op Ic on | off .Xc @@ -5141,6 +5133,9 @@ Ignore function keys from and use the .Nm internal set only. +.It kittykeys +Supports the Kitty keyboard protocol. +This is added automatically if the terminal answers the Kitty keyboard query. .It margins Supports DECSLRM margins. .It mouse diff --git a/tmux.h b/tmux.h index b247b9cbe..ece2287de 100644 --- a/tmux.h +++ b/tmux.h @@ -1829,6 +1829,7 @@ struct tty_term { #define TERM_VT100LIKE 0x20 #define TERM_SIXEL 0x40 #define TERM_INVALIDMS 0x80 +#define TERM_KITTYKEYS 0x100 int flags; LIST_ENTRY(tty_term) entry; @@ -1911,7 +1912,6 @@ struct tty { #define TTY_HAVESYNC 0x10000 #define TTY_HAVEKKB 0x20000 #define TTY_KKBPUSHED 0x40000 -#define TTY_KKBSUPPORT 0x80000 #define TTY_ALL_REQUEST_FLAGS \ (TTY_HAVEDA|TTY_HAVEDA2|TTY_HAVEXDA|TTY_HAVESYNC|TTY_HAVEKKB) int flags; @@ -3545,12 +3545,10 @@ void input_cancel_requests(struct client *); /* input-key.c */ void input_key_build(void); -int input_key_pane(struct window_pane *, key_code, struct mouse_event *, - int); -int input_key(struct screen *, struct bufferevent *, key_code, int); +int input_key_pane(struct window_pane *, key_code, struct mouse_event *); +int input_key(struct screen *, struct bufferevent *, key_code); int input_key_get_mouse(struct screen *, struct mouse_event *, u_int, u_int, const char **, size_t *); -int input_key_client_supports_extended(struct client *, key_code); /* input-kitty.c */ void input_kitty_reset(struct screen *); diff --git a/tty-features.c b/tty-features.c index 0b12745e2..88b1ea017 100644 --- a/tty-features.c +++ b/tty-features.c @@ -235,6 +235,13 @@ static const struct tty_feature tty_feature_sync = { 0 }; +/* Terminal supports the Kitty keyboard protocol. */ +static const struct tty_feature tty_feature_kittykeys = { + "kittykeys", + NULL, + TERM_KITTYKEYS +}; + /* Terminal supports extended keys. */ static const char *const tty_feature_extkeys_capabilities[] = { "Eneks=\\E[>4;2m", @@ -386,6 +393,7 @@ static const struct tty_feature *const tty_features[] = { &tty_feature_extkeys, &tty_feature_focus, &tty_feature_ignorefkeys, + &tty_feature_kittykeys, &tty_feature_margins, &tty_feature_mouse, &tty_feature_osc7, diff --git a/tty-kitty.c b/tty-kitty.c index 30f86a379..3a4c756ec 100644 --- a/tty-kitty.c +++ b/tty-kitty.c @@ -261,10 +261,6 @@ tty_keys_kitty_query(struct tty *tty, const char *buf, size_t len, *size = 0; if (tty->flags & TTY_HAVEKKB) return (-1); - if (options_get_number(global_options, "extended-keys") == 0 || - options_get_number(global_options, "extended-keys-format") != - EXTENDED_KEYS_KITTY) - return (-1); if (buf[0] != '\033') return (-1); @@ -291,8 +287,9 @@ tty_keys_kitty_query(struct tty *tty, const char *buf, size_t len, *size = i + 1; tty->kitty_keys = flags; - tty->flags |= (TTY_HAVEKKB|TTY_KKBSUPPORT); + tty->flags |= TTY_HAVEKKB; log_debug("%s: received Kitty keyboard flags %u", c->name, flags); + tty_parse_client_features(c, "kittykeys", ","); tty_update_features(tty); return (0); } @@ -304,18 +301,13 @@ tty_update_kitty(struct tty *tty, struct screen *s) char buf[32]; if (options_get_number(global_options, "extended-keys") == 0 || - options_get_number(global_options, "extended-keys-format") != - EXTENDED_KEYS_KITTY) { + (~tty->term->flags & TERM_KITTYKEYS)) { if (tty->flags & TTY_KKBPUSHED) { tty_puts(tty, "\033[flags &= ~TTY_KKBPUSHED; } return; } - if ((tty->flags & (TTY_HAVEKKB|TTY_KKBSUPPORT)) != - (TTY_HAVEKKB|TTY_KKBSUPPORT)) - return; - flags = KITTY_KEY_DISAMBIGUATE; if (s != NULL && (s->kitty_keys.flags & KITTY_KEY_SUPPORTED) != 0) flags = s->kitty_keys.flags & KITTY_KEY_SUPPORTED; @@ -345,9 +337,7 @@ tty_keys_kitty(struct tty *tty, const char *buf, size_t len, size_t *size, int result; *size = 0; - if ((tty->flags & TTY_KKBPUSHED) == 0 || - options_get_number(global_options, "extended-keys-format") != - EXTENDED_KEYS_KITTY) + if ((tty->flags & TTY_KKBPUSHED) == 0) return (-1); if (len == 0 || buf[0] != '\033') return (-1); diff --git a/tty.c b/tty.c index 85303b8c9..93dc8efeb 100644 --- a/tty.c +++ b/tty.c @@ -409,10 +409,7 @@ tty_send_requests(struct tty *tty) return; if (tty->term->flags & TERM_VT100LIKE) { - if (~tty->flags & TTY_HAVEKKB && - options_get_number(global_options, "extended-keys") != 0 && - options_get_number(global_options, "extended-keys-format") == - EXTENDED_KEYS_KITTY) + if (~tty->flags & TTY_HAVEKKB) tty_puts(tty, "\033[?u"); if (~tty->flags & TTY_HAVEDA) tty_puts(tty, "\033[c"); @@ -562,19 +559,14 @@ void tty_update_features(struct tty *tty) { struct client *c = tty->client; - int extended_keys, format; if (tty_apply_features(tty->term)) tty_term_apply_overrides(tty->term); if (tty_use_margin(tty)) tty_putcode(tty, TTYC_ENMG); - extended_keys = options_get_number(global_options, "extended-keys"); - format = options_get_number(global_options, "extended-keys-format"); - if (extended_keys == 0 || - (format == EXTENDED_KEYS_KITTY && - (tty->flags & (TTY_HAVEKKB|TTY_KKBSUPPORT)) == - (TTY_HAVEKKB|TTY_KKBSUPPORT))) + if (options_get_number(global_options, "extended-keys") == 0 || + (tty->term->flags & TERM_KITTYKEYS)) tty_puts(tty, tty_term_string(tty->term, TTYC_DSEKS)); else tty_puts(tty, tty_term_string(tty->term, TTYC_ENEKS)); diff --git a/window.c b/window.c index 36854969e..e0ab51f19 100644 --- a/window.c +++ b/window.c @@ -1980,8 +1980,7 @@ window_pane_copy_paste(struct window_pane *wp, char *buf, size_t len) } static void -window_pane_copy_key(struct window_pane *wp, key_code key, - int extended_encoding) +window_pane_copy_key(struct window_pane *wp, key_code key) { struct window_pane *loop; @@ -1992,7 +1991,7 @@ window_pane_copy_key(struct window_pane *wp, key_code key, (~loop->flags & PANE_INPUTOFF) && window_pane_is_visible(loop) && options_get_number(loop->options, "synchronize-panes")) - input_key_pane(loop, key, NULL, extended_encoding); + input_key_pane(loop, key, NULL); } } @@ -2020,7 +2019,6 @@ window_pane_key(struct window_pane *wp, struct client *c, struct session *s, struct winlink *wl, key_code key, struct mouse_event *m) { struct window_mode_entry *wme; - int extended_encoding; if (KEYC_IS_MOUSE(key) && m == NULL) return (-1); @@ -2043,14 +2041,13 @@ window_pane_key(struct window_pane *wp, struct client *c, struct session *s, if (wp->fd == -1 || wp->flags & PANE_INPUTOFF) return (0); - extended_encoding = input_key_client_supports_extended(c, key); - if (input_key_pane(wp, key, m, extended_encoding) != 0) + if (input_key_pane(wp, key, m) != 0) return (-1); if (KEYC_IS_MOUSE(key)) return (0); if (options_get_number(wp->options, "synchronize-panes")) - window_pane_copy_key(wp, key, extended_encoding); + window_pane_copy_key(wp, key); return (0); }