Index: gtk/gtkactivatable.c
===================================================================
--- gtk/gtkactivatable.c	(revision 0)
+++ gtk/gtkactivatable.c	(revision 0)
@@ -0,0 +1,240 @@
+/* gtkactivatable.c
+ * Copyright (C) 2006-2007 Async Open Source,
+ *                         Johan Dahlin <jdahlin@async.com.br>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include "config.h"
+#include "gtkactivatable.h"
+#include "gtkactiongroup.h"
+#include "gtktypeutils.h"
+#include "gtkprivate.h"
+#include "gtkintl.h"
+#include "gtkalias.h"
+
+
+static void gtk_activatable_class_init (gpointer g_iface);
+
+GType
+gtk_activatable_get_type (void)
+{
+  static GType activatable_type = 0;
+
+  if (!activatable_type)
+    activatable_type =
+      g_type_register_static_simple (G_TYPE_INTERFACE, I_("GtkActivatable"),
+				     sizeof (GtkActivatableIface),
+				     (GClassInitFunc) gtk_activatable_class_init,
+				     0, NULL, 0);
+
+  return activatable_type;
+}
+
+static void
+gtk_activatable_class_init (gpointer g_iface)
+{
+  /**
+   * GtkActivatable:related-action:
+   * 
+   * The action that this activatable will activate and recieve
+   * updates from for various states and possibly appearance.
+   *
+   * Since: 2.16
+   */
+  g_object_interface_install_property (g_iface,
+				       g_param_spec_object ("related-action",
+							    P_("Related Action"),
+							    P_("The action this activatable will activate and receive updates from"),
+							    GTK_TYPE_ACTION,
+							    GTK_PARAM_READWRITE));
+
+  /**
+   * GtkActivatable:use-action-appearance:
+   * 
+   * Whether this activatable should reset its layout
+   * and appearance when setting the related action or when
+   * the action changes appearance 
+   *
+   * Since: 2.16
+   */
+  g_object_interface_install_property (g_iface,
+				       g_param_spec_boolean ("use-action-appearance",
+							     P_("Use Action Appearance"),
+							     P_("Whether to use the related actions appearance properties"),
+							     FALSE,
+							     GTK_PARAM_READWRITE));
+
+
+}
+
+
+/**
+ * gtk_activatable_update:
+ * @activatable: a #GtkActivatable
+ * @action: the related #GtkAction
+ * @property_name: the name of the action property to update from, or %NULL
+ *
+ * This is called when @activatable needs to be updated for a property
+ * change on its related action. When called with %NULL, as when setting
+ * the action initially, all relavent properties should be updated.
+ *
+ * Since: 2.16
+ **/
+void
+gtk_activatable_update (GtkActivatable *activatable,
+			GtkAction      *action,
+			const gchar    *property_name)
+{
+  GtkActivatableIface *iface;
+
+  g_return_if_fail (GTK_IS_ACTIVATABLE (activatable));
+
+  iface = GTK_ACTIVATABLE_GET_IFACE (activatable);
+  if (iface->update)
+    iface->update (activatable, action, property_name);
+  else
+    g_critical ("GtkActivatable->update() unimplemented for type %s", 
+		g_type_name (G_OBJECT_TYPE (activatable)));
+}
+
+
+/**
+ * gtk_activatable_set_related_action:
+ * @activatable: a #GtkActivatable
+ * @action: the #GtkAction to set
+ *
+ * Sets the related action on the @activatable object.
+ *
+ * Since: 2.16
+ **/
+void
+gtk_activatable_set_related_action (GtkActivatable *activatable,
+				    GtkAction      *action)
+{
+  g_return_if_fail (GTK_IS_ACTIVATABLE (activatable));
+  g_return_if_fail (action == NULL || GTK_IS_ACTION (action));
+
+  g_object_set (activatable, "related-action", action, NULL);
+}
+
+void
+_gtk_activatable_do_set_related_action (GtkActivatable *activatable,
+					GtkAction      *action)
+{
+  GtkActionGroup *group;
+  GtkAction *prev_action;
+
+  /* XXX Add a weak_ref here and nullify our pointers when actions die */
+  prev_action = gtk_activatable_get_related_action (activatable);
+  
+  if (prev_action)
+    {
+      gtk_action_remove_from_proxy_list (prev_action, GTK_WIDGET (activatable));
+
+      group = gtk_action_get_group (prev_action);
+
+      if (group)
+	_gtk_action_group_emit_disconnect_proxy (group, prev_action, GTK_WIDGET (activatable));
+
+      g_object_unref (prev_action);
+    }
+
+  if (action)
+    {
+      g_object_ref (action);
+
+      gtk_action_add_to_proxy_list (action, GTK_WIDGET (activatable));
+
+      group = gtk_action_get_group (action);
+
+      if (group)
+	_gtk_action_group_emit_connect_proxy (group, action, GTK_WIDGET (activatable));
+    }
+}
+
+/**
+ * gtk_activatable_get_related_action:
+ * @activatable: a #GtkActivatable
+ *
+ * Gets the related #GtkAction for @activatable.
+ *
+ * Returns: the related #GtkAction if one is set.
+ *
+ * Since: 2.16
+ **/
+GtkAction *
+gtk_activatable_get_related_action (GtkActivatable *activatable)
+{
+  GtkAction *action;
+
+  g_return_val_if_fail (GTK_IS_ACTIVATABLE (activatable), NULL);
+
+  g_object_get (activatable, "related-action", &action, NULL);
+
+  /* g_object_get() gives us a ref... */
+  if (action)
+    g_object_unref (action);
+
+  return action;
+}
+
+/**
+ * gtk_activatable_set_use_action_appearance:
+ * @activatable: a #GtkActivatable
+ * @use_appearance: whether to use the actions appearance
+ *
+ * Sets whether this activatable should reset its layout
+ * and appearance when setting the related action or when
+ * the action changes appearance 
+ *
+ * <para><note>If set to %TRUE with a related action set, 
+ * this will also update the appearance.</note></para>
+ *
+ * Since: 2.16
+ **/
+void
+gtk_activatable_set_use_action_appearance  (GtkActivatable *activatable,
+					    gboolean        use_appearance)
+{
+  g_object_set (activatable, "use-action-appearance", use_appearance, NULL);
+}
+
+/**
+ * gtk_activatable_get_use_action_appearance:
+ * @activatable: a #GtkActivatable
+ *
+ * Gets whether this activatable should reset its layout
+ * and appearance when setting the related action or when
+ * the action changes appearance.
+ *
+ * Returns: whether @activatable uses its actions appearance.
+ *
+ * Since: 2.16
+ **/
+gboolean
+gtk_activatable_get_use_action_appearance  (GtkActivatable *activatable)
+{
+  gboolean use_appearance;
+
+  g_object_get (activatable, "use-action-appearance", &use_appearance, NULL);  
+
+  return use_appearance;
+}
+
+#define __GTK_ACTIVATABLE_C__
+#include "gtkaliasdef.c"
Index: gtk/gtkactivatable.h
===================================================================
--- gtk/gtkactivatable.h	(revision 0)
+++ gtk/gtkactivatable.h	(revision 0)
@@ -0,0 +1,71 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2008 Tristan Van Berkom <tristan.van.berkom@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#if defined(GTK_DISABLE_SINGLE_INCLUDES) && !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#ifndef __GTK_ACTIVATABLE_H__
+#define __GTK_ACTIVATABLE_H__
+
+#include <gtk/gtkaction.h>
+#include <gtk/gtktypeutils.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_ACTIVATABLE            (gtk_activatable_get_type ())
+#define GTK_ACTIVATABLE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_ACTIVATABLE, GtkActivatable))
+#define GTK_ACTIVATABLE_CLASS(obj)      (G_TYPE_CHECK_CLASS_CAST ((obj), GTK_TYPE_ACTIVATABLE, GtkActivatableIface))
+#define GTK_IS_ACTIVATABLE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_ACTIVATABLE))
+#define GTK_ACTIVATABLE_GET_IFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GTK_TYPE_ACTIVATABLE, GtkActivatableIface))
+
+
+typedef struct _GtkActivatable      GtkActivatable; /* Dummy typedef */
+typedef struct _GtkActivatableIface GtkActivatableIface;
+
+struct _GtkActivatableIface
+{
+  GTypeInterface g_iface;
+
+  /* virtual table */
+  void   (* update)  (GtkActivatable *, GtkAction *, const gchar *);
+};
+
+
+GType      gtk_activatable_get_type                   (void) G_GNUC_CONST;
+
+void       gtk_activatable_update                     (GtkActivatable *activatable,
+						       GtkAction      *action,
+						       const gchar    *property_name);
+
+void       gtk_activatable_set_related_action         (GtkActivatable *activatable,
+						       GtkAction      *action);
+GtkAction *gtk_activatable_get_related_action         (GtkActivatable *activatable);
+
+void       gtk_activatable_set_use_action_appearance  (GtkActivatable *activatable,
+						       gboolean        use_appearance);
+gboolean   gtk_activatable_get_use_action_appearance  (GtkActivatable *activatable);
+
+/* For use in activatable implementations */
+void       _gtk_activatable_do_set_related_action     (GtkActivatable *activatable,
+						       GtkAction      *action);
+
+G_END_DECLS
+
+#endif /* __GTK_ACTIVATABLE_H__ */
Index: gtk/gtkwidget.h
===================================================================
--- gtk/gtkwidget.h	(revision 21809)
+++ gtk/gtkwidget.h	(working copy)
@@ -146,6 +146,7 @@
 typedef struct _GtkClipboard	   GtkClipboard;
 typedef struct _GtkTooltip         GtkTooltip;
 typedef struct _GtkWindow          GtkWindow;
+typedef struct _GtkActionGroup     GtkActionGroup;
 typedef void     (*GtkCallback)        (GtkWidget        *widget,
 					gpointer	  data);
 
Index: gtk/gtktogglebutton.c
===================================================================
--- gtk/gtktogglebutton.c	(revision 21809)
+++ gtk/gtktogglebutton.c	(working copy)
@@ -29,6 +29,8 @@
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
 #include "gtktogglebutton.h"
+#include "gtktoggleaction.h"
+#include "gtkactivatable.h"
 #include "gtkprivate.h"
 #include "gtkintl.h"
 #include "gtkalias.h"
@@ -67,10 +69,19 @@
 					     GParamSpec           *pspec);
 static void gtk_toggle_button_update_state  (GtkButton            *button);
 
-static guint toggle_button_signals[LAST_SIGNAL] = { 0 };
 
-G_DEFINE_TYPE (GtkToggleButton, gtk_toggle_button, GTK_TYPE_BUTTON)
+static void gtk_toggle_button_activatable_interface_init (GtkActivatableIface  *iface);
+static void gtk_toggle_button_activatable_update         (GtkActivatable       *activatable,
+							  GtkAction            *action,
+							  const gchar          *property_name);
 
+static GtkActivatableIface *parent_activatable_iface;
+static guint                toggle_button_signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE_WITH_CODE (GtkToggleButton, gtk_toggle_button, GTK_TYPE_BUTTON,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+						gtk_toggle_button_activatable_interface_init))
+
 static void
 gtk_toggle_button_class_init (GtkToggleButtonClass *class)
 {
@@ -139,6 +150,37 @@
 }
 
 
+static void 
+gtk_toggle_button_activatable_interface_init (GtkActivatableIface  *iface)
+{
+  parent_activatable_iface = g_type_interface_peek_parent (iface);
+  iface->update = gtk_toggle_button_activatable_update;
+}
+
+static void
+gtk_toggle_button_activatable_update (GtkActivatable   *activatable,
+				      GtkAction        *action,
+				      const gchar      *property_name)
+{
+  GtkToggleButton *button;
+
+  parent_activatable_iface->update (activatable, action, property_name);
+
+  button = GTK_TOGGLE_BUTTON (activatable);
+
+  if (property_name == NULL || strcmp (property_name, "active") == 0)
+    {
+      gtk_action_block_activate (action);
+      gtk_toggle_button_set_active (button, gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
+      gtk_action_unblock_activate (action);
+    }
+
+  if (!gtk_activatable_get_use_action_appearance (activatable))
+    return;
+
+}
+
+
 GtkWidget*
 gtk_toggle_button_new (void)
 {
Index: gtk/gtktoggleaction.c
===================================================================
--- gtk/gtktoggleaction.c	(revision 21809)
+++ gtk/gtktoggleaction.c	(working copy)
@@ -54,11 +54,6 @@
 G_DEFINE_TYPE (GtkToggleAction, gtk_toggle_action, GTK_TYPE_ACTION)
 
 static void gtk_toggle_action_activate     (GtkAction       *action);
-static void gtk_toggle_action_real_toggled (GtkToggleAction *action);
-static void connect_proxy                  (GtkAction       *action,
-					    GtkWidget       *proxy);
-static void disconnect_proxy               (GtkAction       *action,
-					    GtkWidget       *proxy);
 static void set_property                   (GObject         *object,
 					    guint            prop_id,
 					    const GValue    *value,
@@ -87,15 +82,13 @@
   gobject_class->get_property = get_property;
 
   action_class->activate = gtk_toggle_action_activate;
-  action_class->connect_proxy = connect_proxy;
-  action_class->disconnect_proxy = disconnect_proxy;
 
   action_class->menu_item_type = GTK_TYPE_CHECK_MENU_ITEM;
   action_class->toolbar_item_type = GTK_TYPE_TOGGLE_TOOL_BUTTON;
 
   action_class->create_menu_item = create_menu_item;
 
-  klass->toggled = gtk_toggle_action_real_toggled;
+  klass->toggled = NULL;
 
   g_object_class_install_property (gobject_class,
                                    PROP_DRAW_AS_RADIO,
@@ -232,64 +225,6 @@
   gtk_toggle_action_toggled (toggle_action);
 }
 
-static void
-gtk_toggle_action_real_toggled (GtkToggleAction *action)
-{
-  GSList *slist;
-
-  g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
-
-  for (slist = gtk_action_get_proxies (GTK_ACTION (action)); slist; slist = slist->next)
-    {
-      GtkWidget *proxy = slist->data;
-
-      gtk_action_block_activate_from (GTK_ACTION (action), proxy);
-      if (GTK_IS_CHECK_MENU_ITEM (proxy))
-	gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (proxy),
-					action->private_data->active);
-      else if (GTK_IS_TOGGLE_TOOL_BUTTON (proxy))
-	gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (proxy),
-					   action->private_data->active);
-      else if (GTK_IS_TOGGLE_BUTTON (proxy))
-	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (proxy),
-				      action->private_data->active);
-      else {
-	g_warning ("Don't know how to toggle `%s' widgets",
-		   G_OBJECT_TYPE_NAME (proxy));
-      }
-      gtk_action_unblock_activate_from (GTK_ACTION (action), proxy);
-    }
-}
-
-static void
-connect_proxy (GtkAction *action, 
-	       GtkWidget *proxy)
-{
-  GtkToggleAction *toggle_action;
-
-  toggle_action = GTK_TOGGLE_ACTION (action);
-
-  /* do this before hand, so that we don't call the "activate" handler */
-  if (GTK_IS_CHECK_MENU_ITEM (proxy))
-    gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (proxy),
-				    toggle_action->private_data->active);
-  else if (GTK_IS_TOGGLE_TOOL_BUTTON (proxy))
-    gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (proxy),
-				       toggle_action->private_data->active);
-  else if (GTK_IS_TOGGLE_BUTTON (proxy))
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (proxy),
-				  toggle_action->private_data->active);
-
-  GTK_ACTION_CLASS (parent_class)->connect_proxy (action, proxy);
-}
-
-static void
-disconnect_proxy (GtkAction *action, 
-		  GtkWidget *proxy)
-{
-  GTK_ACTION_CLASS (parent_class)->disconnect_proxy (action, proxy);
-}
-
 /**
  * gtk_toggle_action_toggled:
  * @action: the action object
Index: gtk/gtkcheckmenuitem.c
===================================================================
--- gtk/gtkcheckmenuitem.c	(revision 21809)
+++ gtk/gtkcheckmenuitem.c	(working copy)
@@ -27,6 +27,8 @@
 #include "config.h"
 #include "gtkcheckmenuitem.h"
 #include "gtkaccellabel.h"
+#include "gtkactivatable.h"
+#include "gtktoggleaction.h"
 #include "gtkmarshalers.h"
 #include "gtkprivate.h"
 #include "gtkintl.h"
@@ -53,19 +55,26 @@
 						      GdkRectangle          *area);
 static void gtk_real_check_menu_item_draw_indicator  (GtkCheckMenuItem      *check_menu_item,
 						      GdkRectangle          *area);
-static void gtk_check_menu_item_set_property (GObject         *object,
-					      guint            prop_id,
-					      const GValue    *value,
-					      GParamSpec      *pspec);
-static void gtk_check_menu_item_get_property (GObject         *object,
-					      guint            prop_id,
-					      GValue          *value,
-					      GParamSpec      *pspec);
+static void gtk_check_menu_item_set_property         (GObject               *object,
+						      guint                  prop_id,
+						      const GValue          *value,
+						      GParamSpec            *pspec);
+static void gtk_check_menu_item_get_property         (GObject               *object,
+						      guint                  prop_id,
+						      GValue                *value,
+						      GParamSpec            *pspec);
 
+static void gtk_check_menu_item_activatable_interface_init (GtkActivatableIface  *iface);
+static void gtk_check_menu_item_activatable_update         (GtkActivatable       *activatable,
+							    GtkAction            *action,
+							    const gchar          *property_name);
 
-static guint check_menu_item_signals[LAST_SIGNAL] = { 0 };
+static GtkActivatableIface *parent_activatable_iface;
+static guint                check_menu_item_signals[LAST_SIGNAL] = { 0 };
 
-G_DEFINE_TYPE (GtkCheckMenuItem, gtk_check_menu_item, GTK_TYPE_MENU_ITEM)
+G_DEFINE_TYPE_WITH_CODE (GtkCheckMenuItem, gtk_check_menu_item, GTK_TYPE_MENU_ITEM,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+						gtk_check_menu_item_activatable_interface_init))
 
 static void
 gtk_check_menu_item_class_init (GtkCheckMenuItemClass *klass)
@@ -107,8 +116,7 @@
   
   gtk_widget_class_install_style_property (widget_class,
                                            g_param_spec_int ("indicator-size",
-                                                             P_("Indicator Size")
-,
+                                                             P_("Indicator Size"),
                                                              P_("Size of check or radio indicator"),
                                                              0,
                                                              G_MAXINT,
@@ -134,6 +142,39 @@
 		  G_TYPE_NONE, 0);
 }
 
+static void 
+gtk_check_menu_item_activatable_interface_init (GtkActivatableIface  *iface)
+{
+  parent_activatable_iface = g_type_interface_peek_parent (iface);
+  iface->update = gtk_check_menu_item_activatable_update;
+}
+
+static void 
+gtk_check_menu_item_activatable_update (GtkActivatable       *activatable,
+					GtkAction            *action,
+					const gchar          *property_name)
+{
+  GtkCheckMenuItem *check_menu_item;
+
+  check_menu_item = GTK_CHECK_MENU_ITEM (activatable);
+
+  parent_activatable_iface->update (activatable, action, property_name);
+
+  if (property_name == NULL || strcmp (property_name, "active") == 0)
+    {
+      gtk_action_block_activate (action);
+      gtk_check_menu_item_set_active (check_menu_item, gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
+      gtk_action_unblock_activate (action);
+    }
+
+  if (!gtk_activatable_get_use_action_appearance (activatable))
+    return;
+
+  if (property_name == NULL || strcmp (property_name, "draw-as-radio") == 0)
+    gtk_check_menu_item_set_draw_as_radio (check_menu_item, 
+					   gtk_toggle_action_get_draw_as_radio (GTK_TOGGLE_ACTION (action)));
+}
+
 GtkWidget*
 gtk_check_menu_item_new (void)
 {
@@ -351,6 +392,8 @@
   gtk_check_menu_item_toggled (check_menu_item);
   gtk_widget_queue_draw (GTK_WIDGET (check_menu_item));
 
+  GTK_MENU_ITEM_CLASS (gtk_check_menu_item_parent_class)->activate (menu_item);
+
   g_object_notify (G_OBJECT (check_menu_item), "active");
 }
 
Index: gtk/gtkrecentchooserdefault.c
===================================================================
--- gtk/gtkrecentchooserdefault.c	(revision 21809)
+++ gtk/gtkrecentchooserdefault.c	(working copy)
@@ -65,6 +65,7 @@
 #include "gtktooltip.h"
 #include "gtktypebuiltins.h"
 #include "gtkvbox.h"
+#include "gtkactivatable.h"
 
 #include "gtkrecentmanager.h"
 #include "gtkrecentfilter.h"
@@ -76,8 +77,16 @@
 #include "gtkprivate.h"
 #include "gtkalias.h"
 
-
+enum 
+{
+  PROP_0,
 
+  /* activatable properties */
+  PROP_ACTIVATABLE_ACTION,
+  PROP_ACTIVATABLE_USE_APPEARANCE
+};
+
+
 struct _GtkRecentChooserDefault
 {
   GtkVBox parent_instance;
@@ -280,7 +289,9 @@
 			 _gtk_recent_chooser_default,
 			 GTK_TYPE_VBOX,
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_RECENT_CHOOSER,
-				 		gtk_recent_chooser_iface_init))
+				 		gtk_recent_chooser_iface_init)
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+				 		_gtk_recent_chooser_activatable_iface_init))
 
 
 
