diff --git a/imsettings-xim-fixes.patch b/imsettings-xim-fixes.patch
new file mode 100644
index 0000000..8ec432f
--- /dev/null
+++ b/imsettings-xim-fixes.patch
@@ -0,0 +1,412 @@
+Index: applet/imsettings-applet.schemas.in
+===================================================================
+--- applet/imsettings-applet.schemas.in (リビジョン 263)
++++ applet/imsettings-applet.schemas.in (リビジョン 277)
+@@ -50,7 +50,7 @@
+ /apps/imsettings-applet/sync_on_forward
+ imsettings-applet
+ bool
+- FALSE
++ TRUE
+
+ Enable this when accelerator keys etc doesn't work
+
+Index: applet/main.c
+===================================================================
+--- applet/main.c (リビジョン 263)
++++ applet/main.c (リビジョン 277)
+@@ -779,7 +779,8 @@
+ val = gconf_client_get(client, "/apps/imsettings-applet/sync_on_forward", NULL);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (applet->checkbox_sync),
+ val == NULL ? TRUE : gconf_value_get_bool(val));
+- gconf_value_free(val);
++ if (val)
++ gconf_value_free(val);
+
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (applet->checkbox_showicon),
+ gtk_status_icon_get_visible(applet->status_icon));
+@@ -1223,7 +1224,8 @@
+ "synchronous", val == NULL ? TRUE : gconf_value_get_bool(val),
+ NULL);
+ }
+- gconf_value_free(val);
++ if (val)
++ gconf_value_free(val);
+
+ dbus_bus_add_match(applet->conn,
+ "type='signal',"
+Index: backends/xim/loopback.h
+===================================================================
+--- backends/xim/loopback.h (リビジョン 263)
++++ backends/xim/loopback.h (リビジョン 277)
+@@ -80,6 +80,9 @@
+ struct _XimLoopbackIC {
+ Sequence *sequence_state;
+ GXimICAttr *icattr;
++ GQueue *keyeventq;
++ gboolean wait_for_reply;
++ gboolean resend;
+ };
+
+ GType xim_loopback_get_type(void) G_GNUC_CONST;
+Index: backends/xim/proxy.c
+===================================================================
+--- backends/xim/proxy.c (リビジョン 263)
++++ backends/xim/proxy.c (リビジョン 277)
+@@ -1337,8 +1337,8 @@
+ g_queue_get_length(priv->sendq));
+ } else {
+ retval = g_xim_server_connection_cmd_set_ic_values_reply(conn, simid, icid);
+- DEC_PENDING (XIM_PROXY_CONNECTION (conn), G_XIM_SET_IC_VALUES_REPLY, 0, simid, icid);
+ }
++ DEC_PENDING (XIM_PROXY_CONNECTION (conn), G_XIM_SET_IC_VALUES_REPLY, 0, simid, icid);
+ g_free(req);
+ end:
+
+Index: backends/xim/compose.c
+===================================================================
+--- backends/xim/compose.c (リビジョン 263)
++++ backends/xim/compose.c (リビジョン 277)
+@@ -125,12 +125,10 @@
+ {
+ GSList *list = NULL, *l;
+
+- if (seq->string) {
+- g_set_error(error, sequence_get_error_quark(), SEQ_ERR_INVALID_SEQUENCE,
+- "Child sequence won't be matched.");
++ /* Overriding old entry like what XKB does */
++ g_free(seq->string);
++ seq->string = NULL;
+
+- return FALSE;
+- }
+ if (seq->candidates == NULL) {
+ seq->candidates = g_tree_new(_sequence_compare);
+ }
+@@ -139,7 +137,7 @@
+ Sequence *s = l->data;
+
+ if (s->keysym == next->keysym &&
+- s->modifiers == next->modifiers &&+
++ s->modifiers == next->modifiers &&
+ s->mod_mask == next->mod_mask) {
+ g_set_error(error, sequence_get_error_quark(), SEQ_ERR_SEQUENCE_EXISTS,
+ "Sequence [keysym:0x%lx,mods:0x%x,mask:0x%x] already exists.",
+@@ -155,6 +153,23 @@
+ }
+
+ static gboolean
++sequence_replace(Sequence *seq,
++ Sequence *next,
++ GError **error)
++{
++ g_free(seq->string);
++ if (seq->candidates) {
++ g_tree_foreach(seq->candidates, _sequence_list_free, NULL);
++ g_tree_destroy(seq->candidates);
++ seq->candidates = NULL;
++ }
++ seq->string = g_strdup(next->string);
++ seq->composed = next->composed;
++
++ return TRUE;
++}
++
++static gboolean
+ sequence_terminate(Sequence *seq,
+ const gchar *string,
+ gulong keysym,
+@@ -186,7 +201,7 @@
+ for (l = list; l != NULL; l = g_slist_next(l)) {
+ Sequence *s = l->data;
+
+- if (s->keysym == keysym && (modifiers & s->mod_mask) == s->modifiers) {
++ if (s->keysym == keysym && (modifiers & ~s->mod_mask) == s->modifiers) {
+ return s;
+ }
+ }
+@@ -487,9 +502,7 @@
+
+ keysym = XStringToKeysym(seqbuf);
+ if (keysym == NoSymbol) {
+- /* dirty hack to get rid of known warnings */
+- if (strncmp(seqbuf, "combining_", 10) != 0)
+- g_warning("Invalid symbol: %s", seqbuf);
++ d(g_warning("Invalid symbol: %s", seqbuf));
+ goto fail;
+ }
+ sequence = sequence_new(keysym, modifiers, mod_mask);
+@@ -574,7 +587,8 @@
+ symbol[i] = 0;
+ result_keysym = XStringToKeysym(symbol);
+ if (result_keysym == NoSymbol) {
+- g_warning("Invalid symbol for result: %s", symbol);
++ d(g_warning("Invalid symbol for result: %s", symbol));
++ goto fail;
+ }
+ if (rhs_type == RHS_STRING)
+ rhs_type = RHS_BOTH;
+@@ -617,8 +631,18 @@
+ } else {
+ if ((i + 1) == seqarray->len) {
+ if (child->candidates != NULL) {
++ /* XXX: XKB seems to be overwriting old data. */
++ sequence_replace(child, s, &error);
++ if (error) {
++ g_warning("%s: %s", error->message, seq);
++ g_clear_error(&error);
++ sequence_free(s);
++ goto fail;
++ }
++#if 0
+ g_warning("Duplicate sequence: %s", seq);
+ goto fail;
++#endif
+ } else if (s->composed != child->composed ||
+ (s->string == NULL && child->string != NULL) ||
+ (s->string != NULL && child->string == NULL) ||
+Index: backends/xim/loopback.c
+===================================================================
+--- backends/xim/loopback.c (リビジョン 263)
++++ backends/xim/loopback.c (リビジョン 277)
+@@ -39,6 +39,23 @@
+ #include
+ #include "loopback.h"
+
++/*
++ * Borrow an idea from IsModifierKey() in Xutil.h
++ */
++#define IS_MODIFIER_KEY(x) \
++ ((((x) >= GDK_Shift_L) && ((x) <= GDK_Hyper_R)) || \
++ (((x) >= GDK_ISO_Lock) && ((x) <= GDK_ISO_Group_Lock)) || \
++ ((x) == GDK_Mode_switch) || \
++ ((x) == GDK_Num_Lock))
++
++typedef struct _XimLoopbackQueueContainer {
++ GXimProtocol *proto;
++ guint16 imid;
++ guint16 icid;
++ guint16 flag;
++ GdkEvent *event;
++} XimLoopbackQueueContainer;
++
+ enum {
+ PROP_0,
+ PROP_SYNCHRONOUS,
+@@ -70,6 +87,10 @@
+ guint16 imid,
+ GSList *attributes,
+ gpointer data);
++static gboolean xim_loopback_real_xim_destroy_ic (GXimProtocol *proto,
++ guint16 imid,
++ guint16 icid,
++ gpointer data);
+ static gboolean xim_loopback_real_xim_set_ic_values (GXimProtocol *proto,
+ guint16 imid,
+ guint16 icid,
+@@ -98,6 +119,7 @@
+ guint16 imid,
+ guint16 icid,
+ gpointer data);
++static gboolean _process_keyevent (gpointer data);
+
+ //static guint signals[LAST_SIGNAL] = { 0 };
+
+@@ -111,7 +133,12 @@
+ static XimLoopbackIC *
+ xim_loopback_ic_new(void)
+ {
+- return g_new0(XimLoopbackIC, 1);
++ XimLoopbackIC *retval = g_new0(XimLoopbackIC, 1);
++
++ G_XIM_CHECK_ALLOC (retval, NULL);
++ retval->keyeventq = g_queue_new();
++
++ return retval;
+ }
+
+ static void
+@@ -119,7 +146,10 @@
+ {
+ XimLoopbackIC *ic = data;
+
+- g_free(ic);
++ if (ic) {
++ g_queue_free(ic->keyeventq);
++ g_free(ic);
++ }
+ }
+
+ static void
+@@ -208,6 +238,7 @@
+ {"XIM_ENCODING_NEGOTIATION", G_CALLBACK (xim_loopback_real_xim_encoding_negotiation), loopback},
+ {"XIM_GET_IM_VALUES", G_CALLBACK (xim_loopback_real_xim_get_im_values), loopback},
+ {"XIM_CREATE_IC", G_CALLBACK (xim_loopback_real_xim_create_ic), loopback},
++ {"XIM_DESTROY_IC", G_CALLBACK (xim_loopback_real_xim_destroy_ic), loopback},
+ {"XIM_SET_IC_VALUES", G_CALLBACK (xim_loopback_real_xim_set_ic_values), loopback},
+ {"XIM_GET_IC_VALUES", G_CALLBACK (xim_loopback_real_xim_get_ic_values), loopback},
+ {"XIM_SET_IC_FOCUS", G_CALLBACK (xim_loopback_real_xim_set_ic_focus), loopback},
+@@ -730,6 +761,34 @@
+ }
+
+ static gboolean
++xim_loopback_real_xim_destroy_ic(GXimProtocol *proto,
++ guint16 imid,
++ guint16 icid,
++ gpointer data)
++{
++ XimLoopbackConnection *lconn = XIM_LOOPBACK_CONNECTION (proto);
++ XimLoopbackIC *ic = g_hash_table_lookup(lconn->ic_table, GUINT_TO_POINTER ((guint)icid));
++
++ if (ic == NULL) {
++ gchar *msg = g_strdup_printf("Invalid input-context ID: [%d,%d]", imid, icid);
++ gboolean retval;
++
++ g_xim_message_warning(G_XIM_PROTOCOL_GET_IFACE (proto)->message,
++ msg);
++ retval = g_xim_connection_cmd_error(G_XIM_CONNECTION (proto),
++ imid, icid, G_XIM_EMASK_VALID_IMID | G_XIM_EMASK_VALID_ICID,
++ G_XIM_ERR_BadProtocol,
++ 0, msg);
++ g_free(msg);
++
++ return retval;
++ }
++ g_hash_table_remove(lconn->ic_table, GUINT_TO_POINTER ((guint)icid));
++
++ return g_xim_server_connection_cmd_destroy_ic_reply(G_XIM_SERVER_CONNECTION (proto), imid, icid);;
++}
++
++static gboolean
+ xim_loopback_real_xim_set_ic_values(GXimProtocol *proto,
+ guint16 imid,
+ guint16 icid,
+@@ -884,6 +943,27 @@
+ icid);
+ goto end;
+ }
++ if (!ic->resend &&
++ (ic->wait_for_reply || g_queue_get_length(ic->keyeventq) > 0)) {
++ XimLoopbackQueueContainer *c = g_new0(XimLoopbackQueueContainer, 1);
++
++ c->proto = g_object_ref(proto);
++ c->imid = imid;
++ c->icid = icid;
++ c->flag = flag;
++ c->event = gdk_event_copy(event);
++ g_queue_push_tail(ic->keyeventq, c);
++ g_xim_message_debug(G_XIM_PROTOCOL_GET_IFACE (proto)->message, "loopback/proto/event",
++ "Queueing a keyevent. (imid: %d, icid: %d, type: %s, keyval: %X)",
++ imid, icid,
++ event->type == GDK_KEY_PRESS ? "KeyPress" : "KeyRelease",
++ event->key.keyval);
++
++ return TRUE;
++ }
++
++ if (IS_MODIFIER_KEY (event->key.keyval))
++ goto end;
+ if (event->type == GDK_KEY_RELEASE)
+ goto end;
+
+@@ -914,8 +994,10 @@
+ lookup_type = G_XIM_XLookupKeySym;
+ retval = g_xim_server_connection_cmd_commit(G_XIM_SERVER_CONNECTION (proto),
+ imid, icid,
+- G_XIM_XLookupSynchronous | lookup_type,
++ (sflag ? G_XIM_XLookupSynchronous : 0) | lookup_type,
+ keysym, s);
++ /* Ensure that we'll try to find out a sequence from the beginning next time */
++ ic->sequence_state = NULL;
+
+ d(g_print("result: %s [%s]: 0x%x\n", gdk_keyval_name(keysym), string, event->key.hardware_keycode));
+
+@@ -929,15 +1011,21 @@
+ } else {
+ ic->sequence_state = NULL;
+ }
+-
+
+ end:
+ if (!retval)
+ retval = g_xim_connection_cmd_forward_event(G_XIM_CONNECTION (proto),
+ imid, icid, sflag, event);
+-
+- if (flag & G_XIM_Event_Synchronous)
++ if (flag & G_XIM_Event_Synchronous) {
+ g_xim_connection_cmd_sync_reply(G_XIM_CONNECTION (proto), imid, icid);
++ /* sending XIM_SYNC_REPLY usually means synchronization is done. */
++ ic->wait_for_reply = FALSE;
++ } else if (sflag & G_XIM_Event_Synchronous) {
++ ic->wait_for_reply = TRUE;
++ }
++ if (!ic->wait_for_reply && g_queue_get_length(ic->keyeventq)) {
++ g_idle_add_full(G_PRIORITY_HIGH_IDLE, _process_keyevent, ic->keyeventq, NULL);
++ }
+
+ return retval;
+ }
+@@ -948,10 +1036,62 @@
+ guint16 icid,
+ gpointer data)
+ {
+- /* Nothing to do */
++ XimLoopbackConnection *lconn = XIM_LOOPBACK_CONNECTION (proto);
++ XimLoopbackIC *ic = g_hash_table_lookup(lconn->ic_table, GUINT_TO_POINTER ((guint)icid));
++ gboolean flag = g_atomic_int_get(&ic->wait_for_reply);
++
++ retry:
++ if (flag) {
++ if (!g_atomic_int_compare_and_exchange(&ic->wait_for_reply, flag, FALSE))
++ goto retry;
++ }
++ if (g_queue_get_length(ic->keyeventq) > 0) {
++ g_idle_add_full(G_PRIORITY_HIGH_IDLE, _process_keyevent, ic->keyeventq, NULL);
++ }
++
+ return TRUE;
+ }
+
++static gboolean
++_process_keyevent(gpointer data)
++{
++ GQueue *q = data;
++ XimLoopbackQueueContainer *c;
++ XimLoopbackConnection *lconn;
++ XimLoopbackIC *ic;
++ gboolean retval;
++ GClosure *closure;
++
++ c = g_queue_pop_head(q);
++ closure = (GClosure *)g_xim_protocol_lookup_protocol_by_id(c->proto, G_XIM_FORWARD_EVENT, 0);
++ if (closure == NULL) {
++ g_xim_message_bug(G_XIM_PROTOCOL_GET_IFACE (c->proto)->message,
++ "No closure to re-send back a XIM_FORWARD_EVENT.");
++ } else {
++ lconn = XIM_LOOPBACK_CONNECTION (c->proto);
++ ic = g_hash_table_lookup(lconn->ic_table, GUINT_TO_POINTER ((guint)c->icid));
++ ic->resend = TRUE;
++ g_xim_message_debug(G_XIM_PROTOCOL_GET_IFACE (c->proto)->message, "loopback/proto/event",
++ "Re-processing XIM_FORWARD_EVENT (imid: %d, icid: %d, type: %s, keyval: %X)",
++ c->imid, c->icid,
++ c->event->type == GDK_KEY_PRESS ? "KeyPress" : "KeyRelease",
++ c->event->key.keyval);
++ retval = g_xim_protocol_closure_emit_signal((GXimProtocolClosure *)closure,
++ c->proto,
++ c->imid, c->icid, c->flag, c->event);
++ ic->resend = FALSE;
++ if (!retval) {
++ g_xim_message_warning(G_XIM_PROTOCOL_GET_IFACE (c->proto)->message,
++ "Unable to re-send back a XIM_FORWARD_EVENT. this event will be discarded.");
++ }
++ }
++ g_object_unref(c->proto);
++ gdk_event_free(c->event);
++ g_free(c);
++
++ return FALSE;
++}
++
+ /*
+ * Public functions
+ */
diff --git a/imsettings.spec b/imsettings.spec
index 36fe60f..cc6eb05 100644
--- a/imsettings.spec
+++ b/imsettings.spec
@@ -1,6 +1,6 @@
Name: imsettings
Version: 0.106.1
-Release: 1%{?dist}
+Release: 2%{?dist}
License: LGPLv2+
URL: http://code.google.com/p/imsettings/
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
@@ -15,6 +15,7 @@ Source0: http://imsettings.googlecode.com/files/%{name}-%{version}.tar.bz2
# workaround for KDE, it will be removed when we have a correct fix
Source1: imsettings-kde.sh
Patch0: imsettings-constraint-of-language.patch
+Patch1: imsettings-xim-fixes.patch
Summary: Delivery framework for general Input Method configuration
Group: Applications/System
@@ -80,6 +81,7 @@ This package contains a plugin to get this working on Xfce.
%prep
%setup -q
%patch0 -p1 -b .0-lang
+%patch1 -p0 -b .1-xim-fixes
%build
%configure \
@@ -197,6 +199,11 @@ fi
%changelog
+* Wed Mar 18 2009 Akira TAGOH - 0.106.1-2
+- Fix XIM-related issues.
+- Fix a parser error during reading Compose data. (#484142)
+- Get rid of more debugging messages.
+
* Tue Mar 10 2009 Akira TAGOH - 0.106.1-1
- New upstream release.
- Fix a double-free issue. (#485595)