diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 1ed841c..e807a53 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -155,6 +155,7 @@ gtk_public_h_sources =          \
 	gtkaccessible.h		\
 	gtkaction.h		\
 	gtkactiongroup.h	\
+	gtkactivatable.h	\
 	gtkadjustment.h		\
 	gtkalignment.h		\
 	gtkarrow.h		\
@@ -401,6 +402,7 @@ gtk_base_c_sources =            \
 	gtkaccessible.c		\
 	gtkaction.c		\
 	gtkactiongroup.c	\
+	gtkactivatable.c	\
 	gtkadjustment.c		\
 	gtkalignment.c		\
 	gtkarrow.c		\
diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols
index 55dabbc..e31e9f8 100644
--- a/gtk/gtk.symbols
+++ b/gtk/gtk.symbols
@@ -192,6 +192,13 @@ gtk_action_group_translate_string
 #endif
 #endif
 
+#if IN_HEADER(__GTK_ACTIVATABLE_H__)
+#if IN_FILE(__GTK_ACTIVATABLE_C__)
+gtk_activatable_activate
+gtk_activatable_get_type G_GNUC_CONST
+#endif
+#endif
+
 #if IN_HEADER(__GTK_ADJUSTMENT_H__)
 #if IN_FILE(__GTK_ADJUSTMENT_C__)
 gtk_adjustment_changed
@@ -2330,7 +2337,6 @@ gtk_menu_set_title
 
 #if IN_HEADER(__GTK_MENU_ITEM_H__)
 #if IN_FILE(__GTK_MENU_ITEM_C__)
-gtk_menu_item_activate
 gtk_menu_item_deselect
 gtk_menu_item_get_right_justified
 gtk_menu_item_get_submenu
diff --git a/gtk/gtkactivatable.c b/gtk/gtkactivatable.c
new file mode 100644
index 0000000..49a831d
--- /dev/null
+++ b/gtk/gtkactivatable.c
@@ -0,0 +1,96 @@
+/* gtkactivatable.c
+ * Copyright (C) 2008 Jan Arne Petersen <jpetersen@jpetersen.org>
+ *
+ * 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 "gtkwidget.h"
+#include "gtkintl.h"
+#include "gtkalias.h"
+
+enum {
+  ACTIVATE,
+  LAST_SIGNAL
+};
+
+static guint activatable_signals[LAST_SIGNAL] = { 0 };
+
+static void gtk_activatable_base_init (gpointer g_class);
+
+GType
+gtk_activatable_get_type (void)
+{
+  static GType gtk_activatable_type_id = 0;
+
+  if (G_UNLIKELY (gtk_activatable_type_id == 0)) {
+      static const GTypeInfo g_define_type_info =
+        {
+          sizeof (GtkActivatableIface),
+          (GBaseInitFunc) gtk_activatable_base_init,
+          (GBaseFinalizeFunc) NULL,
+          (GClassInitFunc) NULL,
+          (GClassFinalizeFunc) NULL,
+          NULL,
+          0,
+          0,
+          (GInstanceInitFunc) NULL
+        };
+
+      gtk_activatable_type_id = g_type_register_static (G_TYPE_INTERFACE, I_("GtkActivatable"),
+                                                       &g_define_type_info, 0);
+      g_type_interface_add_prerequisite (gtk_activatable_type_id, GTK_TYPE_WIDGET);
+  }
+  return gtk_activatable_type_id;
+}
+
+void
+gtk_activatable_activate (GtkActivatable *activatable)
+{
+  g_return_if_fail (GTK_IS_ACTIVATABLE (activatable));
+
+  g_signal_emit (activatable, activatable_signals[ACTIVATE], 0);
+}
+
+static void
+gtk_activatable_base_init (gpointer g_class)
+{
+  static gboolean initialized = FALSE;
+
+  if (! initialized)
+    {
+      /**
+       * GtkActivatable::activated:
+       * @activatable: the #GtkActivatable on which the signal is emitted
+       *
+       * This signal is emitted when the widget is activated.
+       */
+      activatable_signals[ACTIVATE] =
+        g_signal_new (I_("activate"),
+                      GTK_TYPE_ACTIVATABLE,
+                      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, 
+                      G_STRUCT_OFFSET (GtkActivatableIface, activate),
+                      NULL, NULL,
+                      g_cclosure_marshal_VOID__VOID,
+                      G_TYPE_NONE, 0);
+
+      initialized = TRUE;
+    }
+}
+
+#define __GTK_ACTIVATABLE_C__
+#include "gtkaliasdef.c"
diff --git a/gtk/gtkactivatable.h b/gtk/gtkactivatable.h
new file mode 100644
index 0000000..f3eb729
--- /dev/null
+++ b/gtk/gtkactivatable.h
@@ -0,0 +1,51 @@
+/* gtkactivatable.h
+ * Copyright (C) 2008 Jan Arne Petersen <jpetersen@jpetersen.org>
+ *
+ * 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.
+ */
+
+
+#ifndef __GTK_ACTIVATABLE_H__
+#define __GTK_ACTIVATABLE_H__
+
+#include <glib-object.h>
+
+#include <gtk/gtkadjustment.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_IS_ACTIVATABLE(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_ACTIVATABLE))
+#define GTK_ACTIVATABLE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GTK_TYPE_ACTIVATABLE, GtkActivatableIface))
+
+typedef struct _GtkActivatable GtkActivatable;
+typedef struct _GtkActivatableIface GtkActivatableIface;
+
+struct _GtkActivatableIface {
+    GTypeInterface parent;
+
+    /* Virtual Table */
+    void     (* activate)     (GtkActivatable *activatable);
+};
+
+GType    gtk_activatable_get_type     (void) G_GNUC_CONST;
+
+void     gtk_activatable_activate     (GtkActivatable *activatable);
+
+G_END_DECLS
+
+#endif /* __GTK_ACTIVATABLE_H__ */
diff --git a/gtk/gtkbutton.c b/gtk/gtkbutton.c
index f444add..ee09914 100644
--- a/gtk/gtkbutton.c
+++ b/gtk/gtkbutton.c
@@ -26,6 +26,7 @@
 
 #include <config.h>
 #include <string.h>
+#include "gtkactivatable.h"
 #include "gtkalignment.h"
 #include "gtkbutton.h"
 #include "gtklabel.h"
@@ -55,7 +56,6 @@ enum {
   CLICKED,
   ENTER,
   LEAVE,
-  ACTIVATE,
   LAST_SIGNAL
 };
 
@@ -124,7 +124,6 @@ static gint gtk_button_leave_notify   (GtkWidget          *widget,
 				       GdkEventCrossing   *event);
 static void gtk_real_button_pressed   (GtkButton          *button);
 static void gtk_real_button_released  (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,
 			               GtkWidget          *widget);