@@ -528,6 +539,12 @@
     case GTK_RECENT_CHOOSER_PROP_FILTER:
       set_current_filter (impl, g_value_get_object (value));
       break;
+    case PROP_ACTIVATABLE_ACTION:
+      _gtk_recent_chooser_set_related_action (GTK_RECENT_CHOOSER (impl), g_value_get_object (value));
+      break;
+    case PROP_ACTIVATABLE_USE_APPEARANCE: 
+      _gtk_recent_chooser_set_use_action_appearance (GTK_RECENT_CHOOSER (impl), g_value_get_boolean (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -571,6 +588,12 @@
     case GTK_RECENT_CHOOSER_PROP_FILTER:
       g_value_set_object (value, impl->current_filter);
       break;
+    case PROP_ACTIVATABLE_ACTION:
+      g_value_set_object (value, _gtk_recent_chooser_get_related_action (GTK_RECENT_CHOOSER (impl)));
+      break;
+    case PROP_ACTIVATABLE_USE_APPEARANCE: 
+      g_value_set_boolean (value, _gtk_recent_chooser_get_use_action_appearance (GTK_RECENT_CHOOSER (impl)));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
Index: gtk/gtkrecentchooserprivate.h
===================================================================
--- gtk/gtkrecentchooserprivate.h	(revision 21809)
+++ gtk/gtkrecentchooserprivate.h	(working copy)
@@ -25,18 +25,27 @@
 
 #include "gtkrecentmanager.h"
 #include "gtkrecentchooser.h"
+#include "gtkactivatable.h"
 
 G_BEGIN_DECLS
 
-GtkRecentManager *_gtk_recent_chooser_get_recent_manager (GtkRecentChooser  *chooser);
-GList *           _gtk_recent_chooser_get_items          (GtkRecentChooser  *chooser,
-                                                          GtkRecentFilter   *filter,
-                                                          GtkRecentSortFunc  func,
-                                                          gpointer           data);
+GtkRecentManager *_gtk_recent_chooser_get_recent_manager     (GtkRecentChooser  *chooser);
+GList *           _gtk_recent_chooser_get_items              (GtkRecentChooser  *chooser,
+							      GtkRecentFilter   *filter,
+							      GtkRecentSortFunc  func,
+							      gpointer           data);
 
-void              _gtk_recent_chooser_item_activated     (GtkRecentChooser  *chooser);
-void              _gtk_recent_chooser_selection_changed  (GtkRecentChooser  *chooser);
+void              _gtk_recent_chooser_item_activated         (GtkRecentChooser  *chooser);
+void              _gtk_recent_chooser_selection_changed      (GtkRecentChooser  *chooser);
 
+void              _gtk_recent_chooser_activatable_iface_init (GtkActivatableIface  *iface);
+void              _gtk_recent_chooser_set_related_action     (GtkRecentChooser     *recent_chooser, 
+							      GtkAction            *action);
+GtkAction        *_gtk_recent_chooser_get_related_action     (GtkRecentChooser     *recent_chooser);
+void              _gtk_recent_chooser_set_use_action_appearance (GtkRecentChooser  *recent_chooser, 
+								 gboolean           use_appearance);
+gboolean          _gtk_recent_chooser_get_use_action_appearance (GtkRecentChooser  *recent_chooser);
+
 G_END_DECLS
 
 #endif /* ! __GTK_RECENT_CHOOSER_PRIVATE_H__ */
Index: gtk/gtktoggletoolbutton.c
===================================================================
--- gtk/gtktoggletoolbutton.c	(revision 21809)
+++ gtk/gtktoggletoolbutton.c	(working copy)
@@ -1,4 +1,4 @@
-/* gtktoggletoolbutton.c
+ /* gtktoggletoolbutton.c
  *
  * Copyright (C) 2002 Anders Carlsson <andersca@gnome.org>
  * Copyright (C) 2002 James Henstridge <james@daa.com.au>
@@ -27,6 +27,8 @@
 #include "gtkstock.h"
 #include "gtkintl.h"
 #include "gtkradiotoolbutton.h"
+#include "gtktoggleaction.h"
+#include "gtkactivatable.h"
 #include "gtkprivate.h"
 #include "gtkalias.h"
 
@@ -67,10 +69,19 @@
 static void menu_item_activated (GtkWidget           *widget,
 				 GtkToggleToolButton *button);
 
-static guint         toggle_signals[LAST_SIGNAL] = { 0 };
 
-G_DEFINE_TYPE (GtkToggleToolButton, gtk_toggle_tool_button, GTK_TYPE_TOOL_BUTTON)
+static void gtk_toggle_tool_button_activatable_interface_init (GtkActivatableIface  *iface);
+static void gtk_toggle_tool_button_activatable_update         (GtkActivatable       *activatable,
+							       GtkAction            *action,
+							       const gchar          *property_name);
 
+static GtkActivatableIface *parent_activatable_iface;
+static guint                toggle_signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE_WITH_CODE (GtkToggleToolButton, gtk_toggle_tool_button, GTK_TYPE_TOOL_BUTTON,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+						gtk_toggle_tool_button_activatable_interface_init))
+
 static void
 gtk_toggle_tool_button_class_init (GtkToggleToolButtonClass *klass)
 {
@@ -292,6 +303,34 @@
     }
 }
 
+
+static void 
+gtk_toggle_tool_button_activatable_interface_init (GtkActivatableIface  *iface)
+{
+  parent_activatable_iface = g_type_interface_peek_parent (iface);
+  iface->update = gtk_toggle_tool_button_activatable_update;
+}
+
+static void
+gtk_toggle_tool_button_activatable_update (GtkActivatable  *activatable,
+					   GtkAction       *action,
+					   const gchar     *property_name)
+{
+  GtkToggleToolButton *button;
+
+  parent_activatable_iface->update (activatable, action, property_name);
+
+  button = GTK_TOGGLE_TOOL_BUTTON (activatable);
+
+  if (property_name == NULL || strcmp (property_name, "active") == 0)
+    {
+      gtk_action_block_activate (action);
+      gtk_toggle_tool_button_set_active (button, gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
+      gtk_action_unblock_activate (action);
+    }
+}
+
+
 /**
  * gtk_toggle_tool_button_new:
  * 
Index: gtk/gtk.h
===================================================================
--- gtk/gtk.h	(revision 21809)
+++ gtk/gtk.h	(working copy)
@@ -37,6 +37,7 @@
 #include <gtk/gtkaccessible.h>
 #include <gtk/gtkaction.h>
 #include <gtk/gtkactiongroup.h>
+#include <gtk/gtkactivatable.h>
 #include <gtk/gtkadjustment.h>
 #include <gtk/gtkalignment.h>
 #include <gtk/gtkarrow.h>
Index: gtk/gtk.symbols
===================================================================
--- gtk/gtk.symbols	(revision 21809)
+++ gtk/gtk.symbols	(working copy)
@@ -144,33 +144,64 @@
 #if IN_HEADER(__GTK_ACTION_H__)
 #if IN_FILE(__GTK_ACTION_C__)
 gtk_action_activate
+gtk_action_add_to_proxy_list
+gtk_action_block_activate
+#ifndef GTK_DISABLE_DEPRECATED
 gtk_action_block_activate_from
+#endif
 gtk_action_connect_accelerator
+#ifndef GTK_DISABLE_DEPRECATED
 gtk_action_connect_proxy
+#endif
 gtk_action_create_icon
 gtk_action_create_menu_item
 gtk_action_create_tool_item
 gtk_action_create_menu
 gtk_action_disconnect_accelerator
+#ifndef GTK_DISABLE_DEPRECATED
 gtk_action_disconnect_proxy
+#endif
 gtk_action_get_accel_closure
 gtk_action_get_accel_path
+gtk_action_get_group
+gtk_action_get_label
 gtk_action_get_name
 gtk_action_get_proxies
+#ifndef GTK_DISABLE_DEPRECATED
 gtk_widget_get_action
+#endif
+gtk_action_get_icon_name
+gtk_action_get_is_important
 gtk_action_get_sensitive
+gtk_action_get_short_label
+gtk_action_get_stock_id
+gtk_action_get_tooltip
 gtk_action_get_type G_GNUC_CONST
 gtk_action_get_visible
+gtk_action_get_visible_horizontal
+gtk_action_get_visible_vertical
 gtk_action_is_sensitive
 gtk_action_is_visible
 gtk_action_new
+gtk_action_remove_from_proxy_list
 gtk_action_set_accel_group
 gtk_action_set_accel_path
+gtk_action_set_icon_name
+gtk_action_set_is_important
+gtk_action_set_label
 gtk_action_set_sensitive
+gtk_action_set_short_label
+gtk_action_set_stock_id
+gtk_action_set_tooltip
 gtk_action_set_visible
+gtk_action_set_visible_horizontal
+gtk_action_set_visible_vertical
+gtk_action_unblock_activate
+#ifndef GTK_DISABLE_DEPRECATED
 gtk_action_unblock_activate_from
 #endif
 #endif
+#endif
 
 #if IN_HEADER(__GTK_ACTION_GROUP_H__)
 #if IN_FILE(__GTK_ACTION_GROUP_C__)
@@ -198,6 +229,17 @@
 #endif
 #endif
 
+#if IN_HEADER(__GTK_ACTIVATABLE_H__)
+#if IN_FILE(__GTK_ACTIVATABLE_C__)
+gtk_activatable_get_related_action
+gtk_activatable_get_type G_GNUC_CONST
+gtk_activatable_get_use_action_appearance
+gtk_activatable_set_related_action
+gtk_activatable_set_use_action_appearance
+gtk_activatable_update
+#endif
+#endif
+
 #if IN_HEADER(__GTK_ADJUSTMENT_H__)
 #if IN_FILE(__GTK_ADJUSTMENT_C__)
 gtk_adjustment_changed
@@ -3225,6 +3267,7 @@
 gtk_recent_action_get_type G_GNUC_CONST
 gtk_recent_action_new
 gtk_recent_action_new_for_manager
+gtk_recent_action_set_current_chooser
 gtk_recent_action_set_show_numbers
 gtk_recent_action_get_show_numbers
 #endif
Index: gtk/gtktoolbutton.c
===================================================================
--- gtk/gtktoolbutton.c	(revision 21809)
+++ gtk/gtktoolbutton.c	(working copy)
@@ -32,6 +32,7 @@
 #include "gtkvbox.h"
 #include "gtkintl.h"
 #include "gtktoolbar.h"
+#include "gtkactivatable.h"
 #include "gtkprivate.h"
 #include "gtkalias.h"
 
@@ -77,12 +78,13 @@
 					    GtkStyle           *prev_style);
 
 static void gtk_tool_button_construct_contents (GtkToolItem *tool_item);
-      
-static GObjectClass *parent_class = NULL;
-static guint         toolbutton_signals[LAST_SIGNAL] = { 0 };
 
-#define GTK_TOOL_BUTTON_GET_PRIVATE(obj)(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_TOOL_BUTTON, GtkToolButtonPrivate))
+static void gtk_tool_button_activatable_interface_init (GtkActivatableIface  *iface);
+static void gtk_tool_button_activatable_update         (GtkActivatable       *activatable,
+							GtkAction            *action,
+							const gchar          *property_name);
 
+
 struct _GtkToolButtonPrivate
 {
   GtkWidget *button;
@@ -97,22 +99,41 @@
   guint contents_invalid : 1;
 };
 
+static GObjectClass        *parent_class = NULL;
+static GtkActivatableIface *parent_activatable_iface;
+static guint                toolbutton_signals[LAST_SIGNAL] = { 0 };
+
+#define GTK_TOOL_BUTTON_GET_PRIVATE(obj)(G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_TOOL_BUTTON, GtkToolButtonPrivate))
+
 GType
 gtk_tool_button_get_type (void)
 {
   static GType type = 0;
+  
+  if (!type)
+    {
+      static const GInterfaceInfo activatable_info =
+      {
+        (GInterfaceInitFunc) gtk_tool_button_activatable_interface_init,
+        (GInterfaceFinalizeFunc) NULL,
+        NULL
+      };
 
-  if (!type)
-    type = g_type_register_static_simple (GTK_TYPE_TOOL_ITEM,
-					  I_("GtkToolButton"),
-					  sizeof (GtkToolButtonClass),
-					  (GClassInitFunc) gtk_tool_button_class_init,
-					  sizeof (GtkToolButton),
-					  (GInstanceInitFunc) gtk_tool_button_init,
-					  0);
+      type = g_type_register_static_simple (GTK_TYPE_TOOL_ITEM,
+					    I_("GtkToolButton"),
+					    sizeof (GtkToolButtonClass),
+					    (GClassInitFunc) gtk_tool_button_class_init,
+					    sizeof (GtkToolButton),
+					    (GInstanceInitFunc) gtk_tool_button_init,
+					    0);
+
+      g_type_add_interface_static (type, GTK_TYPE_ACTIVATABLE,
+                                   &activatable_info);
+    }
   return type;
 }
 
+
 static void
 gtk_tool_button_class_init (GtkToolButtonClass *klass)
 {
@@ -666,6 +687,13 @@
 button_clicked (GtkWidget     *widget,
 		GtkToolButton *button)
 {
+  GtkAction *action;
+
+  action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (button));
+  
+  if (action)
+    gtk_action_activate (action);
+
   g_signal_emit_by_name (button, "clicked");
 }
 
@@ -698,6 +726,68 @@
   gtk_tool_button_update_icon_spacing (GTK_TOOL_BUTTON (widget));
 }
 
+static void 
+gtk_tool_button_activatable_interface_init (GtkActivatableIface  *iface)
+{
+  parent_activatable_iface = g_type_interface_peek_parent (iface);
+  iface->update = gtk_tool_button_activatable_update;
+}
+
+static void
+gtk_tool_button_activatable_update (GtkActivatable       *activatable,
+				    GtkAction            *action,
+				    const gchar          *property_name)
+{
+  GtkToolButton *button;
+
+  parent_activatable_iface->update (activatable, action, property_name);
+
+  if (!gtk_activatable_get_use_action_appearance (activatable))
+    return;
+
+  button = GTK_TOOL_BUTTON (activatable);
+  
+  if (property_name == NULL)
+    {
+      gtk_tool_button_set_use_underline (button, TRUE);
+
+      if (gtk_action_get_stock_id (action))
+	gtk_tool_button_set_stock_id (button, gtk_action_get_stock_id (action));
+      else if (gtk_action_get_icon_name (action))
+	gtk_tool_button_set_icon_name (button, gtk_action_get_icon_name (action));
+      else
+	gtk_tool_button_set_label (button, gtk_action_get_short_label (action));
+    }
+  else if (strcmp (property_name, "short-label") == 0)
+    {
+      if (!gtk_action_get_stock_id (action) &&
+	  !gtk_action_get_icon_name (action))
+	{
+	  gtk_tool_button_set_use_underline (button, TRUE);
+	  gtk_tool_button_set_label (button, gtk_action_get_short_label (action));
+	}
+    }
+  else if (strcmp (property_name, "stock-id") == 0)
+    {
+      if (gtk_action_get_stock_id (action))
+	{	
+	  gtk_tool_button_set_label (button, NULL);
+	  gtk_tool_button_set_icon_name (button, NULL);
+	}
+      gtk_tool_button_set_stock_id (button, gtk_action_get_stock_id (action));
+    }
+  else if (strcmp (property_name, "icon-name") == 0)
+    {
+      if (gtk_action_get_icon_name (action))
+	{	
+	  gtk_tool_button_set_label (button, NULL);
+	  gtk_tool_button_set_stock_id (button, NULL);
+	}
+      gtk_tool_button_set_icon_name (button, gtk_action_get_icon_name (action));
+    }
+}
+
+
 /**
  * gtk_tool_button_new_from_stock:
  * @stock_id: the name of the stock item 
Index: gtk/gtkbutton.c
===================================================================
--- gtk/gtkbutton.c	(revision 21809)
+++ gtk/gtkbutton.c	(working copy)
@@ -36,6 +36,7 @@
 #include "gtkvbox.h"
 #include "gtkstock.h"
 #include "gtkiconfactory.h"
+#include "gtkactivatable.h"
 #include "gtkprivate.h"
 #include "gtkintl.h"
 #include "gtkalias.h"
@@ -69,7 +70,11 @@
   PROP_FOCUS_ON_CLICK,
   PROP_XALIGN,
   PROP_YALIGN,
-  PROP_IMAGE_POSITION
+  PROP_IMAGE_POSITION,
+
+  /* activatable properties */
+  PROP_ACTIVATABLE_ACTION,
+  PROP_ACTIVATABLE_USE_APPEARANCE
 };
 
 #define GTK_BUTTON_GET_PRIVATE(o)       (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_BUTTON, GtkButtonPrivate))
@@ -80,14 +85,17 @@
   gfloat          xalign;
   gfloat          yalign;
   GtkWidget      *image;
-  guint           align_set      : 1;
-  guint           image_is_stock : 1;
-  guint           has_grab       : 1;
+  guint           align_set             : 1;
+  guint           image_is_stock        : 1;
+  guint           has_grab              : 1;
+  guint           use_action_appearance : 1;
   guint32         grab_time;
   GtkPositionType image_position;
+  GtkAction      *action;
 };
 
 static void gtk_button_destroy        (GtkObject          *object);
