summaryrefslogtreecommitdiff
path: root/gtk/gtkkeyhash.c
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>2002-09-23 21:35:00 +0000
committerOwen Taylor <otaylor@src.gnome.org>2002-09-23 21:35:00 +0000
commita16b63eb359a5b85c9a34ab7e5a25009e4f7a452 (patch)
tree3b6ba2515dc8ba5f8c0fc04acf2d7430d435e613 /gtk/gtkkeyhash.c
parentbe19be61b7c7b10a14b3105e0ff48398080b9463 (diff)
downloadgtk+-a16b63eb359a5b85c9a34ab7e5a25009e4f7a452.tar.gz
Add a keys_changed signal emitted when the keymap changes. (#72148)
Mon Sep 23 16:48:46 2002 Owen Taylor <otaylor@redhat.com> * gdk/gdkkeys.[ch] gdk/x11/gdkkeys-x11.c gdk/x11/gdkevents-x11.c: Add a keys_changed signal emitted when the keymap changes. (#72148) * gtk/gtkkeyhash.c (_gtk_key_hash_remove_entry): Hook up code to handle keymap changes, change to keep a linked list of keymap entries so that we can reinsert them in the same order on a keymap change.
Diffstat (limited to 'gtk/gtkkeyhash.c')
-rw-r--r--gtk/gtkkeyhash.c143
1 files changed, 82 insertions, 61 deletions
diff --git a/gtk/gtkkeyhash.c b/gtk/gtkkeyhash.c
index c08f018402..7dbfcf67ee 100644
--- a/gtk/gtkkeyhash.c
+++ b/gtk/gtkkeyhash.c
@@ -21,20 +21,18 @@
#include "gtkdebug.h"
#include "gtkkeyhash.h"
-/* We need to add a ::changed signal to GdkKeyMap to properly deal
- * with changes to the key map while we are running.
- */
-#undef HAVE_CHANGED_SIGNAL
-
typedef struct _GtkKeyHashEntry GtkKeyHashEntry;
struct _GtkKeyHashEntry
{
guint keyval;
GdkModifierType modifiers;
- GdkKeymapKey *keys;
- gint n_keys;
gpointer value;
+
+ /* Set as a side effect of generating key_hash->keycode_hash
+ */
+ GdkKeymapKey *keys;
+ gint n_keys;
};
struct _GtkKeyHash
@@ -42,6 +40,7 @@ struct _GtkKeyHash
GdkKeymap *keymap;
GHashTable *keycode_hash;
GHashTable *reverse_hash;
+ GList *entries_list;
GDestroyNotify destroy_notify;
};
@@ -60,6 +59,7 @@ key_hash_insert_entry (GtkKeyHash *key_hash,
{
gint i;
+ g_free (entry->keys);
gdk_keymap_get_entries_for_keyval (key_hash->keymap,
entry->keyval,
&entry->keys, &entry->n_keys);
@@ -75,33 +75,39 @@ key_hash_insert_entry (GtkKeyHash *key_hash,
}
}
-#ifdef HAVE_CHANGED_SIGNAL
-static void
-key_hash_reinsert_entry (gpointer key,
- gpointer value,
- gpointer data)
+static GHashTable *
+key_hash_get_keycode_hash (GtkKeyHash *key_hash)
{
- GtkKeyHashEntry *entry = value;
- GtkKeyHash *key_hash = data;
+ if (!key_hash->keycode_hash)
+ {
+ GList *tmp_list;
+
+ key_hash->keycode_hash = g_hash_table_new (g_direct_hash, NULL);
+
+ /* Preserve the original insertion order
+ */
+ for (tmp_list = g_list_last (key_hash->entries_list);
+ tmp_list;
+ tmp_list = tmp_list->prev)
+ key_hash_insert_entry (key_hash, tmp_list->data);
+ }
- g_free (entry->keys);
- key_hash_insert_entry (key_hash, entry);
+ return key_hash->keycode_hash;
}
static void
-key_hash_keymap_changed (GdkKeymap *keymap,
- GtkKeyHash *key_hash)
+key_hash_keys_changed (GdkKeymap *keymap,
+ GtkKeyHash *key_hash)
{
- /* The keymap changed, so we have to clear and reinsert all our entries
+ /* The keymap changed, so we have to regenerate the keycode hash
*/
- g_hash_table_foreach (key_hash->keycode_hash, key_hash_clear_keycode, NULL);
-
- /* FIXME: Here we reinsert in random order, but I think we actually have to
- * insert in the same order as the original order to keep GtkBindingSet happy.
- */
- g_hash_table_foreach (key_hash->reverse_hash, key_hash_reinsert_entry, key_hash);
+ if (key_hash->keycode_hash)
+ {
+ g_hash_table_foreach (key_hash->keycode_hash, key_hash_clear_keycode, NULL);
+ g_hash_table_destroy (key_hash->keycode_hash);
+ key_hash->keycode_hash = NULL;
+ }
}
-#endif /* HAVE_CHANGED_SIGNAL */
/**
* _gtk_key_hash_new:
@@ -120,12 +126,11 @@ _gtk_key_hash_new (GdkKeymap *keymap,
GtkKeyHash *key_hash = g_new (GtkKeyHash, 1);
key_hash->keymap = keymap;
-#ifdef HAVE_CHANGED_SIGNAL
- g_signal_connect (keymap, "changed",
- G_CALLBACK (key_hash_keymap_changed), key_hash);
-#endif
+ g_signal_connect (keymap, "keys_changed",
+ G_CALLBACK (key_hash_keys_changed), key_hash);
- key_hash->keycode_hash = g_hash_table_new (g_direct_hash, NULL);
+ key_hash->entries_list = NULL;
+ key_hash->keycode_hash = NULL;
key_hash->reverse_hash = g_hash_table_new (g_direct_hash, NULL);
key_hash->destroy_notify = item_destroy_notify;
@@ -144,8 +149,7 @@ key_hash_free_entry (GtkKeyHash *key_hash,
}
static void
-key_hash_free_entry_foreach (gpointer key,
- gpointer value,
+key_hash_free_entry_foreach (gpointer value,
gpointer data)
{
GtkKeyHashEntry *entry = value;
@@ -163,16 +167,20 @@ key_hash_free_entry_foreach (gpointer key,
void
_gtk_key_hash_free (GtkKeyHash *key_hash)
{
-#if HAVE_CHANGED_SIGNAL
g_signal_handlers_disconnect_by_func (key_hash->keymap,
- G_CALLBACK (key_hash_keymap_changed), key_hash);
-#endif
+ G_CALLBACK (key_hash_keys_changed), key_hash);
- g_hash_table_foreach (key_hash->keycode_hash, key_hash_clear_keycode, NULL);
- g_hash_table_foreach (key_hash->reverse_hash, key_hash_free_entry_foreach, key_hash);
- g_hash_table_destroy (key_hash->keycode_hash);
+ if (key_hash->keycode_hash)
+ {
+ g_hash_table_foreach (key_hash->keycode_hash, key_hash_clear_keycode, NULL);
+ g_hash_table_destroy (key_hash->keycode_hash);
+ }
+
g_hash_table_destroy (key_hash->reverse_hash);
+ g_list_foreach (key_hash->entries_list, key_hash_free_entry_foreach, key_hash);
+ g_list_free (key_hash->entries_list);
+
g_free (key_hash);
}
@@ -196,9 +204,13 @@ _gtk_key_hash_add_entry (GtkKeyHash *key_hash,
entry->value = value;
entry->keyval = keyval;
entry->modifiers = modifiers;
+ entry->keys = NULL;
- g_hash_table_insert (key_hash->reverse_hash, value, entry);
- key_hash_insert_entry (key_hash, entry);
+ key_hash->entries_list = g_list_prepend (key_hash->entries_list, entry);
+ g_hash_table_insert (key_hash->reverse_hash, value, key_hash->entries_list);
+
+ if (key_hash->keycode_hash)
+ key_hash_insert_entry (key_hash, entry);
}
/**
@@ -213,30 +225,37 @@ void
_gtk_key_hash_remove_entry (GtkKeyHash *key_hash,
gpointer value)
{
- GtkKeyHashEntry *entry = g_hash_table_lookup (key_hash->reverse_hash, value);
- if (entry)
+ GList *entry_node = g_hash_table_lookup (key_hash->reverse_hash, value);
+
+ if (entry_node)
{
- gint i;
+ GtkKeyHashEntry *entry = entry_node->data;
- for (i = 0; i < entry->n_keys; i++)
+ if (key_hash->keycode_hash)
{
- GSList *old_keys = g_hash_table_lookup (key_hash->keycode_hash,
- GUINT_TO_POINTER (entry->keys[i].keycode));
-
- GSList *new_keys = g_slist_remove (old_keys, entry);
- if (new_keys != old_keys)
+ gint i;
+
+ for (i = 0; i < entry->n_keys; i++)
{
- if (new_keys)
- g_hash_table_insert (key_hash->keycode_hash,
- GUINT_TO_POINTER (entry->keys[i].keycode),
- new_keys);
- else
- g_hash_table_remove (key_hash->keycode_hash,
- GUINT_TO_POINTER (entry->keys[i].keycode));
+ GSList *old_keys = g_hash_table_lookup (key_hash->keycode_hash,
+ GUINT_TO_POINTER (entry->keys[i].keycode));
+
+ GSList *new_keys = g_slist_remove (old_keys, entry);
+ if (new_keys != old_keys)
+ {
+ if (new_keys)
+ g_hash_table_insert (key_hash->keycode_hash,
+ GUINT_TO_POINTER (entry->keys[i].keycode),
+ new_keys);
+ else
+ g_hash_table_remove (key_hash->keycode_hash,
+ GUINT_TO_POINTER (entry->keys[i].keycode));
+ }
}
}
-
- g_hash_table_remove (key_hash->reverse_hash, value);
+
+ g_hash_table_remove (key_hash->reverse_hash, entry_node);
+ key_hash->entries_list = g_list_delete_link (key_hash->entries_list, entry_node);
key_hash_free_entry (key_hash, entry);
}
@@ -304,7 +323,8 @@ _gtk_key_hash_lookup (GtkKeyHash *key_hash,
GdkModifierType state,
gint group)
{
- GSList *keys = g_hash_table_lookup (key_hash->keycode_hash, GUINT_TO_POINTER ((guint)hardware_keycode));
+ GHashTable *keycode_hash = key_hash_get_keycode_hash (key_hash);
+ GSList *keys = g_hash_table_lookup (keycode_hash, GUINT_TO_POINTER ((guint)hardware_keycode));
GSList *results = NULL;
gboolean have_exact = FALSE;
guint keyval;
@@ -404,7 +424,8 @@ _gtk_key_hash_lookup_keyval (GtkKeyHash *key_hash,
if (n_keys)
{
- GSList *entries = g_hash_table_lookup (key_hash->keycode_hash, GUINT_TO_POINTER (keys[0].keycode));
+ GHashTable *keycode_hash = key_hash_get_keycode_hash (key_hash);
+ GSList *entries = g_hash_table_lookup (keycode_hash, GUINT_TO_POINTER (keys[0].keycode));
while (entries)
{