@@ -141,10 +140,15 @@ static void gtk_button_state_changed   (GtkWidget             *widget,
 static void gtk_button_grab_notify     (GtkWidget             *widget,
 					gboolean               was_grabbed);
 
+/* GtkActivatable */
+static void gtk_button_activatable_init (GtkActivatableIface *iface);
+static void gtk_button_activate         (GtkActivatable      *activatable);
+
 
 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_init));
 
 static void
 gtk_button_class_init (GtkButtonClass *klass)
@@ -191,7 +195,6 @@ gtk_button_class_init (GtkButtonClass *klass)
   klass->clicked = NULL;
   klass->enter = gtk_button_update_state;
   klass->leave = gtk_button_update_state;
-  klass->activate = gtk_real_button_activate;
 
   g_object_class_install_property (gobject_class,
                                    PROP_LABEL,
@@ -386,25 +389,6 @@ gtk_button_class_init (GtkButtonClass *klass)
 		  _gtk_marshal_VOID__VOID,
 		  G_TYPE_NONE, 0);
 
-  /**
-   * GtkButton::activate:
-   * @widget: the object which received the signal.
-   *
-   * The ::activate signal on GtkButton is an action signal and
-   * emitting it causes the button to animate press then release. 
-   * Applications should never connect to this signal, but use the
-   * #GtkButton::clicked signal.
-   */
-  button_signals[ACTIVATE] =
-    g_signal_new (I_("activate"),
-		  G_OBJECT_CLASS_TYPE (object_class),
-		  G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
-		  G_STRUCT_OFFSET (GtkButtonClass, activate),
-		  NULL, NULL,
-		  _gtk_marshal_VOID__VOID,
-		  G_TYPE_NONE, 0);
-  widget_class->activate_signal = button_signals[ACTIVATE];
-
   gtk_widget_class_install_style_property (widget_class,
 					   g_param_spec_boxed ("default-border",
 							       P_("Default Spacing"),
@@ -1496,36 +1480,6 @@ button_activate_timeout (gpointer data)
 }
 
 static void
-gtk_real_button_activate (GtkButton *button)
-{
-  GtkWidget *widget = GTK_WIDGET (button);
-  GtkButtonPrivate *priv;
-  guint32 time;
-
-  priv = GTK_BUTTON_GET_PRIVATE (button);
-
-  if (GTK_WIDGET_REALIZED (button) && !button->activate_timeout)
-    {
-      time = gtk_get_current_event_time ();
-      if (gdk_keyboard_grab (button->event_window, TRUE, time) == 
-	  GDK_GRAB_SUCCESS)
-	{
-	  priv->has_grab = TRUE;
-	  priv->grab_time = time;
-	}
-
-      gtk_grab_add (widget);
-      
-      button->activate_timeout = gdk_threads_add_timeout (ACTIVATE_TIMEOUT,
-						button_activate_timeout,
-						button);
-      button->button_down = TRUE;
-      gtk_button_update_state (button);
-      gtk_widget_queue_draw (GTK_WIDGET (button));
-    }
-}
-
-static void
 gtk_button_finish_activate (GtkButton *button,
 			    gboolean   do_it)
 {
@@ -1553,6 +1507,42 @@ gtk_button_finish_activate (GtkButton *button,
     gtk_button_clicked (button);
 }
 
+static void
+gtk_button_activatable_init (GtkActivatableIface *iface)
+{
+  iface->activate = gtk_button_activate;
+}
+
+static void
+gtk_button_activate (GtkActivatable *activatable)
+{
+  GtkButton *button = GTK_BUTTON (activatable);
+  GtkButtonPrivate *priv;
+  guint32 time;
+
+  priv = GTK_BUTTON_GET_PRIVATE (button);
+
+  if (GTK_WIDGET_REALIZED (button) && !button->activate_timeout)
+    {
+      time = gtk_get_current_event_time ();
+      if (gdk_keyboard_grab (button->event_window, TRUE, time) == 
+	  GDK_GRAB_SUCCESS)
+	{
+	  priv->has_grab = TRUE;
+	  priv->grab_time = time;
+	}
+
+      gtk_grab_add (GTK_WIDGET (button));
+      
+      button->activate_timeout = gdk_threads_add_timeout (ACTIVATE_TIMEOUT,
+						button_activate_timeout,
+						button);
+      button->button_down = TRUE;
+      gtk_button_update_state (button);
+      gtk_widget_queue_draw (GTK_WIDGET (button));
+    }
+}
+
 /**
  * gtk_button_set_label:
  * @button: a #GtkButton
diff --git a/gtk/gtkbutton.h b/gtk/gtkbutton.h
index 3d66e01..d29a33b 100644
--- a/gtk/gtkbutton.h
+++ b/gtk/gtkbutton.h
@@ -76,7 +76,6 @@ struct _GtkButtonClass
   void (* clicked)  (GtkButton *button);
   void (* enter)    (GtkButton *button);
   void (* leave)    (GtkButton *button);
-  void (* activate) (GtkButton *button);
   
   /* Padding for future expansion */
   void (*_gtk_reserved1) (void);
diff --git a/gtk/gtkcheckmenuitem.c b/gtk/gtkcheckmenuitem.c
index dc43231..281dc17 100644
--- a/gtk/gtkcheckmenuitem.c
+++ b/gtk/gtkcheckmenuitem.c
@@ -25,6 +25,7 @@
  */
 
 #include <config.h>
+#include "gtkactivatable.h"
 #include "gtkcheckmenuitem.h"
 #include "gtkaccellabel.h"
 #include "gtkmarshalers.h"
@@ -46,7 +47,6 @@ enum {
 
 static gint gtk_check_menu_item_expose               (GtkWidget             *widget,
 						      GdkEventExpose        *event);
-static void gtk_check_menu_item_activate             (GtkMenuItem           *menu_item);
 static void gtk_check_menu_item_toggle_size_request  (GtkMenuItem           *menu_item,
 						      gint                  *requisition);
 static void gtk_check_menu_item_draw_indicator       (GtkCheckMenuItem      *check_menu_item,
@@ -62,10 +62,15 @@ static void gtk_check_menu_item_get_property (GObject         *object,
 					      GValue          *value,
 					      GParamSpec      *pspec);
 
+/* GtkActivatable */
+static void gtk_check_menu_item_activatable_init (GtkActivatableIface *iface);
+static void gtk_check_menu_item_activate         (GtkActivatable      *activatable);
 
 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_init))
 
 static void
 gtk_check_menu_item_class_init (GtkCheckMenuItemClass *klass)
@@ -117,7 +122,6 @@ gtk_check_menu_item_class_init (GtkCheckMenuItemClass *klass)
 
   widget_class->expose_event = gtk_check_menu_item_expose;
   
-  menu_item_class->activate = gtk_check_menu_item_activate;
   menu_item_class->hide_on_activate = FALSE;
   menu_item_class->toggle_size_request = gtk_check_menu_item_toggle_size_request;
   
@@ -195,7 +199,7 @@ gtk_check_menu_item_set_active (GtkCheckMenuItem *check_menu_item,
   is_active = is_active != 0;
 
   if (check_menu_item->active != is_active)
-    gtk_menu_item_activate (GTK_MENU_ITEM (check_menu_item));
+    gtk_activatable_activate (GTK_ACTIVATABLE (check_menu_item));
 }
 
 /**
@@ -361,9 +365,15 @@ gtk_check_menu_item_expose (GtkWidget      *widget,
 }
 
 static void
-gtk_check_menu_item_activate (GtkMenuItem *menu_item)
+gtk_check_menu_item_activatable_init (GtkActivatableIface *iface)
 {
-  GtkCheckMenuItem *check_menu_item = GTK_CHECK_MENU_ITEM (menu_item);
+  iface->activate = gtk_check_menu_item_activate;
+}
+
+static void
+gtk_check_menu_item_activate (GtkActivatable *activatable)
+{
+  GtkCheckMenuItem *check_menu_item = GTK_CHECK_MENU_ITEM (activatable);
   check_menu_item->active = !check_menu_item->active;
 
   gtk_check_menu_item_toggled (check_menu_item);
diff --git a/gtk/gtkdialog.c b/gtk/gtkdialog.c
index 934d2db..7f9204f 100644
--- a/gtk/gtkdialog.c
+++ b/gtk/gtkdialog.c
@@ -27,6 +27,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <config.h>
+#include "gtkactivatable.h"
 #include "gtkbutton.h"
 #include "gtkdialog.h"
 #include "gtkhbbox.h"
@@ -623,7 +624,6 @@ gtk_dialog_add_action_widget (GtkDialog *dialog,
                               gint       response_id)
 {
   ResponseData *ad;
-  guint signal_id;
   
   g_return_if_fail (GTK_IS_DIALOG (dialog));
   g_return_if_fail (GTK_IS_WIDGET (child));
@@ -632,22 +632,29 @@ gtk_dialog_add_action_widget (GtkDialog *dialog,
 
   ad->response_id = response_id;
 
-  if (GTK_IS_BUTTON (child))
-    signal_id = g_signal_lookup ("clicked", GTK_TYPE_BUTTON);
-  else
-    signal_id = GTK_WIDGET_GET_CLASS (child)->activate_signal;
-
-  if (signal_id)
+  if (GTK_IS_ACTIVATABLE (child))
     {
-      GClosure *closure;
-
-      closure = g_cclosure_new_object (G_CALLBACK (action_widget_activated),
-				       G_OBJECT (dialog));
-      g_signal_connect_closure_by_id (child,
-				      signal_id,
-				      0,
-				      closure,
-				      FALSE);
+      guint signal_id;
+
+      if (GTK_IS_BUTTON (child))
+	signal_id = g_signal_lookup ("clicked", GTK_TYPE_BUTTON);
+      else
+	signal_id = g_signal_lookup ("activate", GTK_TYPE_ACTIVATABLE);
+
+      if (signal_id)
+	{
+	  GClosure *closure;
+
+	  closure = g_cclosure_new_object (G_CALLBACK (action_widget_activated),
+					   G_OBJECT (dialog));
+	  g_signal_connect_closure_by_id (child,
+					  signal_id,
+					  0,
+					  closure,
+					  FALSE);
+	}
+      else
+	g_assert_not_reached ();
     }
   else
     g_warning ("Only 'activatable' widgets can be packed into the action area of a GtkDialog");
@@ -1386,7 +1393,6 @@ gtk_dialog_buildable_custom_finished (GtkBuildable *buildable,
   GObject *object;
   GtkDialog *dialog;
   ResponseData *ad;
-  guint signal_id;
   
   if (strcmp (tagname, "action-widgets"))
     {
@@ -1415,22 +1421,29 @@ gtk_dialog_buildable_custom_finished (GtkBuildable *buildable,
       ad = get_response_data (GTK_WIDGET (object), TRUE);
       ad->response_id = atoi (item->response_id);
 
-      if (GTK_IS_BUTTON (object))
-	signal_id = g_signal_lookup ("clicked", GTK_TYPE_BUTTON);
-      else
-	signal_id = GTK_WIDGET_GET_CLASS (object)->activate_signal;
-      
-      if (signal_id)
+      if (GTK_IS_ACTIVATABLE (object))
 	{
-	  GClosure *closure;
-	  
-	  closure = g_cclosure_new_object (G_CALLBACK (action_widget_activated),
-					   G_OBJECT (dialog));
-	  g_signal_connect_closure_by_id (object,
-					  signal_id,
-					  0,
-					  closure,
-					  FALSE);
+	  guint signal_id;
+
+	  if (GTK_IS_BUTTON (child))
+	    signal_id = g_signal_lookup ("clicked", GTK_TYPE_BUTTON);
+	  else
+	    signal_id = g_signal_lookup ("activatable", GTK_TYPE_ACTIVATABLE);
+
+	  if (signal_id)
+	    {
+	      GClosure *closure;
+
+	      closure = g_cclosure_new_object (G_CALLBACK (action_widget_activated),
+					       G_OBJECT (dialog));
+	      g_signal_connect_closure_by_id (object,
+					      signal_id,
+					      0,
+					      closure,
+					      FALSE);
+	    }
+	  else
+	    g_assert_not_reached ();
 	}
 
       if (ad->response_id == GTK_RESPONSE_HELP)
diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c
index 6ca2320..1bf1a84 100644
--- a/gtk/gtkentry.c
+++ b/gtk/gtkentry.c
@@ -31,6 +31,7 @@
 #include <pango/pango.h>
 
 #include "gdk/gdkkeysyms.h"
+#include "gtkactivatable.h"
 #include "gtkbindings.h"
 #include "gtkcelleditable.h"
 #include "gtkclipboard.h"
@@ -272,7 +273,6 @@ static void gtk_entry_copy_clipboard     (GtkEntry        *entry);
 static void gtk_entry_paste_clipboard    (GtkEntry        *entry);
 static void gtk_entry_toggle_overwrite   (GtkEntry        *entry);
 static void gtk_entry_select_all         (GtkEntry        *entry);
-static void gtk_entry_real_activate      (GtkEntry        *entry);
 static gboolean gtk_entry_popup_menu     (GtkWidget      *widget);
 
 static void gtk_entry_keymap_direction_changed (GdkKeymap *keymap,
@@ -383,11 +383,17 @@ static void         begin_change                       (GtkEntry *entry);
 static void         end_change                         (GtkEntry *entry);
 static void         emit_changed                       (GtkEntry *entry);
 
+/* GtkActivatable */
+static void gtk_entry_activatable_init (GtkActivatableIface *iface);
+static void gtk_entry_activate         (GtkActivatable      *activatable);
+
 G_DEFINE_TYPE_WITH_CODE (GtkEntry, gtk_entry, GTK_TYPE_WIDGET,
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
                                                 gtk_entry_editable_init)
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_EDITABLE,
-                                                gtk_entry_cell_editable_init))
+                                                gtk_entry_cell_editable_init)
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+						gtk_entry_activatable_init))
 
 static void
 add_move_binding (GtkBindingSet  *binding_set,
@@ -465,7 +471,6 @@ gtk_entry_class_init (GtkEntryClass *class)
   class->copy_clipboard = gtk_entry_copy_clipboard;
   class->paste_clipboard = gtk_entry_paste_clipboard;
   class->toggle_overwrite = gtk_entry_toggle_overwrite;
-  class->activate = gtk_entry_real_activate;
   
   quark_inner_border = g_quark_from_static_string ("gtk-entry-inner-border");
   quark_password_hint = g_quark_from_static_string ("gtk-entry-password-hint");
@@ -636,17 +641,6 @@ gtk_entry_class_init (GtkEntryClass *class)
 		  GTK_TYPE_MENU);
   
  /* Action signals */