+static void gtk_button_dispose        (GObject            *object);
 static void gtk_button_set_property   (GObject            *object,
                                        guint               prop_id,
                                        const GValue       *value,
@@ -124,6 +132,7 @@
 				       GdkEventCrossing   *event);
 static void gtk_real_button_pressed   (GtkButton          *button);
 static void gtk_real_button_released  (GtkButton          *button);
+static void gtk_real_button_clicked   (GtkButton          *button);
 static void gtk_real_button_activate  (GtkButton          *button);
 static void gtk_button_update_state   (GtkButton          *button);
 static void gtk_button_add            (GtkContainer       *container,
@@ -142,9 +151,23 @@
 					gboolean               was_grabbed);
 
 
+static void gtk_button_activatable_interface_init (GtkActivatableIface  *iface);
+static void gtk_button_activatable_update         (GtkActivatable       *activatable,
+						   GtkAction            *action,
+						   const gchar          *property_name);
+static void gtk_button_set_related_action         (GtkButton            *button, 
+						   GtkAction            *action);
+static void gtk_button_set_use_action_appearance  (GtkButton            *button, 
+						   gboolean              use_appearance);
+static void gtk_button_action_notify              (GtkAction            *action,
+						   GParamSpec           *pspec,
+						   GtkButton            *button);
+
 static guint button_signals[LAST_SIGNAL] = { 0 };
 
-G_DEFINE_TYPE (GtkButton, gtk_button, GTK_TYPE_BIN)
+G_DEFINE_TYPE_WITH_CODE (GtkButton, gtk_button, GTK_TYPE_BIN,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+						gtk_button_activatable_interface_init))
 
 static void
 gtk_button_class_init (GtkButtonClass *klass)
@@ -159,7 +182,8 @@
   widget_class = (GtkWidgetClass*) klass;
   container_class = (GtkContainerClass*) klass;
   
-  gobject_class->constructor = gtk_button_constructor;
+  gobject_class->constructor  = gtk_button_constructor;
+  gobject_class->dispose      = gtk_button_dispose;
   gobject_class->set_property = gtk_button_set_property;
   gobject_class->get_property = gtk_button_get_property;
 
@@ -188,7 +212,7 @@
 
   klass->pressed = gtk_real_button_pressed;
   klass->released = gtk_real_button_released;
-  klass->clicked = NULL;
+  klass->clicked = gtk_real_button_clicked;
   klass->enter = gtk_button_update_state;
   klass->leave = gtk_button_update_state;
   klass->activate = gtk_real_button_activate;
@@ -303,6 +327,9 @@
                                                       GTK_POS_LEFT,
                                                       GTK_PARAM_READWRITE));
 
+  g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_ACTION, "related-action");
+  g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_USE_APPEARANCE, "use-action-appearance");
+
   /**
    * GtkButton::pressed:
    * @button: the object that received the signal
@@ -600,6 +627,21 @@
   GTK_CONTAINER_CLASS (gtk_button_parent_class)->add (container, widget);
 }
 
+static void 
+gtk_button_dispose (GObject *object)
+{
+  GtkButton *button = GTK_BUTTON (object);
+  GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (button);
+
+  if (priv->action)
+    {
+      g_signal_handlers_disconnect_by_func (priv->action, gtk_button_action_notify, button);
+      _gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (button), NULL);
+      priv->action = NULL;
+    }
+  G_OBJECT_CLASS (gtk_button_parent_class)->dispose (object);
+}
+
 static void
 gtk_button_set_property (GObject         *object,
                          guint            prop_id,
@@ -638,6 +680,12 @@
     case PROP_IMAGE_POSITION:
       gtk_button_set_image_position (button, g_value_get_enum (value));
       break;
+    case PROP_ACTIVATABLE_ACTION:
+      gtk_button_set_related_action (button, g_value_get_object (value));
+      break;
+    case PROP_ACTIVATABLE_USE_APPEARANCE:
+      gtk_button_set_use_action_appearance (button, g_value_get_boolean (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -682,12 +730,166 @@
     case PROP_IMAGE_POSITION:
       g_value_set_enum (value, priv->image_position);
       break;
+    case PROP_ACTIVATABLE_ACTION:
+      g_value_set_object (value, priv->action);
+      break;
+    case PROP_ACTIVATABLE_USE_APPEARANCE:
+      g_value_set_boolean (value, priv->use_action_appearance);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
     }
 }
 
+static void 
+gtk_button_activatable_interface_init (GtkActivatableIface  *iface)
+{
+  iface->update = gtk_button_activatable_update;
+}
+
+static void
+activatable_update_stock_id (GtkButton *button,
+			     GtkAction *action)
+{
+	      
+  if (!gtk_button_get_use_stock (button))
+    return;
+
+  gtk_button_set_label (button, gtk_action_get_stock_id (action));
+}
+
+static void
+activatable_update_short_label (GtkButton *button,
+				GtkAction *action)
+{
+  GtkWidget *image;
+
+  if (gtk_button_get_use_stock (button))
+    return;
+
+  image = gtk_button_get_image (button);
+
+  /* Dont touch custom child... */
+  if (GTK_IS_IMAGE (image) ||
+      GTK_BIN (button)->child == NULL || 
+      GTK_IS_LABEL (GTK_BIN (button)->child))
+    {
+      gtk_button_set_label (button, gtk_action_get_short_label (action));
+      gtk_button_set_use_underline (button, TRUE);
+    }
+}
+
+static void
+activatable_update_icon_name (GtkButton *button,
+			      GtkAction *action)
+{
+  GtkWidget *image;
+	      
+  if (gtk_button_get_use_stock (button))
+    return;
+
+  image = gtk_button_get_image (button);
+
+  if (GTK_IS_IMAGE (image) &&
+      (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
+       gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME))
+    gtk_image_set_from_icon_name (GTK_IMAGE (image),
+				  gtk_action_get_icon_name (action), GTK_ICON_SIZE_MENU);
+}
+
+
+static void 
+gtk_button_activatable_update (GtkActivatable       *activatable,
+			       GtkAction            *action,
+			       const gchar          *property_name)
+{
+  GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (activatable);
+
+  if (property_name == NULL)
+    {
+      if (gtk_action_is_visible (action))
+	gtk_widget_show (GTK_WIDGET (activatable));
+      else
+	gtk_widget_hide (GTK_WIDGET (activatable));
+
+      gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
+
+      if (priv->use_action_appearance)
+	{
+	  activatable_update_stock_id (GTK_BUTTON (activatable), action);
+	  activatable_update_short_label (GTK_BUTTON (activatable), action);
+	  activatable_update_icon_name (GTK_BUTTON (activatable), action);
+	}
+    }
+  else if (strcmp (property_name, "visible") == 0)
+    {
+      if (gtk_action_is_visible (action))
+	gtk_widget_show (GTK_WIDGET (activatable));
+      else
+	gtk_widget_hide (GTK_WIDGET (activatable));
+    }
+  else if (strcmp (property_name, "sensitive") == 0)
+    gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
+
+  if (!priv->use_action_appearance)
+    return;
+
+  if (strcmp (property_name, "stock-id") == 0)
+    activatable_update_stock_id (GTK_BUTTON (activatable), action);
+  if (strcmp (property_name, "short-label") == 0)
+    activatable_update_short_label (GTK_BUTTON (activatable), action);
+  if (strcmp (property_name, "icon-name") == 0)
+    activatable_update_icon_name (GTK_BUTTON (activatable), action);
+}
+
+static void
+gtk_button_action_notify (GtkAction   *action,
+			  GParamSpec  *pspec,
+			  GtkButton   *button)
+{
+  gtk_activatable_update (GTK_ACTIVATABLE (button), action, pspec->name);
+}
+
+static void
+gtk_button_set_related_action (GtkButton   *button, 
+			       GtkAction   *action)
+{
+  GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (button);
+
+  if (priv->action == action)
+    return;
+
+  if (priv->action)
+    g_signal_handlers_disconnect_by_func (priv->action, gtk_button_action_notify, button);
+
+  _gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (button), action);
+
+  priv->action = action;
+
+  if (action)
+    {
+      g_signal_connect (G_OBJECT (action), "notify", G_CALLBACK (gtk_button_action_notify), button);
+      
+      gtk_activatable_update (GTK_ACTIVATABLE (button), action, NULL);
+    }
+}
+
+static void
+gtk_button_set_use_action_appearance (GtkButton   *button, 
+				      gboolean     use_appearance)
+{
+  GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (button);
+
+  if (priv->use_action_appearance != use_appearance)
+    {
+      priv->use_action_appearance = use_appearance;
+
+      if (priv->action && use_appearance)
+	  gtk_activatable_update (GTK_ACTIVATABLE (button), priv->action, NULL);
+      }
+}
+
 GtkWidget*
 gtk_button_new (void)
 {
@@ -1494,6 +1696,15 @@
     }
 }
 
+static void 
+gtk_real_button_clicked (GtkButton  *button)
+{
+  GtkButtonPrivate *priv = GTK_BUTTON_GET_PRIVATE (button);
+
+  if (priv->action)
+    gtk_action_activate (priv->action);
+}
+
 static gboolean
 button_activate_timeout (gpointer data)
 {
Index: gtk/gtkaction.c
===================================================================
--- gtk/gtkaction.c	(revision 21809)
+++ gtk/gtkaction.c	(working copy)
@@ -47,6 +47,7 @@
 #include "gtktoolbar.h"
 #include "gtkprivate.h"
 #include "gtkbuildable.h"
+#include "gtkactivatable.h"
 #include "gtkalias.h"
 
 
@@ -70,6 +71,8 @@
   guint is_important       : 1;
   guint hide_if_empty      : 1;
   guint visible_overflown  : 1;
+  guint recursion_guard    : 1;
+  guint activate_blocked   : 1;
 
   /* accelerator */
   guint          accel_count;
@@ -105,7 +108,8 @@
   PROP_HIDE_IF_EMPTY,
   PROP_SENSITIVE,
   PROP_VISIBLE,
-  PROP_ACTION_GROUP
+  PROP_ACTION_GROUP,
+  PROP_ACCEL_PATH
 };
 
 /* GtkBuildable */
@@ -118,10 +122,6 @@
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
 						gtk_action_buildable_init))
 
-
-static GQuark      quark_gtk_action_proxy  = 0;
-static const gchar gtk_action_proxy_key[] = "gtk-action";
-
 static void gtk_action_finalize     (GObject *object);
 static void gtk_action_set_property (GObject         *object,
 				     guint            prop_id,
@@ -133,31 +133,9 @@
 				     GParamSpec      *pspec);
 static void gtk_action_set_action_group (GtkAction	*action,
 					 GtkActionGroup *action_group);
-static void gtk_action_set_is_important (GtkAction	*action,
-					 gboolean        is_important);
-static void gtk_action_set_label        (GtkAction	*action,
-					 const gchar    *label);
-static void gtk_action_set_short_label  (GtkAction	*action,
-					 const gchar    *label);
-static void gtk_action_set_visible_horizontal (GtkAction *action,
-					       gboolean   visible_horizontal);
-static void gtk_action_set_visible_vertical   (GtkAction *action,
-					       gboolean   visible_vertical);
-static void gtk_action_set_tooltip      (GtkAction	*action,
-					 const gchar    *tooltip);
-static void gtk_action_set_stock_id     (GtkAction	*action,
-					 const gchar    *stock_id);
-static void gtk_action_set_icon_name     (GtkAction	*action,
-					 const gchar    *icon_name);
-static void gtk_action_sync_tooltip     (GtkAction      *action,
-					 GtkWidget      *proxy);
 
 static GtkWidget *create_menu_item    (GtkAction *action);
 static GtkWidget *create_tool_item    (GtkAction *action);
