]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkbutton.c
Removed some GTK_WIDGET_DRAWABLE() tests - we need to update the value
[~andy/gtk] / gtk / gtkbutton.c
index 6263d4b763fd2283633b40ef31cdf7d5e44af03e..8e3593bff95d51dbb83f0b67978a11282f0666e5 100644 (file)
@@ -39,18 +39,20 @@ enum {
 };
 enum {
   ARG_0,
-  ARG_LABEL
+  ARG_LABEL,
+  ARG_RELIEF
 };
-  
+
 
 
 static void gtk_button_class_init     (GtkButtonClass   *klass);
 static void gtk_button_init           (GtkButton        *button);
-static void gtk_button_set_arg        (GtkButton        *button,
+static void gtk_button_set_arg        (GtkObject        *object,
+                                      GtkArg           *arg,
+                                      guint             arg_id);
+static void gtk_button_get_arg        (GtkObject        *object,
                                       GtkArg           *arg,
                                       guint             arg_id);
-static void gtk_button_map            (GtkWidget        *widget);
-static void gtk_button_unmap          (GtkWidget        *widget);
 static void gtk_button_realize        (GtkWidget        *widget);
 static void gtk_button_size_request   (GtkWidget        *widget,
                                       GtkRequisition   *requisition);
@@ -80,38 +82,38 @@ static void gtk_button_add            (GtkContainer     *container,
                                       GtkWidget        *widget);
 static void gtk_button_remove         (GtkContainer     *container,
                                       GtkWidget        *widget);
-static void gtk_button_foreach        (GtkContainer     *container,
-                                      GtkCallback       callback,
-                                      gpointer          callback_data);
 static void gtk_real_button_pressed   (GtkButton        *button);
 static void gtk_real_button_released  (GtkButton        *button);
 static void gtk_real_button_enter     (GtkButton        *button);
 static void gtk_real_button_leave     (GtkButton        *button);
+static GtkType gtk_button_child_type  (GtkContainer     *container);
 
 
-static GtkContainerClass *parent_class;
+static GtkBinClass *parent_class = NULL;
 static guint button_signals[LAST_SIGNAL] = { 0 };
 
 
-guint
-gtk_button_get_type ()
+GtkType
+gtk_button_get_type (void)
 {
-  static guint button_type = 0;
+  static GtkType button_type = 0;
 
   if (!button_type)
     {
-      GtkTypeInfo button_info =
+      static const GtkTypeInfo button_info =
       {
        "GtkButton",
        sizeof (GtkButton),
        sizeof (GtkButtonClass),
        (GtkClassInitFunc) gtk_button_class_init,
        (GtkObjectInitFunc) gtk_button_init,
-       (GtkArgSetFunc) gtk_button_set_arg,
-       (GtkArgGetFunc) NULL,
+        /* reserved_1 */ NULL,
+       /* reserved_2 */ NULL,
+       (GtkClassInitFunc) NULL,
       };
 
-      button_type = gtk_type_unique (gtk_container_get_type (), &button_info);
+      button_type = gtk_type_unique (GTK_TYPE_BIN, &button_info);
+      gtk_type_set_chunk_alloc (button_type, 16);
     }
 
   return button_type;
@@ -128,51 +130,53 @@ gtk_button_class_init (GtkButtonClass *klass)
   widget_class = (GtkWidgetClass*) klass;
   container_class = (GtkContainerClass*) klass;
 
-  parent_class = gtk_type_class (gtk_container_get_type ());
+  parent_class = gtk_type_class (GTK_TYPE_BIN);
 
-  gtk_object_add_arg_type ("GtkButton::label", GTK_TYPE_STRING, GTK_ARG_WRITABLE, ARG_LABEL);
+  gtk_object_add_arg_type ("GtkButton::label", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_LABEL);
+  gtk_object_add_arg_type ("GtkButton::relief", GTK_TYPE_RELIEF_STYLE, GTK_ARG_READWRITE, ARG_RELIEF);
 
   button_signals[PRESSED] =
     gtk_signal_new ("pressed",
                     GTK_RUN_FIRST,
                     object_class->type,
                     GTK_SIGNAL_OFFSET (GtkButtonClass, pressed),
-                    gtk_signal_default_marshaller,
+                    gtk_marshal_NONE__NONE,
                    GTK_TYPE_NONE, 0);
   button_signals[RELEASED] =
     gtk_signal_new ("released",
                     GTK_RUN_FIRST,
                     object_class->type,
                     GTK_SIGNAL_OFFSET (GtkButtonClass, released),
-                    gtk_signal_default_marshaller,
+                    gtk_marshal_NONE__NONE,
                    GTK_TYPE_NONE, 0);
   button_signals[CLICKED] =
     gtk_signal_new ("clicked",
-                    GTK_RUN_FIRST,
+                    GTK_RUN_FIRST | GTK_RUN_ACTION,
                     object_class->type,
                     GTK_SIGNAL_OFFSET (GtkButtonClass, clicked),
-                    gtk_signal_default_marshaller,
+                    gtk_marshal_NONE__NONE,
                    GTK_TYPE_NONE, 0);
   button_signals[ENTER] =
     gtk_signal_new ("enter",
                     GTK_RUN_FIRST,
                     object_class->type,
                     GTK_SIGNAL_OFFSET (GtkButtonClass, enter),
-                    gtk_signal_default_marshaller,
+                    gtk_marshal_NONE__NONE,
                    GTK_TYPE_NONE, 0);
   button_signals[LEAVE] =
     gtk_signal_new ("leave",
                     GTK_RUN_FIRST,
                     object_class->type,
                     GTK_SIGNAL_OFFSET (GtkButtonClass, leave),
-                    gtk_signal_default_marshaller,
+                    gtk_marshal_NONE__NONE,
                    GTK_TYPE_NONE, 0);
 
   gtk_object_class_add_signals (object_class, button_signals, LAST_SIGNAL);
 
+  object_class->set_arg = gtk_button_set_arg;
+  object_class->get_arg = gtk_button_get_arg;
+
   widget_class->activate_signal = button_signals[CLICKED];
-  widget_class->map = gtk_button_map;
-  widget_class->unmap = gtk_button_unmap;
   widget_class->realize = gtk_button_realize;
   widget_class->draw = gtk_button_draw;
   widget_class->draw_focus = gtk_button_draw_focus;
@@ -189,7 +193,7 @@ gtk_button_class_init (GtkButtonClass *klass)
 
   container_class->add = gtk_button_add;
   container_class->remove = gtk_button_remove;
-  container_class->foreach = gtk_button_foreach;
+  container_class->child_type = gtk_button_child_type;
 
   klass->pressed = gtk_real_button_pressed;
   klass->released = gtk_real_button_released;
@@ -201,36 +205,75 @@ gtk_button_class_init (GtkButtonClass *klass)
 static void
 gtk_button_init (GtkButton *button)
 {
-  GTK_WIDGET_SET_FLAGS (button, GTK_CAN_FOCUS);
+  GTK_WIDGET_SET_FLAGS (button, GTK_CAN_FOCUS | GTK_RECEIVES_DEFAULT);
+  GTK_WIDGET_UNSET_FLAGS (button, GTK_NO_WINDOW);
 
   button->child = NULL;
   button->in_button = FALSE;
   button->button_down = FALSE;
+  button->relief = GTK_RELIEF_NORMAL;
+}
+
+static GtkType
+gtk_button_child_type  (GtkContainer     *container)
+{
+  if (!GTK_BIN (container)->child)
+    return GTK_TYPE_WIDGET;
+  else
+    return GTK_TYPE_NONE;
 }
 
 static void
-gtk_button_set_arg (GtkButton *button,
+gtk_button_set_arg (GtkObject *object,
                    GtkArg    *arg,
                    guint      arg_id)
 {
-  GtkWidget *label;
+  GtkButton *button;
+
+  button = GTK_BUTTON (object);
 
   switch (arg_id)
     {
+      GtkWidget *child;
+
     case ARG_LABEL:
-      gtk_container_disable_resize (GTK_CONTAINER (button));
-      
-      if (button->child)
-       {
-         gtk_widget_unparent (button->child);
-         button->child = NULL;
-       }
-      
-      label = gtk_label_new (GTK_VALUE_STRING(*arg));
-      gtk_widget_show (label);
-      
-      gtk_container_add (GTK_CONTAINER (button), label);
-      gtk_container_enable_resize (GTK_CONTAINER (button));
+      child = GTK_BIN (button)->child;
+      if (!child)
+       child = gtk_widget_new (GTK_TYPE_LABEL,
+                               "visible", TRUE,
+                               "parent", button,
+                               NULL);
+      if (GTK_IS_LABEL (child))
+       gtk_label_set_text (GTK_LABEL (child),
+                      GTK_VALUE_STRING (*arg) ? GTK_VALUE_STRING (*arg) : "");
+      break;
+    case ARG_RELIEF:
+      gtk_button_set_relief (button, GTK_VALUE_ENUM (*arg));
+      break;
+    default:
+      break;
+    }
+}
+
+static void
+gtk_button_get_arg (GtkObject *object,
+                   GtkArg    *arg,
+                   guint      arg_id)
+{
+  GtkButton *button;
+
+  button = GTK_BUTTON (object);
+
+  switch (arg_id)
+    {
+    case ARG_LABEL:
+      if (GTK_BIN (button)->child && GTK_IS_LABEL (GTK_BIN (button)->child))
+       GTK_VALUE_STRING (*arg) = g_strdup (GTK_LABEL (GTK_BIN (button)->child)->label);
+      else
+       GTK_VALUE_STRING (*arg) = NULL;
+      break;
+    case ARG_RELIEF:
+      GTK_VALUE_ENUM (*arg) = gtk_button_get_relief (button);
       break;
     default:
       arg->type = GTK_TYPE_INVALID;
@@ -239,7 +282,7 @@ gtk_button_set_arg (GtkButton *button,
 }
 
 GtkWidget*
-gtk_button_new ()
+gtk_button_new (void)
 {
   return GTK_WIDGET (gtk_type_new (gtk_button_get_type ()));
 }
@@ -263,60 +306,66 @@ gtk_button_new_with_label (const gchar *label)
 void
 gtk_button_pressed (GtkButton *button)
 {
+  g_return_if_fail (button != NULL);
+  g_return_if_fail (GTK_IS_BUTTON (button));
+
   gtk_signal_emit (GTK_OBJECT (button), button_signals[PRESSED]);
 }
 
 void
 gtk_button_released (GtkButton *button)
 {
+  g_return_if_fail (button != NULL);
+  g_return_if_fail (GTK_IS_BUTTON (button));
+
   gtk_signal_emit (GTK_OBJECT (button), button_signals[RELEASED]);
 }
 
 void
 gtk_button_clicked (GtkButton *button)
 {
+  g_return_if_fail (button != NULL);
+  g_return_if_fail (GTK_IS_BUTTON (button));
+
   gtk_signal_emit (GTK_OBJECT (button), button_signals[CLICKED]);
 }
 
 void
 gtk_button_enter (GtkButton *button)
 {
+  g_return_if_fail (button != NULL);
+  g_return_if_fail (GTK_IS_BUTTON (button));
+
   gtk_signal_emit (GTK_OBJECT (button), button_signals[ENTER]);
 }
 
 void
 gtk_button_leave (GtkButton *button)
 {
+  g_return_if_fail (button != NULL);
+  g_return_if_fail (GTK_IS_BUTTON (button));
+
   gtk_signal_emit (GTK_OBJECT (button), button_signals[LEAVE]);
 }
 
-static void
-gtk_button_map (GtkWidget *widget)
+void
+gtk_button_set_relief (GtkButton *button,
+                      GtkReliefStyle newrelief)
 {
-  GtkButton *button;
-
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_BUTTON (widget));
-
-  GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
-  gdk_window_show (widget->window);
-
-  button = GTK_BUTTON (widget);
+  g_return_if_fail (button != NULL);
+  g_return_if_fail (GTK_IS_BUTTON (button));
 
-  if (button->child &&
-      GTK_WIDGET_VISIBLE (button->child) &&
-      !GTK_WIDGET_MAPPED (button->child))
-    gtk_widget_map (button->child);
+  button->relief = newrelief;
+  gtk_widget_queue_draw (GTK_WIDGET (button));
 }
 
-static void
-gtk_button_unmap (GtkWidget *widget)
+GtkReliefStyle
+gtk_button_get_relief (GtkButton *button)
 {
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_BUTTON (widget));
+  g_return_val_if_fail (button != NULL, GTK_RELIEF_NORMAL);
+  g_return_val_if_fail (GTK_IS_BUTTON (button), GTK_RELIEF_NORMAL);
 
-  GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
-  gdk_window_hide (widget->window);
+  return button->relief;
 }
 
 static void
@@ -384,12 +433,12 @@ gtk_button_size_request (GtkWidget      *widget,
                              DEFAULT_SPACING);
     }
 
-  if (button->child && GTK_WIDGET_VISIBLE (button->child))
+  if (GTK_BIN (button)->child && GTK_WIDGET_VISIBLE (GTK_BIN (button)->child))
     {
-      gtk_widget_size_request (button->child, &button->child->requisition);
+      gtk_widget_size_request (GTK_BIN (button)->child, &GTK_BIN (button)->child->requisition);
 
-      requisition->width += button->child->requisition.width;
-      requisition->height += button->child->requisition.height;
+      requisition->width += GTK_BIN (button)->child->requisition.width;
+      requisition->height += GTK_BIN (button)->child->requisition.height;
     }
 }
 
@@ -417,14 +466,14 @@ gtk_button_size_allocate (GtkWidget     *widget,
 
   button = GTK_BUTTON (widget);
 
-  if (button->child && GTK_WIDGET_VISIBLE (button->child))
+  if (GTK_BIN (button)->child && GTK_WIDGET_VISIBLE (GTK_BIN (button)->child))
     {
       child_allocation.x = (CHILD_SPACING + GTK_WIDGET (widget)->style->klass->xthickness);
       child_allocation.y = (CHILD_SPACING + GTK_WIDGET (widget)->style->klass->ythickness);
 
-      child_allocation.width = MAX (1, widget->allocation.width - child_allocation.x * 2 -
+      child_allocation.width = MAX (1, (gint)widget->allocation.width - child_allocation.x * 2 -
                                 border_width * 2);
-      child_allocation.height = MAX (1, widget->allocation.height - child_allocation.y * 2 -
+      child_allocation.height = MAX (1, (gint)widget->allocation.height - child_allocation.y * 2 -
                                  border_width * 2);
 
       if (GTK_WIDGET_CAN_DEFAULT (button))
@@ -433,103 +482,72 @@ gtk_button_size_allocate (GtkWidget     *widget,
                                 DEFAULT_LEFT_POS);
          child_allocation.y += (GTK_WIDGET (widget)->style->klass->ythickness +
                                 DEFAULT_TOP_POS);
-         child_allocation.width =  MAX (1, child_allocation.width - 
-                                       (GTK_WIDGET (widget)->style->klass->xthickness * 2 + DEFAULT_SPACING));
-         child_allocation.height = MAX (1, child_allocation.height - 
-                                        (GTK_WIDGET (widget)->style->klass->xthickness * 2 + DEFAULT_SPACING));
+         child_allocation.width =  MAX (1, (gint)child_allocation.width -
+                                        (gint)(GTK_WIDGET (widget)->style->klass->xthickness * 2 + DEFAULT_SPACING));
+         child_allocation.height = MAX (1, (gint)child_allocation.height -
+                                        (gint)(GTK_WIDGET (widget)->style->klass->xthickness * 2 + DEFAULT_SPACING));
        }
 
-      gtk_widget_size_allocate (button->child, &child_allocation);
+      gtk_widget_size_allocate (GTK_BIN (button)->child, &child_allocation);
     }
 }
 
+/*
+ * +------------------------------------------------+
+ * |                   BORDER                       |
+ * |  +------------------------------------------+  |
+ * |  |\\\\\\\\\\\\\\\\DEFAULT\\\\\\\\\\\\\\\\\  |  |
+ * |  |\\+------------------------------------+  |  |
+ * |  |\\| |           SPACING       3      | |  |  |
+ * |  |\\| +--------------------------------+ |  |  |
+ * |  |\\| |########## FOCUS ###############| |  |  |
+ * |  |\\| |#+----------------------------+#| |  |  |
+ * |  |\\| |#|         RELIEF            \|#| |  |  |
+ * |  |\\| |#|  +-----------------------+\|#| |  |  |
+ * |  |\\|1|#|  +     THE TEXT          +\|#|2|  |  |
+ * |  |\\| |#|  +-----------------------+\|#| |  |  |
+ * |  |\\| |#| \\\\\ ythickness \\\\\\\\\\|#| |  |  |
+ * |  |\\| |#+----------------------------+#| |  |  |
+ * |  |\\| |########### 1 ##################| |  |  |
+ * |  |\\| +--------------------------------+ |  |  |
+ * |  |\\| |        default spacing   4     | |  |  |
+ * |  |\\+------------------------------------+  |  |
+ * |  |\            ythickness                   |  |
+ * |  +------------------------------------------+  |
+ * |                border_width                    |
+ * +------------------------------------------------+
+ */
+
 static void
 gtk_button_paint (GtkWidget    *widget,
                  GdkRectangle *area)
-{
-  GdkRectangle restrict_area;
-  GdkRectangle new_area;
-
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_BUTTON (widget));
-
-  if (GTK_WIDGET_DRAWABLE (widget))
-    {
-      restrict_area.x = GTK_WIDGET (widget)->style->klass->xthickness;
-      restrict_area.y = GTK_WIDGET (widget)->style->klass->ythickness;
-      restrict_area.width = GTK_WIDGET (widget)->allocation.width - 
-       restrict_area.x * 2 - GTK_CONTAINER (widget)->border_width * 2;
-      restrict_area.height = GTK_WIDGET (widget)->allocation.height - 
-       restrict_area.y * 2 - GTK_CONTAINER (widget)->border_width * 2;
-
-      if (GTK_WIDGET_CAN_DEFAULT (widget))
-       {
-         restrict_area.x += DEFAULT_LEFT_POS;
-         restrict_area.y += DEFAULT_TOP_POS;
-         restrict_area.width -= DEFAULT_SPACING;
-         restrict_area.height -= DEFAULT_SPACING;
-       }
-
-      if (gdk_rectangle_intersect (area, &restrict_area, &new_area))
-       {
-         gtk_style_set_background (widget->style, widget->window, GTK_WIDGET_STATE (widget));
-         gdk_window_clear_area (widget->window,
-                                new_area.x, new_area.y,
-                                new_area.width, new_area.height);
-       }
-    }
-}
-
-static void
-gtk_button_draw (GtkWidget    *widget,
-                GdkRectangle *area)
-{
-  GtkButton *button;
-  GdkRectangle child_area;
-  GdkRectangle tmp_area;
-
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_BUTTON (widget));
-  g_return_if_fail (area != NULL);
-
-  if (GTK_WIDGET_DRAWABLE (widget))
-    {
-      button = GTK_BUTTON (widget);
-
-      tmp_area = *area;
-      tmp_area.x -= GTK_CONTAINER (button)->border_width;
-      tmp_area.y -= GTK_CONTAINER (button)->border_width;
-
-      gtk_button_paint (widget, &tmp_area);
-
-      if (button->child && gtk_widget_intersect (button->child, &tmp_area, &child_area))
-       gtk_widget_draw (button->child, &child_area);
-
-      gtk_widget_draw_default (widget);
-      gtk_widget_draw_focus (widget);
-    }
-}
-
-static void
-gtk_button_draw_focus (GtkWidget *widget)
 {
   GtkButton *button;
   GtkShadowType shadow_type;
   gint width, height;
   gint x, y;
-
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_BUTTON (widget));
-
+   
   if (GTK_WIDGET_DRAWABLE (widget))
     {
       button = GTK_BUTTON (widget);
-
+       
       x = 0;
       y = 0;
       width = widget->allocation.width - GTK_CONTAINER (widget)->border_width * 2;
       height = widget->allocation.height - GTK_CONTAINER (widget)->border_width * 2;
 
+      gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
+      gdk_window_clear_area (widget->window, area->x, area->y, area->width, area->height);
+
+      if (GTK_WIDGET_HAS_DEFAULT (widget) &&
+         GTK_BUTTON (widget)->relief == GTK_RELIEF_NORMAL)
+       {
+         gtk_paint_box (widget->style, widget->window,
+                        GTK_STATE_NORMAL, GTK_SHADOW_IN,
+                        area, widget, "buttondefault",
+                        x, y, width, height);
+       }
+
       if (GTK_WIDGET_CAN_DEFAULT (widget))
        {
          x += widget->style->klass->xthickness;
@@ -539,7 +557,7 @@ gtk_button_draw_focus (GtkWidget *widget)
          x += DEFAULT_LEFT_POS;
          y += DEFAULT_TOP_POS;
        }
-
+       
       if (GTK_WIDGET_HAS_FOCUS (widget))
        {
          x += 1;
@@ -547,78 +565,78 @@ gtk_button_draw_focus (GtkWidget *widget)
          width -= 2;
          height -= 2;
        }
-      else
-       {
-         if (GTK_WIDGET_STATE (widget) == GTK_STATE_ACTIVE)
-           gdk_draw_rectangle (widget->window,
-                               widget->style->bg_gc[GTK_WIDGET_STATE (widget)], FALSE,
-                               x + 1, y + 1, width - 4, height - 4);
-         else
-           gdk_draw_rectangle (widget->window,
-                               widget->style->bg_gc[GTK_WIDGET_STATE (widget)], FALSE,
-                               x + 2, y + 2, width - 5, height - 5);
-       }
-
+       
       if (GTK_WIDGET_STATE (widget) == GTK_STATE_ACTIVE)
        shadow_type = GTK_SHADOW_IN;
       else
        shadow_type = GTK_SHADOW_OUT;
 
-      gtk_draw_shadow (widget->style, widget->window,
-                      GTK_WIDGET_STATE (widget), shadow_type,
+      if ((button->relief != GTK_RELIEF_NONE) ||
+         ((GTK_WIDGET_STATE(widget) != GTK_STATE_NORMAL) &&
+          (GTK_WIDGET_STATE(widget) != GTK_STATE_INSENSITIVE)))
+       gtk_paint_box (widget->style, widget->window,
+                      GTK_WIDGET_STATE (widget),
+                      shadow_type, area, widget, "button",
                       x, y, width, height);
-
+       
       if (GTK_WIDGET_HAS_FOCUS (widget))
        {
          x -= 1;
          y -= 1;
          width += 2;
          height += 2;
-
-         gdk_draw_rectangle (widget->window,
-                             widget->style->black_gc, FALSE,
-                             x, y, width - 1, height - 1);
+            
+         gtk_paint_focus (widget->style, widget->window,
+                          area, widget, "button",
+                          x, y, width - 1, height - 1);
        }
     }
 }
 
 static void