-  
-  signals[ACTIVATE] =
-    g_signal_new (I_("activate"),
-		  G_OBJECT_CLASS_TYPE (gobject_class),
-		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
-		  G_STRUCT_OFFSET (GtkEntryClass, activate),
-		  NULL, NULL,
-		  _gtk_marshal_VOID__VOID,
-		  G_TYPE_NONE, 0);
-  widget_class->activate_signal = signals[ACTIVATE];
-
   signals[MOVE_CURSOR] = 
     g_signal_new (I_("move_cursor"),
 		  G_OBJECT_CLASS_TYPE (gobject_class),
@@ -1857,14 +1851,6 @@ _gtk_entry_get_selected_text (GtkEntry *entry)
   return text;
 }
 
-static void
-drag_begin_cb (GtkWidget      *widget,
-               GdkDragContext *context,
-               gpointer        data)
-{
-  g_signal_handlers_disconnect_by_func (widget, drag_begin_cb, NULL);
-}
-
 static gint
 gtk_entry_motion_notify (GtkWidget      *widget,
 			 GdkEventMotion *event)
@@ -2989,31 +2975,6 @@ gtk_entry_select_all (GtkEntry *entry)
 }
 
 static void
-gtk_entry_real_activate (GtkEntry *entry)
-{
-  GtkWindow *window;
-  GtkWidget *toplevel;
-  GtkWidget *widget;
-
-  widget = GTK_WIDGET (entry);
-
-  if (entry->activates_default)
-    {
-      toplevel = gtk_widget_get_toplevel (widget);
-      if (GTK_IS_WINDOW (toplevel))
-	{
-	  window = GTK_WINDOW (toplevel);
-      
-	  if (window &&
-	      widget != window->default_widget &&
-	      !(widget == window->focus_widget &&
-		(!window->default_widget || !GTK_WIDGET_SENSITIVE (window->default_widget))))
-	    gtk_window_activate_default (window);
-	}
-    }
-}
-
-static void
 gtk_entry_keymap_direction_changed (GdkKeymap *keymap,
 				    GtkEntry  *entry)
 {
@@ -6318,5 +6279,37 @@ gtk_entry_get_cursor_hadjustment (GtkEntry *entry)
   return g_object_get_qdata (G_OBJECT (entry), quark_cursor_hadjustment);
 }
 
