rpms/imsettings/F-10 imsettings-disable-imsettings-xim.patch, NONE, 1.1 imsettings-sync-default.patch, NONE, 1.1 imsettings-sync-forward-mode.patch, NONE, 1.1 imsettings-xim-fixes.patch, NONE, 1.1 imsettings.spec, 1.23, 1.24

Akira TAGOH tagoh at fedoraproject.org
Tue Mar 17 06:35:08 UTC 2009


Author: tagoh

Update of /cvs/pkgs/rpms/imsettings/F-10
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv32494

Modified Files:
	imsettings.spec 
Added Files:
	imsettings-disable-imsettings-xim.patch 
	imsettings-sync-default.patch 
	imsettings-sync-forward-mode.patch imsettings-xim-fixes.patch 
Log Message:
* Mon Mar 17 2009 Akira TAGOH <tagoh at redhat.com> - 0.105.1-4
- Fix a dead key not working. (#483840)
- Get rid of more debugging messages. (#484142)
- Disable imsettings-xim in xinput.sh. (#485595)
- Fix a parser error on reading Compose data.
- Fix a double-free issue.
- Workaround to get the accelerator keys working again.
  Note that this workaround might affects to the performance. you may want
  to disable this with:
  gconftool-2 -t bool -s /apps/imsettings-applet/sync_on_forward false
  (#488675)
- Fix getting-stuck-issue on keyevent. (#488976, #489611)

imsettings-disable-imsettings-xim.patch:

--- NEW FILE imsettings-disable-imsettings-xim.patch ---
 2009-01-08  Akira TAGOH  <tagoh at redhat.com>
 
	* data/xinput.sh.in.in: stop bringing imsettings-xim up. we are relying
	on XDG's autostart to provide full features of imsettings now.

Index: data/xinput.sh.in.in
===================================================================
--- data/xinput.sh.in.in	(リビジョン 229)
+++ data/xinput.sh.in.in	(リビジョン 230)
@@ -1,5 +1,5 @@
 #!/bin/bash
-# Copyright (C) 1999-2004,2007-2008 Red Hat, Inc. All rights reserved. This
+# Copyright (C) 1999-2004,2007-2009 Red Hat, Inc. All rights reserved. This
 # copyrighted material is made available to anyone wishing to use, modify,
 # copy, or redistribute it subject to the terms and conditions of the
 # GNU General Public License version 2.
@@ -21,7 +21,7 @@
 function is_gtk_supported() {
     [ -n "$IMSETTINGS_DISABLE_DESKTOP_CHECK" ] && return 0
     case "$DESKTOP_SESSION" in
-	*gnome|*kde|openbox|xfce4)
+	*gnome|openbox|xfce4)
 	    return 0
 	    ;;
 	*)
@@ -76,7 +76,10 @@
 	echo "*** DRY RUN MODE: running IM through imsettings"
     else
 	which imsettings-start > /dev/null 2>&1 && LANG="$tmplang" imsettings-start -n "$IMSETTINGS_MODULE" || :
-	which imsettings-xim > /dev/null 2>&1 && imsettings-xim &
+	# NOTE: We don't bring up imsettings-xim nor imsettings-applet here to support XIM.
+	#       imsettings-applet will starts through XDG autostart mechanism.
+	#       If the desktop doesn't support that, this function shouldn't be invoked.
+	#       but run_xim() instead.
     fi
 }
 

imsettings-sync-default.patch:

--- NEW FILE imsettings-sync-default.patch ---
Index: applet/main.c
===================================================================
--- applet/main.c	(リビジョン 257)
+++ applet/main.c	(リビジョン 258)
@@ -1215,6 +1215,16 @@
 	if (applet->server)
 		g_object_set_qdata(G_OBJECT (applet->server), quark_applet, applet);
 
+	val = gconf_client_get(client, "/apps/imsettings-applet/sync_on_forward", NULL);
+	if (val == NULL || gconf_value_get_bool(val)) {
+		if (XIM_IS_LOOPBACK (applet->server->default_server)) {
+			g_object_set(G_OBJECT (applet->server->default_server),
+				     "synchronous", gconf_value_get_bool(val),
+				     NULL);
+		}
+	}
+	gconf_value_free(val);
+
 	dbus_bus_add_match(applet->conn,
 			   "type='signal',"
 			   "interface='" IMSETTINGS_XIM_INTERFACE_DBUS "'",

imsettings-sync-forward-mode.patch:

--- NEW FILE imsettings-sync-forward-mode.patch ---
diff -pruN imsettings-0.105.1.orig/applet/imsettings-applet.schemas.in imsettings-0.105.1/applet/imsettings-applet.schemas.in
--- imsettings-0.105.1.orig/applet/imsettings-applet.schemas.in	2008-09-24 18:49:35.000000000 +0900
+++ imsettings-0.105.1/applet/imsettings-applet.schemas.in	2009-03-09 16:46:03.000000000 +0900
@@ -58,5 +58,19 @@
 	</long>
       </locale>
     </schema>
+    <schema>
+      <key>/schemas/apps/imsettings-applet/sync_on_forward</key>
+      <applyto>/apps/imsettings-applet/sync_on_forward</applyto>
+      <owner>imsettings-applet</owner>
+      <type>bool</type>
+      <default>TRUE</default>
+      <locale name="C">
+	<short>Enable this when accelerator keys etc doesn't work</short>
+	<long>
+	  When this option is enabled, all of key events will be sent to Input
+	  Method synchronously.  This might affects a performance.
+	</long>
+      </locale>
+    </schema>
   </schemalist>
 </gconfschemafile>
diff -pruN imsettings-0.105.1.orig/applet/main.c imsettings-0.105.1/applet/main.c
--- imsettings-0.105.1.orig/applet/main.c	2009-03-09 16:45:31.000000000 +0900
+++ imsettings-0.105.1/applet/main.c	2009-03-09 16:52:21.000000000 +0900
@@ -47,6 +47,7 @@
 #include <libgxim/gximmisc.h>
 #include "client.h"
 #include "proxy.h"
+#include "loopback.h"
 #include "utils.h"
 #endif
 #ifdef ENABLE_XSETTINGS
@@ -80,6 +81,7 @@ typedef struct _IMApplet {
 	gboolean             is_enabled;
 	gboolean             need_update_xinputrc;
 	GtkWidget           *checkbox_showicon;
+	GtkWidget           *checkbox_sync;
 #ifdef ENABLE_XIM
 	XimProxy            *server;
 	gchar               *xim_server;
@@ -356,6 +358,33 @@ _preference_showicon_toggled(GtkToggleBu
 	g_object_unref(client);
 }
 
+#ifdef ENABLE_XIM
+static void
+_preference_sync_toggled(GtkToggleButton *button,
+			 gpointer         data)
+{
+	IMApplet *applet = data;
+	GConfClient *client = gconf_client_get_default();
+	GConfValue *val;
+	GError *error = NULL;
+
+	val = gconf_value_new(GCONF_VALUE_BOOL);
+	if (gtk_toggle_button_get_active(button)) {
+		gconf_value_set_bool(val, TRUE);
+	} else {
+		gconf_value_set_bool(val, FALSE);
+	}
+	gconf_client_set(client, "/apps/imsettings-applet/sync_on_forward",
+			 val, &error);
+	if (error) {
+		notify_notification(applet, NOTIFY_URGENCY_CRITICAL, N_("Unable to store a value to GConf"), error->message, 5);
+		g_error_free(error);
+	}
+	gconf_value_free(val);
+	g_object_unref(client);
+}
+#endif /* ENABLE_XIM */
+
 static void
 _gconf_show_icon_cb(GConfClient *conf,
 		    guint        cnxn_id,
@@ -461,6 +490,22 @@ _gconf_xsettings_cb(GConfClient *client,
 #endif
 
 static void
+_gconf_sync_cb(GConfClient *conf,
+	       guint        cnxn_id,
+	       GConfEntry  *entry,
+	       gpointer     user_data)
+{
+	IMApplet *applet = user_data;
+	GConfValue *val = gconf_entry_get_value(entry);
+	
+	if (XIM_IS_LOOPBACK (applet->server->default_server)) {
+		g_object_set(G_OBJECT (applet->server->default_server),
+			     "synchronous", gconf_value_get_bool(val),
+			     NULL);
+	}
+}
+
+static void
 _lookup_ignorable_modifiers(GdkKeymap *keymap)
 {
 	egg_keymap_resolve_virtual_modifiers(keymap,
@@ -720,12 +765,18 @@ _preference_activated(GtkMenuItem *item,
 		      gpointer     data)
 {
 	IMApplet *applet = data;
+	GConfClient *client = gconf_client_get_default();
+	GConfValue *val;
 
 	if (applet->dialog == NULL) {
 		gchar *iconfile;
 #ifdef ENABLE_XSETTINGS
 		GtkWidget *align_xsettings;
 #endif
+#ifdef ENABLE_XIM
+		GtkWidget *align_sync;
+		GtkTooltips *tooltips_sync;
+#endif /* ENABLE_XIM */
 		GtkWidget *align_showicon;
 		GtkWidget *button_trigger_grab;
 		GtkWidget *vbox_item_trigger, *vbox_item_trigger_value;
@@ -763,6 +814,23 @@ _preference_activated(GtkMenuItem *item,
 				 G_CALLBACK (_preference_xsettings_toggled), applet);
 #endif /* ENABLE_XSETTINGS */
 
+#ifdef ENABLE_XIM
+		/* sync mode */
+		align_sync = gtk_alignment_new(0, 0, 0, 0);
+		applet->checkbox_sync = gtk_check_button_new_with_mnemonic(_("_Enable this when accelerator keys etc doesn't work"));
+		gtk_container_add(GTK_CONTAINER (align_sync), applet->checkbox_sync);
+		gtk_alignment_set_padding(GTK_ALIGNMENT (align_sync), 9, 6, 6, 6);
+		gtk_widget_set_sensitive(applet->checkbox_sync,
+					 (applet->server != NULL &&
+					  XIM_IS_LOOPBACK (applet->server->default_server)));
+		g_signal_connect(applet->checkbox_sync, "toggled",
+				 G_CALLBACK (_preference_sync_toggled), applet);
+		tooltips_sync = gtk_tooltips_new();
+		gtk_tooltips_set_tip(tooltips_sync, applet->checkbox_sync,
+				     _("When this option is enabled, all of key events will be sent to Input Method synchronously. this might affects a performance."),
+				     "");
+#endif /* ENABLE_XIM */
+
 		/* trigger key */
 		vbox_item_trigger = gtk_vbox_new(FALSE, 0);
 
@@ -813,6 +881,7 @@ _preference_activated(GtkMenuItem *item,
 #ifdef ENABLE_XSETTINGS
 		gtk_box_pack_start(GTK_BOX (GTK_DIALOG (applet->dialog)->vbox), align_xsettings, TRUE, TRUE, 0);
 #endif
+		gtk_box_pack_start(GTK_BOX (GTK_DIALOG (applet->dialog)->vbox), align_sync, TRUE, TRUE, 0);
 		gtk_box_pack_start(GTK_BOX (GTK_DIALOG (applet->dialog)->vbox), vbox_item_trigger, TRUE, TRUE, 0);
 
 		/* */
@@ -824,6 +893,11 @@ _preference_activated(GtkMenuItem *item,
 		_preference_update_entry(applet);
 	}
 
+	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);
+
 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (applet->checkbox_showicon),
 				     gtk_status_icon_get_visible(applet->status_icon));
 #ifdef ENABLE_XSETTINGS
@@ -835,6 +909,8 @@ _preference_activated(GtkMenuItem *item,
 	gtk_editable_set_editable(GTK_EDITABLE (applet->entry_grabkey), FALSE);
 	gtk_widget_show(applet->dialog);
 	gtk_widget_grab_focus(applet->close_button);
+
+	g_object_unref(client);
 }
 
 static void
@@ -1227,6 +1303,8 @@ _create_applet(gboolean is_xsettings_dis
 #endif
 	gconf_client_notify_add(client, "/apps/imsettings-applet/show_icon",
 				_gconf_show_icon_cb, applet, NULL, &error);
+	gconf_client_notify_add(client, "/apps/imsettings-applet/sync_on_forward",
+				_gconf_sync_cb, applet, NULL, &error);
 
 	val = gconf_client_get(client, "/apps/imsettings-applet/trigger_key", NULL);
 	key = gconf_value_get_string(val);

imsettings-xim-fixes.patch:

--- NEW FILE imsettings-xim-fixes.patch ---
Index: backends/xim/loopback.h
===================================================================
--- backends/xim/loopback.h	(リビジョン 242)
+++ backends/xim/loopback.h	(リビジョン 276)
@@ -63,6 +63,7 @@
 
 	GHashTable         *conn_table;
 	guint               latest_imid;
+	gboolean            sync_on_forward;
 };
 
 struct _XimLoopbackConnectionClass {
@@ -79,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	(リビジョン 242)
+++ backends/xim/proxy.c	(リビジョン 276)
@@ -1338,8 +1338,8 @@
 	} 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);
 	g_free(req);
-	DEC_PENDING (XIM_PROXY_CONNECTION (conn), G_XIM_SET_IC_VALUES_REPLY, 0, simid, icid);
   end:
 
 	return retval;
Index: backends/xim/compose.c
===================================================================
--- backends/xim/compose.c	(リビジョン 242)
+++ backends/xim/compose.c	(リビジョン 276)
@@ -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;
 			}
 		}
@@ -424,6 +439,12 @@
 	gboolean pending = FALSE;
 	Sequence *node, *sequence;
 	GError *error = NULL;
+	enum {
+		RHS_NONE,
+		RHS_STRING,
+		RHS_KEYSYM,
+		RHS_BOTH
+	} rhs_type = RHS_NONE;
 
 	g_return_val_if_fail (compose != NULL, FALSE);
 	g_return_val_if_fail (compose->fp != NULL, FALSE);
@@ -481,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);
@@ -501,82 +520,97 @@
 		p = data;
 
 		if (*p == 0 || _is_comment(*p)) {
-			g_warning("Invalid entry [no string]: %s", buf);
+			g_warning("Invalid entry [no string nor keysym]: %s", buf);
 			goto fail;
 		}
 
 		if (*p != '"') {
-			g_warning("Invalid data [no initiator for string]: %s", data);
-			goto fail;
-		}
-		p++;
-		pending = FALSE;
-		for (i = 0; *p && i < 1024; p++) {
-			if (*p == '\\') {
-				if (!pending) {
-					pending = TRUE;
+			/* this line may be a keysym only */
+			rhs_type = RHS_KEYSYM;
+			string[0] = 0;
+		} else {
+			p++;
+			pending = FALSE;
+			for (i = 0; *p && i < 1024; p++) {
+				if (*p == '\\') {
+					if (!pending) {
+						pending = TRUE;
+						continue;
+					}
+				}
+				if (pending) {
+					/* FIXME: hexadecimal, octadecimal support */
+					switch (*p) {
+					    case '\\':
+					    case '"':
+						    string[i++] = *p;
+						    break;
+					    case 'n':
+						    string[i++] = '\n';
+						    break;
+					    case 'r':
+						    string[i++] = '\r';
+						    break;
+					    case 't':
+						    string[i++] = '\t';
+						    break;
+					    default:
+						    g_warning("unknown escape format: \\%c", *p);
+						    break;
+					}
+					pending = FALSE;
 					continue;
 				}
+				if (*p == '"')
+					break;
+				string[i++] = *p;
 			}
-			if (pending) {
-				/* FIXME: hexadecimal, octadecimal support */
-				switch (*p) {
-				    case '\\':
-				    case '"':
-					    string[i++] = *p;
-					    break;
-				    case 'n':
-					    string[i++] = '\n';
-					    break;
-				    case 'r':
-					    string[i++] = '\r';
-					    break;
-				    case 't':
-					    string[i++] = '\t';
-					    break;
-				    default:
-					    g_warning("unknown escape format: \\%c", *p);
-					    break;
-				}
-				pending = FALSE;
-				continue;
+			string[i] = 0;
+			if (*p != '"') {
+				g_warning("Invalid data [no terminator for string]: %s", data);
+				goto fail;
 			}
-			if (*p == '"')
-				break;
-			string[i++] = *p;
+			p++;
+			_skip_whitespaces(p);
+			rhs_type = RHS_STRING;
 		}
-		string[i] = 0;
-		if (*p != '"') {
-			g_warning("Invalid data [no terminator for string]: %s", data);
-			goto fail;
-		}
-		p++;
-
 		/* get symbol */
-		_skip_whitespaces(p);
 		if (*p == 0 || _is_comment(*p)) {
-			g_warning("Invalid entry [no symbol]: %s", buf);
-			goto fail;
+			if (rhs_type == RHS_KEYSYM) {
+				g_warning("Invalid entry [no keysym]: %s", buf);
+				goto fail;
+			}
+			result_keysym = NoSymbol;
+		} else {
+			for (i = 0; *p && !_is_whitespace(*p) && i < 1024; i++, p++)
+				symbol[i] = *p;
+			symbol[i] = 0;
+			result_keysym = XStringToKeysym(symbol);
+			if (result_keysym == NoSymbol) {
+				d(g_warning("Invalid symbol for result: %s", symbol));
+				goto fail;
+			}
+			if (rhs_type == RHS_STRING)
+				rhs_type = RHS_BOTH;
 		}
-		for (i = 0; *p && !_is_whitespace(*p) && i < 1024; i++, p++)
-			symbol[i] = *p;
-		symbol[i] = 0;
-		result_keysym = XStringToKeysym(symbol);
-		if (result_keysym == NoSymbol) {
-			g_warning("Invalid symbol for result: %s", symbol);
+		if (string[0] != 0) {
+			utf8_string = g_convert(string, -1, "UTF-8", charset, NULL, NULL, &error);
+			if (error) {
+				g_warning("%s: %s", error->message, buf);
+				/* error might be still re-used later */
+				g_clear_error(&error);
+				goto fail;
+			}
+		} else {
+			utf8_string = NULL;
 		}
-		utf8_string = g_convert(string, -1, "UTF-8", charset, NULL, NULL, &error);
-		if (error) {
-			g_warning("%s: %s", error->message, buf);
-			g_error_free(error);
-			goto fail;
-		}
 		sequence_terminate(sequence, utf8_string, result_keysym, &error);
 		g_free(utf8_string);
 		if (error) {
 			/* unlikely to happen usually */
 			g_warning("%s", error->message);
-			g_error_free(error);
+			/* error might be still re-used later */
+			g_clear_error(&error);
 			goto fail;
 		}
 
@@ -589,6 +623,7 @@
 				sequence_add(node, s, &error);
 				if (error) {
 					g_warning("%s: %s", error->message, seq);
+					g_clear_error(&error);
 					sequence_free(s);
 					goto fail;
 				}
@@ -596,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	(リビジョン 242)
+++ backends/xim/loopback.c	(リビジョン 276)
@@ -39,8 +39,26 @@
 #include <libgxim/gximtransport.h>
 #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,
 	LAST_PROP
 };
 enum {
@@ -69,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,
@@ -97,6 +119,7 @@
 							   guint16        imid,
 							   guint16        icid,
 							   gpointer       data);
+static gboolean _process_keyevent                         (gpointer       data);
 
 //static guint signals[LAST_SIGNAL] = { 0 };
 
@@ -110,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
@@ -118,10 +146,49 @@
 {
 	XimLoopbackIC *ic = data;
 
-	g_free(ic);
+	if (ic) {
+		g_queue_free(ic->keyeventq);
+		g_free(ic);
+	}
 }
 
 static void
+xim_loopback_real_set_property(GObject      *object,
+			       guint         prop_id,
+			       const GValue *value,
+			       GParamSpec   *pspec)
+{
+	XimLoopback *loopback = XIM_LOOPBACK (object);
+
+	switch (prop_id) {
+	    case PROP_SYNCHRONOUS:
+		    loopback->sync_on_forward = g_value_get_boolean(value);
+		    break;
+	    default:
+		    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		    break;
+	}
+}
+
+static void
+xim_loopback_real_get_property(GObject    *object,
+			       guint       prop_id,
+			       GValue     *value,
+			       GParamSpec *pspec)
+{
+	XimLoopback *loopback = XIM_LOOPBACK (object);
+
+	switch (prop_id) {
+	    case PROP_SYNCHRONOUS:
+		    g_value_set_boolean(value, loopback->sync_on_forward);
+		    break;
+	    default:
+		    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		    break;
+	}
+}
+
+static void
 xim_loopback_real_finalize(GObject *object)
 {
 	XimLoopback *loopback = XIM_LOOPBACK (object);
@@ -144,11 +211,19 @@
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	GXimCoreClass *core_class = G_XIM_CORE_CLASS (klass);
 
+	object_class->set_property = xim_loopback_real_set_property;
+	object_class->get_property = xim_loopback_real_get_property;
 	object_class->finalize     = xim_loopback_real_finalize;
 
 	core_class->setup_connection = xim_loopback_real_setup_connection;
 
 	/* properties */
+	g_object_class_install_property(object_class, PROP_SYNCHRONOUS,
+					g_param_spec_boolean("synchronous",
+							     _("Synchronous"),
+							     _("Request to send a key event synchronously"),
+							     TRUE,
+							     G_PARAM_READWRITE));
 
 	/* signals */
 }
@@ -163,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},
@@ -666,7 +742,7 @@
 				g_xim_server_connection_cmd_set_event_mask(G_XIM_SERVER_CONNECTION (proto),
 									   imid, icid,
 									   KeyPressMask | KeyReleaseMask,
-									   ~(KeyPressMask | KeyReleaseMask));
+									   loopback->sync_on_forward ? ~NoEventMask : ~(KeyPressMask | KeyReleaseMask));
 			} else {
 				g_xim_connection_cmd_error(G_XIM_CONNECTION (proto),
 							   imid, 0, G_XIM_EMASK_VALID_IMID,
@@ -685,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,
@@ -839,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;
 
@@ -856,16 +981,23 @@
 			GString *s = g_string_new(NULL);
 			guchar *ctext = NULL;
 			gint len = 0;
+			GXimLookupType lookup_type = G_XIM_XLookupChars;
 
-			gdk_string_to_compound_text_for_display(dpy, string, NULL, NULL, &ctext, &len);
-			g_string_append_len(s, (gchar *)ctext, len);
-			g_free(ctext);
+			if (string) {
+				gdk_string_to_compound_text_for_display(dpy, string, NULL, NULL, &ctext, &len);
+				g_string_append_len(s, (gchar *)ctext, len);
+				g_free(ctext);
+			}
 
 			/* XXX: need to look at the keymap? */
+			if (string == NULL)
+				lookup_type = G_XIM_XLookupKeySym;
 			retval = g_xim_server_connection_cmd_commit(G_XIM_SERVER_CONNECTION (proto),
 								    imid, icid,
-								    G_XIM_XLookupSynchronous | G_XIM_XLookupChars,
+								    (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));
 
@@ -879,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;
 }
@@ -898,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
  */


Index: imsettings.spec
===================================================================
RCS file: /cvs/pkgs/rpms/imsettings/F-10/imsettings.spec,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- imsettings.spec	28 Oct 2008 11:15:22 -0000	1.23
+++ imsettings.spec	17 Mar 2009 06:34:36 -0000	1.24
@@ -1,6 +1,6 @@
 Name:		imsettings
 Version:	0.105.1
-Release:	3%{?dist}
+Release:	4%{?dist}
 License:	LGPLv2+
 URL:		http://code.google.com/p/imsettings/
 BuildRoot:	%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
@@ -18,6 +18,10 @@
 Patch0:		imsettings-constraint-of-language.patch
 Patch1:		imsettings-fix-unpredictable-session-order.patch
 Patch2:		imsettings-fix-registertriggerkeys.patch
+Patch3:		imsettings-disable-imsettings-xim.patch
+Patch4:		imsettings-sync-forward-mode.patch
+Patch5:		imsettings-sync-default.patch
+Patch6:		imsettings-xim-fixes.patch
 
 Summary:	Delivery framework for general Input Method configuration
 Group:		Applications/System
@@ -84,6 +88,10 @@
 %patch0 -p1 -b .0-lang
 %patch1 -p0 -b .1-session-order
 %patch2 -p0 -b .2-triggerkeys
+%patch3 -p0 -b .3-disable-imsettings-xim
+%patch4 -p1 -b .5-sync
+%patch5 -p0 -b .9-sync-default
+%patch6 -p0 -b .6-xim-fixes
 autoreconf
 
 %build
@@ -202,6 +210,19 @@
 
 
 %changelog
+* Mon Mar 17 2009 Akira TAGOH <tagoh at redhat.com> - 0.105.1-4
+- Fix a dead key not working. (#483840)
+- Get rid of more debugging messages. (#484142)
+- Disable imsettings-xim in xinput.sh. (#485595)
+- Fix a parser error on reading Compose data.
+- Fix a double-free issue.
+- Workaround to get the accelerator keys working again.
+  Note that this workaround might affects to the performance. you may want
+  to disable this with:
+  gconftool-2 -t bool -s /apps/imsettings-applet/sync_on_forward false
+  (#488675)
+- Fix getting-stuck-issue on keyevent. (#488976, #489611)
+
 * Tue Oct 28 2008 Akira TAGOH <tagoh at redhat.com> - 0.105.1-3
 - imsettings-fix-registertriggerkeys.patch: Fix to send
   XIM_REGISTER_TRIGGERKEYS anyway. (#468833)




More information about the fedora-extras-commits mailing list