-static void       connect_proxy       (GtkAction *action,
-				       GtkWidget *proxy);
-static void       disconnect_proxy    (GtkAction *action,
-				       GtkWidget *proxy);
 
 static void       closure_accel_activate (GClosure     *closure,
 					  GValue       *return_value,
@@ -174,8 +152,6 @@
 {
   GObjectClass *gobject_class;
 
-  quark_gtk_action_proxy = g_quark_from_static_string (gtk_action_proxy_key);
-
   gobject_class = G_OBJECT_CLASS (klass);
 
   gobject_class->finalize     = gtk_action_finalize;
@@ -184,15 +160,16 @@
 
   klass->activate = NULL;
 
-  klass->create_menu_item = create_menu_item;
-  klass->create_tool_item = create_tool_item;
-  klass->create_menu = NULL;
-  klass->connect_proxy = connect_proxy;
-  klass->disconnect_proxy = disconnect_proxy;
-
-  klass->menu_item_type = GTK_TYPE_IMAGE_MENU_ITEM;
+  klass->create_menu_item  = create_menu_item;
+  klass->create_tool_item  = create_tool_item;
+  klass->create_menu       = NULL;
+  klass->menu_item_type    = GTK_TYPE_IMAGE_MENU_ITEM;
   klass->toolbar_item_type = GTK_TYPE_TOOL_BUTTON;
 
+  /* < deprecated vfuncs > */
+  klass->connect_proxy    = NULL;
+  klass->disconnect_proxy = NULL;
+
   g_object_class_install_property (gobject_class,
 				   PROP_NAME,
 				   g_param_spec_string ("name",
@@ -325,6 +302,13 @@
 							 P_("The GtkActionGroup this GtkAction is associated with, or NULL (for internal use)."),
 							 GTK_TYPE_ACTION_GROUP,
 							 GTK_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class,
+				   PROP_ACCEL_PATH,
+				   g_param_spec_string ("accel-path",
+							P_("Accelerator Path"),
+							P_("The accelerator path to be shared by all proxies"),
+							NULL,
+							GTK_PARAM_READWRITE));
 
   /**
    * GtkAction::activate:
@@ -362,6 +346,7 @@
   action->private_data->visible_overflown  = TRUE;
   action->private_data->is_important = FALSE;
   action->private_data->hide_if_empty = TRUE;
+  action->private_data->activate_blocked = FALSE;
 
   action->private_data->sensitive = TRUE;
   action->private_data->visible = TRUE;
@@ -515,6 +500,9 @@
     case PROP_ACTION_GROUP:
       gtk_action_set_action_group (action, g_value_get_object (value));
       break;
+    case PROP_ACCEL_PATH:
+      gtk_action_set_accel_path (action, g_value_get_string (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -575,6 +563,9 @@
     case PROP_ACTION_GROUP:
       g_value_set_object (value, action->private_data->action_group);
       break;
+    case PROP_ACCEL_PATH:
+      g_value_set_string (value, gtk_action_get_accel_path (action));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -601,16 +592,6 @@
   return g_object_new (toolbar_item_type, NULL);
 }
 
-static void
-remove_proxy (GtkAction *action,
-	      GtkWidget *proxy)
-{
-  if (GTK_IS_MENU_ITEM (proxy))
-    gtk_action_disconnect_accelerator (action);
-  
-  action->private_data->proxies = g_slist_remove (action->private_data->proxies, proxy);
-}
-
 /**
  * _gtk_action_sync_menu_visible:
  * @action: a #GtkAction, or %NULL to determine the action from @proxy
@@ -641,7 +622,7 @@
   g_return_if_fail (action == NULL || GTK_IS_ACTION (action));
 
   if (action == NULL)
-    action = g_object_get_qdata (G_OBJECT (proxy), quark_gtk_action_proxy);
+    action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (proxy));
 
   if (action)
     {
@@ -656,221 +637,6 @@
     gtk_widget_hide (proxy);
 }
 
-gboolean _gtk_menu_is_empty (GtkWidget *menu);
-
-static gboolean
-gtk_action_create_menu_proxy (GtkToolItem *tool_item, 
-			      GtkAction   *action)
-{
-  GtkWidget *menu_item;
-  
-  if (action->private_data->visible_overflown)
-    {
-      menu_item = gtk_action_create_menu_item (action);
-
-      g_object_ref_sink (menu_item);
-      
-      gtk_tool_item_set_proxy_menu_item (tool_item, 
-					 "gtk-action-menu-item", menu_item);
-      g_object_unref (menu_item);
-    }
-  else
-    gtk_tool_item_set_proxy_menu_item (tool_item, 
-				       "gtk-action-menu-item", NULL);
-
-  return TRUE;
-}
-
-static void
-connect_proxy (GtkAction     *action, 
-	       GtkWidget     *proxy)
-{
-  g_object_ref (action);
-  g_object_set_qdata_full (G_OBJECT (proxy), quark_gtk_action_proxy, action,
-			   g_object_unref);
-
-  /* add this widget to the list of proxies */
-  action->private_data->proxies = g_slist_prepend (action->private_data->proxies, proxy);
-  g_object_weak_ref (G_OBJECT (proxy), (GWeakNotify)remove_proxy, action);
-  
-  gtk_widget_set_sensitive (proxy, gtk_action_is_sensitive (action));
-  if (gtk_action_is_visible (action))
-    gtk_widget_show (proxy);
-  else
-    gtk_widget_hide (proxy);
-  gtk_widget_set_no_show_all (proxy, TRUE);
-
-  if (GTK_IS_MENU_ITEM (proxy))
-    {
-      GtkWidget *label;
-      /* menu item specific synchronisers ... */
-      
-      if (action->private_data->accel_quark)
- 	{
-	  gtk_action_connect_accelerator (action);
- 	  gtk_menu_item_set_accel_path (GTK_MENU_ITEM (proxy),
- 					g_quark_to_string (action->private_data->accel_quark));
- 	}
-      
-      label = GTK_BIN (proxy)->child;
-
-      /* make sure label is a label */
-      if (label && !GTK_IS_LABEL (label))
-	{
-	  gtk_container_remove (GTK_CONTAINER (proxy), label);
-	  label = NULL;
-	}
-
-      if (!label)
-	label = g_object_new (GTK_TYPE_ACCEL_LABEL,
-			      "use-underline", TRUE,
-			      "xalign", 0.0,
-			      "visible", TRUE,
-			      "parent", proxy,
-			      NULL);
-      
-      if (GTK_IS_ACCEL_LABEL (label) && action->private_data->accel_quark)
-	g_object_set (label,
-		      "accel-closure", action->private_data->accel_closure,
-		      NULL);
-
-      gtk_label_set_label (GTK_LABEL (label), action->private_data->label);
-
-      if (GTK_IS_IMAGE_MENU_ITEM (proxy))
-	{
-	  GtkWidget *image;
-
-	  image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (proxy));
-	  if (image && !GTK_IS_IMAGE (image))
-	    {
-	      gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (proxy), NULL);
-	      image = NULL;
-	    }
-	  if (!image)
-	    {
-	      image = gtk_image_new ();
-	      gtk_widget_show (image);
-	      gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (proxy),
-					     image);
-	    }
-	  
-	  if (action->private_data->stock_id &&
-	      gtk_icon_factory_lookup_default (action->private_data->stock_id))
-	    gtk_image_set_from_stock (GTK_IMAGE (image),
-				      action->private_data->stock_id, GTK_ICON_SIZE_MENU);
-	  else if (action->private_data->icon_name)
-	    gtk_image_set_from_icon_name (GTK_IMAGE (image),
-					  action->private_data->icon_name, GTK_ICON_SIZE_MENU);
-	}
-      
-      if (gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy)) == NULL)
-	g_signal_connect_object (proxy, "activate",
-				 G_CALLBACK (gtk_action_activate), action,
-				 G_CONNECT_SWAPPED);
-
-    }
-  else if (GTK_IS_TOOL_ITEM (proxy))
-    {
-      /* toolbar button specific synchronisers ... */
-      if (GTK_IS_TOOL_BUTTON (proxy))
-	{
-	  g_object_set (proxy,
-		        "visible-horizontal", action->private_data->visible_horizontal,
-		        "visible-vertical", action->private_data->visible_vertical,
-		        "is-important", action->private_data->is_important,
-			"label", action->private_data->short_label,
-			"use-underline", TRUE,
-			"stock-id", action->private_data->stock_id,
-			"icon-name", action->private_data->icon_name,
-			NULL);
-
-	  g_signal_connect_object (proxy, "clicked",
-				   G_CALLBACK (gtk_action_activate), action,
-				   G_CONNECT_SWAPPED);
-        }
-      else 
-        {
-           g_object_set (proxy,
-	 	         "visible-horizontal", action->private_data->visible_horizontal,
-		         "visible-vertical", action->private_data->visible_vertical,
-		         "is-important", action->private_data->is_important,
-		         NULL);
-       }
-
-      gtk_action_sync_tooltip (action, proxy);
-
-      g_signal_connect_object (proxy, "create-menu-proxy",
-			       G_CALLBACK (gtk_action_create_menu_proxy),
-			       action, 0);
-
-      gtk_tool_item_rebuild_menu (GTK_TOOL_ITEM (proxy));
-    }
-  else if (GTK_IS_BUTTON (proxy))
-    {
-      /* button specific synchronisers ... */
-      if (gtk_button_get_use_stock (GTK_BUTTON (proxy)))
-	{
-	  /* synchronise stock-id */
-	  g_object_set (proxy,
-			"label", action->private_data->stock_id,
-			NULL);
-	}
-      else 
-	{
-	  GtkWidget *image;
-
-	  image = gtk_button_get_image (GTK_BUTTON (proxy));
-
-	  if (GTK_IS_IMAGE (image) ||
-	      GTK_BIN (proxy)->child == NULL || 
-	      GTK_IS_LABEL (GTK_BIN (proxy)->child))
-	    {
-	      /* synchronise the label */
-	      g_object_set (proxy,
-			    "label", action->private_data->short_label,
-			    "use-underline", TRUE,
-			    NULL);
-	    }
-
-	  if (GTK_IS_IMAGE (image) &&
-	      (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
-	       gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME))
-	    gtk_image_set_from_icon_name (GTK_IMAGE (image),
-					  action->private_data->icon_name, GTK_ICON_SIZE_MENU);
-	}
-      /* we leave the button alone if there is a custom child */
-      g_signal_connect_object (proxy, "clicked",
-			       G_CALLBACK (gtk_action_activate), action,
-			       G_CONNECT_SWAPPED);
-    }
-
-  if (action->private_data->action_group)
-    _gtk_action_group_emit_connect_proxy (action->private_data->action_group, action, proxy);
-}
-
-static void
-disconnect_proxy (GtkAction *action, 
-		  GtkWidget *proxy)
-{
-  g_object_set_qdata (G_OBJECT (proxy), quark_gtk_action_proxy, NULL);
-
-  g_object_weak_unref (G_OBJECT (proxy), (GWeakNotify)remove_proxy, action);
-  remove_proxy (action, proxy);
-
-  /* disconnect the activate handler */
-  g_signal_handlers_disconnect_by_func (proxy,
-					G_CALLBACK (gtk_action_activate),
-					action);
-
-  /* toolbar button specific synchronisers ... */
-  g_signal_handlers_disconnect_by_func (proxy,
-					G_CALLBACK (gtk_action_create_menu_proxy),
-					action);
-
-  if (action->private_data->action_group)
-    _gtk_action_group_emit_disconnect_proxy (action->private_data->action_group, action, proxy);
-}
-
 void
 _gtk_action_emit_activate (GtkAction *action)
 {
@@ -908,11 +674,43 @@
 {
   g_return_if_fail (GTK_IS_ACTION (action));
   
-  if (gtk_action_is_sensitive (action))
+  if (action->private_data->activate_blocked == FALSE &&
+      gtk_action_is_sensitive (action))
     _gtk_action_emit_activate (action);
 }
 
 /**
+ * gtk_action_block_activate:
+ *
+ * Disable activation signals from the action 
+ *
+ * This is needed when updating the state of your proxy
+ * #GtkActivatable widget could result in calling gtk_action_activate(),
+ * this is a convenience function to avoid recursing in those
+ * cases (updating toggle state for instance).
+ */
+void
+gtk_action_block_activate (GtkAction *action)
+{
+  g_return_if_fail (GTK_IS_ACTION (action));
+
+  action->private_data->activate_blocked = TRUE;
+}
+
+/**
+ * gtk_action_unblock_activate:
+ *
+ * Reenable activation signals from the action 
+ */
+void
+gtk_action_unblock_activate (GtkAction *action)
+{
+  g_return_if_fail (GTK_IS_ACTION (action));
+
+  action->private_data->activate_blocked = FALSE;
+}
+
+/**
  * gtk_action_create_icon:
  * @action: the action object
  * @icon_size: the size of the icon that should be created.
@@ -957,7 +755,8 @@
 
   menu_item = GTK_ACTION_GET_CLASS (action)->create_menu_item (action);
 
-  GTK_ACTION_GET_CLASS (action)->connect_proxy (action, menu_item);
+  gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (menu_item), TRUE);
+  gtk_activatable_set_related_action (GTK_ACTIVATABLE (menu_item), action);
 
   return menu_item;
 }
@@ -981,12 +780,81 @@
 
   button = GTK_ACTION_GET_CLASS (action)->create_tool_item (action);
 
-  GTK_ACTION_GET_CLASS (action)->connect_proxy (action, button);
+  gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (button), TRUE);
+  gtk_activatable_set_related_action (GTK_ACTIVATABLE (button), action);
 
   return button;
 }
 
+
+static void
+remove_proxy (GtkAction *action,
+	      GtkWidget *proxy)
+{
+  action->private_data->proxies = g_slist_remove (action->private_data->proxies, proxy);
+}
+
 /**
+ * gtk_action_add_to_proxy_list:
+ * @action: the action object
+ * @proxy: the proxy widget
+ *
+ * Adds @proxy to @action's list of proxy #GtkActivatable widgets.
+ *
+ * <para><note>This is used internally by gtk_activatable_set_related_action()
+ * to maintain the list of proxies in the action</note></para>
+ *
+ * Since: 2.16
+ */
+void
+gtk_action_add_to_proxy_list (GtkAction     *action,
+			      GtkWidget     *proxy)
+{
+  action->private_data->proxies = g_slist_prepend (action->private_data->proxies, proxy);
+  g_object_weak_ref (G_OBJECT (proxy), (GWeakNotify)remove_proxy, action);
+}
+
+
+/**
+ * gtk_action_remove_from_proxy_list:
+ * @action: the action object
+ * @proxy: the proxy widget
+ *
+ * Removes @proxy from @action's list of proxy #GtkActivatable widgets.
+ *
+ * <para><note>This is used internally by gtk_activatable_set_related_action() 
+ * implementations to maintain the list of proxies in the action</note></para>
+ *
+ * Since: 2.16
+ */
+void
+gtk_action_remove_from_proxy_list (GtkAction     *action,
+				   GtkWidget     *proxy)
+{
+  g_object_weak_unref (G_OBJECT (proxy), (GWeakNotify)remove_proxy, action);
+  remove_proxy (action, proxy);
+}
+
+
+/**
+ * gtk_action_get_group:
+ * @action: the action object
+ *
+ * Gets the #GtkActionGroup that this @action is in.
+ *
+ * Returns: the #GtkActionGroup
+ *
+ * Since: 2.16
+ */
+GtkActionGroup *
+gtk_action_get_group (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
+
+  return action->private_data->action_group;
+}
+
+/**
  * gtk_action_connect_proxy:
  * @action: the action object
  * @proxy: the proxy widget
@@ -1000,22 +868,20 @@
  * first.
  *
  * Since: 2.4
+ *
+ * Deprecated 2.16: Use gtk_activatable_set_related_action() instead.
  */
 void
 gtk_action_connect_proxy (GtkAction *action,
 			  GtkWidget *proxy)
 {
-  GtkAction *prev_action;
-
   g_return_if_fail (GTK_IS_ACTION (action));
   g_return_if_fail (GTK_IS_WIDGET (proxy));
+  g_return_if_fail (GTK_IS_ACTIVATABLE (proxy));
 
-  prev_action = g_object_get_qdata (G_OBJECT (proxy), quark_gtk_action_proxy);
+  gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (proxy), TRUE);
 
-  if (prev_action)
-    GTK_ACTION_GET_CLASS (action)->disconnect_proxy (prev_action, proxy);
-
-  GTK_ACTION_GET_CLASS (action)->connect_proxy (action, proxy);
+  gtk_activatable_set_related_action (GTK_ACTIVATABLE (proxy), action);
 }
 
 /**
@@ -1027,6 +893,8 @@
  * Does <emphasis>not</emphasis> destroy the widget, however.
  *
  * Since: 2.4
+ *
+ * Deprecated 2.16: Use gtk_activatable_set_related_action() instead.
  */
 void
 gtk_action_disconnect_proxy (GtkAction *action,
@@ -1035,9 +903,7 @@
   g_return_if_fail (GTK_IS_ACTION (action));
   g_return_if_fail (GTK_IS_WIDGET (proxy));
 
-  g_return_if_fail (g_object_get_qdata (G_OBJECT (proxy), quark_gtk_action_proxy) == action);
-
-  GTK_ACTION_GET_CLASS (action)->disconnect_proxy (action, proxy);
+  gtk_activatable_set_related_action (GTK_ACTIVATABLE (proxy), NULL);
 }
 
 /**
@@ -1072,16 +938,18 @@
  *  %NULL, if it is not attached to an action.
  *
  * Since: 2.10
+ *
+ * Deprecated 2.16: Use gtk_activatable_get_related_action() instead.
  */
 GtkAction*
 gtk_widget_get_action (GtkWidget *widget)
 {
   g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+  g_return_val_if_fail (GTK_IS_ACTIVATABLE (widget), NULL);
   
-  return g_object_get_qdata (G_OBJECT (widget), quark_gtk_action_proxy);
+  return gtk_activatable_get_related_action (GTK_ACTIVATABLE (widget));
 }
 
-
 /**
  * gtk_action_get_name:
  * @action: the action object
@@ -1144,22 +1012,6 @@
   return action->private_data->sensitive;
 }
 
-void
-_gtk_action_sync_sensitive (GtkAction *action)
-{
-  GSList *p;
-  GtkWidget *proxy;
-  gboolean sensitive;
-
-  sensitive = gtk_action_is_sensitive (action);
-
-  for (p = action->private_data->proxies; p; p = p->next)
-    {
-      proxy = (GtkWidget *)p->data;
-      gtk_widget_set_sensitive (proxy, sensitive);
-    }      
-}
-
 /**
  * gtk_action_set_sensitive:
  * @action: the action object
@@ -1184,8 +1036,6 @@
     {
       action->private_data->sensitive = sensitive;
 
-      _gtk_action_sync_sensitive (action);
-
       g_object_notify (G_OBJECT (action), "sensitive");
     }
 }
@@ -1233,36 +1083,6 @@
   return action->private_data->visible;
 }
 
-void
-_gtk_action_sync_visible (GtkAction *action)
-{
-  GSList *p;
-  GtkWidget *proxy;
-  GtkWidget *menu;
-  gboolean visible;
-
-  visible = gtk_action_is_visible (action);
-    
-  for (p = action->private_data->proxies; p; p = p->next)
-    {
-      proxy = (GtkWidget *)p->data;
-
-      if (GTK_IS_MENU_ITEM (proxy))
-	{
-	  menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy));
-	  
-	  _gtk_action_sync_menu_visible (action, proxy, _gtk_menu_is_empty (menu));
-	}
-      else
-	{
-	  if (visible)
-	    gtk_widget_show (proxy);
-	  else
-	    gtk_widget_hide (proxy);
-	}
-    } 
-}
-
 /**
  * gtk_action_set_visible:
  * @action: the action object
@@ -1287,50 +1107,79 @@
     {
       action->private_data->visible = visible;
 
-      _gtk_action_sync_visible (action);
-
       g_object_notify (G_OBJECT (action), "visible");
     }
 }
 
-static void 
+
+/**
+ * gtk_action_set_is_important:
+ * @action: the action object
+ * @is_important: %TRUE to make the action important
+ * 
+ * Sets whether the action is important, this attribute is used
+ * primarily by toolbar items.
+ *
+ * Since: 2.16
+ **/
+void 
 gtk_action_set_is_important (GtkAction *action,
 			     gboolean   is_important)
 {
-  GSList *p;
-  GtkWidget *proxy;
+  g_return_if_fail (GTK_IS_ACTION (action));
 
   is_important = is_important != FALSE;
   
   if (action->private_data->is_important != is_important)
     {
       action->private_data->is_important = is_important;
-
-      for (p = action->private_data->proxies; p; p = p->next)
-	{
-	  proxy = (GtkWidget *)p->data;
-
-	  if (GTK_IS_TOOL_ITEM (proxy))
-	    gtk_tool_item_set_is_important (GTK_TOOL_ITEM (proxy),
-					    is_important);
-	}
       
       g_object_notify (G_OBJECT (action), "is-important");
     }  
 }
 
-static void 
+
+/**
+ * gtk_action_get_is_important:
+ * @action: a #GtkAction
+ *
+ * Checks whether @action is important or not
+ * 
+ * Returns: whether @action is important
+ *
+ * Since: 2.16
+ */
+gboolean 
+gtk_action_get_is_important (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
+
+  return action->private_data->is_important;
+}
+
+
+/**
+ * gtk_action_set_label:
+ * @action: a #GtkAction
+ * @label: the label text to set
+ *
+ * Sets the label of @action.
+ *
+ * Since: 2.16
+ */
+void 
 gtk_action_set_label (GtkAction	  *action,
 		      const gchar *label)
 {
-  GSList *p;
-  GtkWidget *proxy, *child;
   gchar *tmp;
   
+  g_return_if_fail (GTK_IS_ACTION (action));
+
   tmp = action->private_data->label;
   action->private_data->label = g_strdup (label);
   g_free (tmp);
   action->private_data->label_set = (action->private_data->label != NULL);
+
   /* if label is unset, then use the label from the stock item */
   if (!action->private_data->label_set && action->private_data->stock_id)
     {
@@ -1339,21 +1188,7 @@
       if (gtk_stock_lookup (action->private_data->stock_id, &stock_item))
 	action->private_data->label = g_strdup (stock_item.label);
     }
-  
-  for (p = action->private_data->proxies; p; p = p->next)
-    {
-      proxy = (GtkWidget *)p->data;
-      
-      if (GTK_IS_MENU_ITEM (proxy))
-	{
-	  child = GTK_BIN (proxy)->child;
-	  
-	  if (GTK_IS_LABEL (child))
-	    gtk_label_set_label (GTK_LABEL (child), 
-				 action->private_data->label);
-	}
-    }
-  
+
   g_object_notify (G_OBJECT (action), "label");
   
   /* if short_label is unset, set short_label=label */
@@ -1364,12 +1199,38 @@
     }
 }
 
