--- a/gtkhtml/gtkhtml-private.h +++ a/gtkhtml/gtkhtml-private.h @@ -53,6 +53,7 @@ struct _GtkHTMLPrivate { gint im_pre_pos; GtkHTMLFontStyle im_orig_style; gboolean im_block_reset; + gint im_cumulative_cursor_move; HTMLObject *dnd_object; gint dnd_object_offset; --- a/gtkhtml/gtkhtml.c +++ a/gtkhtml/gtkhtml.c @@ -124,7 +124,7 @@ struct _ClipboardContents { }; #define d_s(x) -#define D_IM(x) +#define D_IM(x) x static GtkLayoutClass *parent_class = NULL; @@ -3213,6 +3213,12 @@ gtk_html_im_commit_cb (GtkIMContext *context, const gchar *str, GtkHTML *html) html_undo_thaw (html->engine->undo); } + /* Let cursor jump back when im_preedit starts */ + html_cursor_exactly_jump_to_position_no_spell (html->engine->cursor, html->engine, + html->engine->cursor->position - + html->priv->im_cumulative_cursor_move); + html->priv->im_cumulative_cursor_move = 0; + pos = html->engine->cursor->position; if (html->engine->mark && html->engine->mark->position > pos) pos = html->engine->mark->position; @@ -3230,6 +3236,7 @@ static void gtk_html_im_preedit_start_cb (GtkIMContext *context, GtkHTML *html) { html->priv->im_pre_len = 0; + html->priv->im_cumulative_cursor_move = 0; } static void @@ -3277,6 +3284,7 @@ gtk_html_im_preedit_changed_cb (GtkIMContext *context, GtkHTML *html) html->priv->im_orig_style = html_engine_get_font_style (html->engine); gtk_im_context_get_preedit_string (html->priv->im_context, &preedit_string, &attrs, &cursor_pos); + html->priv->im_cumulative_cursor_move += cursor_pos; D_IM (printf ("IM preedit changed to %s\n", preedit_string);) html->priv->im_pre_len = g_utf8_strlen (preedit_string, -1); @@ -3450,6 +3458,7 @@ gtk_html_init (GtkHTML* html) html->priv->need_im_reset = FALSE; html->priv->im_block_reset = FALSE; html->priv->im_pre_len = 0; + html->priv->im_cumulative_cursor_move = 0; g_signal_connect (G_OBJECT (html->priv->im_context), "commit", G_CALLBACK (gtk_html_im_commit_cb), html);