-gtk_button_draw_default (GtkWidget *widget)
+gtk_button_draw (GtkWidget    *widget,
+                GdkRectangle *area)
 {
-  gint width, height;
-  gint x, y;
+  GtkButton *button;
+  GdkRectangle child_area;
+  GdkRectangle tmp_area;
 
   g_return_if_fail (widget != NULL);
   g_return_if_fail (GTK_IS_BUTTON (widget));
+  g_return_if_fail (area != NULL);
 
   if (GTK_WIDGET_DRAWABLE (widget))
     {
-      x = 0;
-      y = 0;
-      width = widget->allocation.width - GTK_CONTAINER (widget)->border_width * 2;
-      height = widget->allocation.height - GTK_CONTAINER (widget)->border_width * 2;
+      button = GTK_BUTTON (widget);
 
-      if (GTK_WIDGET_HAS_DEFAULT (widget))
-       {
-         gtk_draw_shadow (widget->style, widget->window,
-                          GTK_STATE_NORMAL, GTK_SHADOW_IN,
-                          x, y, width, height);
-       }
-      else
-       {
-         gdk_draw_rectangle (widget->window, widget->style->bg_gc[GTK_STATE_NORMAL],
-                             FALSE, x, y, width - 1, height - 1);
-         gdk_draw_rectangle (widget->window, widget->style->bg_gc[GTK_STATE_NORMAL],
-                             FALSE, x + 1, y + 1, width - 3, height - 3);
-       }
+      tmp_area = *area;
+      tmp_area.x -= GTK_CONTAINER (button)->border_width;
+      tmp_area.y -= GTK_CONTAINER (button)->border_width;
+
+      gtk_button_paint (widget, &tmp_area);
+
+      if (GTK_BIN (button)->child && gtk_widget_intersect (GTK_BIN (button)->child, &tmp_area, &child_area))
+       gtk_widget_draw (GTK_BIN (button)->child, &child_area);
     }
 }
 
