Detection, done like sync:

- ESC[?u goes to every VT100-like terminal at attach, whatever the
  options.
- A reply turns on a new kittykeys terminal feature. Users can force
  it on or off with terminal-features kittykeys, including kittykeys@
  to turn it off.
- Changing extended-keys now takes effect immediately for attached
  clients (options.c).

Use, per client, when extended-keys is on: Kitty for clients that have
kittykeys, modifyOtherKeys for clients with extkeys, VT10x otherwise.

Pane side:

- Applications can request either protocol; Kitty wins if one asks for
  both.
- Each application gets what it asked for, whichever client typed the
  key.
- ESC[?u is answered truthfully.
- The per-client gate is gone. window.c and popup.c are simply
  master's versions again.

extended-keys always is back to its master meaning, forcing
modifyOtherKeys mode 1 only. Forcing Kitty on every program would have
sent bash ESC[97;5u for Ctrl-A.

extended-keys-format kitty is still accepted, but now behaves the same
as csi-u.
This commit is contained in:
Michael Grant
2026-09-19 07:32:57 +01:00
parent 1abf9f7023
commit 8c96fde851
18 changed files with 118 additions and 214 deletions

16
CHANGES
View File

@@ -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.

View File

@@ -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);

View File

@@ -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));
/*

View File

@@ -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

51
input.c
View File

@@ -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)

View File

@@ -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)

View File

@@ -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);

View File

@@ -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

View File

@@ -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'

View File

@@ -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"

View File

@@ -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);

View File

@@ -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);

79
tmux.1
View File

@@ -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

8
tmux.h
View File

@@ -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 *);

View File

@@ -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,

View File

@@ -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[<u");
tty->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);

14
tty.c
View File

@@ -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));

View File

@@ -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);
}