Blob Blame History Raw
--- 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);
 }