diff options
Diffstat (limited to 'widgets/text')
-rw-r--r-- | widgets/text/e-text.c | 64 | ||||
-rw-r--r-- | widgets/text/e-text.h | 1 |
2 files changed, 62 insertions, 3 deletions
diff --git a/widgets/text/e-text.c b/widgets/text/e-text.c index 932144a343..86c68d651f 100644 --- a/widgets/text/e-text.c +++ b/widgets/text/e-text.c @@ -132,6 +132,7 @@ static void e_text_insert(EText *text, const char *string); 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, @@ -329,6 +330,8 @@ insert_preedit_text (EText *text) pango_layout_set_attributes (text->layout, attrs); pango_attr_list_unref (attrs); } + + update_im_cursor_position (text); } if (preedit_string) @@ -3720,6 +3723,7 @@ e_text_init (EText *text) 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; @@ -3820,17 +3824,71 @@ e_text_commit_cb (GtkIMContext *context, } } +/* + * 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); } diff --git a/widgets/text/e-text.h b/widgets/text/e-text.h index 4d2e4abcf0..174b9e328d 100644 --- a/widgets/text/e-text.h +++ b/widgets/text/e-text.h @@ -109,6 +109,7 @@ struct _EText { 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 */ |