summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <matthiasc@src.gnome.org>2009-01-31 20:32:06 +0000
committerMatthias Clasen <matthiasc@src.gnome.org>2009-01-31 20:32:06 +0000
commit17f8a2c23aba669cbcf7a5c9fc650d8dee78d7f6 (patch)
treec7de6c9d8687106b08c1dd861f09eeb98c1105df
parentfd1ba235fb913b057b83270f69106289b1f7c0a3 (diff)
downloadgdk-pixbuf-17f8a2c23aba669cbcf7a5c9fc650d8dee78d7f6.tar.gz
Bug 162726 – Multiple Latin layouts in XKB break keyboard shortcuts
* gtk/gtkkeyhash.c (_gtk_key_hash_lookup): Change the handling of fuzzy matches: As long there are any exact matches, only exact matches are returned. If there are no exact matches, fuzzy matches will be returned, as long as they are not shadowing a possible exact match. This means that fuzzy matches won't be considered if their keyval is present in the current group. Problem reported by many people, patch by Simos Xenitellis. svn path=/trunk/; revision=22266
-rw-r--r--ChangeLog12
-rw-r--r--gtk/gtkkeyhash.c88
2 files changed, 95 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index b4e770c10..810d35b37 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
2009-01-31 Matthias Clasen <mclasen@redhat.com>
+ Bug 162726 – Multiple Latin layouts in XKB break keyboard shortcuts
+
+ * gtk/gtkkeyhash.c (_gtk_key_hash_lookup): Change the handling of
+ fuzzy matches: As long there are any exact matches, only exact
+ matches are returned. If there are no exact matches, fuzzy matches
+ will be returned, as long as they are not shadowing a possible exact
+ match. This means that fuzzy matches won't be considered if their
+ keyval is present in the current group. Problem reported by
+ many people, patch by Simos Xenitellis.
+
+2009-01-31 Matthias Clasen <mclasen@redhat.com>
+
* NEWS: Updates
2009-01-30 Fridrich Strba <fridrich.strba@bluewin.ch>
diff --git a/gtk/gtkkeyhash.c b/gtk/gtkkeyhash.c
index 06440994f..3de8830eb 100644
--- a/gtk/gtkkeyhash.c
+++ b/gtk/gtkkeyhash.c
@@ -304,6 +304,54 @@ sort_lookup_results (GSList *slist)
return g_slist_sort (slist, lookup_result_compare);
}
+static gint
+lookup_result_compare_by_keyval (gconstpointer a,
+ gconstpointer b)
+{
+ const GtkKeyHashEntry *entry_a = a;
+ const GtkKeyHashEntry *entry_b = b;
+
+ if (entry_a->keyval < entry_b->keyval)
+ return -1;
+ else if (entry_a->keyval > entry_b->keyval)
+ return 1;
+ else
+ return 0;
+}
+
+static GSList *
+sort_lookup_results_by_keyval (GSList *slist)
+{
+ return g_slist_sort (slist, lookup_result_compare_by_keyval);
+}
+
+/* Return true if keyval is defined in keyboard group
+ */
+static gboolean
+keyval_in_group (GdkKeymap *keymap,
+ guint keyval,
+ gint group)
+{
+ GtkKeyHashEntry entry;
+ gint i;
+
+ gdk_keymap_get_entries_for_keyval (keymap,
+ keyval,
+ &entry.keys, &entry.n_keys);
+
+ for (i = 0; i < entry.n_keys; i++)
+ {
+ if (entry.keys[i].group == group)
+ {
+ g_free (entry.keys);
+ return TRUE;
+ }
+ }
+
+ g_free (entry.keys);
+ return FALSE;
+}
+
/**
* _gtk_key_hash_lookup:
* @key_hash: a #GtkKeyHash
@@ -317,10 +365,15 @@ sort_lookup_results (GSList *slist)
* a given event. The results are sorted so that entries with less
* modifiers come before entries with more modifiers.
*
- * Return value: A #GSList of all matching entries. If there were exact
- * matches, they are returned, otherwise all fuzzy matches are
- * returned. (A fuzzy match is a match in keycode and level, but not
- * in group.)
+ * The matches returned by this function can be exact (i.e. keycode, level
+ * and group all match) or fuzzy (i.e. keycode and level match, but group
+ * does not). As long there are any exact matches, only exact matches
+ * are returned. If there are no exact matches, fuzzy matches will be
+ * returned, as long as they are not shadowing a possible exact match.
+ * This means that fuzzy matches won't be considered if their keyval is
+ * present in the current group.
+ *
+ * Return value: A #GSList of matching entries.
**/
GSList *
_gtk_key_hash_lookup (GtkKeyHash *key_hash,
@@ -409,6 +462,31 @@ _gtk_key_hash_lookup (GtkKeyHash *key_hash,
}
}
+ if (!have_exact && results)
+ {
+ /* If there are fuzzy matches, check that the current group doesn't also
+ * define these keyvals; if yes, discard results because a widget up in
+ * the stack may have an exact match and we don't want to 'steal' it.
+ */
+ gint oldkeyval;
+ GtkKeyHashEntry *keyhashentry;
+
+ results = sort_lookup_results_by_keyval (results);
+ for (l = results; l; l = l->next)
+ {
+ keyhashentry = l->data;
+ if (l == results || oldkeyval != keyhashentry->keyval)
+ {
+ oldkeyval = keyhashentry->keyval;
+ if (keyval_in_group (key_hash->keymap, oldkeyval, group))
+ {
+ g_slist_free (results);
+ return NULL;
+ }
+ }
+ }
+ }
+
results = sort_lookup_results (results);
for (l = results; l; l = l->next)
l->data = ((GtkKeyHashEntry *)l->data)->value;
@@ -442,7 +520,7 @@ _gtk_key_hash_lookup_keyval (GtkKeyHash *key_hash,
if (!keyval) /* Key without symbol */
return NULL;
- /* Find some random keycode for this keycode
+ /* Find some random keycode for this keyval
*/
gdk_keymap_get_entries_for_keyval (key_hash->keymap, keyval,
&keys, &n_keys);