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;