From a3a8cf0cf4a1d3888e2f41877efd3820277a201a Mon Sep 17 00:00:00 2001 From: "Joscha.Wloch" Date: Thu, 6 Jun 2024 13:56:33 +0200 Subject: [PATCH] clients: keyboard: fix backspace deleting two characters with qt The implementation of the 'zwp_input_method_context_v1_delete_surrounding_text' function in 'qtwayland' interprets the first index parameter as the number of characters to be deleted before the cursor and the second as the number of characters to be deleted after the cursor. In the current implementation of the keyboard, this means that if the cursor is between two characters, both the character before the cursor and the character after the cursor are deleted. As only the character before the cursor is to be deleted, it is sufficient to pass a '0' as the second parameter. Deleting a character at the end of the preedit string now also takes UTF-8 characters into account. Signed-off-by: Joscha.Wloch --- clients/keyboard.c | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/clients/keyboard.c b/clients/keyboard.c index e4a80183d..a8c26b348 100644 --- a/clients/keyboard.c +++ b/clients/keyboard.c @@ -570,6 +570,22 @@ prev_utf8_char(const char *s, const char *p) return NULL; } +static int utf8_char_size(const char* c) +{ + if (c != NULL) + { + if ((*c & 0x80) == 0) + return 1; + if ((*c & 0xe0) == 0xc0) + return 2; + if ((*c & 0xf0) == 0xe0) + return 3; + if ((*c & 0xf8) == 0xf0) + return 4; + } + return 0; +} + static void delete_before_cursor(struct virtual_keyboard *keyboard) { @@ -590,8 +606,8 @@ delete_before_cursor(struct virtual_keyboard *keyboard) end = keyboard->surrounding_text + keyboard->surrounding_cursor; zwp_input_method_context_v1_delete_surrounding_text(keyboard->context, - start - keyboard->surrounding_text, - end - start); + (start - keyboard->surrounding_text) - keyboard->surrounding_cursor, + 0); zwp_input_method_context_v1_commit_string(keyboard->context, keyboard->serial, ""); @@ -673,7 +689,23 @@ keyboard_handle_key(struct keyboard *keyboard, uint32_t time, const struct key * if (strlen(keyboard->keyboard->preedit_string) == 0) { delete_before_cursor(keyboard->keyboard); } else { - keyboard->keyboard->preedit_string[strlen(keyboard->keyboard->preedit_string) - 1] = '\0'; + const size_t len = strlen(keyboard->keyboard->preedit_string); + const char *prev_utf8 = prev_utf8_char(keyboard->keyboard->preedit_string + (len - MIN(len, 4)), + keyboard->keyboard->preedit_string + strlen(keyboard->keyboard->preedit_string)); + + if (prev_utf8) + { + const int pref_utf8_offset = prev_utf8 - keyboard->keyboard->preedit_string; + if ((strlen(keyboard->keyboard->preedit_string + pref_utf8_offset) - utf8_char_size(prev_utf8)) == 0) + { + keyboard->keyboard->preedit_string[pref_utf8_offset] = '\0'; + } + else + { + keyboard->keyboard->preedit_string[strlen(keyboard->keyboard->preedit_string) - 1] = '\0'; + } + } + virtual_keyboard_send_preedit(keyboard->keyboard, -1); } break;