Index: gtk/gtkbuilderprivate.h
===================================================================
--- gtk/gtkbuilderprivate.h	(revision 18969)
+++ gtk/gtkbuilderprivate.h	(working copy)
@@ -42,6 +42,7 @@
   gchar *constructor;
   GSList *properties;
   GSList *signals;
+  GSList *bindings;
   GObject *object;
   CommonInfo *parent;
 } ObjectInfo;
@@ -74,6 +75,15 @@
 } SignalInfo;
 
 typedef struct {
+  TagInfo tag;
+  gchar *object_name;
+  gchar *property;
+  gchar *settings;
+  gchar *key;
+  int flags;
+} BindingInfo;
+
+typedef struct {
   GMarkupParser *parser;
   gchar *tagname;
   const gchar *start;
@@ -107,9 +117,13 @@
                             ChildInfo *child_info);
 void      _gtk_builder_add_signals (GtkBuilder *builder,
 				    GSList     *signals);
+void      _gtk_builder_add_bindings (GtkBuilder *builder,
+                                     GSList     *bindings);
 void      _gtk_builder_finish (GtkBuilder *builder);
 void _free_signal_info (SignalInfo *info,
                         gpointer user_data);
+void _free_binding_info (BindingInfo *info,
+                         gpointer user_data);
 gboolean _gtk_builder_boolean_from_string (const gchar  *string,
 					   gboolean     *value,
 					   GError      **error);
Index: gtk/gtkbuilder.c
===================================================================
--- gtk/gtkbuilder.c	(revision 18969)
+++ gtk/gtkbuilder.c	(working copy)
@@ -67,6 +67,7 @@
   GHashTable *objects;
   GHashTable *delayed_properties;
   GSList *signals;
+  GSList *bindings;
   gchar *current_root;
   GSList *root_objects;
   gchar *filename;
@@ -141,6 +142,9 @@
   g_slist_foreach (priv->signals, (GFunc) _free_signal_info, NULL);
   g_slist_free (priv->signals);
   
+  g_slist_foreach (priv->bindings, (GFunc) _free_binding_info, NULL);
+  g_slist_free (priv->bindings);
+
   g_slist_foreach (priv->root_objects, (GFunc) g_object_unref, NULL);
   g_slist_free (priv->root_objects);
 
@@ -554,6 +558,14 @@
                                            g_slist_copy (signals));
 }
 
+void
+_gtk_builder_add_bindings (GtkBuilder *builder,
+			   GSList     *bindings)
+{
+  builder->priv->bindings = g_slist_concat (builder->priv->bindings,
+                                            g_slist_copy (bindings));
+}
+
 static void
 apply_delayed_properties (const gchar *window_name,
                           GSList      *props,
@@ -741,6 +753,34 @@
   return g_hash_table_lookup (builder->priv->objects, name);
 }
 
