]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkbindings.c
Use the correct screen for getting the height. (Fix from Stephen Browne,
[~andy/gtk] / gtk / gtkbindings.c
index fcc672ea5e98aae5d50fe3991bb19c286e9f62a0..d6c65a022c21c8b4a481c376108c14e0d6399a76 100644 (file)
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
-#include <ctype.h>
 #include <string.h>
 #include <stdarg.h>
+#include <gdkkeysyms.h>
 #include "gtkbindings.h"
-#include "gtksignal.h"
+#include "gtkkeyhash.h"
 #include "gtkwidget.h"
 #include "gtkrc.h"
 
@@ -50,6 +50,7 @@ typedef struct {
 
 /* --- variables --- */
 static GHashTable      *binding_entry_hash_table = NULL;
+static GSList           *binding_key_hashes = NULL;
 static GSList          *binding_set_list = NULL;
 static const gchar     *key_class_binding_set = "gtk-class-binding-set";
 static GQuark           key_id_class_binding_set = 0;
@@ -78,7 +79,7 @@ binding_signal_free (GtkBindingSignal *sig)
   
   for (i = 0; i < sig->n_args; i++)
     {
-      if (GTK_FUNDAMENTAL_TYPE (sig->args[i].arg_type) == GTK_TYPE_STRING)
+      if (G_TYPE_FUNDAMENTAL (sig->args[i].arg_type) == G_TYPE_STRING)
        g_free (sig->args[i].d.string_data);
     }
   g_free (sig->args);
@@ -108,11 +109,81 @@ binding_entries_compare (gconstpointer  a,
   return (ea->keyval == eb->keyval && ea->modifiers == eb->modifiers);
 }
 
+static void
+binding_key_hash_insert_entry (GtkKeyHash      *key_hash,
+                              GtkBindingEntry *entry)
+{
+  guint keyval = entry->keyval;
+  
+  /* We store lowercased accelerators. To deal with this, if <Shift>
+   * was specified, uppercase.
+   */
+  if (entry->modifiers & GDK_SHIFT_MASK)
+    {
+      if (keyval == GDK_Tab)
+       keyval = GDK_ISO_Left_Tab;
+      else
+       keyval = gdk_keyval_to_upper (keyval);
+    }
+  
+  _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers & ~GDK_RELEASE_MASK, entry);
+}
+
+static void
+binding_key_hash_destroy (gpointer data)
+{
+  GtkKeyHash *key_hash = data;
+  
+  binding_key_hashes = g_slist_remove (binding_key_hashes, key_hash);
+  _gtk_key_hash_free (key_hash);
+}
+
+static void
+insert_entries_into_key_hash (gpointer key,
+                             gpointer value,
+                             gpointer data)
+{
+  GtkKeyHash *key_hash = data;
+  GtkBindingEntry *entry = value;
+
+  for (; entry; entry = entry->hash_next)
+    binding_key_hash_insert_entry (key_hash, entry);
+}
+
+static GtkKeyHash *
+binding_key_hash_for_keymap (GdkKeymap *keymap)
+{
+  static GQuark key_hash_quark = 0;
+  GtkKeyHash *key_hash;
+
+  if (!key_hash_quark)
+    key_hash_quark = g_quark_from_static_string ("gtk-binding-key-hash");
+  
+  key_hash = g_object_get_qdata (G_OBJECT (keymap), key_hash_quark);
+
+  if (!key_hash)
+    {
+      key_hash = _gtk_key_hash_new (keymap, NULL);
+      g_object_set_qdata_full (G_OBJECT (keymap), key_hash_quark, key_hash, binding_key_hash_destroy);
+
+      if (binding_entry_hash_table)
+       g_hash_table_foreach (binding_entry_hash_table,
+                             insert_entries_into_key_hash,
+                             key_hash);
+
+      binding_key_hashes = g_slist_prepend (binding_key_hashes, key_hash);
+    }
+
+  return key_hash;
+}
+
+
 static GtkBindingEntry*
-binding_entry_new (GtkBindingSet *binding_set,
-                  guint          keyval,
-                  guint          modifiers)
+binding_entry_new (GtkBindingSet  *binding_set,
+                  guint           keyval,
+                  GdkModifierType modifiers)
 {
+  GSList *tmp_list;
   GtkBindingEntry *entry;
   
   if (!binding_entry_hash_table)
@@ -133,6 +204,12 @@ binding_entry_new (GtkBindingSet *binding_set,
   if (entry->hash_next)
     g_hash_table_remove (binding_entry_hash_table, entry->hash_next);
   g_hash_table_insert (binding_entry_hash_table, entry, entry);
+
+  for (tmp_list = binding_key_hashes; tmp_list; tmp_list = tmp_list->next)
+    {
+      GtkKeyHash *key_hash = tmp_list->data;
+      binding_key_hash_insert_entry (key_hash, entry);
+    }
   
   return entry;
 }
@@ -168,6 +245,7 @@ binding_entry_destroy (GtkBindingEntry *entry)
   register GtkBindingEntry *tmp;
   GtkBindingEntry *begin;
   register GtkBindingEntry *last;
+  GSList *tmp_list;
 
   /* unlink from binding set
    */
@@ -215,6 +293,12 @@ binding_entry_destroy (GtkBindingEntry *entry)
       g_hash_table_insert (binding_entry_hash_table, begin, begin);
     }
 
+  for (tmp_list = binding_key_hashes; tmp_list; tmp_list = tmp_list->next)
+    {
+      GtkKeyHash *key_hash = tmp_list->data;
+      _gtk_key_hash_remove_entry (key_hash, entry);
+    }
+
   entry->destroyed = TRUE;
 
   if (!entry->in_emission)
@@ -222,24 +306,9 @@ binding_entry_destroy (GtkBindingEntry *entry)
 }
 
 static GtkBindingEntry*