-static void 
-gtk_action_set_short_label (GtkAction	*action,
+/**
+ * gtk_action_get_label:
+ * @action: a #GtkAction
+ *
+ * Gets the label text of @action.
+ *
+ * Returns: the label text
+ *
+ * Since: 2.16
+ */
+G_CONST_RETURN gchar * 
+gtk_action_get_label (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
+
+  return action->private_data->label;
+}
+
+
+/**
+ * gtk_action_set_short_label:
+ * @action: a #GtkAction
+ * @label: the label text to set
+ *
+ * Sets a shorter label on @action.
+ *
+ * Since: 2.16
+ */
+void 
+gtk_action_set_short_label (GtkAction   *action,
 			    const gchar *label)
 {
-  GSList *p;
-  GtkWidget *proxy, *child;
   gchar *tmp;
 
   tmp = action->private_data->short_label;
@@ -1380,152 +1241,177 @@
   if (!action->private_data->short_label_set)
     action->private_data->short_label = g_strdup (action->private_data->label);
 
-  for (p = action->private_data->proxies; p; p = p->next)
-    {
-      proxy = (GtkWidget *)p->data;
+  g_object_notify (G_OBJECT (action), "short-label");
+}
 
-      if (GTK_IS_TOOL_BUTTON (proxy))
-	gtk_tool_button_set_label (GTK_TOOL_BUTTON (proxy),
-				   action->private_data->short_label);
-      else if (GTK_IS_BUTTON (proxy) &&
-	       !gtk_button_get_use_stock (GTK_BUTTON (proxy)))
-	{
-	  GtkWidget *image;
+/**
+ * gtk_action_get_short_label:
+ * @action: a #GtkAction
+ * @label: the label text to set
+ *
+ * Sets a shorter label on @action.
+ *
+ * Since: 2.16
+ */
+G_CONST_RETURN gchar * 
+gtk_action_get_short_label (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
 
-	  child = GTK_BIN (proxy)->child;
-
-	  image = gtk_button_get_image (GTK_BUTTON (proxy));
-
-	  if (GTK_IS_IMAGE (image) ||
-	      child == NULL || GTK_IS_LABEL (child))
-	    gtk_button_set_label (GTK_BUTTON (proxy),
-				  action->private_data->short_label);
-	}
-    }
-
-  g_object_notify (G_OBJECT (action), "short-label");
+  return action->private_data->short_label;
 }
 
-static void 
+
+/**
+ * gtk_action_set_visible_horizontal:
+ * @action: a #GtkAction
+ * @visible_horizontal: whether the action is visible horizontally
+ *
+ * Sets whether @action is visible when horizontal
+ *
+ * Since: 2.16
+ */
+void 
 gtk_action_set_visible_horizontal (GtkAction *action,
 				   gboolean   visible_horizontal)
 {
-  GSList *p;
-  GtkWidget *proxy;
+  g_return_if_fail (GTK_IS_ACTION (action));
 
   visible_horizontal = visible_horizontal != FALSE;
   
   if (action->private_data->visible_horizontal != visible_horizontal)
     {
       action->private_data->visible_horizontal = visible_horizontal;
-
-      for (p = action->private_data->proxies; p; p = p->next)
-	{
-	  proxy = (GtkWidget *)p->data;
-
-	  if (GTK_IS_TOOL_ITEM (proxy))
-	    gtk_tool_item_set_visible_horizontal (GTK_TOOL_ITEM (proxy),
-						  visible_horizontal);
-	}
       
       g_object_notify (G_OBJECT (action), "visible-horizontal");
     }  
 }
 
-static void 
+/**
+ * gtk_action_get_visible_horizontal:
+ * @action: a #GtkAction
+ *
+ * Checks whether @action is visible when horizontal
+ * 
+ * Returns: whether @action is visible when horizontal
+ *
+ * Since: 2.16
+ */
+gboolean 
+gtk_action_get_visible_horizontal (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
+
+  return action->private_data->visible_horizontal;
+}
+
+/**
+ * gtk_action_set_visible_vertical:
+ * @action: a #GtkAction
+ * @visible_vertical: whether the action is visible vertically
+ *
+ * Sets whether @action is visible when vertical 
+ *
+ * Since: 2.16
+ */
+void 
 gtk_action_set_visible_vertical (GtkAction *action,
 				 gboolean   visible_vertical)
 {
-  GSList *p;
-  GtkWidget *proxy;
+  g_return_if_fail (GTK_IS_ACTION (action));
 
   visible_vertical = visible_vertical != FALSE;
   
   if (action->private_data->visible_vertical != visible_vertical)
     {
       action->private_data->visible_vertical = visible_vertical;
-
-      for (p = action->private_data->proxies; p; p = p->next)
-	{
-	  proxy = (GtkWidget *)p->data;
-
-	  if (GTK_IS_TOOL_ITEM (proxy))
-	    gtk_tool_item_set_visible_vertical (GTK_TOOL_ITEM (proxy),
-						visible_vertical);
-	}
       
       g_object_notify (G_OBJECT (action), "visible-vertical");
     }  
 }
 
-static void 
-gtk_action_sync_tooltip (GtkAction *action,
-			 GtkWidget *proxy)
+/**
+ * gtk_action_get_visible_vertical:
+ * @action: a #GtkAction
+ *
+ * Checks whether @action is visible when horizontal
+ * 
+ * Returns: whether @action is visible when horizontal
+ *
+ * Since: 2.16
+ */
+gboolean 
+gtk_action_get_visible_vertical (GtkAction *action)
 {
-  gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (proxy),
-				  action->private_data->tooltip);
+  g_return_val_if_fail (GTK_IS_ACTION (action), FALSE);
+
+  return action->private_data->visible_vertical;
 }
 
-static void 
+/**
+ * gtk_action_set_tooltip:
+ * @action: a #GtkAction
+ * @tooltip: the tooltip text
+ *
+ * Sets the tooltip text on @action
+ *
+ * Since: 2.16
+ */
+void 
 gtk_action_set_tooltip (GtkAction   *action,
 			const gchar *tooltip)
 {
-  GSList *p;
-  GtkWidget *proxy;
   gchar *tmp;
 
+  g_return_if_fail (GTK_IS_ACTION (action));
+
   tmp = action->private_data->tooltip;
   action->private_data->tooltip = g_strdup (tooltip);
   g_free (tmp);
 
-  for (p = action->private_data->proxies; p; p = p->next)
-    {
-      proxy = (GtkWidget *)p->data;
+  g_object_notify (G_OBJECT (action), "tooltip");
+}
 
-      if (GTK_IS_TOOL_ITEM (proxy))
-        gtk_action_sync_tooltip (action, proxy);
-    }
 
-  g_object_notify (G_OBJECT (action), "tooltip");
+/**
+ * gtk_action_get_tooltip:
+ * @action: a #GtkAction
+ *
+ * Gets the tooltip text of @action.
+ *
+ * Returns: the tooltip text
+ *
+ * Since: 2.16
+ */
+G_CONST_RETURN gchar * 
+gtk_action_get_tooltip (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
+
+  return action->private_data->tooltip;
 }
 
-static void 
+/**
+ * gtk_action_set_stock_id:
+ * @action: a #GtkAction
+ * @tooltip: the tooltip text
+ *
+ * Sets the stock id on @action
+ *
+ * Since: 2.16
+ */
+void 
 gtk_action_set_stock_id (GtkAction   *action,
 			 const gchar *stock_id)
 {
-  GSList *p;
-  GtkWidget *proxy, *image;
   gchar *tmp;
-  
+
+  g_return_if_fail (GTK_IS_ACTION (action));
+
   tmp = action->private_data->stock_id;
   action->private_data->stock_id = g_strdup (stock_id);
   g_free (tmp);
 
-  for (p = action->private_data->proxies; p; p = p->next)
-    {
-      proxy = (GtkWidget *)p->data;
-      
-      if (GTK_IS_IMAGE_MENU_ITEM (proxy))
-	{
-	  image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (proxy));
-	  
-	  if (GTK_IS_IMAGE (image))
-	    gtk_image_set_from_stock (GTK_IMAGE (image),
-				      action->private_data->stock_id, GTK_ICON_SIZE_MENU);
-	} 
-      else if (GTK_IS_TOOL_BUTTON (proxy))
-	{
-	  gtk_tool_button_set_stock_id (GTK_TOOL_BUTTON (proxy),
-					action->private_data->stock_id);
-	}
-      else if (GTK_IS_BUTTON (proxy) &&
-	       gtk_button_get_use_stock (GTK_BUTTON (proxy)))
-	{
-	  gtk_button_set_label (GTK_BUTTON (proxy),
-				action->private_data->stock_id);
-	}
-    }
-
   g_object_notify (G_OBJECT (action), "stock-id");
   
   /* update label and short_label if appropriate */
@@ -1543,54 +1429,67 @@
     }
 }
 
-static void 
+/**
+ * gtk_action_get_stock_id:
+ * @action: a #GtkAction
+ *
+ * Gets the stock id of @action.
+ *
+ * Returns: the stock id
+ *
+ * Since: 2.16
+ */
+G_CONST_RETURN gchar * 
+gtk_action_get_stock_id (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
+
+  return action->private_data->stock_id;
+}
+
+/**
+ * gtk_action_set_icon_name:
+ * @action: a #GtkAction
+ * @tooltip: the icon name to set
+ *
+ * Sets the icon name on @action
+ *
+ * Since: 2.16
+ */
+void 
 gtk_action_set_icon_name (GtkAction   *action,
 			  const gchar *icon_name)
 {
-  GSList *p;
-  GtkWidget *proxy, *image;
   gchar *tmp;
-  
+
+  g_return_if_fail (GTK_IS_ACTION (action));
+
   tmp = action->private_data->icon_name;
   action->private_data->icon_name = g_strdup (icon_name);
   g_free (tmp);
 
-  for (p = action->private_data->proxies; p; p = p->next)
-    {
-      proxy = (GtkWidget *)p->data;
-      
-      if (GTK_IS_IMAGE_MENU_ITEM (proxy))
-	{
-	  image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (proxy));
-	  
-	  if (GTK_IS_IMAGE (image) &&
-	      (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
-	       gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME))
-	    gtk_image_set_from_icon_name (GTK_IMAGE (image),
-					  action->private_data->icon_name, GTK_ICON_SIZE_MENU);
-	} 
-      else if (GTK_IS_TOOL_BUTTON (proxy))
-	{
-	  gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (proxy),
-					 action->private_data->icon_name);
-	}
-      else if (GTK_IS_BUTTON (proxy) &&
-	       !gtk_button_get_use_stock (GTK_BUTTON (proxy)))
-	{
-	  image = gtk_button_get_image (GTK_BUTTON (proxy));
-	  
-	  if (GTK_IS_IMAGE (image) &&
-	      (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
-	       gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME))
-	    gtk_image_set_from_icon_name (GTK_IMAGE (image),
-					  action->private_data->icon_name, GTK_ICON_SIZE_MENU);
-	}
-    }
-  
   g_object_notify (G_OBJECT (action), "icon-name");
 }
 
