gnome-settings-daemon r610 - in trunk: . plugins/common plugins/keybindings plugins/media-keys
- From: jensg svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-settings-daemon r610 - in trunk: . plugins/common plugins/keybindings plugins/media-keys
- Date: Mon, 24 Nov 2008 20:48:15 +0000 (UTC)
Author: jensg
Date: Mon Nov 24 20:48:15 2008
New Revision: 610
URL: http://svn.gnome.org/viewvc/gnome-settings-daemon?rev=610&view=rev
Log:
2008-11-24 Jens Granseuer <jensgr gmx net>
When multiple keys (keycodes) were mapped to the same keysym, g-s-d
would only accept the first of those keycodes in the keymap as a
valid shortcut. To fix this, instead of checking against a single
keycode, we need to grab all keycodes that match the respective
keysym (bug #561275).
With thanks to Mario Limonciello <mario_limonciello dell com>
* plugins/common/eggaccelerators.c:
(egg_accelerator_parse_virtual):
* plugins/common/eggaccelerators.h: possibly return multiple keycodes
* plugins/common/gsd-keygrab.c: (grab_key_unsafe),
(key_uses_keycode), (match_key): grab all matching keys
* plugins/common/gsd-keygrab.h:
* plugins/keybindings/gsd-keybindings-manager.c: (parse_binding),
(bindings_get_entry), (same_keycode), (same_key),
(key_already_used), (binding_register_keys),
(gsd_keybindings_manager_stop):
* plugins/media-keys/gsd-media-keys-manager.c: (update_kbd_cb),
(init_kbd), (gsd_media_keys_manager_stop): update to handle changes
in data structures
Modified:
trunk/ChangeLog
trunk/plugins/common/eggaccelerators.c
trunk/plugins/common/eggaccelerators.h
trunk/plugins/common/gsd-keygrab.c
trunk/plugins/common/gsd-keygrab.h
trunk/plugins/keybindings/gsd-keybindings-manager.c
trunk/plugins/media-keys/gsd-media-keys-manager.c
Modified: trunk/plugins/common/eggaccelerators.c
==============================================================================
--- trunk/plugins/common/eggaccelerators.c (original)
+++ trunk/plugins/common/eggaccelerators.c Mon Nov 24 20:48:15 2008
@@ -188,6 +188,8 @@
* egg_accelerator_parse_virtual:
* @accelerator: string representing an accelerator
* @accelerator_key: return location for accelerator keyval
+ * @accelerator_codes: return location for a 0-terminated array
+ * of accelerator keycodes
* @accelerator_mods: return location for accelerator modifier mask
*
* Parses a string representing a virtual accelerator. The format
@@ -212,7 +214,7 @@
gboolean
egg_accelerator_parse_virtual (const gchar *accelerator,
guint *accelerator_key,
- guint *keycode,
+ guint **accelerator_codes,
EggVirtualModifierType *accelerator_mods)
{
guint keyval;
@@ -224,8 +226,8 @@
*accelerator_key = 0;
if (accelerator_mods)
*accelerator_mods = 0;
- if (keycode)
- *keycode = 0;
+ if (accelerator_codes)
+ *accelerator_codes = NULL;
g_return_val_if_fail (accelerator != NULL, FALSE);
@@ -345,20 +347,40 @@
{
bad_keyval = TRUE;
}
- else if (keycode != NULL)
+ else if (accelerator_codes != NULL)
{
- *keycode = tmp_keycode;
/* 0x00 is an invalid keycode too. */
- if (*keycode == 0)
+ if (tmp_keycode == 0) {
bad_keyval = TRUE;
+ } else {
+ *accelerator_codes = g_new0 (guint, 2);
+ (*accelerator_codes)[0] = tmp_keycode;
+ }
}
}
}
- else if (keycode != NULL)
+ else if (accelerator_codes != NULL)
{
- *keycode = XKeysymToKeycode (GDK_DISPLAY(), keyval);
- if (*keycode == 0)
- bad_keyval = TRUE;
+ GdkKeymapKey *keys;
+ gint n_keys, i, j;
+
+ if (!gdk_keymap_get_entries_for_keyval (NULL, keyval, &keys, &n_keys)) {
+ bad_keyval = TRUE;
+ } else {
+ *accelerator_codes = g_new0 (guint, n_keys + 1);
+
+ for (i = 0, j = 0; i < n_keys; ++i) {
+ if (keys[i].level == 0)
+ (*accelerator_codes)[j++] = keys[i].keycode;
+ }
+
+ if (j == 0) {
+ g_free (*accelerator_codes);
+ *accelerator_codes = NULL;
+ bad_keyval = TRUE;
+ }
+ g_free (keys);
+ }
}
accelerator += len;
Modified: trunk/plugins/common/eggaccelerators.h
==============================================================================
--- trunk/plugins/common/eggaccelerators.h (original)
+++ trunk/plugins/common/eggaccelerators.h Mon Nov 24 20:48:15 2008
@@ -72,7 +72,7 @@
gboolean egg_accelerator_parse_virtual (const gchar *accelerator,
guint *accelerator_key,
- guint *keycode,
+ guint **accelerator_codes,
EggVirtualModifierType *accelerator_mods);
void egg_keymap_resolve_virtual_modifiers (GdkKeymap *keymap,
EggVirtualModifierType virtual_mods,
Modified: trunk/plugins/common/gsd-keygrab.c
==============================================================================
--- trunk/plugins/common/gsd-keygrab.c (original)
+++ trunk/plugins/common/gsd-keygrab.c Mon Nov 24 20:48:15 2008
@@ -152,10 +152,14 @@
for (l = screens; l; l = l->next) {
GdkScreen *screen = l->data;
- grab_key_real (key->keycode,
- gdk_screen_get_root_window (screen),
- grab,
- result | key->state);
+ guint *code;
+
+ for (code = key->keycodes; *code; ++code) {
+ grab_key_real (*code,
+ gdk_screen_get_root_window (screen),
+ grab,
+ result | key->state);
+ }
}
}
}
@@ -185,6 +189,20 @@
}
gboolean
+key_uses_keycode (const Key *key, guint keycode)
+{
+ if (key->keycodes != NULL) {
+ guint *c;
+
+ for (c = key->keycodes; *c; ++c) {
+ if (*c == keycode)
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+gboolean
match_key (Key *key, XEvent *event)
{
guint keyval;
@@ -223,6 +241,6 @@
/* The key we passed doesn't have a keysym, so try with just the keycode */
return (key != NULL
- && key->keycode == event->xkey.keycode
- && key->state == (event->xkey.state & gsd_used_mods));
+ && key->state == (event->xkey.state & gsd_used_mods)
+ && key_uses_keycode (key, event->xkey.keycode));
}
Modified: trunk/plugins/common/gsd-keygrab.h
==============================================================================
--- trunk/plugins/common/gsd-keygrab.h (original)
+++ trunk/plugins/common/gsd-keygrab.h Mon Nov 24 20:48:15 2008
@@ -28,7 +28,7 @@
typedef struct {
guint keysym;
guint state;
- guint keycode;
+ guint *keycodes;
} Key;
@@ -39,6 +39,9 @@
gboolean match_key (Key *key,
XEvent *event);
+gboolean key_uses_keycode (const Key *key,
+ guint keycode);
+
G_END_DECLS
#endif /* __GSD_COMMON_KEYGRAB_H */
Modified: trunk/plugins/keybindings/gsd-keybindings-manager.c
==============================================================================
--- trunk/plugins/keybindings/gsd-keybindings-manager.c (original)
+++ trunk/plugins/keybindings/gsd-keybindings-manager.c Mon Nov 24 20:48:15 2008
@@ -119,6 +119,8 @@
binding->key.keysym = 0;
binding->key.state = 0;
+ g_free (binding->key.keycodes);
+ binding->key.keycodes = NULL;
if (binding->binding_str == NULL ||
binding->binding_str[0] == '\0' ||
@@ -126,14 +128,10 @@
return FALSE;
}
- if (egg_accelerator_parse_virtual (binding->binding_str,
- &binding->key.keysym,
- &binding->key.keycode,
- &binding->key.state) == FALSE) {
- return FALSE;
- }
-
- return TRUE;
+ return egg_accelerator_parse_virtual (binding->binding_str,
+ &binding->key.keysym,
+ &binding->key.keycodes,
+ &binding->key.state);
}
static gint
@@ -207,16 +205,17 @@
g_free (new_binding->binding_str);
g_free (new_binding->action);
g_free (new_binding->gconf_key);
+
+ new_binding->previous_key.keysym = new_binding->key.keysym;
+ new_binding->previous_key.state = new_binding->key.state;
+ new_binding->previous_key.keycodes = new_binding->key.keycodes;
+ new_binding->key.keycodes = NULL;
}
new_binding->binding_str = key;
new_binding->action = action;
new_binding->gconf_key = gconf_key;
- new_binding->previous_key.keysym = new_binding->key.keysym;
- new_binding->previous_key.state = new_binding->key.state;
- new_binding->previous_key.keycode = new_binding->key.keycode;
-
if (parse_binding (new_binding)) {
if (!tmp_elem)
manager->priv->binding_list = g_slist_prepend (manager->priv->binding_list, new_binding);
@@ -225,6 +224,7 @@
g_free (new_binding->binding_str);
g_free (new_binding->action);
g_free (new_binding->gconf_key);
+ g_free (new_binding->previous_key.keycodes);
g_free (new_binding);
if (tmp_elem)
@@ -236,6 +236,40 @@
}
static gboolean
+same_keycode (const Key *key, const Key *other)
+{
+ if (key->keycodes != NULL && other->keycodes != NULL) {
+ guint *c;
+
+ for (c = key->keycodes; *c; ++c) {
+ if (key_uses_keycode (other, *c))
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static gboolean
+same_key (const Key *key, const Key *other)
+{
+ if (key->state == other->state) {
+ if (key->keycodes != NULL && other->keycodes != NULL) {
+ guint *c1, *c2;
+
+ for (c1 = key->keycodes, c2 = other->keycodes;
+ *c1 || *c2; ++c1, ++c2) {
+ if (*c1 != *c2)
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
key_already_used (GsdKeybindingsManager *manager,
Binding *binding)
{
@@ -244,7 +278,8 @@
for (li = manager->priv->binding_list; li != NULL; li = li->next) {
Binding *tmp_binding = (Binding*) li->data;
- if (tmp_binding != binding && tmp_binding->key.keycode == binding->key.keycode &&
+ if (tmp_binding != binding &&
+ same_keycode (&tmp_binding->key, &binding->key) &&
tmp_binding->key.state == binding->key.state) {
return TRUE;
}
@@ -262,29 +297,34 @@
gdk_error_trap_push ();
/* Now check for changes and grab new key if not already used */
- for (li = manager->priv->binding_list ; li != NULL; li = li->next) {
+ for (li = manager->priv->binding_list; li != NULL; li = li->next) {
Binding *binding = (Binding *) li->data;
if (manager->priv->allowed_keys != NULL &&
- !g_slist_find_custom (manager->priv->allowed_keys,
- binding->gconf_key,
- g_strcmp0)) {
+ !g_slist_find_custom (manager->priv->allowed_keys,
+ binding->gconf_key,
+ (GCompareFunc) g_strcmp0)) {
continue;
}
- if (binding->previous_key.keycode != binding->key.keycode ||
- binding->previous_key.state != binding->key.state) {
+ if (!same_key (&binding->previous_key, &binding->key)) {
/* Ungrab key if it changed and not clashing with previously set binding */
- if (! key_already_used (manager, binding)) {
+ if (!key_already_used (manager, binding)) {
+ gint i;
+
need_flush = TRUE;
- if (binding->previous_key.keycode) {
+ if (binding->previous_key.keycodes) {
grab_key_unsafe (&binding->previous_key, FALSE, manager->priv->screens);
}
grab_key_unsafe (&binding->key, TRUE, manager->priv->screens);
binding->previous_key.keysym = binding->key.keysym;
binding->previous_key.state = binding->key.state;
- binding->previous_key.keycode = binding->key.keycode;
+ g_free (binding->previous_key.keycodes);
+ for (i = 0; binding->key.keycodes[i]; ++i);
+ binding->previous_key.keycodes = g_new0 (guint, i);
+ for (i = 0; binding->key.keycodes[i]; ++i)
+ binding->previous_key.keycodes[i] = binding->key.keycodes[i];
} else
g_warning ("Key binding (%s) is already in use", binding->binding_str);
}
@@ -448,7 +488,7 @@
if (strcmp (gconf_entry_get_key (entry), ALLOWED_KEYS_KEY) == 0) {
g_slist_foreach (manager->priv->allowed_keys, (GFunc)g_free, NULL);
g_slist_free (manager->priv->allowed_keys);
- manager->priv->allowed_keys = gconf_client_get_list (client,
+ manager->priv->allowed_keys = gconf_client_get_list (client,
ALLOWED_KEYS_KEY,
GCONF_VALUE_STRING,
NULL);
@@ -497,7 +537,7 @@
client = gconf_client_get_default ();
- manager->priv->allowed_keys = gconf_client_get_list (client,
+ manager->priv->allowed_keys = gconf_client_get_list (client,
ALLOWED_KEYS_KEY,
GCONF_VALUE_STRING,
NULL);
@@ -564,6 +604,8 @@
g_free (b->binding_str);
g_free (b->action);
g_free (b->gconf_key);
+ g_free (b->previous_key.keycodes);
+ g_free (b->key.keycodes);
g_free (b);
}
g_slist_free (p->binding_list);
Modified: trunk/plugins/media-keys/gsd-media-keys-manager.c
==============================================================================
--- trunk/plugins/media-keys/gsd-media-keys-manager.c (original)
+++ trunk/plugins/media-keys/gsd-media-keys-manager.c Mon Nov 24 20:48:15 2008
@@ -305,8 +305,7 @@
}
key = g_new0 (Key, 1);
- if (egg_accelerator_parse_virtual (tmp, &key->keysym, &key->keycode, &key->state) == FALSE
- || key->keycode == 0) {
+ if (!egg_accelerator_parse_virtual (tmp, &key->keysym, &key->keycodes, &key->state)) {
g_free (tmp);
g_free (key);
break;
@@ -361,17 +360,8 @@
}
key = g_new0 (Key, 1);
- if (!egg_accelerator_parse_virtual (tmp, &key->keysym, &key->keycode, &key->state)
- || key->keycode == 0) {
+ if (!egg_accelerator_parse_virtual (tmp, &key->keysym, &key->keycodes, &key->state)) {
g_debug ("Unable to parse: '%s'", tmp);
-
- g_free (tmp);
- g_free (key);
- continue;
- }
- /* avoid grabbing all the keyboard when KeyCode cannot be retrieved */
- if (key->keycode == AnyKey) {
- g_warning ("The shortcut key \"%s\" cannot be found on the current system, ignoring the binding", tmp);
g_free (tmp);
g_free (key);
continue;
@@ -1027,8 +1017,11 @@
}
for (i = 0; i < HANDLED_KEYS; ++i) {
- g_free (keys[i].key);
- keys[i].key = NULL;
+ if (keys[i].key) {
+ g_free (keys[i].key->keycodes);
+ g_free (keys[i].key);
+ keys[i].key = NULL;
+ }
}
if (priv->volume) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]