+/* activatable */
+static void
+gtk_entry_activatable_init (GtkActivatableIface *iface)
+{
+  iface->activate = gtk_entry_activate;
+}
+
+static void
+gtk_entry_activate (GtkActivatable *activatable)
+{
+  GtkWindow *window;
+  GtkWidget *toplevel;
+  GtkWidget *widget;
+
+  widget = GTK_WIDGET (activatable);
+
+  if (GTK_ENTRY (activatable)->activates_default)
+    {
+      toplevel = gtk_widget_get_toplevel (widget);
+      if (GTK_IS_WINDOW (toplevel))
+	{
+	  window = GTK_WINDOW (toplevel);
+      
+	  if (window &&
+	      widget != window->default_widget &&
+	      !(widget == window->focus_widget &&
+		(!window->default_widget || !GTK_WIDGET_SENSITIVE (window->default_widget))))
+	    gtk_window_activate_default (window);
+	}
+    }
+}
+
 #define __GTK_ENTRY_C__
 #include "gtkaliasdef.c"
diff --git a/gtk/gtkentry.h b/gtk/gtkentry.h
index 24bf28d..0eb112f 100644
--- a/gtk/gtkentry.h
+++ b/gtk/gtkentry.h
@@ -119,7 +119,6 @@ struct _GtkEntryClass
   
   /* Action signals
    */
-  void (* activate)           (GtkEntry       *entry);
   void (* move_cursor)        (GtkEntry       *entry,
 			       GtkMovementStep step,
 			       gint            count,
diff --git a/gtk/gtkexpander.c b/gtk/gtkexpander.c
index cb8e53f..f4c7f66 100644
--- a/gtk/gtkexpander.c
+++ b/gtk/gtkexpander.c
@@ -25,6 +25,7 @@
 #include <string.h>
 #include "gtkexpander.h"
 
+#include "gtkactivatable.h"
 #include "gtklabel.h"
 #include "gtkbuildable.h"
 #include "gtkcontainer.h"
@@ -122,11 +123,14 @@ static void gtk_expander_forall (GtkContainer *container,
 				 GtkCallback     callback,
 				 gpointer        callback_data);
 
-static void gtk_expander_activate (GtkExpander *expander);
 
 static void get_expander_bounds (GtkExpander  *expander,
 				 GdkRectangle *rect);
 
+/* GtkActivatable */
+static void gtk_expander_activatable_init (GtkActivatableIface *iface);
+static void gtk_expander_activate         (GtkActivatable      *activatable);
+
 /* GtkBuildable */
 static void gtk_expander_buildable_init           (GtkBuildableIface *iface);
 static void gtk_expander_buildable_add_child      (GtkBuildable *buildable,
@@ -135,6 +139,8 @@ static void gtk_expander_buildable_add_child      (GtkBuildable *buildable,
 						   const gchar  *type);
 
 G_DEFINE_TYPE_WITH_CODE (GtkExpander, gtk_expander, GTK_TYPE_BIN,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+						gtk_expander_activatable_init)
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
 						gtk_expander_buildable_init))
 
@@ -177,8 +183,6 @@ gtk_expander_class_init (GtkExpanderClass *klass)
   container_class->remove = gtk_expander_remove;
   container_class->forall = gtk_expander_forall;
 