+/**
+ * gtk_action_get_icon_name:
+ * @action: a #GtkAction
+ *
+ * Gets the icon name of @action.
+ *
+ * Returns: the icon name
+ *
+ * Since: 2.16
+ */
+G_CONST_RETURN gchar * 
+gtk_action_get_icon_name (GtkAction *action)
+{
+  g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
 
+  return action->private_data->icon_name;
+}
+
+
 /**
  * gtk_action_block_activate_from:
  * @action: the action object
@@ -1603,6 +1502,9 @@
  * This function is intended for use by action implementations.
  * 
  * Since: 2.4
+ *
+ * Deprecated 2.16: activatables are now responsible for activating the
+ * action directly so this doesnt apply anymore.
  */
 void
 gtk_action_block_activate_from (GtkAction *action, 
@@ -1626,6 +1528,9 @@
  * This function is intended for use by action implementations.
  * 
  * Since: 2.4
+ *
+ * Deprecated 2.16: activatables are now responsible for activating the
+ * action directly so this doesnt apply anymore.
  */
 void
 gtk_action_unblock_activate_from (GtkAction *action, 
@@ -1688,6 +1593,8 @@
   g_return_if_fail (GTK_IS_ACTION (action));
 
   action->private_data->accel_quark = g_quark_from_string (accel_path);
+
+  g_object_notify (G_OBJECT (action), "accel-path");
 }
 
 /**
Index: gtk/gtkaction.h
===================================================================
--- gtk/gtkaction.h	(revision 21809)
+++ gtk/gtkaction.h	(working copy)
@@ -46,8 +46,8 @@
 #define GTK_IS_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_ACTION))
 #define GTK_ACTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_ACTION, GtkActionClass))
 
-typedef struct _GtkAction      GtkAction;
-typedef struct _GtkActionClass GtkActionClass;
+typedef struct _GtkAction        GtkAction;
+typedef struct _GtkActionClass   GtkActionClass;
 typedef struct _GtkActionPrivate GtkActionPrivate;
 
 struct _GtkAction
@@ -105,22 +105,47 @@
 GtkWidget *  gtk_action_create_menu_item       (GtkAction     *action);
 GtkWidget *  gtk_action_create_tool_item       (GtkAction     *action);
 GtkWidget *  gtk_action_create_menu            (GtkAction     *action);
-void         gtk_action_connect_proxy          (GtkAction     *action,
-						GtkWidget     *proxy);
-void         gtk_action_disconnect_proxy       (GtkAction     *action,
-						GtkWidget     *proxy);
 GSList *     gtk_action_get_proxies            (GtkAction     *action);
-GtkAction *  gtk_widget_get_action             (GtkWidget     *widget);
 void         gtk_action_connect_accelerator    (GtkAction     *action);
 void         gtk_action_disconnect_accelerator (GtkAction     *action);
 G_CONST_RETURN gchar *gtk_action_get_accel_path (GtkAction     *action);
 GClosure    *gtk_action_get_accel_closure      (GtkAction     *action);
 
-/* protected ... for use by child actions */
-void         gtk_action_block_activate_from    (GtkAction     *action,
+
+void                  gtk_action_set_label               (GtkAction      *action,
+							  const gchar    *label);
+G_CONST_RETURN gchar *gtk_action_get_label               (GtkAction      *action);
+void                  gtk_action_set_short_label         (GtkAction      *action,
+							  const gchar    *short_label);
+G_CONST_RETURN gchar *gtk_action_get_short_label         (GtkAction      *action);
+void                  gtk_action_set_tooltip             (GtkAction      *action,
+							  const gchar    *tooltip);
+G_CONST_RETURN gchar *gtk_action_get_tooltip             (GtkAction      *action);
+void                  gtk_action_set_stock_id            (GtkAction      *action,
+							  const gchar    *stock_id);
+G_CONST_RETURN gchar *gtk_action_get_stock_id            (GtkAction      *action);
+void                  gtk_action_set_icon_name           (GtkAction      *action,
+							  const gchar    *icon_name);
+G_CONST_RETURN gchar *gtk_action_get_icon_name           (GtkAction      *action);
+void                  gtk_action_set_visible_horizontal  (GtkAction      *action,
+							  gboolean        visible_horizontal);
+gboolean              gtk_action_get_visible_horizontal  (GtkAction      *action);
+void                  gtk_action_set_visible_vertical    (GtkAction      *action,
+							  gboolean        visible_vertical);
+gboolean              gtk_action_get_visible_vertical    (GtkAction      *action);
+void                  gtk_action_set_is_important        (GtkAction      *action,
+							  gboolean        is_important);
+gboolean              gtk_action_get_is_important        (GtkAction      *action);
+
+
+/* protected ... for use by child activatable proxies */
+void         gtk_action_block_activate         (GtkAction     *action);
+void         gtk_action_unblock_activate       (GtkAction     *action);
+void         gtk_action_add_to_proxy_list      (GtkAction     *action,
 						GtkWidget     *proxy);
-void         gtk_action_unblock_activate_from  (GtkAction     *action,
+void         gtk_action_remove_from_proxy_list (GtkAction     *action,
 						GtkWidget     *proxy);
+GtkActionGroup *gtk_action_get_group           (GtkAction     *action);
 void         _gtk_action_emit_activate         (GtkAction     *action);
 
 /* protected ... for use by action groups */
@@ -128,12 +153,23 @@
 						const gchar   *accel_path);
 void         gtk_action_set_accel_group        (GtkAction     *action,
 						GtkAccelGroup *accel_group);
-void         _gtk_action_sync_sensitive        (GtkAction     *action);
-void         _gtk_action_sync_visible          (GtkAction     *action);
 void         _gtk_action_sync_menu_visible     (GtkAction     *action,
 						GtkWidget     *proxy,
 						gboolean       empty);
 
+#ifndef GTK_DISABLE_DEPRECATED
+GtkAction   *gtk_widget_get_action             (GtkWidget     *widget);
+void         gtk_action_connect_proxy          (GtkAction     *action,
+						GtkWidget     *proxy);
+void         gtk_action_disconnect_proxy       (GtkAction     *action,
+						GtkWidget     *proxy);
+void         gtk_action_block_activate_from    (GtkAction     *action,
+						GtkWidget     *proxy);
+void         gtk_action_unblock_activate_from  (GtkAction     *action,
+						GtkWidget     *proxy);
+#endif /* GTK_DISABLE_DEPRECATED */
+
+
 G_END_DECLS
 
 #endif  /* __GTK_ACTION_H__ */
Index: gtk/gtkradioaction.c
===================================================================
--- gtk/gtkradioaction.c	(revision 21809)
+++ gtk/gtkradioaction.c	(working copy)
@@ -324,6 +324,8 @@
 	  if (tmp_action->private_data->active && (tmp_action != toggle_action)) 
 	    {
 	      toggle_action->private_data->active = !toggle_action->private_data->active;
+
+	      g_object_notify (G_OBJECT (action), "active");
 	      break;
 	    }
 	}
@@ -331,6 +333,7 @@
   else
     {
       toggle_action->private_data->active = !toggle_action->private_data->active;
+      g_object_notify (G_OBJECT (action), "active");
 
       tmp_list = radio_action->private_data->group;
       while (tmp_list)
Index: gtk/gtkrecentchooser.c
===================================================================
--- gtk/gtkrecentchooser.c	(revision 21809)
+++ gtk/gtkrecentchooser.c	(working copy)
@@ -24,6 +24,8 @@
 #include "gtkrecentchooser.h"
 #include "gtkrecentchooserprivate.h"
 #include "gtkrecentmanager.h"
+#include "gtkrecentaction.h"
+#include "gtkactivatable.h"
 #include "gtkintl.h"
 #include "gtktypebuiltins.h"
 #include "gtkprivate.h"
@@ -39,8 +41,25 @@
   LAST_SIGNAL
 };
 
-static void gtk_recent_chooser_class_init (gpointer g_iface);
+static void gtk_recent_chooser_class_init         (gpointer        g_iface);
 
+static void gtk_recent_chooser_activatable_update (GtkActivatable *activatable,
+						   GtkAction      *action,
+						   const gchar    *property_name);
+
+
+static void delegate_selection_changed            (GtkRecentAction *action,
+						   GtkRecentChooser *chooser);
+static void delegate_item_activated               (GtkRecentAction  *action,
+						   GtkRecentChooser *chooser);
+
+
+static GQuark      quark_gtk_related_action               = 0;
+static GQuark      quark_gtk_use_action_appearance        = 0;
+static const gchar gtk_related_action_key[]               = "gtk-related-action";
+static const gchar gtk_use_action_appearance_key[]        = "gtk-use-action-appearance";
+
+
 static guint chooser_signals[LAST_SIGNAL] = { 0, };
 
 GType
@@ -66,6 +85,9 @@
 gtk_recent_chooser_class_init (gpointer g_iface)
 {
   GType iface_type = G_TYPE_FROM_INTERFACE (g_iface);
+
+  quark_gtk_related_action        = g_quark_from_static_string (gtk_related_action_key);
+  quark_gtk_use_action_appearance = g_quark_from_static_string (gtk_use_action_appearance_key);
   
   /**
    * GtkRecentChooser::selection-changed
@@ -1074,5 +1096,157 @@
   g_signal_emit (chooser, chooser_signals[SELECTION_CHANGED], 0);
 }
 
+
+void
+_gtk_recent_chooser_activatable_iface_init (GtkActivatableIface *iface)
+{
+  iface->update = gtk_recent_chooser_activatable_update;
+}
+
+static void
+gtk_recent_chooser_activatable_update (GtkActivatable *activatable,
+				       GtkAction      *action,
+				       const gchar    *property_name)
+{
+  GtkRecentChooser *recent_chooser = GTK_RECENT_CHOOSER (activatable);
+  GtkRecentChooser *action_chooser = GTK_RECENT_CHOOSER (action);
+
+  if (property_name == NULL || strcmp (property_name, "visible") == 0)
+    {
+      if (gtk_action_is_visible (action))
+	gtk_widget_show (GTK_WIDGET (activatable));
+      else
+	gtk_widget_hide (GTK_WIDGET (activatable));
+    }
+  else if (property_name == NULL || strcmp (property_name, "sensitive") == 0)
+    gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
+  else if (property_name || strcmp (property_name, "show-numbers") == 0)
+    gtk_recent_chooser_set_show_numbers (recent_chooser, 
+					 gtk_recent_action_get_show_numbers (GTK_RECENT_ACTION (action)));
+  else if (property_name || strcmp (property_name, "show-private") == 0)
+    gtk_recent_chooser_set_show_numbers (recent_chooser, gtk_recent_chooser_get_show_numbers (action_chooser));
+  else if (property_name || strcmp (property_name, "show-not-found") == 0)
+    gtk_recent_chooser_set_show_not_found (recent_chooser, gtk_recent_chooser_get_show_not_found (action_chooser));
+  else if (property_name || strcmp (property_name, "show-tips") == 0)
+    gtk_recent_chooser_set_show_tips (recent_chooser, gtk_recent_chooser_get_show_tips (action_chooser));
+  else if (property_name || strcmp (property_name, "show-icons") == 0)
+    gtk_recent_chooser_set_show_icons (recent_chooser, gtk_recent_chooser_get_show_icons (action_chooser));
+  else if (property_name || strcmp (property_name, "limit") == 0)
+    gtk_recent_chooser_set_limit (recent_chooser, gtk_recent_chooser_get_limit (action_chooser));
+  else if (property_name || strcmp (property_name, "local-only") == 0)
+    gtk_recent_chooser_set_local_only (recent_chooser, gtk_recent_chooser_get_local_only (action_chooser));
+  else if (property_name || strcmp (property_name, "sort-type") == 0)
+    gtk_recent_chooser_set_sort_type (recent_chooser, gtk_recent_chooser_get_sort_type (action_chooser));
+  else if (property_name || strcmp (property_name, "filter") == 0)
+    gtk_recent_chooser_set_filter (recent_chooser, gtk_recent_chooser_get_filter (action_chooser));
+/*   else if (property_name || strcmp (property_name, "manager") == 0) */
+/*     gtk_recent_chooser_set_manager (recent_chooser, gtk_recent_chooser_get_manager (action_chooser)); */
+  else if (property_name || strcmp (property_name, "sort-info") == 0)
+    {
+      GtkRecentActionSortInfo *info;
+
+      g_object_get (G_OBJECT (action_chooser), "sort-info", &info, NULL);
+
+      gtk_recent_chooser_set_sort_func (recent_chooser,
+					info ? info->sort_func : NULL,
+					info ? info->sort_data : NULL,
+					info ? info->data_destroy : NULL);
+    }
+}
+
+static void
+gtk_recent_chooser_action_notify (GtkAction   *action,
+				  GParamSpec  *pspec,
+				  GtkRecentChooser *recent_chooser)
+{
+  gtk_activatable_update (GTK_ACTIVATABLE (recent_chooser), action, pspec->name);
+}
+
+
+static void
+delegate_selection_changed (GtkRecentAction  *action,
+                            GtkRecentChooser *chooser)
+{
+  gtk_recent_action_set_current_chooser (action, chooser);
+
+  g_signal_emit_by_name (action, "selection-changed");
+}
+
+static void
+delegate_item_activated (GtkRecentAction  *action,
+                         GtkRecentChooser *chooser)
+{
+  gtk_recent_action_set_current_chooser (action, chooser);
+
+  g_signal_emit_by_name (action, "item-activated");
+}
+
+void
+_gtk_recent_chooser_set_related_action (GtkRecentChooser *recent_chooser, 
+					GtkAction        *action)
+{
+  GtkAction *prev_action;
+
+  prev_action = g_object_get_qdata (G_OBJECT (recent_chooser), quark_gtk_related_action);
+
+  if (prev_action == action)
+    return;
+
+  if (prev_action)
+    {
+      g_signal_handlers_disconnect_by_func (prev_action, gtk_recent_chooser_action_notify, recent_chooser);
+      g_signal_handlers_disconnect_by_func (recent_chooser, delegate_selection_changed, prev_action);
+      g_signal_handlers_disconnect_by_func (recent_chooser, delegate_item_activated, prev_action);
+
+    }
+  g_object_set_qdata (G_OBJECT (recent_chooser), quark_gtk_related_action, action);
+
+  if (action)
+    {
+      g_signal_connect (G_OBJECT (action), "notify", G_CALLBACK (gtk_recent_chooser_action_notify), recent_chooser);
+
+      g_signal_connect_swapped (recent_chooser, "selection-changed",
+                                G_CALLBACK (delegate_selection_changed),
+                                action);
+      g_signal_connect_swapped (recent_chooser, "item-activated",
+                                G_CALLBACK (delegate_item_activated),
+                                action);
+      
+      gtk_activatable_update (GTK_ACTIVATABLE (recent_chooser), action, NULL);
+    }
+}
+
+GtkAction *
+_gtk_recent_chooser_get_related_action (GtkRecentChooser *recent_chooser)
+{
+  return g_object_get_qdata (G_OBJECT (recent_chooser), quark_gtk_related_action);
+}
+
+void
+_gtk_recent_chooser_set_use_action_appearance (GtkRecentChooser *recent_chooser, 
+					       gboolean          use_appearance)
+{
+  GtkAction *action;
+  gboolean   use_action_appearance;
+
+  action                = g_object_get_qdata (G_OBJECT (recent_chooser), quark_gtk_related_action);
+  use_action_appearance = GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (recent_chooser), quark_gtk_related_action));
+
+  if (use_action_appearance != use_appearance)
+    {
+
+      g_object_set_qdata (G_OBJECT (recent_chooser), quark_gtk_related_action, GINT_TO_POINTER (use_appearance));
+
+      if (action && use_appearance)
+	gtk_activatable_update (GTK_ACTIVATABLE (recent_chooser), action, NULL);
+    }
+}
+
+gboolean
+_gtk_recent_chooser_get_use_action_appearance (GtkRecentChooser *recent_chooser)
+{
+  return GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (recent_chooser), quark_gtk_related_action));
+}
+
 #define __GTK_RECENT_CHOOSER_C__
 #include "gtkaliasdef.c"
Index: gtk/gtkactiongroup.c
===================================================================
--- gtk/gtkactiongroup.c	(revision 21809)
+++ gtk/gtkactiongroup.c	(working copy)
@@ -626,8 +626,10 @@
 {
   /* Minor optimization, the action_groups state only affects actions 
    * that are themselves sensitive */
-  if (gtk_action_get_sensitive (action))
-    _gtk_action_sync_sensitive (action);
+/*   if (gtk_action_get_sensitive (action)) */
+/*     _gtk_action_sync_sensitive (action); */
+  g_object_notify (G_OBJECT (action), "sensitive");
+
 }
 
 /**
@@ -691,8 +693,10 @@
 {
   /* Minor optimization, the action_groups state only affects actions 
    * that are themselves visible */
-  if (gtk_action_get_visible (action))
-    _gtk_action_sync_visible (action);
+/*   if (gtk_action_get_visible (action)) */
+/*     _gtk_action_sync_visible (action); */
+
+  g_object_notify (G_OBJECT (action), "visible");
 }
 
 /**
Index: gtk/gtkactiongroup.h
===================================================================
--- gtk/gtkactiongroup.h	(revision 21809)
+++ gtk/gtkactiongroup.h	(working copy)
@@ -47,7 +47,6 @@
 #define GTK_IS_ACTION_GROUP_CLASS(vtable)  (G_TYPE_CHECK_CLASS_TYPE ((vtable), GTK_TYPE_ACTION_GROUP))
 #define GTK_ACTION_GROUP_GET_CLASS(inst)   (G_TYPE_INSTANCE_GET_CLASS ((inst), GTK_TYPE_ACTION_GROUP, GtkActionGroupClass))
 
-typedef struct _GtkActionGroup        GtkActionGroup;
 typedef struct _GtkActionGroupPrivate GtkActionGroupPrivate;
 typedef struct _GtkActionGroupClass   GtkActionGroupClass;
 typedef struct _GtkActionEntry        GtkActionEntry;
Index: gtk/Makefile.am
===================================================================
--- gtk/Makefile.am	(revision 21809)
+++ gtk/Makefile.am	(working copy)
@@ -148,6 +148,7 @@
 	gtkaccessible.h		\
 	gtkaction.h		\
 	gtkactiongroup.h	\
+	gtkactivatable.h	\
 	gtkadjustment.h		\
 	gtkalignment.h		\
 	gtkarrow.h		\
@@ -397,6 +398,7 @@
 	gtkaccessible.c		\
 	gtkaction.c		\
 	gtkactiongroup.c	\
+	gtkactivatable.c	\
 	gtkadjustment.c		\
 	gtkalignment.c		\
 	gtkarrow.c		\
Index: gtk/gtkprivate.h
===================================================================
--- gtk/gtkprivate.h	(revision 21809)
+++ gtk/gtkprivate.h	(working copy)
@@ -47,7 +47,8 @@
   PRIVATE_GTK_CHILD_VISIBLE     = 1 <<  10,  /* If widget should be mapped when parent is mapped */
   PRIVATE_GTK_REDRAW_ON_ALLOC   = 1 <<  11,  /* If we should queue a draw on the entire widget when it is reallocated */
   PRIVATE_GTK_ALLOC_NEEDED      = 1 <<  12,  /* If we we should allocate even if the allocation is the same */
-  PRIVATE_GTK_REQUEST_NEEDED    = 1 <<  13   /* Whether we need to call gtk_widget_size_request */
+  PRIVATE_GTK_REQUEST_NEEDED    = 1 <<  13,  /* Whether we need to call gtk_widget_size_request */
+  PRIVATE_GTK_ACTION_APPEARANCE = 1 <<  14   /* Whether the widget has the appearacne of the controlling action */
 } GtkPrivateFlags;
 
 /* Macros for extracting a widgets private_flags from GtkWidget.
@@ -66,6 +67,7 @@
 #define GTK_WIDGET_REDRAW_ON_ALLOC(obj)   ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_REDRAW_ON_ALLOC) != 0)
 #define GTK_WIDGET_ALLOC_NEEDED(obj)      ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_ALLOC_NEEDED) != 0)
 #define GTK_WIDGET_REQUEST_NEEDED(obj)    ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_REQUEST_NEEDED) != 0)
+#define GTK_WIDGET_ACTION_APPEARANCE(obj) ((GTK_PRIVATE_FLAGS (obj) & PRIVATE_GTK_ACTION_APPEARANCE) != 0)
 
 /* Macros for setting and clearing private widget flags.
  * we use a preprocessor string concatenation here for a clear
Index: gtk/gtkmenuitem.c
===================================================================
--- gtk/gtkmenuitem.c	(revision 21809)
+++ gtk/gtkmenuitem.c	(working copy)
@@ -37,9 +37,16 @@
 #include "gtkseparatormenuitem.h"
 #include "gtkprivate.h"
 #include "gtkbuildable.h"
+#include "gtkactivatable.h"
 #include "gtkintl.h"
 #include "gtkalias.h"
 
+
+typedef struct {
+  GtkAction *action;
+  gboolean   use_action_appearance;
+} GtkMenuItemPrivate;
+
 enum {
   ACTIVATE,
   ACTIVATE_ITEM,
@@ -54,10 +61,15 @@
   PROP_SUBMENU,
   PROP_ACCEL_PATH,
   PROP_LABEL,
-  PROP_USE_UNDERLINE
+  PROP_USE_UNDERLINE,
+
+  /* activatable properties */
+  PROP_ACTIVATABLE_ACTION,
+  PROP_ACTIVATABLE_USE_APPEARANCE
 };
 
 
+static void gtk_menu_item_dispose        (GObject          *object);
 static void gtk_menu_item_set_property   (GObject          *object,
 					  guint             prop_id,
 					  const GValue     *value,
@@ -85,6 +97,7 @@
 
 static void gtk_real_menu_item_select               (GtkItem     *item);
 static void gtk_real_menu_item_deselect             (GtkItem     *item);
+static void gtk_real_menu_item_activate             (GtkMenuItem *item);
 static void gtk_real_menu_item_activate_item        (GtkMenuItem *item);
 static void gtk_real_menu_item_toggle_size_request  (GtkMenuItem *menu_item,
 						     gint        *requisition);
@@ -120,14 +133,32 @@
 						    GObject             *child,
 						    const gchar         *type);
 
+static void gtk_menu_item_activatable_interface_init (GtkActivatableIface  *iface);
+static void gtk_menu_item_activatable_update         (GtkActivatable       *activatable,
+						      GtkAction            *action,
+						      const gchar          *property_name);
+static void gtk_menu_item_set_related_action         (GtkMenuItem          *menu_item, 
+						      GtkAction            *action);
+static void gtk_menu_item_set_use_action_appearance  (GtkMenuItem          *menu_item, 
+						      gboolean              use_appearance);
+static void gtk_menu_item_action_notify              (GtkAction            *action,
+						      GParamSpec           *pspec,
+						      GtkMenuItem          *menu_item);
+
+
 static guint menu_item_signals[LAST_SIGNAL] = { 0 };
 
 static GtkBuildableIface *parent_buildable_iface;
 
 G_DEFINE_TYPE_WITH_CODE (GtkMenuItem, gtk_menu_item, GTK_TYPE_ITEM,
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
-						gtk_menu_item_buildable_interface_init))
+						gtk_menu_item_buildable_interface_init)
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+						gtk_menu_item_activatable_interface_init))
 
+#define GET_PRIVATE(object)  \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((object), GTK_TYPE_MENU_ITEM, GtkMenuItemPrivate))
+
 static void
 gtk_menu_item_class_init (GtkMenuItemClass *klass)
 {
@@ -137,6 +168,7 @@
   GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
   GtkItemClass *item_class = GTK_ITEM_CLASS (klass);
 
+  gobject_class->dispose      = gtk_menu_item_dispose;
   gobject_class->set_property = gtk_menu_item_set_property;
   gobject_class->get_property = gtk_menu_item_get_property;
 
@@ -157,15 +189,15 @@
   
   container_class->forall = gtk_menu_item_forall;
 
-  item_class->select = gtk_real_menu_item_select;
-  item_class->deselect = gtk_real_menu_item_deselect;
+  item_class->select      = gtk_real_menu_item_select;
+  item_class->deselect    = gtk_real_menu_item_deselect;
 
-  klass->activate = NULL;
-  klass->activate_item = gtk_real_menu_item_activate_item;
-  klass->toggle_size_request = gtk_real_menu_item_toggle_size_request;
+  klass->activate             = gtk_real_menu_item_activate;
+  klass->activate_item        = gtk_real_menu_item_activate_item;
+  klass->toggle_size_request  = gtk_real_menu_item_toggle_size_request;
   klass->toggle_size_allocate = gtk_real_menu_item_toggle_size_allocate;
-  klass->set_label = gtk_real_menu_item_set_label;
-  klass->get_label = gtk_real_menu_item_get_label;
+  klass->set_label            = gtk_real_menu_item_set_label;
+  klass->get_label            = gtk_real_menu_item_get_label;
 
   klass->hide_on_activate = TRUE;
 
@@ -288,6 +320,9 @@
 							 FALSE,
 							 GTK_PARAM_READWRITE));
 
+  g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_ACTION, "related-action");
+  g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_USE_APPEARANCE, "use-action-appearance");
+
   gtk_widget_class_install_style_property_parser (widget_class,
 						  g_param_spec_enum ("selected-shadow-type",
 								     "Selected Shadow Type",
@@ -344,12 +379,19 @@
                                                              P_("The minimum desired width of the menu item in characters"),
                                                              0, G_MAXINT, 12,
                                                              GTK_PARAM_READABLE));