-binding_ht_lookup_list (guint keyval,
-                       guint modifiers)
-{
-  GtkBindingEntry lookup_entry = { 0 };
-  
-  if (!binding_entry_hash_table)
-    return NULL;
-  
-  lookup_entry.keyval = keyval;
-  lookup_entry.modifiers = modifiers;
-  
-  return g_hash_table_lookup (binding_entry_hash_table, &lookup_entry);
-}
-
-static GtkBindingEntry*
-binding_ht_lookup_entry (GtkBindingSet *set,
-                        guint          keyval,
-                        guint          modifiers)
+binding_ht_lookup_entry (GtkBindingSet  *set,
+                        guint           keyval,
+                        GdkModifierType modifiers)
 {
   GtkBindingEntry lookup_entry = { 0 };
   GtkBindingEntry *entry;
@@ -292,11 +361,11 @@ binding_compose_params (GtkObject       *object,
          g_value_init (&tmp_value, G_TYPE_DOUBLE);
          g_value_set_double (&tmp_value, args->d.double_data);
          break;
-       case  G_TYPE_LONG:
+       case G_TYPE_LONG:
          g_value_init (&tmp_value, G_TYPE_LONG);
          g_value_set_long (&tmp_value, args->d.long_data);
          break;
-       case  G_TYPE_STRING:
+       case G_TYPE_STRING:
          /* gtk_rc_parse_flags/enum() has fancier parsing for this; we can't call
           * that since we don't have a GParamSpec, so just do something simple
           */
@@ -314,6 +383,7 @@ binding_compose_params (GtkObject       *object,
                    enum_value = g_enum_get_value_by_nick (class, args->d.string_data);
                  if (enum_value)
                    {
+                     g_value_init (&tmp_value, *types);
                      g_value_set_enum (&tmp_value, enum_value->value);
                      valid = TRUE;
                    }
@@ -339,6 +409,7 @@ binding_compose_params (GtkObject       *object,
                    flags_value = g_flags_get_value_by_nick (class, args->d.string_data);
                  if (flags_value)
                    {
+                     g_value_init (&tmp_value, *types);
                      g_value_set_flags (&tmp_value, flags_value->value);
                      valid = TRUE;
                    }
@@ -349,7 +420,7 @@ binding_compose_params (GtkObject       *object,
          else
            {
              g_value_init (&tmp_value, G_TYPE_STRING);
-             g_value_set_static_string (params, args->d.string_data);
+             g_value_set_static_string (&tmp_value, args->d.string_data);
            }
          break;
        default:
@@ -357,10 +428,13 @@ binding_compose_params (GtkObject       *object,
          break;
        }
 
-      if (valid && !g_value_transform (&tmp_value, params))
-       valid = FALSE;
+      if (valid)
+       {
+         if (!g_value_transform (&tmp_value, params))
+           valid = FALSE;
 
-      g_value_unset (&tmp_value);
+         g_value_unset (&tmp_value);
+       }
       
       types++;
       params++;
@@ -430,7 +504,7 @@ gtk_binding_entry_activate (GtkBindingEntry *entry,
                     sig->signal_name,
                     g_type_name (G_OBJECT_TYPE (object)));
        }
-      else if (!(query.signal_flags & GTK_RUN_ACTION))
+      else if (!(query.signal_flags & G_SIGNAL_ACTION))
        {
          accelerator = gtk_accelerator_name (entry->keyval, entry->modifiers);
          g_warning ("gtk_binding_entry_activate(): binding \"%s::%s\": "
@@ -489,6 +563,7 @@ gtk_binding_set_new (const gchar    *set_name)
   binding_set->class_branch_pspecs = NULL;
   binding_set->entries = NULL;
   binding_set->current = NULL;
+  binding_set->parsed = FALSE;
   
   binding_set_list = g_slist_prepend (binding_set_list, binding_set);
   
@@ -511,10 +586,10 @@ gtk_binding_set_by_class (gpointer object_class)
   if (binding_set)
     return binding_set;
 
-  binding_set = gtk_binding_set_new (gtk_type_name (GTK_CLASS_TYPE (class)));
+  binding_set = gtk_binding_set_new (g_type_name (G_OBJECT_CLASS_TYPE (class)));
   gtk_binding_set_add_path (binding_set,
                            GTK_PATH_CLASS,
-                           gtk_type_name (GTK_CLASS_TYPE (class)),
+                           g_type_name (G_OBJECT_CLASS_TYPE (class)),
                            GTK_PATH_PRIO_GTK);
   g_dataset_id_set_data (class, key_id_class_binding_set, binding_set);
 
@@ -542,13 +617,12 @@ gtk_binding_set_find (const gchar    *set_name)
 gboolean
 gtk_binding_set_activate (GtkBindingSet         *binding_set,
                          guint           keyval,
-                         guint           modifiers,
+                         GdkModifierType modifiers,
                          GtkObject      *object)
 {
   GtkBindingEntry *entry;
   
   g_return_val_if_fail (binding_set != NULL, FALSE);
-  g_return_val_if_fail (object != NULL, FALSE);
   g_return_val_if_fail (GTK_IS_OBJECT (object), FALSE);
   
   keyval = gdk_keyval_to_lower (keyval);
@@ -564,7 +638,7 @@ gtk_binding_set_activate (GtkBindingSet      *binding_set,
 void
 gtk_binding_entry_clear (GtkBindingSet *binding_set,
                         guint           keyval,
-                        guint           modifiers)
+                        GdkModifierType modifiers)
 {
   GtkBindingEntry *entry;
   
@@ -583,7 +657,7 @@ gtk_binding_entry_clear (GtkBindingSet      *binding_set,
 void
 gtk_binding_entry_remove (GtkBindingSet         *binding_set,
                          guint           keyval,
-                         guint           modifiers)
+                         GdkModifierType modifiers)
 {
   GtkBindingEntry *entry;
   
@@ -600,7 +674,7 @@ gtk_binding_entry_remove (GtkBindingSet      *binding_set,
 void
 gtk_binding_entry_add_signall (GtkBindingSet  *binding_set,
                               guint           keyval,
-                              guint           modifiers,
+                              GdkModifierType modifiers,
                               const gchar    *signal_name,
                               GSList         *binding_args)
 {
@@ -630,19 +704,19 @@ gtk_binding_entry_add_signall (GtkBindingSet  *binding_set,
          binding_signal_free (signal);
          return;
        }
-      switch (GTK_FUNDAMENTAL_TYPE (tmp_arg->arg_type))
+      switch (G_TYPE_FUNDAMENTAL (tmp_arg->arg_type))
        {
-       case  GTK_TYPE_LONG:
-         arg->arg_type = GTK_TYPE_LONG;
+       case  G_TYPE_LONG:
+         arg->arg_type = G_TYPE_LONG;
          arg->d.long_data = tmp_arg->d.long_data;
          break;
-       case  GTK_TYPE_DOUBLE:
-         arg->arg_type = GTK_TYPE_DOUBLE;
+       case  G_TYPE_DOUBLE:
+         arg->arg_type = G_TYPE_DOUBLE;
          arg->d.double_data = tmp_arg->d.double_data;
          break;
-       case  GTK_TYPE_STRING:
+       case  G_TYPE_STRING:
           if (tmp_arg->arg_type != GTK_TYPE_IDENTIFIER)
-           arg->arg_type = GTK_TYPE_STRING;
+           arg->arg_type = G_TYPE_STRING;
          else
            arg->arg_type = GTK_TYPE_IDENTIFIER;
          arg->d.string_data = g_strdup (tmp_arg->d.string_data);
@@ -655,7 +729,7 @@ gtk_binding_entry_add_signall (GtkBindingSet  *binding_set,
          break;
        default:
          g_warning ("gtk_binding_entry_add_signall(): unsupported type `%s' for arg[%u]",
-                    gtk_type_name (arg->arg_type), n);
+                    g_type_name (arg->arg_type), n);
          binding_signal_free (signal);
          return;
        }
@@ -678,7 +752,7 @@ gtk_binding_entry_add_signall (GtkBindingSet  *binding_set,
 void
 gtk_binding_entry_add_signal (GtkBindingSet  *binding_set,
                              guint           keyval,
-                             guint           modifiers,
+                             GdkModifierType modifiers,
                              const gchar    *signal_name,
                              guint           n_args,
                              ...)
@@ -690,9 +764,6 @@ gtk_binding_entry_add_signal (GtkBindingSet  *binding_set,
   g_return_if_fail (binding_set != NULL);
   g_return_if_fail (signal_name != NULL);
   
-  keyval = gdk_keyval_to_lower (keyval);
-  modifiers = modifiers & BINDING_MOD_MASK ();
-
   va_start (args, n_args);
   slist = NULL;
   for (i = 0; i < n_args; i++)
@@ -703,46 +774,46 @@ gtk_binding_entry_add_signal (GtkBindingSet  *binding_set,
       slist = g_slist_prepend (slist, arg);
 
       arg->arg_type = va_arg (args, GtkType);
-      switch (GTK_FUNDAMENTAL_TYPE (arg->arg_type))
+      switch (G_TYPE_FUNDAMENTAL (arg->arg_type))
        {
          /* for elaborated commenting about var args collection, take a look
           * at gtk_arg_collect_value() in gtkargcollector.c
           */
-       case GTK_TYPE_CHAR:
-       case GTK_TYPE_UCHAR:
-       case GTK_TYPE_INT:
-       case GTK_TYPE_UINT:
-       case GTK_TYPE_BOOL:
-       case GTK_TYPE_ENUM:
-       case GTK_TYPE_FLAGS:
-         arg->arg_type = GTK_TYPE_LONG;
+       case G_TYPE_CHAR:
+       case G_TYPE_UCHAR:
+       case G_TYPE_INT:
+       case G_TYPE_UINT:
+       case G_TYPE_BOOLEAN:
+       case G_TYPE_ENUM:
+       case G_TYPE_FLAGS:
+         arg->arg_type = G_TYPE_LONG;
          arg->d.long_data = va_arg (args, gint);
          break;
-       case GTK_TYPE_LONG:
-       case GTK_TYPE_ULONG:
-         arg->arg_type = GTK_TYPE_LONG;
+       case G_TYPE_LONG:
+       case G_TYPE_ULONG:
+         arg->arg_type = G_TYPE_LONG;
          arg->d.long_data = va_arg (args, glong);
          break;
-       case GTK_TYPE_FLOAT:
-       case GTK_TYPE_DOUBLE:
-         arg->arg_type = GTK_TYPE_DOUBLE;
+       case G_TYPE_FLOAT:
+       case G_TYPE_DOUBLE:
+         arg->arg_type = G_TYPE_DOUBLE;
          arg->d.double_data = va_arg (args, gdouble);
          break;
-       case GTK_TYPE_STRING:
+       case G_TYPE_STRING:
          if (arg->arg_type != GTK_TYPE_IDENTIFIER)
-           arg->arg_type = GTK_TYPE_STRING;
+           arg->arg_type = G_TYPE_STRING;
          arg->d.string_data = va_arg (args, gchar*);
          if (!arg->d.string_data)
            {
              g_warning ("gtk_binding_entry_add_signal(): type `%s' arg[%u] is `NULL'",
-                        gtk_type_name (arg->arg_type),
+                        g_type_name (arg->arg_type),
                         i);
              i += n_args + 1;
            }
          break;
        default:
          g_warning ("gtk_binding_entry_add_signal(): unsupported type `%s' for arg[%u]",
-                    gtk_type_name (arg->arg_type), i);
+                    g_type_name (arg->arg_type), i);
          i += n_args + 1;
          break;
        }
@@ -832,7 +903,7 @@ gtk_binding_set_add_path (GtkBindingSet          *binding_set,
     }
 }
 
-static inline gboolean
+static gboolean
 binding_match_activate (GSList          *pspec_list,
                        GtkObject       *object,
                        guint            path_length,
@@ -874,20 +945,38 @@ gtk_binding_pattern_compare (gconstpointer new_pattern,
   return np->seq_id < ep->seq_id;
 }
 
-static inline GSList*
-gtk_binding_entries_sort_patterns (GtkBindingEntry    *entries,
-                                  GtkPathType         path_id)
+static GSList*
+gtk_binding_entries_sort_patterns (GSList      *entries,
+                                  GtkPathType  path_id,
+                                  gboolean     is_release)
 {
   GSList *patterns;
+  GSList *tmp_list;
 
   patterns = NULL;
-  while (entries)
+  for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
+    {
+      GtkBindingEntry *entry = tmp_list->data;
+      GtkBindingSet *binding_set;
+
+      binding_set = entry->binding_set;
+      binding_set->current = NULL;
+    }
+  
+  for (; entries; entries = entries->next)
     {
-      register GtkBindingSet *binding_set;
+      GtkBindingEntry *entry = entries->data;
+      GtkBindingSet *binding_set;
       GSList *slist = NULL;
 
-      binding_set = entries->binding_set;
-      binding_set->current = entries;
+      if (is_release != ((entry->modifiers & GDK_RELEASE_MASK) != 0))
+       continue;
+
+      binding_set = entry->binding_set;
+
+      if (binding_set->current)
+       continue;
+      binding_set->current = entry;
 
       switch (path_id)
        {
@@ -909,36 +998,19 @@ gtk_binding_entries_sort_patterns (GtkBindingEntry    *entries,
          pspec = slist->data;
          patterns = g_slist_insert_sorted (patterns, pspec, gtk_binding_pattern_compare);
        }
-
-      entries = entries->hash_next;
     }
 
   return patterns;
 }
-      
 
-gboolean
-gtk_bindings_activate (GtkObject      *object,
-                      guint           keyval,
-                      guint           modifiers)
+static gboolean
+gtk_bindings_activate_list (GtkObject *object,
+                           GSList    *entries,
+                           gboolean   is_release)
 {
-  GtkBindingEntry *entries;
-  GtkWidget *widget;
+  GtkWidget *widget = GTK_WIDGET (object);
   gboolean handled = FALSE;
 
-  g_return_val_if_fail (object != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_OBJECT (object), FALSE);
-
-  if (!GTK_IS_WIDGET (object))
-    return FALSE;
-
-  widget = GTK_WIDGET (object);
-
-  keyval = gdk_keyval_to_lower (keyval);
-  modifiers = modifiers & BINDING_MOD_MASK ();
-
-  entries = binding_ht_lookup_list (keyval, modifiers);
-
   if (!entries)
     return FALSE;
 
@@ -949,7 +1021,7 @@ gtk_bindings_activate (GtkObject      *object,
       GSList *patterns;
 
       gtk_widget_path (widget, &path_length, &path, &path_reversed);
-      patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_WIDGET);
+      patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_WIDGET, is_release);
       handled = binding_match_activate (patterns, object, path_length, path, path_reversed);
       g_slist_free (patterns);
       g_free (path);
@@ -963,7 +1035,7 @@ gtk_bindings_activate (GtkObject      *object,
       GSList *patterns;
 
       gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
-      patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_WIDGET_CLASS);
+      patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_WIDGET_CLASS, is_release);
       handled = binding_match_activate (patterns, object, path_length, path, path_reversed);
       g_slist_free (patterns);
       g_free (path);
@@ -973,24 +1045,24 @@ gtk_bindings_activate (GtkObject      *object,
   if (!handled)
     {
       GSList *patterns;
-      GtkType class_type;
+      GType class_type;
       
-      patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_CLASS);
-      class_type = GTK_OBJECT_TYPE (object);
+      patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_CLASS, is_release);
+      class_type = G_TYPE_FROM_INSTANCE (object);
       while (class_type && !handled)
        {
          guint path_length;
          const gchar *path;
          gchar *path_reversed;
          
-         path = gtk_type_name (class_type);
+         path = g_type_name (class_type);
          path_reversed = g_strdup (path);
          g_strreverse (path_reversed);
          path_length = strlen (path);
          handled = binding_match_activate (patterns, object, path_length, path, path_reversed);
          g_free (path_reversed);
 
-         class_type = gtk_type_parent (class_type);
+         class_type = g_type_parent (class_type);
        }
       g_slist_free (patterns);
     }
@@ -998,11 +1070,82 @@ gtk_bindings_activate (GtkObject      *object,
   return handled;
 }
 
+gboolean
+gtk_bindings_activate (GtkObject      *object,
+                      guint           keyval,
+                      GdkModifierType modifiers)
+{
+  GSList *entries = NULL;
+  GdkDisplay *display;
+  GtkKeyHash *key_hash;
+  gboolean handled = FALSE;
+  gboolean is_release;
+
+  g_return_val_if_fail (GTK_IS_OBJECT (object), FALSE);
+
+  if (!GTK_IS_WIDGET (object))
+    return FALSE;
+
+  is_release = (modifiers & GDK_RELEASE_MASK) != 0;
+  modifiers = modifiers & BINDING_MOD_MASK () & ~GDK_RELEASE_MASK;
+
+  display = gtk_widget_get_display (GTK_WIDGET (object));
+  key_hash = binding_key_hash_for_keymap (gdk_keymap_get_for_display (display));
+  
+  entries = _gtk_key_hash_lookup_keyval (key_hash, keyval, modifiers);
+
+  handled = gtk_bindings_activate_list (object, entries, is_release);
+
+  g_slist_free (entries);
+
+  return handled;
+}
+
+/**
+ * _gtk_bindings_activate_event:
+ * @object: a #GtkObject (generally must be a widget)
+ * @event: a #GdkEventKey
+ * 
+ * Looks up key bindings for @object to find one matching
+ * @event, and if one was found, activate it.
+ * 
+ * Return value: %TRUE if a matching key binding was found
+ **/
+gboolean
+_gtk_bindings_activate_event (GtkObject      *object,
+                             GdkEventKey    *event)
+{
+  GSList *entries = NULL;
+  GdkDisplay *display;
+  GtkKeyHash *key_hash;
+  gboolean handled = FALSE;
+
+  g_return_val_if_fail (GTK_IS_OBJECT (object), FALSE);
+
+  if (!GTK_IS_WIDGET (object))
+    return FALSE;
+
+  display = gtk_widget_get_display (GTK_WIDGET (object));
+  key_hash = binding_key_hash_for_keymap (gdk_keymap_get_for_display (display));
+
+  entries = _gtk_key_hash_lookup (key_hash,
+                                 event->hardware_keycode,
+                                 event->state & BINDING_MOD_MASK () & ~GDK_RELEASE_MASK,
+                                 event->group);
+  
+  handled = gtk_bindings_activate_list (object, entries,
+                                       event->type == GDK_KEY_RELEASE);
+
+  g_slist_free (entries);
+
+  return handled;
+}
+
 static guint
 gtk_binding_parse_signal (GScanner       *scanner,
                          GtkBindingSet  *binding_set,
                          guint           keyval,
-                         guint           modifiers)
+                         GdkModifierType modifiers)
 {
   gchar *signal;
   guint expected_token = 0;
@@ -1049,7 +1192,7 @@ gtk_binding_parse_signal (GScanner       *scanner,
            {
              need_arg = FALSE;
              arg = g_new (GtkBindingArg, 1);
-             arg->arg_type = GTK_TYPE_DOUBLE;
+             arg->arg_type = G_TYPE_DOUBLE;
              arg->d.double_data = scanner->value.v_float;
              if (negate)
                {
@@ -1066,7 +1209,7 @@ gtk_binding_parse_signal (GScanner       *scanner,
            {
              need_arg = FALSE;
              arg = g_new (GtkBindingArg, 1);
-             arg->arg_type = GTK_TYPE_LONG;
+             arg->arg_type = G_TYPE_LONG;
              arg->d.long_data = scanner->value.v_int;
              if (negate)
                {
@@ -1083,7 +1226,7 @@ gtk_binding_parse_signal (GScanner       *scanner,
            {
              need_arg = FALSE;
              arg = g_new (GtkBindingArg, 1);
-             arg->arg_type = GTK_TYPE_STRING;
+             arg->arg_type = G_TYPE_STRING;
              arg->d.string_data = g_strdup (scanner->value.v_string);
              args = g_slist_prepend (args, arg);
            }
@@ -1146,7 +1289,7 @@ gtk_binding_parse_signal (GScanner       *scanner,
       GtkBindingArg *arg;
 
       arg = slist->data;
-      if (GTK_FUNDAMENTAL_TYPE (arg->arg_type) == GTK_TYPE_STRING)
+      if (G_TYPE_FUNDAMENTAL (arg->arg_type) == G_TYPE_STRING)
        g_free (arg->d.string_data);
       g_free (arg);
     }
@@ -1161,7 +1304,7 @@ gtk_binding_parse_bind (GScanner       *scanner,
                        GtkBindingSet  *binding_set)
 {
   guint keyval = 0;
-  guint modifiers = 0;
+  GdkModifierType modifiers = 0;
 
   g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
   
@@ -1233,7 +1376,10 @@ gtk_binding_parse_binding (GScanner       *scanner)
 
   binding_set = gtk_binding_set_find (name);
   if (!binding_set)
-    binding_set = gtk_binding_set_new (name);
+    {
+      binding_set = gtk_binding_set_new (name);
+      binding_set->parsed = 1;
+    }
   g_free (name);
 
   g_scanner_peek_next_token (scanner);
@@ -1258,3 +1404,71 @@ gtk_binding_parse_binding (GScanner       *scanner)
 
   return G_TOKEN_NONE;
 }
+
+static void
+free_pattern_specs (GSList *pattern_specs)
+{
+  GSList *slist;
+
+  for (slist = pattern_specs; slist; slist = slist->next)
+    {
+      PatternSpec *pspec;
+
+      pspec = slist->data;
+
+      g_pattern_spec_free (pspec->pspec);
+      g_free (pspec);
+    }
+
+  g_slist_free (pattern_specs);
+}
+
+static void
+binding_set_delete (GtkBindingSet *binding_set)
+{
+  GtkBindingEntry *entry, *next;
+
+  entry = binding_set->entries;
+  while (entry)
+    {
+      next = entry->set_next;
+      binding_entry_destroy (entry);
+      entry = next;
+    }
+  
+  free_pattern_specs (binding_set->widget_path_pspecs);
+  free_pattern_specs (binding_set->widget_class_pspecs);
+  free_pattern_specs (binding_set->class_branch_pspecs);
+
+  g_free (binding_set->set_name);
+  g_free (binding_set);
+}
+
+/**
+ * _gtk_binding_reset_parsed:
+ * 
+ * Removing all binding sets that were added by
+ * gtk_binding_parse_binding()
+ **/
+void
+_gtk_binding_reset_parsed (void)
+{
+  GSList *slist, *next;
+  
+  slist = binding_set_list;
+  while (slist)
+    {
+      GtkBindingSet *binding_set;
+
+      binding_set = slist->data;
+      next = slist->next;
+
+      if (binding_set->parsed)
+       {
+         binding_set_list = g_slist_delete_link (binding_set_list, slist);
+         binding_set_delete (binding_set);
+       }
+
+      slist = next;
+    }
+}