]> Pileus Git - ~andy/gtk/blob - gtk/gtkbutton.c
doh, this was broken beyond believe.
[~andy/gtk] / gtk / gtkbutton.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include <string.h>
28 #include "gtkbutton.h"
29 #include "gtklabel.h"
30 #include "gtkmain.h"
31 #include "gtksignal.h"
32 #include "gtkimage.h"
33 #include "gtkhbox.h"
34 #include "gtkstock.h"
35 #include "gtkiconfactory.h"
36
37 #define CHILD_SPACING     1
38 #define DEFAULT_LEFT_POS  4
39 #define DEFAULT_TOP_POS   4
40 #define DEFAULT_SPACING   7
41
42
43 enum {
44   PRESSED,
45   RELEASED,
46   CLICKED,
47   ENTER,
48   LEAVE,
49   LAST_SIGNAL
50 };
51
52 enum {
53   ARG_0,
54   ARG_LABEL,
55   ARG_RELIEF
56 };
57
58
59
60 static void gtk_button_class_init     (GtkButtonClass   *klass);
61 static void gtk_button_init           (GtkButton        *button);
62 static void gtk_button_set_arg        (GtkObject        *object,
63                                        GtkArg           *arg,
64                                        guint             arg_id);
65 static void gtk_button_get_arg        (GtkObject        *object,
66                                        GtkArg           *arg,
67                                        guint             arg_id);
68 static void gtk_button_realize        (GtkWidget        *widget);
69 static void gtk_button_size_request   (GtkWidget        *widget,
70                                        GtkRequisition   *requisition);
71 static void gtk_button_size_allocate  (GtkWidget        *widget,
72                                        GtkAllocation    *allocation);
73 static void gtk_button_paint          (GtkWidget        *widget,
74                                        GdkRectangle     *area);
75 static void gtk_button_draw_focus     (GtkWidget        *widget);
76 static void gtk_button_draw_default   (GtkWidget        *widget);
77 static gint gtk_button_expose         (GtkWidget        *widget,
78                                        GdkEventExpose   *event);
79 static gint gtk_button_button_press   (GtkWidget        *widget,
80                                        GdkEventButton   *event);
81 static gint gtk_button_button_release (GtkWidget        *widget,
82                                        GdkEventButton   *event);
83 static gint gtk_button_enter_notify   (GtkWidget        *widget,
84                                        GdkEventCrossing *event);
85 static gint gtk_button_leave_notify   (GtkWidget        *widget,
86                                        GdkEventCrossing *event);
87 static gint gtk_button_focus_in       (GtkWidget        *widget,
88                                        GdkEventFocus    *event);
89 static gint gtk_button_focus_out      (GtkWidget        *widget,
90                                        GdkEventFocus    *event);
91 static void gtk_button_add            (GtkContainer     *container,
92                                        GtkWidget        *widget);
93 static void gtk_button_remove         (GtkContainer     *container,
94                                        GtkWidget        *widget);
95 static void gtk_real_button_pressed   (GtkButton        *button);
96 static void gtk_real_button_released  (GtkButton        *button);
97 static void gtk_real_button_enter     (GtkButton        *button);
98 static void gtk_real_button_leave     (GtkButton        *button);
99 static GtkType gtk_button_child_type  (GtkContainer     *container);
100
101
102 static GtkBinClass *parent_class = NULL;
103 static guint button_signals[LAST_SIGNAL] = { 0 };
104
105
106 GtkType
107 gtk_button_get_type (void)
108 {
109   static GtkType button_type = 0;
110
111   if (!button_type)
112     {
113       static const GTypeInfo button_info =
114       {
115         sizeof (GtkButtonClass),
116         NULL,           /* base_init */
117         NULL,           /* base_finalize */
118         (GClassInitFunc) gtk_button_class_init,
119         NULL,           /* class_finalize */
120         NULL,           /* class_data */
121         sizeof (GtkButton),
122         16,             /* n_preallocs */
123         (GInstanceInitFunc) gtk_button_init,
124       };
125
126       button_type = g_type_register_static (GTK_TYPE_BIN, "GtkButton", &button_info, 0);
127     }
128
129   return button_type;
130 }
131
132 static void
133 gtk_button_class_init (GtkButtonClass *klass)
134 {
135   GtkObjectClass *object_class;
136   GtkWidgetClass *widget_class;
137   GtkContainerClass *container_class;
138
139   object_class = (GtkObjectClass*) klass;
140   widget_class = (GtkWidgetClass*) klass;
141   container_class = (GtkContainerClass*) klass;
142
143   parent_class = gtk_type_class (GTK_TYPE_BIN);
144
145
146   object_class->set_arg = gtk_button_set_arg;
147   object_class->get_arg = gtk_button_get_arg;
148
149   widget_class->realize = gtk_button_realize;
150   widget_class->draw_focus = gtk_button_draw_focus;
151   widget_class->draw_default = gtk_button_draw_default;
152   widget_class->size_request = gtk_button_size_request;
153   widget_class->size_allocate = gtk_button_size_allocate;
154   widget_class->expose_event = gtk_button_expose;
155   widget_class->button_press_event = gtk_button_button_press;
156   widget_class->button_release_event = gtk_button_button_release;
157   widget_class->enter_notify_event = gtk_button_enter_notify;
158   widget_class->leave_notify_event = gtk_button_leave_notify;
159   widget_class->focus_in_event = gtk_button_focus_in;
160   widget_class->focus_out_event = gtk_button_focus_out;
161
162   container_class->add = gtk_button_add;
163   container_class->remove = gtk_button_remove;
164   container_class->child_type = gtk_button_child_type;
165
166   klass->pressed = gtk_real_button_pressed;
167   klass->released = gtk_real_button_released;
168   klass->clicked = NULL;
169   klass->enter = gtk_real_button_enter;
170   klass->leave = gtk_real_button_leave;
171
172   gtk_object_add_arg_type ("GtkButton::label", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_LABEL);
173   gtk_object_add_arg_type ("GtkButton::relief", GTK_TYPE_RELIEF_STYLE, GTK_ARG_READWRITE, ARG_RELIEF);
174
175   button_signals[PRESSED] =
176     gtk_signal_new ("pressed",
177                     GTK_RUN_FIRST,
178                     GTK_CLASS_TYPE (object_class),
179                     GTK_SIGNAL_OFFSET (GtkButtonClass, pressed),
180                     gtk_marshal_VOID__VOID,
181                     GTK_TYPE_NONE, 0);
182   button_signals[RELEASED] =
183     gtk_signal_new ("released",
184                     GTK_RUN_FIRST,
185                     GTK_CLASS_TYPE (object_class),
186                     GTK_SIGNAL_OFFSET (GtkButtonClass, released),
187                     gtk_marshal_VOID__VOID,
188                     GTK_TYPE_NONE, 0);
189   button_signals[CLICKED] =
190     gtk_signal_new ("clicked",
191                     GTK_RUN_FIRST | GTK_RUN_ACTION,
192                     GTK_CLASS_TYPE (object_class),
193                     GTK_SIGNAL_OFFSET (GtkButtonClass, clicked),
194                     gtk_marshal_VOID__VOID,
195                     GTK_TYPE_NONE, 0);
196   widget_class->activate_signal = button_signals[CLICKED];
197   button_signals[ENTER] =
198     gtk_signal_new ("enter",
199                     GTK_RUN_FIRST,
200                     GTK_CLASS_TYPE (object_class),
201                     GTK_SIGNAL_OFFSET (GtkButtonClass, enter),
202                     gtk_marshal_VOID__VOID,
203                     GTK_TYPE_NONE, 0);
204   button_signals[LEAVE] =
205     gtk_signal_new ("leave",
206                     GTK_RUN_FIRST,
207                     GTK_CLASS_TYPE (object_class),
208                     GTK_SIGNAL_OFFSET (GtkButtonClass, leave),
209                     gtk_marshal_VOID__VOID,
210                     GTK_TYPE_NONE, 0);
211 }
212
213 static void
214 gtk_button_init (GtkButton *button)
215 {
216   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_FOCUS | GTK_RECEIVES_DEFAULT);
217   GTK_WIDGET_UNSET_FLAGS (button, GTK_NO_WINDOW);
218
219   button->child = NULL;
220   button->in_button = FALSE;
221   button->button_down = FALSE;
222   button->relief = GTK_RELIEF_NORMAL;
223 }
224
225 static GtkType
226 gtk_button_child_type  (GtkContainer     *container)
227 {
228   if (!GTK_BIN (container)->child)
229     return GTK_TYPE_WIDGET;
230   else
231     return GTK_TYPE_NONE;
232 }
233
234 static void
235 gtk_button_set_arg (GtkObject *object,
236                     GtkArg    *arg,
237                     guint      arg_id)
238 {
239   GtkButton *button;
240
241   button = GTK_BUTTON (object);
242
243   switch (arg_id)
244     {
245       GtkWidget *child;
246
247     case ARG_LABEL:
248       child = GTK_BIN (button)->child;
249       if (!child)
250         child = gtk_widget_new (GTK_TYPE_LABEL,
251                                 "visible", TRUE,
252                                 "parent", button,
253                                 NULL);
254       if (GTK_IS_LABEL (child))
255         gtk_label_set_text (GTK_LABEL (child),
256                        GTK_VALUE_STRING (*arg) ? GTK_VALUE_STRING (*arg) : "");
257       break;
258     case ARG_RELIEF:
259       gtk_button_set_relief (button, GTK_VALUE_ENUM (*arg));
260       break;
261     default:
262       break;
263     }
264 }
265
266 static void
267 gtk_button_get_arg (GtkObject *object,
268                     GtkArg    *arg,
269                     guint      arg_id)
270 {
271   GtkButton *button;
272
273   button = GTK_BUTTON (object);
274
275   switch (arg_id)
276     {
277     case ARG_LABEL:
278       if (GTK_BIN (button)->child && GTK_IS_LABEL (GTK_BIN (button)->child))
279         GTK_VALUE_STRING (*arg) = g_strdup (GTK_LABEL (GTK_BIN (button)->child)->label);
280       else
281         GTK_VALUE_STRING (*arg) = NULL;
282       break;
283     case ARG_RELIEF:
284       GTK_VALUE_ENUM (*arg) = gtk_button_get_relief (button);
285       break;
286     default:
287       arg->type = GTK_TYPE_INVALID;
288       break;
289     }
290 }
291
292 GtkWidget*
293 gtk_button_new (void)
294 {
295   return GTK_WIDGET (gtk_type_new (gtk_button_get_type ()));
296 }
297
298 GtkWidget*
299 gtk_button_new_with_label (const gchar *label)
300 {
301   GtkWidget *button;
302   GtkWidget *label_widget;
303
304   button = gtk_button_new ();
305   label_widget = gtk_label_new (label);
306   gtk_misc_set_alignment (GTK_MISC (label_widget), 0.5, 0.5);
307
308   gtk_container_add (GTK_CONTAINER (button), label_widget);
309   gtk_widget_show (label_widget);
310
311   return button;
312 }
313
314 GtkWidget*
315 gtk_button_new_stock (const gchar   *stock_id,
316                       GtkAccelGroup *accel_group)
317 {
318   GtkWidget *button;
319   GtkStockItem item;
320
321   if (gtk_stock_lookup (stock_id, &item))
322     {
323       GtkWidget *label;
324       GtkWidget *image;
325       GtkWidget *hbox;
326       guint keyval;
327       
328       button = gtk_button_new ();
329
330       label = gtk_label_new (NULL);
331       keyval = gtk_label_parse_uline (GTK_LABEL (label),
332                                       item.label);
333
334       if (keyval && accel_group)
335         {
336           gtk_widget_add_accelerator (button,
337                                       "clicked",
338                                       accel_group,
339                                       keyval,
340                                       GDK_MOD1_MASK,
341                                       GTK_ACCEL_LOCKED);
342         }
343
344       /* Also add the stock accelerator if one was specified. */
345       if (item.keyval && accel_group)
346         {
347           gtk_widget_add_accelerator (button,
348                                       "clicked",
349                                       accel_group,
350                                       item.keyval,
351                                       item.modifier,
352                                       GTK_ACCEL_LOCKED);
353         }
354
355       image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
356       hbox = gtk_hbox_new (FALSE, 0);
357
358       gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 2);
359       gtk_box_pack_end (GTK_BOX (hbox), label, TRUE, TRUE, 2);
360       
361       gtk_container_add (GTK_CONTAINER (button), hbox);
362       gtk_widget_show_all (hbox);
363     }
364   else
365     {
366       button = gtk_button_new_accel (stock_id, accel_group);
367     }
368   
369   return button;
370 }
371
372 GtkWidget*
373 gtk_button_new_accel (const gchar   *uline_label,
374                       GtkAccelGroup *accel_group)
375 {
376   GtkWidget *button;
377   GtkWidget *label;
378   guint keyval;
379
380   button = gtk_button_new ();
381   
382   label = gtk_label_new (NULL);
383   keyval = gtk_label_parse_uline (GTK_LABEL (label), uline_label);
384
385   if (keyval && accel_group)
386     {
387       gtk_widget_add_accelerator (button,
388                                   "clicked",
389                                   accel_group,
390                                   keyval,
391                                   GDK_MOD1_MASK,
392                                   GTK_ACCEL_LOCKED);
393     }
394   
395   gtk_container_add (GTK_CONTAINER (button), label);
396   gtk_widget_show (label);
397
398   return button;
399 }
400
401 void
402 gtk_button_pressed (GtkButton *button)
403 {
404   g_return_if_fail (button != NULL);
405   g_return_if_fail (GTK_IS_BUTTON (button));
406
407   gtk_signal_emit (GTK_OBJECT (button), button_signals[PRESSED]);
408 }
409
410 void
411 gtk_button_released (GtkButton *button)
412 {
413   g_return_if_fail (button != NULL);
414   g_return_if_fail (GTK_IS_BUTTON (button));
415
416   gtk_signal_emit (GTK_OBJECT (button), button_signals[RELEASED]);
417 }
418
419 void
420 gtk_button_clicked (GtkButton *button)
421 {
422   g_return_if_fail (button != NULL);
423   g_return_if_fail (GTK_IS_BUTTON (button));
424
425   gtk_signal_emit (GTK_OBJECT (button), button_signals[CLICKED]);
426 }
427
428 void
429 gtk_button_enter (GtkButton *button)
430 {
431   g_return_if_fail (button != NULL);
432   g_return_if_fail (GTK_IS_BUTTON (button));
433
434   gtk_signal_emit (GTK_OBJECT (button), button_signals[ENTER]);
435 }
436
437 void
438 gtk_button_leave (GtkButton *button)
439 {
440   g_return_if_fail (button != NULL);
441   g_return_if_fail (GTK_IS_BUTTON (button));
442
443   gtk_signal_emit (GTK_OBJECT (button), button_signals[LEAVE]);
444 }
445
446 void
447 gtk_button_set_relief (GtkButton *button,
448                        GtkReliefStyle newrelief)
449 {
450   g_return_if_fail (button != NULL);
451   g_return_if_fail (GTK_IS_BUTTON (button));
452
453   button->relief = newrelief;
454   gtk_widget_queue_draw (GTK_WIDGET (button));
455 }
456
457 GtkReliefStyle
458 gtk_button_get_relief (GtkButton *button)
459 {
460   g_return_val_if_fail (button != NULL, GTK_RELIEF_NORMAL);
461   g_return_val_if_fail (GTK_IS_BUTTON (button), GTK_RELIEF_NORMAL);
462
463   return button->relief;
464 }
465
466 static void
467 gtk_button_realize (GtkWidget *widget)
468 {
469   GtkButton *button;
470   GdkWindowAttr attributes;
471   gint attributes_mask;
472   gint border_width;
473
474   g_return_if_fail (widget != NULL);
475   g_return_if_fail (GTK_IS_BUTTON (widget));
476
477   button = GTK_BUTTON (widget);
478   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
479
480   border_width = GTK_CONTAINER (widget)->border_width;
481
482   attributes.window_type = GDK_WINDOW_CHILD;
483   attributes.x = widget->allocation.x + border_width;
484   attributes.y = widget->allocation.y + border_width;
485   attributes.width = widget->allocation.width - border_width * 2;
486   attributes.height = widget->allocation.height - border_width * 2;
487   attributes.wclass = GDK_INPUT_OUTPUT;
488   attributes.visual = gtk_widget_get_visual (widget);
489   attributes.colormap = gtk_widget_get_colormap (widget);
490   attributes.event_mask = gtk_widget_get_events (widget);
491   attributes.event_mask |= (GDK_EXPOSURE_MASK |
492                             GDK_BUTTON_PRESS_MASK |
493                             GDK_BUTTON_RELEASE_MASK |
494                             GDK_ENTER_NOTIFY_MASK |
495                             GDK_LEAVE_NOTIFY_MASK);
496
497   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
498
499   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
500   gdk_window_set_user_data (widget->window, button);
501
502   widget->style = gtk_style_attach (widget->style, widget->window);
503   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
504 }
505
506 static void
507 gtk_button_size_request (GtkWidget      *widget,
508                          GtkRequisition *requisition)
509 {
510   GtkButton *button;
511
512   g_return_if_fail (widget != NULL);
513   g_return_if_fail (GTK_IS_BUTTON (widget));
514   g_return_if_fail (requisition != NULL);
515
516   button = GTK_BUTTON (widget);
517
518   requisition->width = (GTK_CONTAINER (widget)->border_width + CHILD_SPACING +
519                         GTK_WIDGET (widget)->style->xthickness) * 2;
520   requisition->height = (GTK_CONTAINER (widget)->border_width + CHILD_SPACING +
521                          GTK_WIDGET (widget)->style->ythickness) * 2;
522
523   if (GTK_WIDGET_CAN_DEFAULT (widget))
524     {
525       requisition->width += (GTK_WIDGET (widget)->style->xthickness * 2 +
526                              DEFAULT_SPACING);
527       requisition->height += (GTK_WIDGET (widget)->style->ythickness * 2 +
528                               DEFAULT_SPACING);
529     }
530
531   if (GTK_BIN (button)->child && GTK_WIDGET_VISIBLE (GTK_BIN (button)->child))
532     {
533       GtkRequisition child_requisition;
534
535       gtk_widget_size_request (GTK_BIN (button)->child, &child_requisition);
536
537       requisition->width += child_requisition.width;
538       requisition->height += child_requisition.height;
539     }
540 }
541
542 static void
543 gtk_button_size_allocate (GtkWidget     *widget,
544                           GtkAllocation *allocation)
545 {
546   GtkButton *button;
547   GtkAllocation child_allocation;
548   gint border_width;
549
550   g_return_if_fail (widget != NULL);
551   g_return_if_fail (GTK_IS_BUTTON (widget));
552   g_return_if_fail (allocation != NULL);
553
554   widget->allocation = *allocation;
555   border_width = GTK_CONTAINER (widget)->border_width;
556
557   if (GTK_WIDGET_REALIZED (widget))
558     gdk_window_move_resize (widget->window,
559                             widget->allocation.x + border_width,
560                             widget->allocation.y + border_width,
561                             widget->allocation.width - border_width * 2,
562                             widget->allocation.height - border_width * 2);
563
564   button = GTK_BUTTON (widget);
565
566   if (GTK_BIN (button)->child && GTK_WIDGET_VISIBLE (GTK_BIN (button)->child))
567     {
568       child_allocation.x = (CHILD_SPACING + GTK_WIDGET (widget)->style->xthickness);
569       child_allocation.y = (CHILD_SPACING + GTK_WIDGET (widget)->style->ythickness);
570
571       child_allocation.width = MAX (1, (gint)widget->allocation.width - child_allocation.x * 2 -
572                                  border_width * 2);
573       child_allocation.height = MAX (1, (gint)widget->allocation.height - child_allocation.y * 2 -
574                                   border_width * 2);
575
576       if (GTK_WIDGET_CAN_DEFAULT (button))
577         {
578           child_allocation.x += (GTK_WIDGET (widget)->style->xthickness +
579                                  DEFAULT_LEFT_POS);
580           child_allocation.y += (GTK_WIDGET (widget)->style->ythickness +
581                                  DEFAULT_TOP_POS);
582           child_allocation.width =  MAX (1, (gint)child_allocation.width -
583                                          (gint)(GTK_WIDGET (widget)->style->xthickness * 2 + DEFAULT_SPACING));
584           child_allocation.height = MAX (1, (gint)child_allocation.height -
585                                          (gint)(GTK_WIDGET (widget)->style->xthickness * 2 + DEFAULT_SPACING));
586         }
587
588       gtk_widget_size_allocate (GTK_BIN (button)->child, &child_allocation);
589     }
590 }
591
592 /*
593  * +------------------------------------------------+
594  * |                   BORDER                       |
595  * |  +------------------------------------------+  |
596  * |  |\\\\\\\\\\\\\\\\DEFAULT\\\\\\\\\\\\\\\\\  |  |
597  * |  |\\+------------------------------------+  |  |
598  * |  |\\| |           SPACING       3      | |  |  |
599  * |  |\\| +--------------------------------+ |  |  |
600  * |  |\\| |########## FOCUS ###############| |  |  |
601  * |  |\\| |#+----------------------------+#| |  |  |
602  * |  |\\| |#|         RELIEF            \|#| |  |  |
603  * |  |\\| |#|  +-----------------------+\|#| |  |  |
604  * |  |\\|1|#|  +     THE TEXT          +\|#|2|  |  |
605  * |  |\\| |#|  +-----------------------+\|#| |  |  |
606  * |  |\\| |#| \\\\\ ythickness \\\\\\\\\\|#| |  |  |
607  * |  |\\| |#+----------------------------+#| |  |  |
608  * |  |\\| |########### 1 ##################| |  |  |
609  * |  |\\| +--------------------------------+ |  |  |
610  * |  |\\| |        default spacing   4     | |  |  |
611  * |  |\\+------------------------------------+  |  |
612  * |  |\            ythickness                   |  |
613  * |  +------------------------------------------+  |
614  * |                border_width                    |
615  * +------------------------------------------------+
616  */
617
618 static void
619 gtk_button_paint (GtkWidget    *widget,
620                   GdkRectangle *area)
621 {
622   GtkButton *button;
623   GtkShadowType shadow_type;
624   gint width, height;
625   gint x, y;
626    
627   if (GTK_WIDGET_DRAWABLE (widget))
628     {
629       button = GTK_BUTTON (widget);
630         
631       x = 0;
632       y = 0;
633       width = widget->allocation.width - GTK_CONTAINER (widget)->border_width * 2;
634       height = widget->allocation.height - GTK_CONTAINER (widget)->border_width * 2;
635
636       gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
637       gdk_window_clear_area (widget->window, area->x, area->y, area->width, area->height);
638
639       if (GTK_WIDGET_HAS_DEFAULT (widget) &&
640           GTK_BUTTON (widget)->relief == GTK_RELIEF_NORMAL)
641         {
642           gtk_paint_box (widget->style, widget->window,
643                          GTK_STATE_NORMAL, GTK_SHADOW_IN,
644                          area, widget, "buttondefault",
645                          x, y, width, height);
646         }
647
648       if (GTK_WIDGET_CAN_DEFAULT (widget))
649         {
650           x += widget->style->xthickness;
651           y += widget->style->ythickness;
652           width -= 2 * x + DEFAULT_SPACING;
653           height -= 2 * y + DEFAULT_SPACING;
654           x += DEFAULT_LEFT_POS;
655           y += DEFAULT_TOP_POS;
656         }
657        
658       if (GTK_WIDGET_HAS_FOCUS (widget))
659         {
660           x += 1;
661           y += 1;
662           width -= 2;
663           height -= 2;
664         }
665         
666       if (GTK_WIDGET_STATE (widget) == GTK_STATE_ACTIVE)
667         shadow_type = GTK_SHADOW_IN;
668       else
669         shadow_type = GTK_SHADOW_OUT;
670
671       if ((button->relief != GTK_RELIEF_NONE) ||
672           ((GTK_WIDGET_STATE(widget) != GTK_STATE_NORMAL) &&
673            (GTK_WIDGET_STATE(widget) != GTK_STATE_INSENSITIVE)))
674         gtk_paint_box (widget->style, widget->window,
675                        GTK_WIDGET_STATE (widget),
676                        shadow_type, area, widget, "button",
677                        x, y, width, height);
678        
679       if (GTK_WIDGET_HAS_FOCUS (widget))
680         {
681           x -= 1;
682           y -= 1;
683           width += 2;
684           height += 2;
685
686           gtk_paint_focus (widget->style, widget->window,
687                            area, widget, "button",
688                            x, y, width - 1, height - 1);
689         }
690     }
691 }
692
693 static void
694 gtk_button_draw_focus (GtkWidget *widget)
695 {
696   gtk_widget_draw (widget, NULL);
697 }
698
699 static void
700 gtk_button_draw_default (GtkWidget *widget)
701 {
702   gtk_widget_draw (widget, NULL);
703 }
704
705 static gint
706 gtk_button_expose (GtkWidget      *widget,
707                    GdkEventExpose *event)
708 {
709   GtkBin *bin;
710   GdkEventExpose child_event;
711
712   g_return_val_if_fail (widget != NULL, FALSE);
713   g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
714   g_return_val_if_fail (event != NULL, FALSE);
715
716   if (GTK_WIDGET_DRAWABLE (widget))
717     {
718       bin = GTK_BIN (widget);
719       
720       gtk_button_paint (widget, &event->area);
721
722       child_event = *event;
723       if (bin->child && GTK_WIDGET_NO_WINDOW (bin->child) &&
724           gtk_widget_intersect (bin->child, &event->area, &child_event.area))
725         gtk_widget_event (bin->child, (GdkEvent*) &child_event);
726     }
727
728   return FALSE;
729 }
730
731 static gint
732 gtk_button_button_press (GtkWidget      *widget,
733                          GdkEventButton *event)
734 {
735   GtkButton *button;
736
737   g_return_val_if_fail (widget != NULL, FALSE);
738   g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
739   g_return_val_if_fail (event != NULL, FALSE);
740
741   if (event->type == GDK_BUTTON_PRESS)
742     {
743       button = GTK_BUTTON (widget);
744
745       if (!GTK_WIDGET_HAS_FOCUS (widget))
746         gtk_widget_grab_focus (widget);
747
748       if (event->button == 1)
749         {
750           gtk_grab_add (GTK_WIDGET (button));
751           gtk_button_pressed (button);
752         }
753     }
754
755   return TRUE;
756 }
757
758 static gint
759 gtk_button_button_release (GtkWidget      *widget,
760                            GdkEventButton *event)
761 {
762   GtkButton *button;
763
764   g_return_val_if_fail (widget != NULL, FALSE);
765   g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
766   g_return_val_if_fail (event != NULL, FALSE);
767
768   if (event->button == 1)
769     {
770       button = GTK_BUTTON (widget);
771       gtk_grab_remove (GTK_WIDGET (button));
772       gtk_button_released (button);
773     }
774
775   return TRUE;
776 }
777
778 static gint
779 gtk_button_enter_notify (GtkWidget        *widget,
780                          GdkEventCrossing *event)
781 {
782   GtkButton *button;
783   GtkWidget *event_widget;
784
785   g_return_val_if_fail (widget != NULL, FALSE);
786   g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
787   g_return_val_if_fail (event != NULL, FALSE);
788
789   button = GTK_BUTTON (widget);
790   event_widget = gtk_get_event_widget ((GdkEvent*) event);
791
792   if ((event_widget == widget) &&
793       (event->detail != GDK_NOTIFY_INFERIOR))
794     {
795       button->in_button = TRUE;
796       gtk_button_enter (button);
797     }
798
799   return FALSE;
800 }
801
802 static gint
803 gtk_button_leave_notify (GtkWidget        *widget,
804                          GdkEventCrossing *event)
805 {
806   GtkButton *button;
807   GtkWidget *event_widget;
808
809   g_return_val_if_fail (widget != NULL, FALSE);
810   g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
811   g_return_val_if_fail (event != NULL, FALSE);
812
813   button = GTK_BUTTON (widget);
814   event_widget = gtk_get_event_widget ((GdkEvent*) event);
815
816   if ((event_widget == widget) &&
817       (event->detail != GDK_NOTIFY_INFERIOR))
818     {
819       button->in_button = FALSE;
820       gtk_button_leave (button);
821     }
822
823   return FALSE;
824 }
825
826 static gint
827 gtk_button_focus_in (GtkWidget     *widget,
828                      GdkEventFocus *event)
829 {
830   g_return_val_if_fail (widget != NULL, FALSE);
831   g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
832   g_return_val_if_fail (event != NULL, FALSE);
833
834   GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
835   gtk_widget_draw_focus (widget);
836
837   return FALSE;
838 }
839
840 static gint
841 gtk_button_focus_out (GtkWidget     *widget,
842                       GdkEventFocus *event)
843 {
844   g_return_val_if_fail (widget != NULL, FALSE);
845   g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
846   g_return_val_if_fail (event != NULL, FALSE);
847
848   GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
849   gtk_widget_draw_focus (widget);
850
851   return FALSE;
852 }
853
854 static void
855 gtk_button_add (GtkContainer *container,
856                 GtkWidget    *widget)
857 {
858   g_return_if_fail (container != NULL);
859   g_return_if_fail (widget != NULL);
860
861   if (GTK_CONTAINER_CLASS (parent_class)->add)
862     GTK_CONTAINER_CLASS (parent_class)->add (container, widget);
863
864   GTK_BUTTON (container)->child = GTK_BIN (container)->child;
865 }
866
867 static void
868 gtk_button_remove (GtkContainer *container,
869                    GtkWidget    *widget)
870 {
871   g_return_if_fail (container != NULL);
872   g_return_if_fail (widget != NULL);
873
874   if (GTK_CONTAINER_CLASS (parent_class)->remove)
875     GTK_CONTAINER_CLASS (parent_class)->remove (container, widget);
876
877   GTK_BUTTON (container)->child = GTK_BIN (container)->child;
878 }
879
880 static void
881 gtk_real_button_pressed (GtkButton *button)
882 {
883   GtkStateType new_state;
884
885   g_return_if_fail (button != NULL);
886   g_return_if_fail (GTK_IS_BUTTON (button));
887
888   button->button_down = TRUE;
889
890   new_state = (button->in_button ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL);
891
892   if (GTK_WIDGET_STATE (button) != new_state)
893     {
894       gtk_widget_set_state (GTK_WIDGET (button), new_state);
895       gtk_widget_queue_draw (GTK_WIDGET (button));
896     }
897 }
898
899 static void
900 gtk_real_button_released (GtkButton *button)
901 {
902   GtkStateType new_state;
903
904   g_return_if_fail (button != NULL);
905   g_return_if_fail (GTK_IS_BUTTON (button));
906
907   if (button->button_down)
908     {
909       button->button_down = FALSE;
910
911       if (button->in_button)
912         gtk_button_clicked (button);
913
914       new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
915
916       if (GTK_WIDGET_STATE (button) != new_state)
917         {
918           gtk_widget_set_state (GTK_WIDGET (button), new_state);
919           /* We _draw () instead of queue_draw so that if the operation
920            * blocks, the label doesn't vanish.
921            */
922           gtk_widget_draw (GTK_WIDGET (button), NULL);
923         }
924     }
925 }
926
927 static void
928 gtk_real_button_enter (GtkButton *button)
929 {
930   GtkStateType new_state;
931
932   g_return_if_fail (button != NULL);
933   g_return_if_fail (GTK_IS_BUTTON (button));
934
935   new_state = (button->button_down ? GTK_STATE_ACTIVE : GTK_STATE_PRELIGHT);
936
937   if (GTK_WIDGET_STATE (button) != new_state)
938     {
939       gtk_widget_set_state (GTK_WIDGET (button), new_state);
940       gtk_widget_queue_draw (GTK_WIDGET (button));
941     }
942 }
943
944 static void
945 gtk_real_button_leave (GtkButton *button)
946 {
947   g_return_if_fail (button != NULL);
948   g_return_if_fail (GTK_IS_BUTTON (button));
949
950   if (GTK_WIDGET_STATE (button) != GTK_STATE_NORMAL)
951     {
952       gtk_widget_set_state (GTK_WIDGET (button), GTK_STATE_NORMAL);
953       gtk_widget_queue_draw (GTK_WIDGET (button));
954     }
955 }