+static void
+gtk_button_draw_focus (GtkWidget *widget)
+{
+  gtk_widget_draw (widget, NULL);
+}
+
+static void
+gtk_button_draw_default (GtkWidget *widget)
+{
+  gtk_widget_draw (widget, NULL);
+}
+
 static gint
 gtk_button_expose (GtkWidget      *widget,
                   GdkEventExpose *event)
 {
-  GtkButton *button;
+  GtkButton *bin;
   GdkEventExpose child_event;
 
   g_return_val_if_fail (widget != NULL, FALSE);
@@ -627,17 +645,14 @@ gtk_button_expose (GtkWidget      *widget,
 
   if (GTK_WIDGET_DRAWABLE (widget))
     {
-      button = GTK_BUTTON (widget);
-
+      bin = GTK_BIN (widget);
+      
       gtk_button_paint (widget, &event->area);
 
       child_event = *event;
-      if (button->child && GTK_WIDGET_NO_WINDOW (button->child) &&
-         gtk_widget_intersect (button->child, &event->area, &child_event.area))
-       gtk_widget_event (button->child, (GdkEvent*) &child_event);
-
-      gtk_widget_draw_default (widget);
-      gtk_widget_draw_focus (widget);
+      if (bin->child && GTK_WIDGET_NO_WINDOW (bin->child) &&
+         gtk_widget_intersect (bin->child, &event->area, &child_event.area))
+       gtk_widget_event (bin->child, (GdkEvent*) &child_event);
     }
 
   return FALSE;
@@ -657,8 +672,6 @@ gtk_button_button_press (GtkWidget      *widget,
     {
       button = GTK_BUTTON (widget);
 
-      if (GTK_WIDGET_CAN_DEFAULT (widget) && (event->button == 1))
-       gtk_widget_grab_default (widget);
       if (!GTK_WIDGET_HAS_FOCUS (widget))
        gtk_widget_grab_focus (widget);
 
@@ -772,78 +785,26 @@ static void
 gtk_button_add (GtkContainer *container,
                GtkWidget    *widget)
 {
-  GtkButton *button;
-
   g_return_if_fail (container != NULL);
-  g_return_if_fail (GTK_IS_BUTTON (container));
   g_return_if_fail (widget != NULL);
-  g_return_if_fail (gtk_widget_basic (widget));
 
-  button = GTK_BUTTON (container);
+  if (GTK_CONTAINER_CLASS (parent_class)->add)
+    GTK_CONTAINER_CLASS (parent_class)->add (container, widget);
 
-  if (!button->child)
-    {
-      gtk_widget_set_parent (widget, GTK_WIDGET (container));
-
-      if (GTK_WIDGET_VISIBLE (widget->parent))
-       {
-         if (GTK_WIDGET_REALIZED (widget->parent) &&
-             !GTK_WIDGET_REALIZED (widget))
-           gtk_widget_realize (widget);
-         
-         if (GTK_WIDGET_MAPPED (widget->parent) &&
-             !GTK_WIDGET_MAPPED (widget))
-           gtk_widget_map (widget);
-       }
-      
-      button->child = widget;
-
-      if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
-       gtk_widget_queue_resize (widget);
-    }
+  GTK_BUTTON (container)->child = GTK_BIN (container)->child;
 }
 
 static void
 gtk_button_remove (GtkContainer *container,
                   GtkWidget    *widget)
 {
-  GtkButton *button;
-
   g_return_if_fail (container != NULL);
-  g_return_if_fail (GTK_IS_BUTTON (container));
   g_return_if_fail (widget != NULL);
 
-  button = GTK_BUTTON (container);
-
-  if (button->child == widget)
-    {
-      gboolean widget_was_visible = GTK_WIDGET_VISIBLE(widget);
-
-      gtk_widget_unparent (widget);
-
-      button->child = NULL;
-
-      if (widget_was_visible && GTK_WIDGET_VISIBLE (container))
-       gtk_widget_queue_resize (GTK_WIDGET (container));
-
-    }
-}
-
-static void
-gtk_button_foreach (GtkContainer *container,
-                   GtkCallback   callback,
-                   gpointer      callback_data)
-{
-  GtkButton *button;
-
-  g_return_if_fail (container != NULL);
-  g_return_if_fail (GTK_IS_BUTTON (container));
-  g_return_if_fail (callback != NULL);
-
-  button = GTK_BUTTON (container);
+  if (GTK_CONTAINER_CLASS (parent_class)->remove)
+    GTK_CONTAINER_CLASS (parent_class)->remove (container, widget);
 
-  if (button->child)
-    (* callback) (button->child, callback_data);
+  GTK_BUTTON (container)->child = GTK_BIN (container)->child;
 }
 
 static void