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