mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-04-01 07:15:32 -04:00
input: (kitty kbd): the resulting UTF-8 string may translate to multiple UTF-32 codepoints
When this happened (for example, by specifying a custom compose sequence), the kitty keyboard protocol didn’t emit any text at all. This was caused by the utf32 codepoint being -1. This in turned was caused by us trying to convert the utf8 sequence to a *single* utf32 codepoint. This patch replaces the use of mbrtoc32() with a call to ambstoc32(), and the utf32 codepoint with an utf32 string. The kitty keyboard protocol is updated: * When determining if we’re dealing with text, check *all* codepoints in the utf32 string. * Add support for multiple codepoints when reporting "associated text". The first codepoint is the actual parameter in the emitted sequence, and the remaining codepoints are sub-parameters. I.e. the codepoints are colon separated. Closes #1288
This commit is contained in:
parent
ae26915916
commit
3215d54f31
2 changed files with 32 additions and 12 deletions
|
|
@ -134,6 +134,8 @@
|
||||||
* `xdg\_toplevel::set_min_size()` not being called.
|
* `xdg\_toplevel::set_min_size()` not being called.
|
||||||
* Key bindings with consumed modifiers masking other key bindings
|
* Key bindings with consumed modifiers masking other key bindings
|
||||||
([#1280][1280]).
|
([#1280][1280]).
|
||||||
|
* Multi-character compose sequences with the kitty keyboard protocol
|
||||||
|
([#1288][1288]).
|
||||||
|
|
||||||
[1173]: https://codeberg.org/dnkl/foot/issues/1173
|
[1173]: https://codeberg.org/dnkl/foot/issues/1173
|
||||||
[1190]: https://codeberg.org/dnkl/foot/issues/1190
|
[1190]: https://codeberg.org/dnkl/foot/issues/1190
|
||||||
|
|
@ -144,6 +146,7 @@
|
||||||
[1256]: https://codeberg.org/dnkl/foot/issues/1256
|
[1256]: https://codeberg.org/dnkl/foot/issues/1256
|
||||||
[1249]: https://codeberg.org/dnkl/foot/issues/1249
|
[1249]: https://codeberg.org/dnkl/foot/issues/1249
|
||||||
[1280]: https://codeberg.org/dnkl/foot/issues/1280
|
[1280]: https://codeberg.org/dnkl/foot/issues/1280
|
||||||
|
[1288]: https://codeberg.org/dnkl/foot/issues/1288
|
||||||
|
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
|
||||||
41
input.c
41
input.c
|
|
@ -898,7 +898,7 @@ struct kbd_ctx {
|
||||||
const uint8_t *buf;
|
const uint8_t *buf;
|
||||||
size_t count;
|
size_t count;
|
||||||
} utf8;
|
} utf8;
|
||||||
uint32_t utf32;
|
uint32_t *utf32;
|
||||||
|
|
||||||
enum xkb_compose_status compose_status;
|
enum xkb_compose_status compose_status;
|
||||||
enum wl_keyboard_key_state key_state;
|
enum wl_keyboard_key_state key_state;
|
||||||
|
|
@ -1121,12 +1121,18 @@ kitty_kbd_protocol(struct seat *seat, struct terminal *term,
|
||||||
(seat->kbd.mod_num != XKB_MOD_INVALID ? 1 << seat->kbd.mod_num : 0);
|
(seat->kbd.mod_num != XKB_MOD_INVALID ? 1 << seat->kbd.mod_num : 0);
|
||||||
|
|
||||||
const xkb_keysym_t sym = ctx->sym;
|
const xkb_keysym_t sym = ctx->sym;
|
||||||
const uint32_t utf32 = ctx->utf32;
|
const uint32_t *utf32 = ctx->utf32;
|
||||||
const uint8_t *const utf8 = ctx->utf8.buf;
|
const uint8_t *const utf8 = ctx->utf8.buf;
|
||||||
|
|
||||||
const bool is_text = iswprint(utf32) && (effective & ~caps_num) == 0;
|
|
||||||
const size_t count = ctx->utf8.count;
|
const size_t count = ctx->utf8.count;
|
||||||
|
|
||||||
|
bool is_text = utf32 != NULL && (effective & ~caps_num) == 0;
|
||||||
|
for (size_t i = 0; utf32[i] != U'\0'; i++) {
|
||||||
|
if (!iswprint(utf32[i])) {
|
||||||
|
is_text = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const bool report_associated_text =
|
const bool report_associated_text =
|
||||||
(flags & KITTY_KBD_REPORT_ASSOCIATED) && is_text && !released;
|
(flags & KITTY_KBD_REPORT_ASSOCIATED) && is_text && !released;
|
||||||
|
|
||||||
|
|
@ -1245,7 +1251,7 @@ emit_escapes:
|
||||||
: sym;
|
: sym;
|
||||||
|
|
||||||
if (composed)
|
if (composed)
|
||||||
key = utf32;
|
key = utf32[0]; /* TODO: what if there are multiple codepoints? */
|
||||||
else {
|
else {
|
||||||
key = xkb_keysym_to_utf32(sym_to_use);
|
key = xkb_keysym_to_utf32(sym_to_use);
|
||||||
if (key == 0)
|
if (key == 0)
|
||||||
|
|
@ -1284,7 +1290,7 @@ emit_escapes:
|
||||||
} else
|
} else
|
||||||
event[0] = '\0';
|
event[0] = '\0';
|
||||||
|
|
||||||
char buf[64], *p = buf;
|
char buf[128], *p = buf;
|
||||||
size_t left = sizeof(buf);
|
size_t left = sizeof(buf);
|
||||||
size_t bytes;
|
size_t bytes;
|
||||||
|
|
||||||
|
|
@ -1316,8 +1322,16 @@ emit_escapes:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (report_associated_text) {
|
if (report_associated_text) {
|
||||||
bytes = snprintf(p, left, "%s;%u", !emit_mods ? ";" : "", utf32);
|
bytes = snprintf(p, left, "%s;%u", !emit_mods ? ";" : "", utf32[0]);
|
||||||
p += bytes; left -= bytes;
|
p += bytes; left -= bytes;
|
||||||
|
|
||||||
|
/* Additional text codepoints */
|
||||||
|
if (utf32[0] != U'\0') {
|
||||||
|
for (size_t i = 1; utf32[i] != U'\0'; i++) {
|
||||||
|
bytes = snprintf(p, left, ":%u", utf32[i]);
|
||||||
|
p += bytes; left -= bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes = snprintf(p, left, "%c", final);
|
bytes = snprintf(p, left, "%c", final);
|
||||||
|
|
@ -1514,19 +1528,20 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial,
|
||||||
* and use a malloc:ed buffer when necessary */
|
* and use a malloc:ed buffer when necessary */
|
||||||
uint8_t buf[32];
|
uint8_t buf[32];
|
||||||
uint8_t *utf8 = count < sizeof(buf) ? buf : xmalloc(count + 1);
|
uint8_t *utf8 = count < sizeof(buf) ? buf : xmalloc(count + 1);
|
||||||
uint32_t utf32 = (uint32_t)-1;
|
uint32_t *utf32 = NULL;
|
||||||
|
|
||||||
if (composed) {
|
if (composed) {
|
||||||
xkb_compose_state_get_utf8(
|
xkb_compose_state_get_utf8(
|
||||||
seat->kbd.xkb_compose_state, (char *)utf8, count + 1);
|
seat->kbd.xkb_compose_state, (char *)utf8, count + 1);
|
||||||
|
|
||||||
char32_t wc;
|
if (count > 0)
|
||||||
if (mbrtoc32(&wc, (const char *)utf8, count, &(mbstate_t){0}) == count)
|
utf32 = ambstoc32((const char *)utf8);
|
||||||
utf32 = wc;
|
|
||||||
} else {
|
} else {
|
||||||
xkb_state_key_get_utf8(
|
xkb_state_key_get_utf8(
|
||||||
seat->kbd.xkb_state, key, (char *)utf8, count + 1);
|
seat->kbd.xkb_state, key, (char *)utf8, count + 1);
|
||||||
utf32 = xkb_state_key_get_utf32(seat->kbd.xkb_state, key);
|
|
||||||
|
utf32 = xcalloc(2, sizeof(utf32[0]));
|
||||||
|
utf32[0] = xkb_state_key_get_utf32(seat->kbd.xkb_state, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct kbd_ctx ctx = {
|
struct kbd_ctx ctx = {
|
||||||
|
|
@ -1563,6 +1578,8 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial,
|
||||||
selection_cancel(term);
|
selection_cancel(term);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(utf32);
|
||||||
|
|
||||||
maybe_repeat:
|
maybe_repeat:
|
||||||
clock_gettime(
|
clock_gettime(
|
||||||
term->wl->presentation_clock_id, &term->render.input_time);
|
term->wl->presentation_clock_id, &term->render.input_time);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue