gtkimcontextwayland: Convert byte based offset to char based offset in delete_surroun...
authorAlynx Zhou <alynx.zhou@gmail.com>
Thu, 24 Nov 2022 10:18:49 +0000 (18:18 +0800)
committerAlynx Zhou <alynx.zhou@gmail.com>
Tue, 20 Dec 2022 01:51:08 +0000 (09:51 +0800)
ClutterInputFocus/GtkIMContext uses char based offset for
delete_surrounding, however, text_input_v3 uses byte based offset for
it. Currently only GTK with mutter can work correctly via text_input_v3
because they both forget to convert between char based offset and byte
based offset.

This commit fixes it in GTK by converting byte based offset to char
based offset with the UTF-8 encoded surrounding text.

Fixes <https://gitlab.gnome.org/GNOME/gtk/-/issues/4566>.

gtk/gtkimcontextwayland.c

index 0581772bd65050a3faaeada9d8dc193a4db8c213..9701c73ae737dfb1fa274252c28d63ba0b8c943b 100644 (file)
@@ -239,14 +239,24 @@ text_input_delete_surrounding_text (void                     *data,
 {
   GtkIMContextWaylandGlobal *global = data;
   GtkIMContextWayland *context;
+  char *cursor_pointer;
+  uint32_t char_before_length;
+  uint32_t char_after_length;
 
   if (!global->current)
       return;
   
   context = GTK_IM_CONTEXT_WAYLAND (global->current);
 
-  context->pending_surrounding_delete.before_length = before_length;
-  context->pending_surrounding_delete.after_length = after_length;
+  /* We already got byte lengths from text_input_v3, but GTK uses char lengths
+   * for delete_surrounding, So convert it here.
+   */
+  cursor_pointer = context->surrounding.text + context->surrounding.cursor_idx;
+  char_before_length = g_utf8_pointer_to_offset (cursor_pointer - before_length, cursor_pointer);
+  char_after_length = g_utf8_pointer_to_offset (cursor_pointer, cursor_pointer + after_length);
+
+  context->pending_surrounding_delete.before_length = char_before_length;
+  context->pending_surrounding_delete.after_length = char_after_length;
 }
 
 static void