kitty: implement “report associated text”

In this mode, key events that generate text now add a third CSI
parameter, indicating the actual codepoint.

Remember that we always use the *unshifted* key in the CSI
escapes. With this mode, those CSI escapes now also included the text
codepoint. I.e. what would have been emitted, had we not generated a
CSI escape.

As far as I can tell, this mode has no effect unless “report all keys
as escape sequences” is enabled (reason being, without that, there
aren’t any text events that generate CSIs - they’re always emitted
as-is).

Note that Kitty itself seems to be somewhat buggy in this mode. At
least on Wayland, with my Swedish layout. For example ‘a’ and ‘A’ does
generate the expected CSIs, but ‘å’ and ‘Å’ appears to be treated as
non-text input.

Furthermore, Kitty optimizes away the modifier parameter, if no
modifiers are pressed (e.g. CSI 97;;97u), while we always emit the
modifier (CSI 97;1;97u).

Related to #319
This commit is contained in:
Daniel Eklöf 2021-12-06 23:01:41 +01:00
parent 9649842eca
commit 7a5386d883
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
3 changed files with 40 additions and 18 deletions

View file

@ -43,6 +43,8 @@
(mode `0b10`)
- [Report all keys as escape codes](https://sw.kovidgoyal.net/kitty/keyboard-protocol/#report-all-keys)
(mode `0b1000`)
- [Report associated text](https://sw.kovidgoyal.net/kitty/keyboard-protocol/#report-text)
(mode `0b10000`)
### Changed

53
input.c
View file

@ -1151,10 +1151,18 @@ kitty_kbd_protocol(struct seat *seat, struct terminal *term,
const bool composing = ctx->compose_status == XKB_COMPOSE_COMPOSING;
const bool composed = ctx->compose_status == XKB_COMPOSE_COMPOSED;
const xkb_keysym_t sym = ctx->sym;
const uint32_t utf32 = ctx->utf32;
const uint8_t *const utf8 = ctx->utf8.buf;
const bool is_text = iswprint(utf32);
const size_t count = ctx->utf8.count;
const enum kitty_kbd_flags flags = term->grid->kitty_kbd.flags[term->grid->kitty_kbd.idx];
const bool disambiguate = flags & KITTY_KBD_DISAMBIGUATE;
const bool report_events = flags & KITTY_KBD_REPORT_EVENT;
const bool report_all_as_escapes = flags & KITTY_KBD_REPORT_ALL;
const bool report_associated_text =
(flags & KITTY_KBD_REPORT_ASSOCIATED) && is_text && !released;
if (!report_events && released)
return false;
@ -1173,10 +1181,6 @@ kitty_kbd_protocol(struct seat *seat, struct terminal *term,
const xkb_mod_mask_t caps_num =
(seat->kbd.mod_caps != XKB_MOD_INVALID ? 1 << seat->kbd.mod_caps : 0) |
(seat->kbd.mod_num != XKB_MOD_INVALID ? 1 << seat->kbd.mod_num : 0);
const xkb_keysym_t sym = ctx->sym;
const uint32_t utf32 = ctx->utf32;
const uint8_t *const utf8 = ctx->utf8.buf;
const size_t count = ctx->utf8.count;
if (composing) {
/* We never emit anything while composing, *except* modifiers
@ -1215,7 +1219,7 @@ kitty_kbd_protocol(struct seat *seat, struct terminal *term,
}
/* Plain-text without modifiers, or commposed text, is emitted as-is */
if (((iswprint(utf32) && (effective & ~caps_num) == 0) || composed)
if (((is_text && (effective & ~caps_num) == 0) || composed)
&& !released)
{
term_to_slave(term, utf8, count);
@ -1425,6 +1429,7 @@ emit_escapes:
if (key == 0)
key = sym_to_use;
}
final = 'u';
break;
}
@ -1442,26 +1447,40 @@ emit_escapes:
} else
event[0] = '\0';
char buf[16];
int bytes;
char buf[64], *p = buf;
size_t left = sizeof(buf);
size_t bytes;
if (key < 0)
return false;
if (final == 'u' || final == '~') {
if (encoded_mods > 1 || event[0] != '\0')
bytes = snprintf(buf, sizeof(buf), "\x1b[%u;%u%s%c",
key, encoded_mods, event, final);
else
bytes = snprintf(buf, sizeof(buf), "\x1b[%u%c", key, final);
bytes = snprintf(p, left, "\x1b[%u", key);
p += bytes; left -= bytes;
if (encoded_mods > 1 || event[0] != '\0' || report_associated_text) {
bytes = snprintf(p, left, ";%u%s", encoded_mods, event);
p += bytes; left -= bytes;
if (report_associated_text) {
bytes = snprintf(p, left, ";%u", utf32);
p += bytes; left -= bytes;
}
}
bytes = snprintf(p, left, "%c", final);
p += bytes; left -= bytes;
} else {
if (encoded_mods > 1 || event[0] != '\0')
bytes = snprintf(buf, sizeof(buf), "\x1b[1;%u%s%c", encoded_mods, event, final);
else
bytes = snprintf(buf, sizeof(buf), "\x1b[%c", final);
if (encoded_mods > 1 || event[0] != '\0') {
bytes = snprintf(p, left, "\x1b[1;%u%s%c", encoded_mods, event, final);
p += bytes; left -= bytes;
} else {
bytes = snprintf(p, left, "\x1b[%c", final);
p += bytes; left -= bytes;
}
}
term_to_slave(term, buf, bytes);
term_to_slave(term, buf, sizeof(buf) - left);
return true;
}

View file

@ -135,7 +135,8 @@ enum kitty_kbd_flags {
KITTY_KBD_REPORT_ASSOCIATED = 0x10,
KITTY_KBD_SUPPORTED = (KITTY_KBD_DISAMBIGUATE |
KITTY_KBD_REPORT_EVENT |
KITTY_KBD_REPORT_ALL),
KITTY_KBD_REPORT_ALL |
KITTY_KBD_REPORT_ASSOCIATED),
};
struct grid {