--- evolution-2.7.4/widgets/text/e-text.h.cal 2006-07-13 10:15:56.000000000 -0400 +++ evolution-2.7.4/widgets/text/e-text.h 2006-07-13 10:18:20.000000000 -0400 @@ -109,6 +109,7 @@ const gchar *text; /* Text to display --- from the ETextModel */ gint preedit_len; /* preedit length to display */ + gint preedit_pos; /* preedit cursor position */ PangoLayout *layout; int num_lines; /* Number of lines of text */ --- evolution-2.7.4/widgets/text/e-text.c.cal 2006-07-13 10:15:51.000000000 -0400 +++ evolution-2.7.4/widgets/text/e-text.c 2006-07-13 10:18:20.000000000 -0400 @@ -132,6 +132,7 @@ static void reset_layout_attrs (EText *text); +static void update_im_cursor_position (EText *text); #if 0 /* GtkEditable Methods */ static void e_text_editable_do_insert_text (GtkEditable *editable, @@ -325,6 +326,8 @@ pango_layout_set_attributes (text->layout, attrs); pango_attr_list_unref (attrs); } + + update_im_cursor_position (text); } if (preedit_string) @@ -3723,6 +3726,7 @@ text->model = e_text_model_new (); text->text = e_text_model_get_text (text->model); text->preedit_len = 0; + text->preedit_pos = 0; text->layout = NULL; text->revert = NULL; @@ -3840,17 +3844,71 @@ } } +/* + * Fetch cursor location into Strong or Weak positions so as to + * display the preedit candidate selection window in the right place + */ +static void +e_text_get_cursor_locations (EText *text, + GdkRectangle *strong_pos, + GdkRectangle *weak_pos) +{ + double x1, y1; + PangoRectangle pango_strong_pos; + PangoRectangle pango_weak_pos; + int cx, cy; + gint index; + + gnome_canvas_item_get_bounds (GNOME_CANVAS_ITEM (text), &x1, &y1, NULL, NULL); + + gnome_canvas_get_scroll_offsets (GNOME_CANVAS (GNOME_CANVAS_ITEM (text)->canvas), &cx, &cy); + + index = g_utf8_offset_to_pointer (text->text, text->selection_start) - text->text; + + pango_layout_get_cursor_pos (text->layout, index + text->preedit_pos, + strong_pos ? &pango_strong_pos : NULL, + weak_pos ? &pango_weak_pos : NULL); + + if (strong_pos) { + strong_pos->x = x1 - cx - text->xofs_edit + pango_strong_pos.x / PANGO_SCALE; + strong_pos->y = y1 - cy - text->yofs_edit + pango_strong_pos.y / PANGO_SCALE; + strong_pos->width = 0; + strong_pos->height = pango_strong_pos.height / PANGO_SCALE; + } + + if (weak_pos) { + weak_pos->x = x1 - cx - text->xofs_edit + pango_weak_pos.x / PANGO_SCALE; + weak_pos->y = y1 - cy - text->yofs_edit + pango_weak_pos.y / PANGO_SCALE; + weak_pos->width = 0; + weak_pos->height = pango_weak_pos.height / PANGO_SCALE; + } +} + +/* Update IM's cursor position to display candidate selection window */ +static void +update_im_cursor_position (EText *text) +{ + GdkRectangle area; + + e_text_get_cursor_locations (text, &area, NULL); + + gtk_im_context_set_cursor_location (text->im_context, &area); +} + static void e_text_preedit_changed_cb (GtkIMContext *context, - EText *etext) + EText *etext) { gchar *preedit_string = NULL; + gint cursor_pos; gtk_im_context_get_preedit_string (context, &preedit_string, - NULL, NULL); + NULL, &cursor_pos); + cursor_pos = CLAMP (cursor_pos, 0, g_utf8_strlen (preedit_string, -1)); etext->preedit_len = strlen (preedit_string); - g_free (preedit_string); + etext->preedit_pos = g_utf8_offset_to_pointer (preedit_string, cursor_pos) - preedit_string; + g_free (preedit_string); g_signal_emit (etext, e_text_signals[E_TEXT_KEYPRESS], 0, 0, 0); }