+/**
+ * gtk_builder_add_object:
+ * @builder: a #GtkBuilder
+ * @name: name of object
+ * @object: the object
+ *
+ * Add a GObject to the set of objects known by this builder.  The
+ * new object will be known by @name.
+ *
+ * This call sinks the object.  The object may be referenced by other
+ * objects created by the builder.
+ *
+ * Since 2.14
+ **/
+void
+gtk_builder_add_object (GtkBuilder  *builder,
+                        const gchar *name,
+                        GObject     *object)
+{
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+  g_return_if_fail (name != NULL);
+  g_return_if_fail (object != NULL);
+
+  builder->priv->root_objects =
+    g_slist_prepend (builder->priv->root_objects, object);
+  g_hash_table_insert (builder->priv->objects, g_strdup (name), object);
+}
+
 static void
 object_add_to_list (gchar    *object_id,
                     GObject  *object,
@@ -968,6 +1008,72 @@
 }
 
 /**
+ * GtkBuilderBindFunc:
+ * @builder: a #GtkBuilder
+ * @object: object to bind a property of
+ * @property: name of the property
+ * @settings: name of the settings object
+ * @key: name of the key to bind to
+ * @flags: the binding flags
+ * @user_data: user data
+ *
+ * This is the signature of a function used to bind settings.  It is used
+ * by the gtk_builder_connect_signals_full() method to allow the programmer
+ * to have more control over the settings binding process.  For example, it
+ * allows binding to settings objects that are not known to the builder.
+ *
+ * Since: 2.14
+ **/
+
+/**
+ * gtk_builder_bind_settings_full:
+ * @builder: a #GtkBuilder
+ * @func: the function used to bind the settings
+ * @user_data: arbitrary data that will be passed to the bind function
+ *
+ * Calls @func on each property binding declared in the markup.
+ *
+ * Since: 2.14
+ **/
+void
+gtk_builder_bind_settings_full (GtkBuilder         *builder,
+                                GtkBuilderBindFunc  func,
+                                gpointer            user_data)
+{
+  GSList *l;
+  
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+  g_return_if_fail (func != NULL);
+  
+  if (!builder->priv->bindings)
+    return;
+
+  builder->priv->bindings = g_slist_reverse (builder->priv->bindings);
+  for (l = builder->priv->bindings; l; l = l->next)
+    {
+      BindingInfo *binding = l->data;
+      GObject *object;
+
+      g_assert (binding != NULL);
+      g_assert (binding->property != NULL);
+      g_assert (binding->settings != NULL);
+      g_assert (binding->key != NULL);
+
+      object = g_hash_table_lookup (builder->priv->objects,
+				    binding->object_name);
+      g_assert (object != NULL);
+
+      func (builder, object, binding->property,
+            binding->settings, binding->key,
+            binding->flags, user_data);
+    }
+
+  g_slist_foreach (builder->priv->bindings, (GFunc)_free_binding_info, NULL);
+  g_slist_free (builder->priv->bindings);
+  builder->priv->bindings = NULL;
+}
+
+/**
  * gtk_builder_value_from_string:
  * @builder: a #GtkBuilder
  * @pspec: the #GParamSpec for the property
Index: gtk/gtkbuilder.h
===================================================================
--- gtk/gtkbuilder.h	(revision 18969)
+++ gtk/gtkbuilder.h	(working copy)
@@ -83,6 +83,14 @@
 				       GConnectFlags  flags,
 				       gpointer       user_data);
 
+typedef void (*GtkBuilderBindFunc) (GtkBuilder    *builder,
+				    GObject       *object,
+				    const gchar   *property,
+				    const gchar   *settings,
+                                    const gchar   *key,
+				    int            flags,
+				    gpointer       user_data);
+
 GType        gtk_builder_get_type                (void) G_GNUC_CONST;
 GtkBuilder*  gtk_builder_new                     (void);
 
@@ -95,12 +103,18 @@
                                                   GError       **error);
 GObject*     gtk_builder_get_object              (GtkBuilder    *builder,
                                                   const gchar   *name);
+void         gtk_builder_add_object              (GtkBuilder    *builder,
+                                                  const gchar   *name,
+                                                  GObject       *object);
 GSList*      gtk_builder_get_objects             (GtkBuilder    *builder);
 void         gtk_builder_connect_signals         (GtkBuilder    *builder,
 						  gpointer       user_data);
 void         gtk_builder_connect_signals_full    (GtkBuilder    *builder,
                                                   GtkBuilderConnectFunc func,
 						  gpointer       user_data);
+void         gtk_builder_bind_settings_full      (GtkBuilder    *builder,
+                                                  GtkBuilderBindFunc func,
+                                                  gpointer       user_data);
 void         gtk_builder_set_translation_domain  (GtkBuilder   	*builder,
                                                   const gchar  	*domain);
 const gchar* gtk_builder_get_translation_domain  (GtkBuilder   	*builder);
Index: gtk/gtk.symbols
===================================================================
--- gtk/gtk.symbols	(revision 18969)
+++ gtk/gtk.symbols	(working copy)
@@ -442,6 +442,7 @@
 gtk_builder_add_from_file
 gtk_builder_add_from_string
 gtk_builder_error_quark
+gtk_builder_add_object
 gtk_builder_get_object
 gtk_builder_get_objects
 gtk_builder_get_translation_domain
@@ -451,6 +452,7 @@
 gtk_builder_set_translation_domain
 gtk_builder_connect_signals
 gtk_builder_connect_signals_full
+gtk_builder_bind_settings_full
 gtk_builder_value_from_string
 gtk_builder_value_from_string_type
 #endif
Index: gtk/gtkbuilderparser.c
===================================================================
--- gtk/gtkbuilderparser.c	(revision 18969)
+++ gtk/gtkbuilderparser.c	(working copy)
@@ -307,8 +307,10 @@
 static void
 free_object_info (ObjectInfo *info)
 {
-  /* Do not free the signal items, which GtkBuilder takes ownership of */
+  /* Do not free the signal/bindings items,
+   * which GtkBuilder takes ownership of */
   g_slist_free (info->signals);
+  g_slist_free (info->bindings);
   g_slist_foreach (info->properties,
                    (GFunc)free_property_info, NULL);
   g_slist_free (info->properties);
@@ -504,6 +506,61 @@
   info->tag.name = element_name;
 }
 