-  klass->activate = gtk_expander_activate;
-
   g_type_class_add_private (klass, sizeof (GtkExpanderPrivate));
 
   g_object_class_install_property (gobject_class,
@@ -248,15 +252,6 @@ gtk_expander_class_init (GtkExpanderClass *klass)
 							     G_MAXINT,
 							     DEFAULT_EXPANDER_SPACING,
 							     GTK_PARAM_READABLE));
-
-  widget_class->activate_signal =
-    g_signal_new (I_("activate"),
-		  G_TYPE_FROM_CLASS (gobject_class),
-		  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
-		  G_STRUCT_OFFSET (GtkExpanderClass, activate),
-		  NULL, NULL,
-		  _gtk_marshal_VOID__VOID,
-		  G_TYPE_NONE, 0);
 }
 
 static void
@@ -308,6 +303,20 @@ gtk_expander_buildable_init (GtkBuildableIface *iface)
 }
 
 static void
+gtk_expander_activatable_init (GtkActivatableIface *iface)
+{
+  iface->activate = gtk_expander_activate;
+}
+
+static void
+gtk_expander_activate (GtkActivatable *activatable)
+{
+  GtkExpander *expander = GTK_EXPANDER (activatable);
+
+  gtk_expander_set_expanded (expander, !expander->priv->expanded);
+}
+
+static void
 gtk_expander_set_property (GObject      *object,
 			   guint         prop_id,
 			   const GValue *value,
@@ -935,7 +944,7 @@ gtk_expander_button_release (GtkWidget      *widget,
 
   if (event->button == 1 && expander->priv->button_down)
     {
-      gtk_widget_activate (widget);
+      gtk_activatable_activate (GTK_ACTIVATABLE (widget));
       expander->priv->button_down = FALSE;
       return TRUE;
     }
@@ -1264,12 +1273,6 @@ gtk_expander_forall (GtkContainer *container,
     (* callback) (priv->label_widget, callback_data);
 }
 
-static void
-gtk_expander_activate (GtkExpander *expander)
-{
-  gtk_expander_set_expanded (expander, !expander->priv->expanded);
-}
-
 /**
  * gtk_expander_new:
  * @label: the text of the label
diff --git a/gtk/gtkexpander.h b/gtk/gtkexpander.h
index e5bfa45..954967c 100644
--- a/gtk/gtkexpander.h
+++ b/gtk/gtkexpander.h
@@ -53,7 +53,6 @@ struct _GtkExpanderClass
   /* Key binding signal; to get notification on the expansion
    * state connect to notify:expanded.
    */
-  void        (* activate) (GtkExpander *expander);
 };
 
 GType                 gtk_expander_get_type          (void) G_GNUC_CONST;
diff --git a/gtk/gtkfilechooserentry.c b/gtk/gtkfilechooserentry.c
index aef6d31..cb66789 100644
--- a/gtk/gtkfilechooserentry.c
+++ b/gtk/gtkfilechooserentry.c
@@ -21,6 +21,7 @@
 #include <config.h>
 #include <string.h>
 
+#include "gtkactivatable.h"
 #include "gtkalignment.h"
 #include "gtkcelllayout.h"
 #include "gtkcellrenderertext.h"
@@ -100,7 +101,6 @@ static gboolean gtk_file_chooser_entry_focus          (GtkWidget        *widget,
 						       GtkDirectionType  direction);
 static gboolean gtk_file_chooser_entry_focus_out_event (GtkWidget       *widget,
 							GdkEventFocus   *event);
-static void     gtk_file_chooser_entry_activate       (GtkEntry         *entry);
 static void     gtk_file_chooser_entry_do_insert_text (GtkEditable *editable,
 						       const gchar *new_text,
 						       gint         new_text_length,
@@ -155,7 +155,16 @@ static void pop_up_completion_feedback (GtkFileChooserEntry *chooser_entry,
 
 static GtkEditableClass *parent_editable_iface;
 
+/* GtkActivatable */
+static void gtk_file_chooser_entry_activatable_init (GtkActivatableIface *iface);
+static void gtk_file_chooser_entry_activate         (GtkActivatable      *activatable);
+
+static GtkActivatableIface *parent_activatable_iface;
+
+
 G_DEFINE_TYPE_WITH_CODE (GtkFileChooserEntry, _gtk_file_chooser_entry, GTK_TYPE_ENTRY,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+						gtk_file_chooser_entry_activatable_init)
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
 						gtk_file_chooser_entry_iface_init))
 
@@ -164,7 +173,6 @@ _gtk_file_chooser_entry_class_init (GtkFileChooserEntryClass *class)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
-  GtkEntryClass *entry_class = GTK_ENTRY_CLASS (class);
 
   gobject_class->finalize = gtk_file_chooser_entry_finalize;
   gobject_class->dispose = gtk_file_chooser_entry_dispose;
@@ -173,8 +181,6 @@ _gtk_file_chooser_entry_class_init (GtkFileChooserEntryClass *class)
   widget_class->unmap = gtk_file_chooser_entry_unmap;
   widget_class->focus = gtk_file_chooser_entry_focus;
   widget_class->focus_out_event = gtk_file_chooser_entry_focus_out_event;
-
-  entry_class->activate = gtk_file_chooser_entry_activate;
 }
 
 static void
@@ -189,6 +195,14 @@ gtk_file_chooser_entry_iface_init (GtkEditableClass *iface)
 }
 
 static void
+gtk_file_chooser_entry_activatable_init (GtkActivatableIface *iface)
+{
+  parent_activatable_iface = g_type_interface_peek_parent (iface);
+
+  iface->activate = gtk_file_chooser_entry_activate;
+}
+
+static void
 _gtk_file_chooser_entry_init (GtkFileChooserEntry *chooser_entry)
 {
   GtkEntryCompletion *comp;
@@ -1177,12 +1191,12 @@ commit_completion_and_refresh (GtkFileChooserEntry *chooser_entry)
 }
 
 static void
-gtk_file_chooser_entry_activate (GtkEntry *entry)
+gtk_file_chooser_entry_activate (GtkActivatable *activatable)
 {
-  GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (entry);
+  GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (activatable);
 
   commit_completion_and_refresh (chooser_entry);
-  GTK_ENTRY_CLASS (_gtk_file_chooser_entry_parent_class)->activate (entry);
+  parent_activatable_iface->activate (activatable);
 }
 
 static void
diff --git a/gtk/gtkitem.c b/gtk/gtkitem.c
index b45f915..0f1f55b 100644
--- a/gtk/gtkitem.c
+++ b/gtk/gtkitem.c
@@ -91,7 +91,6 @@ gtk_item_class_init (GtkItemClass *class)
 		  NULL, NULL,
 		  _gtk_marshal_VOID__VOID,
 		  G_TYPE_NONE, 0);
-  widget_class->activate_signal = item_signals[TOGGLE];
 }
 
 static void
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index eb71103..ec9f2f9 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -26,6 +26,7 @@
 #include <config.h>
 #include <math.h>
 #include <string.h>
