From 78666d248a6b5a40effd2a30cb9483cd8141bb1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 6 Dec 2021 23:01:41 +0100 Subject: [PATCH] =?UTF-8?q?kitty:=20implement=20=E2=80=9Creport=20associat?= =?UTF-8?q?ed=20text=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- CHANGELOG.md | 2 ++ input.c | 53 +++++++++++++++++++++++++++++++++++----------------- terminal.h | 3 ++- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b6fd944..828f51aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,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 diff --git a/input.c b/input.c index 2b878cd1..0d47faea 100644 --- a/input.c +++ b/input.c @@ -1156,10 +1156,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; @@ -1178,10 +1186,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 @@ -1220,7 +1224,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); @@ -1430,6 +1434,7 @@ emit_escapes: if (key == 0) key = sym_to_use; } + final = 'u'; break; } @@ -1447,26 +1452,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; } diff --git a/terminal.h b/terminal.h index 15d263d5..394871f6 100644 --- a/terminal.h +++ b/terminal.h @@ -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 {