+static void
+parse_binding (ParserData   *data,
+               const gchar  *element_name,
+               const gchar **names,
+               const gchar **values,
+               GError      **error)
+{
+  BindingInfo *info;
+  gchar *property = NULL;
+  gchar *settings = NULL;
+  gchar *key = NULL;
+  int i;
+
+  g_assert (data->stack != NULL);
+
+  for (i = 0; names[i] != NULL; i++)
+    {
+      if (strcmp (names[i], "property") == 0)
+	property = g_strdup (values[i]);
+      else if (strcmp (names[i], "settings") == 0)
+	settings = g_strdup (values[i]);
+      else if (strcmp (names[i], "key") == 0)
+	key = g_strdup (values[i]);
+      else
+	{
+	  error_invalid_attribute (data, element_name, names[i], error);
+	  return;
+	}
+    }
+
+  if (!property)
+    {
+      error_missing_attribute (data, element_name, "property", error);
+      return;
+    }
+  else if (!settings)
+    {
+      error_missing_attribute (data, element_name, "settings", error);
+      return;
+    }
+  else if (!key)
+    {
+      error_missing_attribute (data, element_name, "key", error);
+      return;
+    }
+
+  info = g_slice_new0 (BindingInfo);
+  info->property = property;
+  info->settings = settings;
+  info->key = key;
+  state_push (data, info);
+
+  info->tag.name = element_name;
+}
+
 /* Called by GtkBuilder */
 void
 _free_signal_info (SignalInfo *info,
@@ -516,6 +573,16 @@
   g_slice_free (SignalInfo, info);
 }
 
+void
+_free_binding_info (BindingInfo *info,
+                    gpointer user_data)
+{
+  g_free (info->property);
+  g_free (info->settings);
+  g_free (info->key);
+  g_slice_free (BindingInfo, info);
+}
+
 static void
 parse_interface (ParserData   *data,
 		 const gchar  *element_name,
@@ -727,6 +794,8 @@
     parse_property (data, element_name, names, values, error);
   else if (strcmp (element_name, "signal") == 0)
     parse_signal (data, element_name, names, values, error);
+  else if (strcmp (element_name, "binding") == 0)
+    parse_binding (data, element_name, names, values, error);
   else if (strcmp (element_name, "interface") == 0)
     parse_interface (data, element_name, names, values, error);
   else if (strcmp (element_name, "placeholder") == 0)
@@ -775,6 +844,7 @@
           GTK_BUILDABLE_GET_IFACE (object_info->object)->parser_finished)
         data->finalizers = g_slist_prepend (data->finalizers, object_info->object);
       _gtk_builder_add_signals (data->builder, object_info->signals);
+      _gtk_builder_add_bindings (data->builder, object_info->bindings);
 
       free_object_info (object_info);
     }
@@ -809,6 +879,14 @@
       object_info->signals =
         g_slist_prepend (object_info->signals, signal_info);
     }
+  else if (strcmp (element_name, "binding") == 0)
+    {
+      BindingInfo *binding_info = state_pop_info (data, BindingInfo);
+      ObjectInfo *object_info = (ObjectInfo*)state_peek_info (data, CommonInfo);
+      binding_info->object_name = g_strdup (object_info->id);
+      object_info->bindings =
+	g_slist_prepend (object_info->bindings, binding_info);
+    }
   else if (strcmp (element_name, "interface") == 0)
     {
     }
Index: docs/reference/gtk/gtk-sections.txt
===================================================================
--- docs/reference/gtk/gtk-sections.txt	(revision 18969)
+++ docs/reference/gtk/gtk-sections.txt	(working copy)
@@ -478,10 +478,12 @@
 gtk_builder_new
 gtk_builder_add_from_file
 gtk_builder_add_from_string
+gtk_builder_add_object
 gtk_builder_get_object
 gtk_builder_get_objects
 gtk_builder_connect_signals
 gtk_builder_connect_signals_full
+gtk_builder_bind_settings_full
 gtk_builder_set_translation_domain
 gtk_builder_get_translation_domain
 gtk_builder_get_type_from_name
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 18969)
+++ ChangeLog	(working copy)
@@ -1,3 +1,19 @@
+2007-11-06  Ryan Lortie  <desrt@desrt.ca>
+
+	* gtk/gtkbuilderprivate.h:
+	* gtk/gtkbuilderparser.c:
+	* gtk/gtkbuilder.c:
+	* gtk/gtkbuilder.h: Add support for <binding> tag to bind a property
+	of a object declared in the builder markup to a key on a settings
+	object.  Add support for manually inserting named objects into the
+	builder which may then be used by the markup.
+
+	New public type: GtkBuilderBindFunc
+	New functions: gtk_builder_add_object, gtk_builder_bind_settings_full
+
+	* gtk/gtk.symbols:
+	* docs/reference/gtk/gtk-sections.txt: Update accordingly.
+
 2007-11-06  Michael Natterer  <mitch@imendio.com>
 
 	* gtk/gtkmenu.c (gtk_menu_popup): call gdk_flush() after showing