+
+  g_type_class_add_private (object_class, sizeof (GtkMenuItemPrivate));
 }
 
 static void
 gtk_menu_item_init (GtkMenuItem *menu_item)
 {
+  GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+
   GTK_WIDGET_SET_FLAGS (menu_item, GTK_NO_WINDOW);
+
+  priv->action = NULL;
+  priv->use_action_appearance = FALSE;
   
   menu_item->submenu = NULL;
   menu_item->toggle_size = 0;
@@ -399,6 +441,24 @@
 		       NULL);
 }
 
+static void
+gtk_menu_item_dispose (GObject *object)
+{
+  GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
+  GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+
+  if (priv->action)
+    {
+      g_signal_handlers_disconnect_by_func (priv->action, gtk_menu_item_action_notify, menu_item);
+
+      gtk_action_disconnect_accelerator (priv->action);
+      _gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (menu_item), NULL);
+      
+      priv->action = NULL;
+    }
+  G_OBJECT_CLASS (gtk_menu_item_parent_class)->dispose (object);
+}
+
 static void 
 gtk_menu_item_set_property (GObject      *object,
 			    guint         prop_id,
@@ -424,7 +484,12 @@
     case PROP_USE_UNDERLINE:
       gtk_menu_item_set_use_underline (menu_item, g_value_get_boolean (value));
       break;
-
+    case PROP_ACTIVATABLE_ACTION:
+      gtk_menu_item_set_related_action (menu_item, g_value_get_object (value));
+      break;
+    case PROP_ACTIVATABLE_USE_APPEARANCE:
+      gtk_menu_item_set_use_action_appearance (menu_item, g_value_get_boolean (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -438,6 +503,7 @@
 			    GParamSpec *pspec)
 {
   GtkMenuItem *menu_item = GTK_MENU_ITEM (object);
+  GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
   
   switch (prop_id)
     {
@@ -456,7 +522,12 @@
     case PROP_USE_UNDERLINE:
       g_value_set_boolean (value, gtk_menu_item_get_use_underline (menu_item));
       break;
-
+    case PROP_ACTIVATABLE_ACTION:
+      g_value_set_object (value, priv->action);
+      break;
+    case PROP_ACTIVATABLE_USE_APPEARANCE:
+      g_value_set_boolean (value, priv->use_action_appearance);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -505,6 +576,144 @@
     parent_buildable_iface->add_child (buildable, builder, child, type);
 }
 
+static void
+gtk_menu_item_activatable_interface_init (GtkActivatableIface *iface)
+{
+  iface->update = gtk_menu_item_activatable_update;
+}
+
+static void 
+activatable_update_label (GtkMenuItem *menu_item)
+{
+  GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+  GtkWidget *child = GTK_BIN (menu_item)->child;
+	  
+  if (GTK_IS_LABEL (child))
+    {
+      const gchar *label;
+
+      label = gtk_action_get_label (priv->action);
+      gtk_label_set_label (GTK_LABEL (child), label ? label : "");
+    }
+}
+
+gboolean _gtk_menu_is_empty (GtkWidget *menu);
+
+static void
+gtk_menu_item_activatable_update (GtkActivatable *activatable,
+				  GtkAction      *action,
+				  const gchar    *property_name)
+{
+  GtkMenuItem *menu_item = GTK_MENU_ITEM (activatable);
+  GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+
+  if (property_name == NULL)
+    {
+      _gtk_action_sync_menu_visible (action, GTK_WIDGET (menu_item), 
+				     _gtk_menu_is_empty (gtk_menu_item_get_submenu (menu_item)));
+
+      gtk_widget_set_sensitive (GTK_WIDGET (menu_item), gtk_action_is_sensitive (action));
+
+      if (priv->use_action_appearance)
+	{
+	  GtkWidget *label = GTK_BIN (menu_item)->child;
+	  
+	  /* make sure label is a label */
+	  if (label && !GTK_IS_LABEL (label))
+	    {
+	      gtk_container_remove (GTK_CONTAINER (menu_item), label);
+	      label = NULL;
+	    }
+	  
+	  if (!label)
+	    label = g_object_new (GTK_TYPE_ACCEL_LABEL,
+				  "use-underline", TRUE,
+				  "xalign", 0.0,
+				  "visible", TRUE,
+				  "parent", menu_item,
+				  NULL);
+	  
+	  if (GTK_IS_ACCEL_LABEL (label) && gtk_action_get_accel_path (action))
+	    g_object_set (label,
+			  "accel-closure", gtk_action_get_accel_closure (action),
+			  NULL);
+
+	  activatable_update_label (menu_item);
+	}
+    }
+  else if (strcmp (property_name, "visible") == 0)
+    _gtk_action_sync_menu_visible (action, GTK_WIDGET (menu_item), 
+				   _gtk_menu_is_empty (gtk_menu_item_get_submenu (menu_item)));
+  else if (strcmp (property_name, "sensitive") == 0)
+    gtk_widget_set_sensitive (GTK_WIDGET (menu_item), gtk_action_is_sensitive (action));
+  else if (priv->use_action_appearance)
+    {
+      if (strcmp (property_name, "label") == 0)
+	  activatable_update_label (menu_item);
+    }
+}
+
+static void
+gtk_menu_item_action_notify (GtkAction   *action,
+			     GParamSpec  *pspec,
+			     GtkMenuItem *menu_item)
+{
+  gtk_activatable_update (GTK_ACTIVATABLE (menu_item), action, pspec->name);
+}
+
+static void
+gtk_menu_item_set_related_action (GtkMenuItem *menu_item, 
+				  GtkAction   *action)
+{
+    GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+
+    if (priv->action == action)
+      return;
+
+    if (priv->action)
+      {
+	g_signal_handlers_disconnect_by_func (priv->action, gtk_menu_item_action_notify, menu_item);
+
+	gtk_action_disconnect_accelerator (priv->action);
+      }
+
+    _gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (menu_item), action);
+
+    priv->action = action;
+
+    if (action)
+      {
+	const gchar *accel_path;
+	
+	g_signal_connect (G_OBJECT (action), "notify", G_CALLBACK (gtk_menu_item_action_notify), menu_item);
+
+	accel_path = gtk_action_get_accel_path (action);
+	if (accel_path)
+	  {
+	    gtk_action_connect_accelerator (action);
+	    gtk_menu_item_set_accel_path (menu_item, accel_path);
+	  }
+
+	gtk_activatable_update (GTK_ACTIVATABLE (menu_item), action, NULL);
+      }
+}
+
+static void
+gtk_menu_item_set_use_action_appearance (GtkMenuItem *menu_item, 
+					 gboolean     use_appearance)
+{
+    GtkMenuItemPrivate *priv = GET_PRIVATE (menu_item);
+
+    if (priv->use_action_appearance != use_appearance)
+      {
+	priv->use_action_appearance = use_appearance;
+
+	if (priv->action && use_appearance)
+	  gtk_activatable_update (GTK_ACTIVATABLE (menu_item), priv->action, NULL);
+      }
+}
+
+
 /**
  * gtk_menu_item_set_submenu:
  * @menu_item: a #GtkMenuItem
@@ -629,7 +838,7 @@
 gtk_menu_item_activate (GtkMenuItem *menu_item)
 {
   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
-  
+
   g_signal_emit (menu_item, menu_item_signals[ACTIVATE], 0);
 }
 
@@ -1142,13 +1351,27 @@
   return TRUE;
 }
 
+static void 
+gtk_real_menu_item_activate (GtkMenuItem *menu_item)
+{
+  GtkMenuItemPrivate *priv;
+
+  priv = GET_PRIVATE (menu_item);
+
+  if (priv->action && gtk_menu_item_get_submenu (menu_item) == NULL)
+    gtk_action_activate (priv->action);
+}
+
+
 static void
 gtk_real_menu_item_activate_item (GtkMenuItem *menu_item)
 {
+  GtkMenuItemPrivate *priv;
   GtkWidget *widget;
 
   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
 
+  priv   = GET_PRIVATE (menu_item);
   widget = GTK_WIDGET (menu_item);
   
   if (widget->parent &&
Index: gtk/gtkimagemenuitem.c
===================================================================
--- gtk/gtkimagemenuitem.c	(revision 21809)
+++ gtk/gtkimagemenuitem.c	(working copy)
@@ -34,6 +34,7 @@
 #include "gtkmenubar.h"
 #include "gtkcontainer.h"
 #include "gtkwindow.h"
+#include "gtkactivatable.h"
 #include "gtkprivate.h"
 #include "gtkalias.h"
 
@@ -70,6 +71,10 @@
 
 static void gtk_image_menu_item_recalculate          (GtkImageMenuItem *image_menu_item);
 
+static void gtk_image_menu_item_activatable_interface_init (GtkActivatableIface  *iface);
+static void gtk_image_menu_item_activatable_update         (GtkActivatable       *activatable,
+							    GtkAction            *action,
+							    const gchar          *property_name);
 
 typedef struct {
   gchar          *label;
@@ -83,8 +88,13 @@
   PROP_ACCEL_GROUP
 };
 
-G_DEFINE_TYPE (GtkImageMenuItem, gtk_image_menu_item, GTK_TYPE_MENU_ITEM)
+static GtkActivatableIface *parent_activatable_iface;
 
+
+G_DEFINE_TYPE_WITH_CODE (GtkImageMenuItem, gtk_image_menu_item, GTK_TYPE_MENU_ITEM,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+						gtk_image_menu_item_activatable_interface_init))
+
 #define GET_PRIVATE(object)  \
   (G_TYPE_INSTANCE_GET_PRIVATE ((object), GTK_TYPE_IMAGE_MENU_ITEM, GtkImageMenuItemPrivate))
 
@@ -504,6 +514,93 @@
     (* callback) (image_menu_item->image, callback_data);
 }
 
+
+static void 
+gtk_image_menu_item_activatable_interface_init (GtkActivatableIface  *iface)
+{
+  parent_activatable_iface = g_type_interface_peek_parent (iface);
+  iface->update = gtk_image_menu_item_activatable_update;
+}
+
+static gboolean
+activatable_update_stock_id (GtkImageMenuItem *image_menu_item, GtkAction *action)
+{
+  GtkWidget   *image;
+  const gchar *stock_id  = gtk_action_get_stock_id (action);
+
+  image = gtk_image_menu_item_get_image (image_menu_item);
+	  
+  if (GTK_IS_IMAGE (image) &&
+      stock_id && gtk_icon_factory_lookup_default (stock_id))
+    {
+      gtk_image_set_from_stock (GTK_IMAGE (image), stock_id, GTK_ICON_SIZE_MENU);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+activatable_update_icon_name (GtkImageMenuItem *image_menu_item, GtkAction *action)
+{
+  GtkWidget   *image;
+  const gchar *icon_name = gtk_action_get_icon_name (action);
+
+  image = gtk_image_menu_item_get_image (image_menu_item);
+	  
+  if (GTK_IS_IMAGE (image) && icon_name &&
+      (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
+       gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME))
+    {
+      gtk_image_set_from_icon_name (GTK_IMAGE (image), icon_name, GTK_ICON_SIZE_MENU);
+    }
+}
+
+static void 
+gtk_image_menu_item_activatable_update (GtkActivatable       *activatable,
+					GtkAction            *action,
+					const gchar          *property_name)
+{
+  GtkImageMenuItem *image_menu_item;
+  GtkWidget *image;
+  gboolean   use_appearance;
+
+  image_menu_item = GTK_IMAGE_MENU_ITEM (activatable);
+
+  parent_activatable_iface->update (activatable, action, property_name);
+
+  use_appearance = gtk_activatable_get_use_action_appearance (activatable);
+  if (!use_appearance)
+    return;
+
+  if (property_name == NULL)
+    {
+      image = gtk_image_menu_item_get_image (image_menu_item);
+      if (image && !GTK_IS_IMAGE (image))
+	{
+	  gtk_image_menu_item_set_image (image_menu_item, NULL);
+	  image = NULL;
+	}
+      
+      if (!image)
+	{
+	  image = gtk_image_new ();
+	  gtk_widget_show (image);
+	  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (activatable),
+					 image);
+	}
+
+      if (!activatable_update_stock_id (image_menu_item, action))
+	activatable_update_icon_name (image_menu_item, action);
+
+    }
+  else if (strcmp (property_name, "stock-id") == 0)
+    activatable_update_stock_id (image_menu_item, action);
+  else if (strcmp (property_name, "icon-name") == 0)
+    activatable_update_icon_name (image_menu_item, action);
+}
+
+
 /**
  * gtk_image_menu_item_new:
  * @returns: a new #GtkImageMenuItem.
Index: gtk/gtktoolitem.c
===================================================================
--- gtk/gtktoolitem.c	(revision 21809)
+++ gtk/gtktoolitem.c	(working copy)
@@ -30,6 +30,7 @@
 #include "gtkmarshalers.h"
 #include "gtktoolshell.h"
 #include "gtkseparatormenuitem.h"
+#include "gtkactivatable.h"
 #include "gtkintl.h"
 #include "gtkmain.h"
 #include "gtkprivate.h"
@@ -69,7 +70,11 @@
   PROP_0,
   PROP_VISIBLE_HORIZONTAL,
   PROP_VISIBLE_VERTICAL,
-  PROP_IS_IMPORTANT
+  PROP_IS_IMPORTANT,
+
+  /* activatable properties */
+  PROP_ACTIVATABLE_ACTION,
+  PROP_ACTIVATABLE_USE_APPEARANCE
 };
 
 #define GTK_TOOL_ITEM_GET_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_TOOL_ITEM, GtkToolItemPrivate))
@@ -90,11 +95,15 @@
   
   gchar *menu_item_id;
   GtkWidget *menu_item;
+
+  GtkAction *action;
+  gboolean   use_action_appearance;
 };
   
-static void gtk_tool_item_finalize    (GObject *object);
-static void gtk_tool_item_parent_set   (GtkWidget   *toolitem,
-				        GtkWidget   *parent);
+static void gtk_tool_item_finalize     (GObject         *object);
+static void gtk_tool_item_dispose      (GObject         *object);
+static void gtk_tool_item_parent_set   (GtkWidget       *toolitem,
+				        GtkWidget       *parent);
 static void gtk_tool_item_set_property (GObject         *object,
 					guint            prop_id,
 					const GValue    *value,
@@ -120,10 +129,23 @@
 
 static gboolean gtk_tool_item_create_menu_proxy (GtkToolItem *item);
 
+static void gtk_tool_item_activatable_interface_init (GtkActivatableIface  *iface);
+static void gtk_tool_item_activatable_update         (GtkActivatable       *activatable,
+						      GtkAction            *action,
+						      const gchar          *property_name);
+static void gtk_tool_item_set_related_action         (GtkToolItem          *item, 
+						      GtkAction            *action);
+static void gtk_tool_item_set_use_action_appearance  (GtkToolItem          *item, 
+						      gboolean              use_appearance);
+static void gtk_tool_item_action_notify              (GtkAction            *action,
+						      GParamSpec           *pspec,
+						      GtkToolItem          *item);
 
 static guint toolitem_signals[LAST_SIGNAL] = { 0 };
 
-G_DEFINE_TYPE (GtkToolItem, gtk_tool_item, GTK_TYPE_BIN)
+G_DEFINE_TYPE_WITH_CODE (GtkToolItem, gtk_tool_item, GTK_TYPE_BIN,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+						gtk_tool_item_activatable_interface_init))
 
 static void
 gtk_tool_item_class_init (GtkToolItemClass *klass)
@@ -136,8 +158,9 @@
   
   object_class->set_property = gtk_tool_item_set_property;
   object_class->get_property = gtk_tool_item_get_property;
-  object_class->finalize = gtk_tool_item_finalize;
-  object_class->notify = gtk_tool_item_property_notify;
+  object_class->finalize     = gtk_tool_item_finalize;
+  object_class->dispose      = gtk_tool_item_dispose;
+  object_class->notify       = gtk_tool_item_property_notify;
 
   widget_class->realize       = gtk_tool_item_realize;
   widget_class->unrealize     = gtk_tool_item_unrealize;
@@ -172,6 +195,10 @@
  							 FALSE,
  							 GTK_PARAM_READWRITE));
 