+#include "gtkactivatable.h"
 #include "gtklabel.h"
 #include "gtkaccellabel.h"
 #include "gtkdnd.h"
@@ -1233,7 +1234,7 @@ gtk_label_mnemonic_activate (GtkWidget *widget,
   while (parent)
     {
       if (GTK_WIDGET_CAN_FOCUS (parent) ||
-	  (!group_cycling && GTK_WIDGET_GET_CLASS (parent)->activate_signal) ||
+	  (!group_cycling && GTK_IS_ACTIVATABLE (parent)) ||
           GTK_IS_NOTEBOOK (parent->parent) ||
 	  GTK_IS_MENU_ITEM (parent))
 	return gtk_widget_mnemonic_activate (parent, group_cycling);
diff --git a/gtk/gtkmenuitem.c b/gtk/gtkmenuitem.c
index c7f00ff..24fc09e 100644
--- a/gtk/gtkmenuitem.c
+++ b/gtk/gtkmenuitem.c
@@ -30,6 +30,7 @@
 #include <string.h>
 
 #include "gtkaccellabel.h"
+#include "gtkactivatable.h"
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
 #include "gtkmenu.h"
@@ -43,7 +44,6 @@
 #define MENU_ITEM_CLASS(w)  GTK_MENU_ITEM_CLASS (GTK_OBJECT (w)->klass)
 
 enum {
-  ACTIVATE,
   ACTIVATE_ITEM,
   TOGGLE_SIZE_REQUEST,
   TOGGLE_SIZE_ALLOCATE,
@@ -107,10 +107,15 @@ static void gtk_menu_item_forall         (GtkContainer    *container,
 static gboolean gtk_menu_item_can_activate_accel (GtkWidget *widget,
 						  guint      signal_id);
 
+/* GtkActivatable */
+static void gtk_menu_item_activatable_init (GtkActivatableIface *iface);
+static void gtk_menu_item_real_activate    (GtkActivatable      *activatable); 
 
 static guint menu_item_signals[LAST_SIGNAL] = { 0 };
 
-G_DEFINE_TYPE (GtkMenuItem, gtk_menu_item, GTK_TYPE_ITEM)
+G_DEFINE_TYPE_WITH_CODE (GtkMenuItem, gtk_menu_item, GTK_TYPE_ITEM,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+						gtk_menu_item_activatable_init))
 
 static void
 gtk_menu_item_class_init (GtkMenuItemClass *klass)
@@ -145,23 +150,12 @@ gtk_menu_item_class_init (GtkMenuItemClass *klass)
   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->toggle_size_allocate = gtk_real_menu_item_toggle_size_allocate;
 
   klass->hide_on_activate = TRUE;
 
-  menu_item_signals[ACTIVATE] =
-    g_signal_new (I_("activate"),
-		  G_OBJECT_CLASS_TYPE (gobject_class),
-		  G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
-		  G_STRUCT_OFFSET (GtkMenuItemClass, activate),
-		  NULL, NULL,
-		  _gtk_marshal_VOID__VOID,
-		  G_TYPE_NONE, 0);
-  widget_class->activate_signal = menu_item_signals[ACTIVATE];
-
   menu_item_signals[ACTIVATE_ITEM] =
     g_signal_new (I_("activate_item"),
 		  G_OBJECT_CLASS_TYPE (gobject_class),
@@ -514,14 +508,6 @@ gtk_menu_item_deselect (GtkMenuItem *menu_item)
 }
 
 void
-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);
-}
-
-void
 gtk_menu_item_toggle_size_request (GtkMenuItem *menu_item,
 				   gint        *requisition)
 {
@@ -1660,5 +1646,16 @@ _gtk_menu_item_is_selectable (GtkWidget *menu_item)
   return TRUE;
 }
 
+static void
+gtk_menu_item_activatable_init (GtkActivatableIface *iface)
+{
+  iface->activate = gtk_menu_item_real_activate;
+}
+
+static void
+gtk_menu_item_real_activate (GtkActivatable *activatable)
+{
+}
+
 #define __GTK_MENU_ITEM_C__
 #include "gtkaliasdef.c"
diff --git a/gtk/gtkmenuitem.h b/gtk/gtkmenuitem.h
index 4da800e..fc144ea 100644
--- a/gtk/gtkmenuitem.h
+++ b/gtk/gtkmenuitem.h
@@ -77,7 +77,6 @@ struct _GtkMenuItemClass
    */
   guint hide_on_activate : 1;
   
-  void (* activate)             (GtkMenuItem *menu_item);
   void (* activate_item)        (GtkMenuItem *menu_item);
   void (* toggle_size_request)  (GtkMenuItem *menu_item,
 				 gint        *requisition);
@@ -101,7 +100,6 @@ void       gtk_menu_item_set_submenu          (GtkMenuItem         *menu_item,
 GtkWidget* gtk_menu_item_get_submenu          (GtkMenuItem         *menu_item);
 void       gtk_menu_item_select               (GtkMenuItem         *menu_item);
 void       gtk_menu_item_deselect             (GtkMenuItem         *menu_item);
-void       gtk_menu_item_activate             (GtkMenuItem         *menu_item);
 void       gtk_menu_item_toggle_size_request  (GtkMenuItem         *menu_item,
 					       gint                *requisition);
 void       gtk_menu_item_toggle_size_allocate (GtkMenuItem         *menu_item,
diff --git a/gtk/gtkoldeditable.c b/gtk/gtkoldeditable.c
index 43c66e9..d361155 100644
--- a/gtk/gtkoldeditable.c
+++ b/gtk/gtkoldeditable.c
@@ -177,7 +177,8 @@ gtk_old_editable_class_init (GtkOldEditableClass *class)
 		    GTK_SIGNAL_OFFSET (GtkOldEditableClass, activate),
 		    _gtk_marshal_NONE__NONE,
 		    GTK_TYPE_NONE, 0);
-  widget_class->activate_signal = editable_signals[ACTIVATE];
+  /* FIXME GtkActivatable conversion. Deprecated class not converted.
+  widget_class->activate_signal = editable_signals[ACTIVATE]; */
 
   editable_signals[SET_EDITABLE] =
     gtk_signal_new (I_("set-editable"),
diff --git a/gtk/gtkoptionmenu.c b/gtk/gtkoptionmenu.c
index abf25bf..6e7e838 100644
--- a/gtk/gtkoptionmenu.c
+++ b/gtk/gtkoptionmenu.c
@@ -1014,7 +1014,7 @@ gtk_option_menu_scroll_event (GtkWidget          *widget,
 	  if (GTK_WIDGET_VISIBLE (item) && GTK_WIDGET_IS_SENSITIVE (item))
 	    {
 	      gtk_option_menu_set_history (option_menu, index);
-	      gtk_menu_item_activate (GTK_MENU_ITEM (item));
+	      gtk_widget_activate (GTK_WIDGET (item));
 	      break;
 	    }
 	      
diff --git a/gtk/gtkradiomenuitem.c b/gtk/gtkradiomenuitem.c
index a362238..dbbf913 100644
--- a/gtk/gtkradiomenuitem.c
+++ b/gtk/gtkradiomenuitem.c
@@ -26,6 +26,7 @@
 
 #include <config.h>
 #include "gtkaccellabel.h"
+#include "gtkactivatable.h"
 #include "gtkmarshalers.h"
 #include "gtkradiomenuitem.h"
 #include "gtkprivate.h"
@@ -40,7 +41,6 @@ enum {
 
 
 static void gtk_radio_menu_item_destroy        (GtkObject             *object);
-static void gtk_radio_menu_item_activate       (GtkMenuItem           *menu_item);
 static void gtk_radio_menu_item_set_property   (GObject               *object,
 						guint                  prop_id,
 						const GValue          *value,
@@ -50,9 +50,15 @@ static void gtk_radio_menu_item_get_property   (GObject               *object,
 						GValue                *value,
 						GParamSpec            *pspec);
 
+/* GtkActivatable */
+static void gtk_radio_menu_item_activatable_init (GtkActivatableIface *iface);
+static void gtk_radio_menu_item_activate         (GtkActivatable      *activatable);
+
 static guint group_changed_signal = 0;
 
-G_DEFINE_TYPE (GtkRadioMenuItem, gtk_radio_menu_item, GTK_TYPE_CHECK_MENU_ITEM)
+G_DEFINE_TYPE_WITH_CODE (GtkRadioMenuItem, gtk_radio_menu_item, GTK_TYPE_CHECK_MENU_ITEM,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+						gtk_radio_menu_item_activatable_init))
 
 GtkWidget*
 gtk_radio_menu_item_new (GSList *group)
@@ -346,8 +352,6 @@ gtk_radio_menu_item_class_init (GtkRadioMenuItemClass *klass)
 
   object_class->destroy = gtk_radio_menu_item_destroy;
 
-  menu_item_class->activate = gtk_radio_menu_item_activate;
-
   /**
    * GtkStyle::group-changed:
    * @style: the object which received the signal
@@ -416,10 +420,16 @@ gtk_radio_menu_item_destroy (GtkObject *object)
 }
 
 static void
-gtk_radio_menu_item_activate (GtkMenuItem *menu_item)
+gtk_radio_menu_item_activatable_init (GtkActivatableIface *iface)
+{
+  iface->activate = gtk_radio_menu_item_activate;
+}
+
+static void
+gtk_radio_menu_item_activate (GtkActivatable *activatable)
 {
-  GtkRadioMenuItem *radio_menu_item = GTK_RADIO_MENU_ITEM (menu_item);
-  GtkCheckMenuItem *check_menu_item = GTK_CHECK_MENU_ITEM (menu_item);
+  GtkRadioMenuItem *radio_menu_item = GTK_RADIO_MENU_ITEM (activatable);
+  GtkCheckMenuItem *check_menu_item = GTK_CHECK_MENU_ITEM (activatable);
   GtkCheckMenuItem *tmp_menu_item;
   GSList *tmp_list;
   gint toggled;
@@ -461,7 +471,7 @@ gtk_radio_menu_item_activate (GtkMenuItem *menu_item)
 
 	  if (tmp_menu_item->active && (tmp_menu_item != check_menu_item))
 	    {
-	      gtk_menu_item_activate (GTK_MENU_ITEM (tmp_menu_item));
+	      gtk_activatable_activate (GTK_ACTIVATABLE (tmp_menu_item));
 	      break;
 	    }
 	}
diff --git a/gtk/gtkspinbutton.c b/gtk/gtkspinbutton.c
index 8f30b7a..c199cab 100644
--- a/gtk/gtkspinbutton.c
+++ b/gtk/gtkspinbutton.c
@@ -34,6 +34,7 @@
 #include <string.h>
 #include <locale.h>
 #include "gdk/gdkkeysyms.h"
+#include "gtkactivatable.h"
 #include "gtkbindings.h"
 #include "gtkspinbutton.h"
 #include "gtkentryprivate.h"
@@ -122,7 +123,6 @@ static gint gtk_spin_button_key_release    (GtkWidget          *widget,
 					    GdkEventKey        *event);
 static gint gtk_spin_button_scroll         (GtkWidget          *widget,
 					    GdkEventScroll     *event);
-static void gtk_spin_button_activate       (GtkEntry           *entry);
 static void gtk_spin_button_snap           (GtkSpinButton      *spin_button,
 					    gdouble             val);
 static void gtk_spin_button_insert_text    (GtkEditable        *editable,
@@ -142,12 +142,19 @@ static gint spin_button_get_arrow_size     (GtkSpinButton      *spin_button);
 static gint spin_button_get_shadow_type    (GtkSpinButton      *spin_button);
 static void spin_button_redraw             (GtkSpinButton      *spin_button);
 
+/* GtkActivatable */
+static void gtk_spin_button_activatable_init (GtkActivatableIface *iface);
+static void gtk_spin_button_activate         (GtkActivatable      *activatable);
+
+GtkActivatableIface *parent_activatable_iface;
 
 static guint spinbutton_signals[LAST_SIGNAL] = {0};
 
 #define NO_ARROW 2
 
 G_DEFINE_TYPE_WITH_CODE (GtkSpinButton, gtk_spin_button, GTK_TYPE_ENTRY,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+						gtk_spin_button_activatable_init)
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
 						gtk_spin_button_editable_init))
 
@@ -195,8 +202,6 @@ gtk_spin_button_class_init (GtkSpinButtonClass *class)
   widget_class->state_changed = gtk_spin_button_state_changed;
   widget_class->style_set = gtk_spin_button_style_set;
 
-  entry_class->activate = gtk_spin_button_activate;
-
   class->input = NULL;
   class->output = NULL;
   class->change_value = gtk_spin_button_real_change_value;
@@ -1410,13 +1415,21 @@ gtk_spin_button_snap (GtkSpinButton *spin_button,
 }
 
 static void
-gtk_spin_button_activate (GtkEntry *entry)
+gtk_spin_button_activatable_init (GtkActivatableIface *iface)
+{
+  parent_activatable_iface = g_type_interface_peek_parent (iface);
+
+  iface->activate = gtk_spin_button_activate;
+}
+
+static void
+gtk_spin_button_activate (GtkActivatable *activatable)
 {
-  if (entry->editable)
-    gtk_spin_button_update (GTK_SPIN_BUTTON (entry));
+  if (GTK_ENTRY (activatable)->editable)
+    gtk_spin_button_update (GTK_SPIN_BUTTON (activatable));
 
   /* Chain up so that entry->activates_default is honored */
-  GTK_ENTRY_CLASS (gtk_spin_button_parent_class)->activate (entry);
+  parent_activatable_iface->activate (activatable);
 }
 
 static void
diff --git a/gtk/gtktearoffmenuitem.c b/gtk/gtktearoffmenuitem.c
index 0148cd2..38f2b24 100644
--- a/gtk/gtktearoffmenuitem.c
+++ b/gtk/gtktearoffmenuitem.c
@@ -26,6 +26,7 @@
 
 #include <config.h>
 
+#include "gtkactivatable.h"
 #include "gtkmenu.h"
 #include "gtktearoffmenuitem.h"
 #include "gtkintl.h"
@@ -39,11 +40,16 @@ static void gtk_tearoff_menu_item_size_request (GtkWidget             *widget,
 				                GtkRequisition        *requisition);
 static gint gtk_tearoff_menu_item_expose     (GtkWidget             *widget,
 					      GdkEventExpose        *event);
-static void gtk_tearoff_menu_item_activate   (GtkMenuItem           *menu_item);
 static void gtk_tearoff_menu_item_parent_set (GtkWidget             *widget,
 					      GtkWidget             *previous);
 
-G_DEFINE_TYPE (GtkTearoffMenuItem, gtk_tearoff_menu_item, GTK_TYPE_MENU_ITEM)
+/* GtkActivatable */
+static void gtk_tearoff_menu_item_activatable_init (GtkActivatableIface *iface);
+static void gtk_tearoff_menu_item_activate         (GtkActivatable      *activatable);
+
+G_DEFINE_TYPE_WITH_CODE (GtkTearoffMenuItem, gtk_tearoff_menu_item, GTK_TYPE_MENU_ITEM,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+						gtk_tearoff_menu_item_activatable_init))
 
 GtkWidget*
 gtk_tearoff_menu_item_new (void)
@@ -55,16 +61,12 @@ static void
 gtk_tearoff_menu_item_class_init (GtkTearoffMenuItemClass *klass)
 {
   GtkWidgetClass *widget_class;
-  GtkMenuItemClass *menu_item_class;
 
   widget_class = (GtkWidgetClass*) klass;
-  menu_item_class = (GtkMenuItemClass*) klass;
 
   widget_class->expose_event = gtk_tearoff_menu_item_expose;
   widget_class->size_request = gtk_tearoff_menu_item_size_request;
   widget_class->parent_set = gtk_tearoff_menu_item_parent_set;
-
-  menu_item_class->activate = gtk_tearoff_menu_item_activate;
 }
 
 static void
@@ -208,14 +210,20 @@ gtk_tearoff_menu_item_expose (GtkWidget      *widget,
 }
 
 static void
-gtk_tearoff_menu_item_activate (GtkMenuItem *menu_item)
+gtk_tearoff_menu_item_activatable_init (GtkActivatableIface *iface)
+{
+  iface->activate = gtk_tearoff_menu_item_activate;
+}
+
+static void
+gtk_tearoff_menu_item_activate (GtkActivatable *activatable)
 {
-  if (GTK_IS_MENU (GTK_WIDGET (menu_item)->parent))
+  if (GTK_IS_MENU (GTK_WIDGET (activatable)->parent))
     {
-      GtkMenu *menu = GTK_MENU (GTK_WIDGET (menu_item)->parent);
+      GtkMenu *menu = GTK_MENU (GTK_WIDGET (activatable)->parent);
       
-      gtk_widget_queue_resize (GTK_WIDGET (menu_item));
-      gtk_menu_set_tearoff_state (GTK_MENU (GTK_WIDGET (menu_item)->parent),
+      gtk_widget_queue_resize (GTK_WIDGET (activatable));
+      gtk_menu_set_tearoff_state (GTK_MENU (GTK_WIDGET (activatable)->parent),
 				  !menu->torn_off);
     }
 }
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 78e425b..1e491d7 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -28,6 +28,7 @@
 #include <stdarg.h>
 #include <string.h>
 #include <locale.h>
+#include "gtkactivatable.h"
 #include "gtkcontainer.h"
 #include "gtkaccelmap.h"
 #include "gtkclipboard.h"
@@ -407,7 +408,6 @@ gtk_widget_class_init (GtkWidgetClass *klass)
 
   object_class->destroy = gtk_widget_real_destroy;
   
-  klass->activate_signal = 0;
   klass->set_scroll_adjustments_signal = 0;
   klass->dispatch_child_properties_changed = gtk_widget_dispatch_child_properties_changed;
   klass->show = gtk_widget_real_show;
@@ -4330,7 +4330,7 @@ gtk_widget_set_accel_path (GtkWidget     *widget,
   AccelPath *apath;
 
   g_return_if_fail (GTK_IS_WIDGET (widget));
-  g_return_if_fail (GTK_WIDGET_GET_CLASS (widget)->activate_signal != 0);
+  g_return_if_fail (GTK_IS_ACTIVATABLE (widget));
 
   if (accel_path)
     {
@@ -4341,7 +4341,7 @@ gtk_widget_set_accel_path (GtkWidget     *widget,
       apath = g_slice_new (AccelPath);
       apath->accel_group = g_object_ref (accel_group);
       apath->path_quark = g_quark_from_string (accel_path);
-      apath->closure = widget_new_accel_closure (widget, GTK_WIDGET_GET_CLASS (widget)->activate_signal);
+      apath->closure = widget_new_accel_closure (widget, g_signal_lookup ("activate", GTK_TYPE_ACTIVATABLE));
     }
   else
     apath = NULL;
@@ -4393,8 +4393,8 @@ static gboolean
 gtk_widget_real_mnemonic_activate (GtkWidget *widget,
                                    gboolean   group_cycling)
 {
-  if (!group_cycling && GTK_WIDGET_GET_CLASS (widget)->activate_signal)
-    gtk_widget_activate (widget);
+  if (!group_cycling && GTK_IS_ACTIVATABLE (widget))
+    gtk_activatable_activate (GTK_ACTIVATABLE (widget));
   else if (GTK_WIDGET_CAN_FOCUS (widget))
     gtk_widget_grab_focus (widget);
   else
@@ -4701,10 +4701,9 @@ gtk_widget_activate (GtkWidget *widget)
 {
   g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
   
-  if (WIDGET_CLASS (widget)->activate_signal)
+  if (GTK_IS_ACTIVATABLE (widget))
     {
-      /* FIXME: we should eventually check the signals signature here */
-      g_signal_emit (widget, WIDGET_CLASS (widget)->activate_signal, 0);
+      gtk_activatable_activate (GTK_ACTIVATABLE (widget));
 
       return TRUE;
     }
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index d20d1f6..fbf47c2 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -237,8 +237,6 @@ struct _GtkWidgetClass
 
   /*< public >*/
   
-  guint activate_signal;
-
   guint set_scroll_adjustments_signal;
 
   /*< private >*/