+  g_object_class_override_property (object_class, PROP_ACTIVATABLE_ACTION, "related-action");
+  g_object_class_override_property (object_class, PROP_ACTIVATABLE_USE_APPEARANCE, "use-action-appearance");
+
+
 /**
  * GtkToolItem::create-menu-proxy:
  * @tool_item: the object the signal was emitted on
@@ -292,6 +319,21 @@
 }
 
 static void
+gtk_tool_item_dispose (GObject *object)
+{
+  GtkToolItem *item = GTK_TOOL_ITEM (object);
+
+  if (item->priv->action)
+    {
+      g_signal_handlers_disconnect_by_func (item->priv->action, gtk_tool_item_action_notify, item);
+      _gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (item), NULL);      
+      item->priv->action = NULL;
+    }
+  G_OBJECT_CLASS (gtk_tool_item_parent_class)->dispose (object);
+}
+
+
+static void
 gtk_tool_item_parent_set (GtkWidget   *toolitem,
 			  GtkWidget   *prev_parent)
 {
@@ -318,6 +360,12 @@
     case PROP_IS_IMPORTANT:
       gtk_tool_item_set_is_important (toolitem, g_value_get_boolean (value));
       break;
+    case PROP_ACTIVATABLE_ACTION:
+      gtk_tool_item_set_related_action (toolitem, g_value_get_object (value));
+      break;
+    case PROP_ACTIVATABLE_USE_APPEARANCE:
+      gtk_tool_item_set_use_action_appearance (toolitem, g_value_get_boolean (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -343,6 +391,12 @@
     case PROP_IS_IMPORTANT:
       g_value_set_boolean (value, toolitem->priv->is_important);
       break;
+    case PROP_ACTIVATABLE_ACTION:
+      g_value_set_object (value, toolitem->priv->action);
+      break;
+    case PROP_ACTIVATABLE_USE_APPEARANCE:
+      g_value_set_boolean (value, toolitem->priv->use_action_appearance);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -503,9 +557,126 @@
 static gboolean
 gtk_tool_item_create_menu_proxy (GtkToolItem *item)
 {
+  GtkWidget *menu_item;
+  gboolean visible_overflown;
+
+  if (item->priv->action)
+    {
+      g_object_get (item->priv->action, "visible-overflown", &visible_overflown, NULL);
+    
+      if (visible_overflown)
+	{
+	  menu_item = gtk_action_create_menu_item (item->priv->action);
+
+	  g_object_ref_sink (menu_item);
+      	  gtk_tool_item_set_proxy_menu_item (item, "gtk-action-menu-item", menu_item);
+	  g_object_unref (menu_item);
+	}
+      else
+	gtk_tool_item_set_proxy_menu_item (item, "gtk-action-menu-item", NULL);
+    }
+
   return FALSE;
 }
 
+static void 
+gtk_tool_item_activatable_interface_init (GtkActivatableIface  *iface)
+{
+  iface->update = gtk_tool_item_activatable_update;
+}
+
+static void 
+gtk_tool_item_activatable_update (GtkActivatable       *activatable,
+				  GtkAction            *action,
+				  const gchar          *property_name)
+{
+  if (property_name == NULL)
+    {
+      if (gtk_action_is_visible (action))
+	gtk_widget_show (GTK_WIDGET (activatable));
+      else
+	gtk_widget_hide (GTK_WIDGET (activatable));
+
+      gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
+
+      gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (activatable),
+				      gtk_action_get_tooltip (action));
+      gtk_tool_item_set_visible_horizontal (GTK_TOOL_ITEM (activatable),
+					    gtk_action_get_visible_horizontal (action));
+      gtk_tool_item_set_visible_vertical (GTK_TOOL_ITEM (activatable),
+					  gtk_action_get_visible_vertical (action));
+      gtk_tool_item_set_is_important (GTK_TOOL_ITEM (activatable),
+				      gtk_action_get_is_important (action));
+    }
+  else if (strcmp (property_name, "visible") == 0)
+    {
+      if (gtk_action_is_visible (action))
+	gtk_widget_show (GTK_WIDGET (activatable));
+      else
+	gtk_widget_hide (GTK_WIDGET (activatable));
+    }
+  else if (strcmp (property_name, "sensitive") == 0)
+    gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
+  else if (strcmp (property_name, "tooltip") == 0)
+    gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (activatable),
+				    gtk_action_get_tooltip (action));
+  else if (strcmp (property_name, "visible-horizontal") == 0)
+    gtk_tool_item_set_visible_horizontal (GTK_TOOL_ITEM (activatable),
+					  gtk_action_get_visible_horizontal (action));
+  else if (strcmp (property_name, "visible-vertical") == 0)
+    gtk_tool_item_set_visible_vertical (GTK_TOOL_ITEM (activatable),
+					gtk_action_get_visible_vertical (action));
+  else if (strcmp (property_name, "is-important") == 0)
+    gtk_tool_item_set_is_important (GTK_TOOL_ITEM (activatable),
+				    gtk_action_get_is_important (action));
+}
+
+static void
+gtk_tool_item_action_notify (GtkAction   *action,
+			     GParamSpec  *pspec,
+			     GtkToolItem *item)
+{
+  gtk_activatable_update (GTK_ACTIVATABLE (item), action, pspec->name);
+}
+
+static void
+gtk_tool_item_set_related_action (GtkToolItem *item, 
+				  GtkAction   *action)
+{
+  if (item->priv->action == action)
+    return;
+
+  if (item->priv->action)
+    g_signal_handlers_disconnect_by_func (item->priv->action, gtk_tool_item_action_notify, item);
+
+  _gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (item), action);
+
+  item->priv->action = action;
+
+  if (action)
+    {
+      g_signal_connect (G_OBJECT (action), "notify", G_CALLBACK (gtk_tool_item_action_notify), item);
+      
+      gtk_tool_item_rebuild_menu (item);
+      
+      gtk_activatable_update (GTK_ACTIVATABLE (item), action, NULL);
+    }
+}
+
+static void
+gtk_tool_item_set_use_action_appearance (GtkToolItem *item, 
+					 gboolean     use_appearance)
+{
+  if (item->priv->use_action_appearance != use_appearance)
+    {
+      item->priv->use_action_appearance = use_appearance;
+      
+      if (item->priv->action && use_appearance)
+	gtk_activatable_update (GTK_ACTIVATABLE (item), item->priv->action, NULL);
+    }
+}
+
+
 /**
  * gtk_tool_item_new:
  * 
Index: gtk/gtkradiomenuitem.c
===================================================================
--- gtk/gtkradiomenuitem.c	(revision 21809)
+++ gtk/gtkradiomenuitem.c	(working copy)
@@ -28,6 +28,7 @@
 #include "gtkaccellabel.h"
 #include "gtkmarshalers.h"
 #include "gtkradiomenuitem.h"
+#include "gtkactivatable.h"
 #include "gtkprivate.h"
 #include "gtkintl.h"
 #include "gtkalias.h"
@@ -420,9 +421,14 @@
   GtkRadioMenuItem *radio_menu_item = GTK_RADIO_MENU_ITEM (menu_item);
   GtkCheckMenuItem *check_menu_item = GTK_CHECK_MENU_ITEM (menu_item);
   GtkCheckMenuItem *tmp_menu_item;
+  GtkAction        *action;
   GSList *tmp_list;
   gint toggled;
 
+  action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (menu_item));
+  if (action && gtk_menu_item_get_submenu (menu_item) == NULL)
+    gtk_action_activate (action);
+
   toggled = FALSE;
 
   if (check_menu_item->active)
@@ -467,7 +473,9 @@
     }
 
   if (toggled)
-    gtk_check_menu_item_toggled (check_menu_item);
+    {
+      gtk_check_menu_item_toggled (check_menu_item);
+    }
 
   gtk_widget_queue_draw (GTK_WIDGET (radio_menu_item));
 }
Index: gtk/gtkrecentaction.c
===================================================================
--- gtk/gtkrecentaction.c	(revision 21809)
+++ gtk/gtkrecentaction.c	(working copy)
@@ -42,7 +42,6 @@
 struct _GtkRecentActionPrivate
 {
   GtkRecentManager *manager;
-  guint manager_changed_id;
 
   guint show_numbers   : 1;
 
@@ -55,10 +54,8 @@
 
   gint limit;
 
-  GtkRecentSortType sort_type;
-  GtkRecentSortFunc sort_func;
-  gpointer sort_data;
-  GDestroyNotify data_destroy;
+  GtkRecentSortType       sort_type;
+  GtkRecentActionSortInfo sort_info;
 
   GtkRecentFilter *current_filter;
 
@@ -69,10 +66,11 @@
 enum
 {
   PROP_0,
-
-  PROP_SHOW_NUMBERS
+  PROP_SHOW_NUMBERS,
+  PROP_SORT_INFO
 };
 
+
 static void gtk_recent_chooser_iface_init (GtkRecentChooserIface *iface);
 
 G_DEFINE_TYPE_WITH_CODE (GtkRecentAction,
@@ -174,8 +172,8 @@
 
   return _gtk_recent_chooser_get_items (chooser,
                                         priv->current_filter,
-                                        priv->sort_func,
-                                        priv->sort_data);
+                                        priv->sort_info.sort_func,
+                                        priv->sort_info.sort_data);
 }
 
 static GtkRecentManager *
@@ -192,32 +190,24 @@
 {
   GtkRecentAction *action = GTK_RECENT_ACTION (chooser);
   GtkRecentActionPrivate *priv = action->priv;
-  GSList *l;
   
-  if (priv->data_destroy)
+  if (priv->sort_info.data_destroy)
     {
-      priv->data_destroy (priv->sort_data);
-      priv->data_destroy = NULL;
+      priv->sort_info.data_destroy (priv->sort_info.sort_data);
+      priv->sort_info.data_destroy = NULL;
     }
       
-  priv->sort_func = NULL;
-  priv->sort_data = NULL;
+  priv->sort_info.sort_func = NULL;
+  priv->sort_info.sort_data = NULL;
   
   if (sort_func)
     {
-      priv->sort_func = sort_func;
-      priv->sort_data = sort_data;
-      priv->data_destroy = data_destroy;
+      priv->sort_info.sort_func = sort_func;
+      priv->sort_info.sort_data = sort_data;
+      priv->sort_info.data_destroy = data_destroy;
     }
 
-  for (l = priv->choosers; l; l = l->next)
-    {
-      GtkRecentChooser *chooser_menu = l->data;
-
-      gtk_recent_chooser_set_sort_func (chooser_menu, priv->sort_func,
-                                        priv->sort_data,
-                                        priv->data_destroy);
-    }
+  g_object_notify (G_OBJECT (action), "sort-info");
 }
 
 static void
@@ -225,7 +215,6 @@
                     GtkRecentFilter *filter)
 {
   GtkRecentActionPrivate *priv = action->priv;
-  GSList *l;
 
   g_object_ref (action);
 
@@ -237,13 +226,6 @@
   if (priv->current_filter)
     g_object_ref_sink (priv->current_filter);
 
-  for (l = priv->choosers; l; l = l->next)
-    {
-      GtkRecentChooser *chooser = l->data;
-
-      gtk_recent_chooser_set_filter (chooser, priv->current_filter);
-    }
-
   g_object_notify (G_OBJECT (action), "filter");
 
   g_object_unref (action);
@@ -281,7 +263,6 @@
   return retval;
 }
 
-
 static void
 gtk_recent_chooser_iface_init (GtkRecentChooserIface *iface)
 {
@@ -353,12 +334,12 @@
                     "local-only", priv->local_only,
                     NULL);
   
-      if (priv->sort_func)
+      if (priv->sort_info.sort_func)
         {
           gtk_recent_chooser_set_sort_func (GTK_RECENT_CHOOSER (widget),
-                                            priv->sort_func,
-                                            priv->sort_data,
-                                            priv->data_destroy);
+                                            priv->sort_info.sort_func,
+                                            priv->sort_info.sort_data,
+                                            priv->sort_info.data_destroy);
         }
 
       g_signal_connect_swapped (widget, "selection_changed",
@@ -408,12 +389,12 @@
                          "local-only", priv->local_only,
                          NULL);
   
-  if (priv->sort_func)
+  if (priv->sort_info.sort_func)
     {
       gtk_recent_chooser_set_sort_func (GTK_RECENT_CHOOSER (widget),
-                                        priv->sort_func,
-                                        priv->sort_data,
-                                        priv->data_destroy);
+                                        priv->sort_info.sort_func,
+                                        priv->sort_info.sort_data,
+                                        priv->sort_info.data_destroy);
     }
 
   g_signal_connect_swapped (widget, "selection_changed",
@@ -458,38 +439,15 @@
 }
 
 static void
-manager_changed_cb (GtkRecentManager *manager,
-                    gpointer          user_data)
-{
-  /* do we need to propagate the signal to all the proxies? guess not */
-}
-
-static void
 set_recent_manager (GtkRecentAction  *action,
                     GtkRecentManager *manager)
 {
   GtkRecentActionPrivate *priv = action->priv;
 
-  if (priv->manager)
-    {
-      if (priv->manager_changed_id)
-        {
-          g_signal_handler_disconnect (priv->manager, priv->manager_changed_id);
-          priv->manager_changed_id = 0;
-        }
-
-      priv->manager = NULL;
-    }
-
   if (manager)
     priv->manager = NULL;
   else
     priv->manager = gtk_recent_manager_get_default ();
-
-  if (priv->manager)
-    priv->manager_changed_id = g_signal_connect (priv->manager, "changed",
-                                                 G_CALLBACK (manager_changed_cb),
-                                                 action);
 }
 
 static void
@@ -500,14 +458,14 @@
 
   priv->manager = NULL;
   
-  if (priv->data_destroy)
+  if (priv->sort_info.data_destroy)
     {
-      priv->data_destroy (priv->sort_data);
-      priv->data_destroy = NULL;
+      priv->sort_info.data_destroy (priv->sort_info.sort_data);
+      priv->sort_info.data_destroy = NULL;
     }
 
-  priv->sort_data = NULL;
-  priv->sort_func = NULL;
+  priv->sort_info.sort_data = NULL;
+  priv->sort_info.sort_func = NULL;
 
   g_slist_free (priv->choosers);
 
@@ -520,14 +478,6 @@
   GtkRecentAction *action = GTK_RECENT_ACTION (gobject);
   GtkRecentActionPrivate *priv = action->priv;
 
-  if (priv->manager_changed_id)
-    {
-      if (priv->manager)
-        g_signal_handler_disconnect (priv->manager, priv->manager_changed_id);
-
-      priv->manager_changed_id = 0;
-    }
-
   if (priv->current_filter)
     {
       g_object_unref (priv->current_filter);
@@ -545,7 +495,6 @@
 {
   GtkRecentAction *action = GTK_RECENT_ACTION (gobject);
   GtkRecentActionPrivate *priv = action->priv;
-  GSList *l;
 
   switch (prop_id)
     {
@@ -574,33 +523,20 @@
       priv->sort_type = g_value_get_enum (value);
       break;
     case GTK_RECENT_CHOOSER_PROP_FILTER:
-      /* this already iterates over the choosers list */
       set_current_filter (action, g_value_get_object (value));
-      return;
+      break;
     case GTK_RECENT_CHOOSER_PROP_SELECT_MULTIPLE:
       g_warning ("%s: Choosers of type `%s' do not support selecting multiple items.",
                  G_STRFUNC,
                  G_OBJECT_TYPE_NAME (gobject));
       return;
     case GTK_RECENT_CHOOSER_PROP_RECENT_MANAGER:
-      /* this is a construct-only property; we set the recent-manager
-       * of the choosers with this value when we create them, so there's
-       * no need to iterate later.
-       */
       set_recent_manager (action, g_value_get_object (value));
-      return;
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
       return;
     }
-
-  /* propagate the properties to the proxies we have created */
-  for (l = priv->choosers; l != NULL; l = l->next)
-    {
-      GObject *proxy = l->data;
-
-      g_object_set_property (proxy, pspec->name, value);
-    }
 }
 
 static void
@@ -616,6 +552,9 @@
     case PROP_SHOW_NUMBERS:
       g_value_set_boolean (value, priv->show_numbers);
       break;
+    case PROP_SORT_INFO:
+      g_value_set_pointer (value, priv->sort_info.sort_func ? &priv->sort_info : NULL);
+      break;
     case GTK_RECENT_CHOOSER_PROP_SHOW_PRIVATE:
       g_value_set_boolean (value, priv->show_private);
       break;
@@ -663,8 +602,8 @@
   gobject_class->get_property = gtk_recent_action_get_property;
 
   action_class->activate = gtk_recent_action_activate;
-  action_class->connect_proxy = gtk_recent_action_connect_proxy;
-  action_class->disconnect_proxy = gtk_recent_action_disconnect_proxy;
+/*   action_class->connect_proxy = gtk_recent_action_connect_proxy; */
+/*   action_class->disconnect_proxy = gtk_recent_action_disconnect_proxy; */
   action_class->create_menu_item = gtk_recent_action_create_menu_item;
   action_class->create_tool_item = gtk_recent_action_create_tool_item;
   action_class->create_menu = gtk_recent_action_create_menu;
@@ -681,6 +620,17 @@
                                                          FALSE,
                                                          G_PARAM_READWRITE));
 
+  /**
+   * GtkRecentAction:sort-info:
+   * 
+   * Info needed to call gtk_recent_chooser_set_sort_func() on concerned proxies
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_SORT_INFO,
+                                   g_param_spec_pointer ("sort-info",
+                                                         P_("Sort Info"),
+                                                         P_("Info to setup sort functions in proxies"),
+                                                         G_PARAM_READABLE));
 }
 
 static void
@@ -700,14 +650,14 @@
   priv->limit = FALLBACK_ITEM_LIMIT;
 
   priv->sort_type = GTK_RECENT_SORT_NONE;
-  priv->sort_func = NULL;
-  priv->sort_data = NULL;
-  priv->data_destroy = NULL;
 
+  priv->sort_info.sort_func = NULL;
+  priv->sort_info.sort_data = NULL;
+  priv->sort_info.data_destroy = NULL;
+
   priv->current_filter = NULL;
 
   priv->manager = NULL;
-  priv->manager_changed_id = 0;
 }
 
 /**
@@ -830,5 +780,26 @@
     }
 }
 
+/**
+ * gtk_recent_action_set_current_chooser:
+ * @action: a #GtkRecentAction
+ * @chooser: the current #GtkRecentChooser
+ *
+ * Used for #GtkActivatable choosers to set the current chooser
+ * in the action before launching a selection change or an activated
+ * item.
+ */
+void
+gtk_recent_action_set_current_chooser (GtkRecentAction  *action,
+				       GtkRecentChooser *chooser)
+{
+  g_return_if_fail (GTK_IS_RECENT_ACTION (action));
+  g_return_if_fail (GTK_IS_RECENT_CHOOSER (chooser));
+
+  action->priv->current_chooser = chooser;
+
+}
+
+
 #define __GTK_RECENT_ACTION_C__
 #include "gtkaliasdef.c"
Index: gtk/gtkrecentaction.h
===================================================================
--- gtk/gtkrecentaction.h	(revision 21809)
+++ gtk/gtkrecentaction.h	(working copy)
@@ -28,6 +28,7 @@
 
 #include <gtk/gtkaction.h>
 #include <gtk/gtkrecentmanager.h>
+#include <gtk/gtkrecentchooser.h>
 
 G_BEGIN_DECLS
 
@@ -41,7 +42,15 @@
 typedef struct _GtkRecentAction         GtkRecentAction;
 typedef struct _GtkRecentActionPrivate  GtkRecentActionPrivate;
 typedef struct _GtkRecentActionClass    GtkRecentActionClass;
+typedef struct _GtkRecentActionSortInfo GtkRecentActionSortInfo;
 
+struct _GtkRecentActionSortInfo
+{
+  GtkRecentSortFunc sort_func;
+  gpointer          sort_data;
+  GDestroyNotify    data_destroy;
+};
+
 struct _GtkRecentAction
 {
   GtkAction parent_instance;
@@ -69,6 +78,9 @@
 void       gtk_recent_action_set_show_numbers (GtkRecentAction  *action,
                                                gboolean          show_numbers);
 
+void       gtk_recent_action_set_current_chooser (GtkRecentAction  *action,
+						  GtkRecentChooser *chooser);
+
 G_END_DECLS
 
 #endif /* __GTK_RECENT_ACTION_H__ */
