]> Pileus Git - ~andy/gtk/blob - gtk/gtkbutton.c
fedd51ac55814982ac5b89610a5cca22878bab86
[~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 /* Time out before giving up on getting a key release when animatng
43  * the close button.
44  */
45 #define ACTIVATE_TIMEOUT 250
46
47 enum {
48   PRESSED,
49   RELEASED,
50   CLICKED,
51   ENTER,
52   LEAVE,
53   ACTIVATE,
54   LAST_SIGNAL
55 };
56
57 enum {
58   ARG_0,
59   ARG_LABEL,
60   ARG_RELIEF
61 };
62
63 static void gtk_button_class_init     (GtkButtonClass   *klass);
64 static void gtk_button_init           (GtkButton        *button);
65 static void gtk_button_set_arg        (GtkObject        *object,
66                                        GtkArg           *arg,
67                                        guint             arg_id);
68 static void gtk_button_get_arg        (GtkObject        *object,
69                                        GtkArg           *arg,
70                                        guint             arg_id);
71 static void gtk_button_realize        (GtkWidget        *widget);
72 static void gtk_button_unrealize      (GtkWidget        *widget);
73 static void gtk_button_size_request   (GtkWidget        *widget,
74                                        GtkRequisition   *requisition);
75 static void gtk_button_size_allocate  (GtkWidget        *widget,
76                                        GtkAllocation    *allocation);
77 static void gtk_button_paint          (GtkWidget        *widget,
78                                        GdkRectangle     *area);
79 static gint gtk_button_expose         (GtkWidget        *widget,
80                                        GdkEventExpose   *event);
81 static gint gtk_button_button_press   (GtkWidget        *widget,
82                                        GdkEventButton   *event);
83 static gint gtk_button_button_release (GtkWidget        *widget,
84                                        GdkEventButton   *event);
85 static gint gtk_button_key_release    (GtkWidget        *widget,
86                                        GdkEventKey      *event);
87 static gint gtk_button_enter_notify   (GtkWidget        *widget,
88                                        GdkEventCrossing *event);
89 static gint gtk_button_leave_notify   (GtkWidget        *widget,
90                                        GdkEventCrossing *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 void gtk_real_button_activate (GtkButton         *button);
100 static GtkType gtk_button_child_type  (GtkContainer     *container);
101
102 static void gtk_button_finish_activate (GtkButton *button,
103                                         gboolean   do_it);
104
105 static GtkBinClass *parent_class = NULL;
106 static guint button_signals[LAST_SIGNAL] = { 0 };
107
108
109 GtkType
110 gtk_button_get_type (void)
111 {
112   static GtkType button_type = 0;
113
114   if (!button_type)
115     {
116       static const GTypeInfo button_info =
117       {
118         sizeof (GtkButtonClass),
119         NULL,           /* base_init */
120         NULL,           /* base_finalize */
121         (GClassInitFunc) gtk_button_class_init,
122         NULL,           /* class_finalize */
123         NULL,           /* class_data */
124         sizeof (GtkButton),
125         16,             /* n_preallocs */
126         (GInstanceInitFunc) gtk_button_init,
127       };
128
129       button_type = g_type_register_static (GTK_TYPE_BIN, "GtkButton", &button_info, 0);
130     }
131
132   return button_type;
133 }
134
135 static void
136 gtk_button_class_init (GtkButtonClass *klass)
137 {
138   GtkObjectClass *object_class;
139   GtkWidgetClass *widget_class;
140   GtkContainerClass *container_class;
141
142   object_class = (GtkObjectClass*) klass;
143   widget_class = (GtkWidgetClass*) klass;
144   container_class = (GtkContainerClass*) klass;
145   
146   parent_class = g_type_class_peek_parent (klass);
147
148   object_class->set_arg = gtk_button_set_arg;
149   object_class->get_arg = gtk_button_get_arg;
150
151   widget_class->realize = gtk_button_realize;
152   widget_class->unrealize = gtk_button_unrealize;
153   widget_class->size_request = gtk_button_size_request;
154   widget_class->size_allocate = gtk_button_size_allocate;
155   widget_class->expose_event = gtk_button_expose;
156   widget_class->button_press_event = gtk_button_button_press;
157   widget_class->button_release_event = gtk_button_button_release;
158   widget_class->key_release_event = gtk_button_key_release;
159   widget_class->enter_notify_event = gtk_button_enter_notify;
160   widget_class->leave_notify_event = gtk_button_leave_notify;
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   klass->activate = gtk_real_button_activate;
172
173   gtk_object_add_arg_type ("GtkButton::label", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_LABEL);
174   gtk_object_add_arg_type ("GtkButton::relief", GTK_TYPE_RELIEF_STYLE, GTK_ARG_READWRITE, ARG_RELIEF);
175
176   button_signals[PRESSED] =
177     gtk_signal_new ("pressed",
178                     GTK_RUN_FIRST,
179                     GTK_CLASS_TYPE (object_class),
180                     GTK_SIGNAL_OFFSET (GtkButtonClass, pressed),
181                     gtk_marshal_VOID__VOID,
182                     GTK_TYPE_NONE, 0);
183   button_signals[RELEASED] =
184     gtk_signal_new ("released",
185                     GTK_RUN_FIRST,
186                     GTK_CLASS_TYPE (object_class),
187                     GTK_SIGNAL_OFFSET (GtkButtonClass, released),
188                     gtk_marshal_VOID__VOID,
189                     GTK_TYPE_NONE, 0);
190   button_signals[CLICKED] =
191     gtk_signal_new ("clicked",
192                     GTK_RUN_FIRST | GTK_RUN_ACTION,
193                     GTK_CLASS_TYPE (object_class),
194                     GTK_SIGNAL_OFFSET (GtkButtonClass, clicked),
195                     gtk_marshal_VOID__VOID,
196                     GTK_TYPE_NONE, 0);
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   button_signals[ACTIVATE] =
212     gtk_signal_new ("activate",
213                     GTK_RUN_FIRST,
214                     GTK_CLASS_TYPE (object_class),
215                     GTK_SIGNAL_OFFSET (GtkButtonClass, activate),
216                     gtk_marshal_VOID__VOID,
217                     GTK_TYPE_NONE, 0);
218   widget_class->activate_signal = button_signals[ACTIVATE];
219 }
220
221 static void
222 gtk_button_init (GtkButton *button)
223 {
224   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_FOCUS | GTK_RECEIVES_DEFAULT);
225   GTK_WIDGET_UNSET_FLAGS (button, GTK_NO_WINDOW);
226
227   button->child = NULL;
228   button->in_button = FALSE;
229   button->button_down = FALSE;
230   button->relief = GTK_RELIEF_NORMAL;
231 }
232
233 static GtkType
234 gtk_button_child_type  (GtkContainer     *container)
235 {
236   if (!GTK_BIN (container)->child)
237     return GTK_TYPE_WIDGET;
238   else
239     return GTK_TYPE_NONE;
240 }
241
242 static void
243 gtk_button_set_arg (GtkObject *object,
244                     GtkArg    *arg,
245                     guint      arg_id)
246 {
247   GtkButton *button;
248
249   button = GTK_BUTTON (object);
250
251   switch (arg_id)
252     {
253       GtkWidget *child;
254
255     case ARG_LABEL:
256       child = GTK_BIN (button)->child;
257       if (!child)
258         child = gtk_widget_new (GTK_TYPE_LABEL,
259                                 "visible", TRUE,
260                                 "parent", button,
261                                 NULL);
262       if (GTK_IS_LABEL (child))
263         gtk_label_set_text (GTK_LABEL (child),
264                        GTK_VALUE_STRING (*arg) ? GTK_VALUE_STRING (*arg) : "");
265       break;
266     case ARG_RELIEF:
267       gtk_button_set_relief (button, GTK_VALUE_ENUM (*arg));
268       break;
269     default:
270       break;
271     }
272 }
273
274 static void
275 gtk_button_get_arg (GtkObject *object,
276                     GtkArg    *arg,
277                     guint      arg_id)
278 {
279   GtkButton *button;
280
281   button = GTK_BUTTON (object);
282
283   switch (arg_id)
284     {
285     case ARG_LABEL:
286       if (GTK_BIN (button)->child && GTK_IS_LABEL (GTK_BIN (button)->child))
287         GTK_VALUE_STRING (*arg) = g_strdup (GTK_LABEL (GTK_BIN (button)->child)->label);
288       else
289         GTK_VALUE_STRING (*arg) = NULL;
290       break;
291     case ARG_RELIEF:
292       GTK_VALUE_ENUM (*arg) = gtk_button_get_relief (button);
293       break;
294     default:
295       arg->type = GTK_TYPE_INVALID;
296       break;
297     }
298 }
299
300 GtkWidget*
301 gtk_button_new (void)
302 {
303   return GTK_WIDGET (gtk_type_new (gtk_button_get_type ()));
304 }
305
306 GtkWidget*
307 gtk_button_new_with_label (const gchar *label)
308 {
309   GtkWidget *button;
310   GtkWidget *label_widget;
311
312   button = gtk_button_new ();
313   label_widget = gtk_label_new (label);
314   gtk_misc_set_alignment (GTK_MISC (label_widget), 0.5, 0.5);
315
316   gtk_container_add (GTK_CONTAINER (button), label_widget);
317   gtk_widget_show (label_widget);
318
319   return button;
320 }
321
322 /**
323  * gtk_button_new_from_stock:
324  * @stock_id: the name of the stock item 
325  * @returns: a new #GtkButton
326  *
327  * Creates a new #GtkButton containing the image and text from a stock item.
328  * Some stock ids have preprocessor macros like #GTK_STOCK_BUTTON_OK and
329  * #GTK_STOCK_BUTTON_APPLY.
330  **/
331 GtkWidget*
332 gtk_button_new_from_stock (const gchar   *stock_id)
333 {
334   GtkWidget *button;
335   GtkStockItem item;
336
337   if (gtk_stock_lookup (stock_id, &item))
338     {
339       GtkWidget *label;
340       GtkWidget *image;
341       GtkWidget *hbox;
342       
343       button = gtk_button_new ();
344
345       label = gtk_label_new_with_mnemonic (item.label);
346
347       gtk_label_set_mnemonic_widget (GTK_LABEL (label), button);
348
349       image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
350       hbox = gtk_hbox_new (FALSE, 0);
351
352       gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 2);
353       gtk_box_pack_end (GTK_BOX (hbox), label, TRUE, TRUE, 2);
354       
355       gtk_container_add (GTK_CONTAINER (button), hbox);
356       gtk_widget_show_all (hbox);
357     }
358   else
359     {
360       button = gtk_button_new_with_mnemonic (stock_id);
361     }
362   
363   return button;
364 }
365
366 /**
367  * gtk_button_new_with_mnemonic:
368  * @label: The text of the button, with an underscore in front of the
369  *         mnemonic character
370  * @returns: a new #GtkButton
371  *
372  * Creates a new #GtkButton containing a label.
373  * If characters in @label are preceded by an underscore, they are underlined
374  * indicating that they represent a keyboard accelerator called a mnemonic.
375  * Pressing Alt and that key activates the button.
376  **/
377 GtkWidget*
378 gtk_button_new_with_mnemonic (const gchar *label)
379 {
380   GtkWidget *button;
381   GtkWidget *label_widget;
382
383   button = gtk_button_new ();
384   
385   label_widget = gtk_label_new_with_mnemonic (label);
386
387   gtk_label_set_mnemonic_widget (GTK_LABEL (label_widget), button);
388   
389   gtk_container_add (GTK_CONTAINER (button), label_widget);
390   gtk_widget_show (label_widget);
391
392   return button;
393 }
394
395 void
396 gtk_button_pressed (GtkButton *button)
397 {
398   g_return_if_fail (button != NULL);
399   g_return_if_fail (GTK_IS_BUTTON (button));
400
401   gtk_signal_emit (GTK_OBJECT (button), button_signals[PRESSED]);
402 }
403
404 void
405 gtk_button_released (GtkButton *button)
406 {
407   g_return_if_fail (button != NULL);
408   g_return_if_fail (GTK_IS_BUTTON (button));
409
410   gtk_signal_emit (GTK_OBJECT (button), button_signals[RELEASED]);
411 }
412
413 void
414 gtk_button_clicked (GtkButton *button)
415 {
416   g_return_if_fail (button != NULL);
417   g_return_if_fail (GTK_IS_BUTTON (button));
418
419   gtk_signal_emit (GTK_OBJECT (button), button_signals[CLICKED]);
420 }
421
422 void
423 gtk_button_enter (GtkButton *button)
424 {
425   g_return_if_fail (button != NULL);
426   g_return_if_fail (GTK_IS_BUTTON (button));
427
428   gtk_signal_emit (GTK_OBJECT (button), button_signals[ENTER]);
429 }
430
431 void
432 gtk_button_leave (GtkButton *button)
433 {
434   g_return_if_fail (button != NULL);
435   g_return_if_fail (GTK_IS_BUTTON (button));
436
437   gtk_signal_emit (GTK_OBJECT (button), button_signals[LEAVE]);
438 }
439
440 void
441 gtk_button_set_relief (GtkButton *button,
442                        GtkReliefStyle newrelief)
443 {
444   g_return_if_fail (button != NULL);
445   g_return_if_fail (GTK_IS_BUTTON (button));
446
447   button->relief = newrelief;
448   gtk_widget_queue_draw (GTK_WIDGET (button));
449 }
450
451 GtkReliefStyle
452 gtk_button_get_relief (GtkButton *button)
453 {
454   g_return_val_if_fail (button != NULL, GTK_RELIEF_NORMAL);
455   g_return_val_if_fail (GTK_IS_BUTTON (button), GTK_RELIEF_NORMAL);
456
457   return button->relief;
458 }
459
460 static void
461 gtk_button_realize (GtkWidget *widget)
462 {
463   GtkButton *button;
464   GdkWindowAttr attributes;
465   gint attributes_mask;
466   gint border_width;
467
468   g_return_if_fail (widget != NULL);
469   g_return_if_fail (GTK_IS_BUTTON (widget));
470
471   button = GTK_BUTTON (widget);
472   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
473
474   border_width = GTK_CONTAINER (widget)->border_width;
475
476   attributes.window_type = GDK_WINDOW_CHILD;
477   attributes.x = widget->allocation.x + border_width;
478   attributes.y = widget->allocation.y + border_width;
479   attributes.width = widget->allocation.width - border_width * 2;
480   attributes.height = widget->allocation.height - border_width * 2;
481   attributes.wclass = GDK_INPUT_OUTPUT;
482   attributes.visual = gtk_widget_get_visual (widget);
483   attributes.colormap = gtk_widget_get_colormap (widget);
484   attributes.event_mask = gtk_widget_get_events (widget);
485   attributes.event_mask |= (GDK_EXPOSURE_MASK |
486                             GDK_BUTTON_PRESS_MASK |
487                             GDK_BUTTON_RELEASE_MASK |
488                             GDK_ENTER_NOTIFY_MASK |
489                             GDK_LEAVE_NOTIFY_MASK);
490
491   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
492
493   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
494   gdk_window_set_user_data (widget->window, button);
495
496   widget->style = gtk_style_attach (widget->style, widget->window);
497   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
498 }
499
500 static void
501 gtk_button_unrealize (GtkWidget *widget)
502 {
503   GtkButton *button = GTK_BUTTON (widget);
504
505   if (button->activate_timeout)
506     gtk_button_finish_activate (button, FALSE);
507     
508   GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
509 }
510
511 static void
512 gtk_button_size_request (GtkWidget      *widget,
513                          GtkRequisition *requisition)
514 {
515   GtkButton *button;
516
517   g_return_if_fail (widget != NULL);
518   g_return_if_fail (GTK_IS_BUTTON (widget));
519   g_return_if_fail (requisition != NULL);
520
521   button = GTK_BUTTON (widget);
522
523   requisition->width = (GTK_CONTAINER (widget)->border_width + CHILD_SPACING +
524                         GTK_WIDGET (widget)->style->xthickness) * 2;
525   requisition->height = (GTK_CONTAINER (widget)->border_width + CHILD_SPACING +
526                          GTK_WIDGET (widget)->style->ythickness) * 2;
527
528   if (GTK_WIDGET_CAN_DEFAULT (widget))
529     {
530       requisition->width += (GTK_WIDGET (widget)->style->xthickness * 2 +
531                              DEFAULT_SPACING);
532       requisition->height += (GTK_WIDGET (widget)->style->ythickness * 2 +
533                               DEFAULT_SPACING);
534     }
535
536   if (GTK_BIN (button)->child && GTK_WIDGET_VISIBLE (GTK_BIN (button)->child))
537     {
538       GtkRequisition child_requisition;
539
540       gtk_widget_size_request (GTK_BIN (button)->child, &child_requisition);
541
542       requisition->width += child_requisition.width;
543       requisition->height += child_requisition.height;
544     }
545 }
546
547 static void
548 gtk_button_size_allocate (GtkWidget     *widget,
549                           GtkAllocation *allocation)
550 {
551   GtkButton *button;
552   GtkAllocation child_allocation;
553   gint border_width;
554
555   g_return_if_fail (widget != NULL);
556   g_return_if_fail (GTK_IS_BUTTON (widget));
557   g_return_if_fail (allocation != NULL);
558
559   widget->allocation = *allocation;
560   border_width = GTK_CONTAINER (widget)->border_width;
561
562   if (GTK_WIDGET_REALIZED (widget))
563     gdk_window_move_resize (widget->window,
564                             widget->allocation.x + border_width,
565                             widget->allocation.y + border_width,
566                             widget->allocation.width - border_width * 2,
567                             widget->allocation.height - border_width * 2);
568
569   button = GTK_BUTTON (widget);
570
571   if (GTK_BIN (button)->child && GTK_WIDGET_VISIBLE (GTK_BIN (button)->child))
572     {
573       child_allocation.x = (CHILD_SPACING + GTK_WIDGET (widget)->style->xthickness);
574       child_allocation.y = (CHILD_SPACING + GTK_WIDGET (widget)->style->ythickness);
575
576       child_allocation.width = MAX (1, (gint)widget->allocation.width - child_allocation.x * 2 -
577                                  border_width * 2);
578       child_allocation.height = MAX (1, (gint)widget->allocation.height - child_allocation.y * 2 -
579                                   border_width * 2);
580
581       if (GTK_WIDGET_CAN_DEFAULT (button))
582         {
583           child_allocation.x += (GTK_WIDGET (widget)->style->xthickness +
584                                  DEFAULT_LEFT_POS);
585           child_allocation.y += (GTK_WIDGET (widget)->style->ythickness +
586                                  DEFAULT_TOP_POS);
587           child_allocation.width =  MAX (1, (gint)child_allocation.width -
588                                          (gint)(GTK_WIDGET (widget)->style->xthickness * 2 + DEFAULT_SPACING));
589           child_allocation.height = MAX (1, (gint)child_allocation.height -
590                                          (gint)(GTK_WIDGET (widget)->style->xthickness * 2 + DEFAULT_SPACING));
591         }
592
593       gtk_widget_size_allocate (GTK_BIN (button)->child, &child_allocation);
594     }
595 }
596
597 /*
598  * +------------------------------------------------+
599  * |                   BORDER                       |
600  * |  +------------------------------------------+  |
601  * |  |\\\\\\\\\\\\\\\\DEFAULT\\\\\\\\\\\\\\\\\  |  |
602  * |  |\\+------------------------------------+  |  |
603  * |  |\\| |           SPACING       3      | |  |  |
604  * |  |\\| +--------------------------------+ |  |  |
605  * |  |\\| |########## FOCUS ###############| |  |  |
606  * |  |\\| |#+----------------------------+#| |  |  |
607  * |  |\\| |#|         RELIEF            \|#| |  |  |
608  * |  |\\| |#|  +-----------------------+\|#| |  |  |
609  * |  |\\|1|#|  +     THE TEXT          +\|#|2|  |  |
610  * |  |\\| |#|  +-----------------------+\|#| |  |  |
611  * |  |\\| |#| \\\\\ ythickness \\\\\\\\\\|#| |  |  |
612  * |  |\\| |#+----------------------------+#| |  |  |
613  * |  |\\| |########### 1 ##################| |  |  |
614  * |  |\\| +--------------------------------+ |  |  |
615  * |  |\\| |        default spacing   4     | |  |  |
616  * |  |\\+------------------------------------+  |  |
617  * |  |\            ythickness                   |  |
618  * |  +------------------------------------------+  |
619  * |                border_width                    |
620  * +------------------------------------------------+
621  */
622
623 static void
624 gtk_button_paint (GtkWidget    *widget,
625                   GdkRectangle *area)
626 {
627   GtkButton *button;
628   GtkShadowType shadow_type;
629   gint width, height;
630   gint x, y;
631    
632   if (GTK_WIDGET_DRAWABLE (widget))
633     {
634       button = GTK_BUTTON (widget);
635         
636       x = 0;
637       y = 0;
638       width = widget->allocation.width - GTK_CONTAINER (widget)->border_width * 2;
639       height = widget->allocation.height - GTK_CONTAINER (widget)->border_width * 2;
640
641       gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
642       gdk_window_clear_area (widget->window, area->x, area->y, area->width, area->height);
643
644       if (GTK_WIDGET_HAS_DEFAULT (widget) &&
645           GTK_BUTTON (widget)->relief == GTK_RELIEF_NORMAL)
646         {
647           gtk_paint_box (widget->style, widget->window,
648                          GTK_STATE_NORMAL, GTK_SHADOW_IN,
649                          area, widget, "buttondefault",
650                          x, y, width, height);
651         }
652
653       if (GTK_WIDGET_CAN_DEFAULT (widget))
654         {
655           x += widget->style->xthickness;
656           y += widget->style->ythickness;
657           width -= 2 * x + DEFAULT_SPACING;
658           height -= 2 * y + DEFAULT_SPACING;
659           x += DEFAULT_LEFT_POS;
660           y += DEFAULT_TOP_POS;
661         }
662        
663       if (GTK_WIDGET_HAS_FOCUS (widget))
664         {
665           x += 1;
666           y += 1;
667           width -= 2;
668           height -= 2;
669         }
670         
671       if (GTK_WIDGET_STATE (widget) == GTK_STATE_ACTIVE)
672         shadow_type = GTK_SHADOW_IN;
673       else
674         shadow_type = GTK_SHADOW_OUT;
675
676       if ((button->relief != GTK_RELIEF_NONE) ||
677           ((GTK_WIDGET_STATE(widget) != GTK_STATE_NORMAL) &&
678            (GTK_WIDGET_STATE(widget) != GTK_STATE_INSENSITIVE)))
679         gtk_paint_box (widget->style, widget->window,
680                        GTK_WIDGET_STATE (widget),
681                        shadow_type, area, widget, "button",
682                        x, y, width, height);
683        
684       if (GTK_WIDGET_HAS_FOCUS (widget))
685         {
686           x -= 1;
687           y -= 1;
688           width += 2;
689           height += 2;
690
691           gtk_paint_focus (widget->style, widget->window,
692                            area, widget, "button",
693                            x, y, width - 1, height - 1);
694         }
695     }
696 }
697
698 static gboolean
699 gtk_button_expose (GtkWidget      *widget,
700                    GdkEventExpose *event)
701 {
702   GtkBin *bin;
703
704   g_return_val_if_fail (widget != NULL, FALSE);
705   g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
706   g_return_val_if_fail (event != NULL, FALSE);
707
708   if (GTK_WIDGET_DRAWABLE (widget))
709     {
710       bin = GTK_BIN (widget);
711       
712       gtk_button_paint (widget, &event->area);
713       
714       (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
715     }
716   
717   return FALSE;
718 }
719
720 static gboolean
721 gtk_button_button_press (GtkWidget      *widget,
722                          GdkEventButton *event)
723 {
724   GtkButton *button;
725
726   g_return_val_if_fail (widget != NULL, FALSE);
727   g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
728   g_return_val_if_fail (event != NULL, FALSE);
729
730   if (event->type == GDK_BUTTON_PRESS)
731     {
732       button = GTK_BUTTON (widget);
733
734       if (!GTK_WIDGET_HAS_FOCUS (widget))
735         gtk_widget_grab_focus (widget);
736
737       if (event->button == 1)
738         gtk_button_pressed (button);
739     }
740
741   return TRUE;
742 }
743
744 static gboolean
745 gtk_button_button_release (GtkWidget      *widget,
746                            GdkEventButton *event)
747 {
748   GtkButton *button;
749
750   g_return_val_if_fail (widget != NULL, FALSE);
751   g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
752   g_return_val_if_fail (event != NULL, FALSE);
753
754   if (event->button == 1)
755     {
756       button = GTK_BUTTON (widget);
757       gtk_button_released (button);
758     }
759
760   return TRUE;
761 }
762
763 static gboolean
764 gtk_button_key_release (GtkWidget   *widget,
765                         GdkEventKey *event)
766 {
767   GtkButton *button = GTK_BUTTON (widget);
768
769   if (button->activate_timeout)
770     {
771       gtk_button_finish_activate (button, TRUE);
772       return TRUE;
773     }
774   else if (GTK_WIDGET_CLASS (parent_class)->key_release_event)
775     return GTK_WIDGET_CLASS (parent_class)->key_release_event (widget, event);
776   else
777     return FALSE;
778 }
779
780 static gboolean
781 gtk_button_enter_notify (GtkWidget        *widget,
782                          GdkEventCrossing *event)
783 {
784   GtkButton *button;
785   GtkWidget *event_widget;
786
787   g_return_val_if_fail (widget != NULL, FALSE);
788   g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
789   g_return_val_if_fail (event != NULL, FALSE);
790
791   button = GTK_BUTTON (widget);
792   event_widget = gtk_get_event_widget ((GdkEvent*) event);
793
794   if ((event_widget == widget) &&
795       (event->detail != GDK_NOTIFY_INFERIOR))
796     {
797       button->in_button = TRUE;
798       gtk_button_enter (button);
799     }
800
801   return FALSE;
802 }
803
804 static gboolean
805 gtk_button_leave_notify (GtkWidget        *widget,
806                          GdkEventCrossing *event)
807 {
808   GtkButton *button;
809   GtkWidget *event_widget;
810
811   g_return_val_if_fail (widget != NULL, FALSE);
812   g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
813   g_return_val_if_fail (event != NULL, FALSE);
814
815   button = GTK_BUTTON (widget);
816   event_widget = gtk_get_event_widget ((GdkEvent*) event);
817
818   if ((event_widget == widget) &&
819       (event->detail != GDK_NOTIFY_INFERIOR))
820     {
821       button->in_button = FALSE;
822       gtk_button_leave (button);
823     }
824
825   return FALSE;
826 }
827
828 static void
829 gtk_button_add (GtkContainer *container,
830                 GtkWidget    *widget)
831 {
832   g_return_if_fail (container != NULL);
833   g_return_if_fail (widget != NULL);
834
835   if (GTK_CONTAINER_CLASS (parent_class)->add)
836     GTK_CONTAINER_CLASS (parent_class)->add (container, widget);
837
838   GTK_BUTTON (container)->child = GTK_BIN (container)->child;
839 }
840
841 static void
842 gtk_button_remove (GtkContainer *container,
843                    GtkWidget    *widget)
844 {
845   g_return_if_fail (container != NULL);
846   g_return_if_fail (widget != NULL);
847
848   if (GTK_CONTAINER_CLASS (parent_class)->remove)
849     GTK_CONTAINER_CLASS (parent_class)->remove (container, widget);
850
851   GTK_BUTTON (container)->child = GTK_BIN (container)->child;
852 }
853
854 static void
855 gtk_real_button_pressed (GtkButton *button)
856 {
857   GtkStateType new_state;
858
859   g_return_if_fail (button != NULL);
860   g_return_if_fail (GTK_IS_BUTTON (button));
861
862   if (button->activate_timeout)
863     return;
864   
865   button->button_down = TRUE;
866
867   new_state = (button->in_button ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL);
868
869   if (GTK_WIDGET_STATE (button) != new_state)
870     {
871       gtk_widget_set_state (GTK_WIDGET (button), new_state);
872       gtk_widget_queue_draw (GTK_WIDGET (button));
873     }
874 }
875
876 static void
877 gtk_real_button_released (GtkButton *button)
878 {
879   GtkStateType new_state;
880
881   g_return_if_fail (button != NULL);
882   g_return_if_fail (GTK_IS_BUTTON (button));
883
884   if (button->button_down)
885     {
886       button->button_down = FALSE;
887
888       if (button->activate_timeout)
889         return;
890   
891       if (button->in_button)
892         gtk_button_clicked (button);
893
894       new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
895
896       if (GTK_WIDGET_STATE (button) != new_state)
897         {
898           gtk_widget_set_state (GTK_WIDGET (button), new_state);
899           /* We _draw () instead of queue_draw so that if the operation
900            * blocks, the label doesn't vanish.
901            */
902           gtk_widget_draw (GTK_WIDGET (button), NULL);
903         }
904     }
905 }
906
907 static void
908 gtk_real_button_enter (GtkButton *button)
909 {
910   GtkStateType new_state;
911
912   g_return_if_fail (button != NULL);
913   g_return_if_fail (GTK_IS_BUTTON (button));
914
915   new_state = (button->button_down ? GTK_STATE_ACTIVE : GTK_STATE_PRELIGHT);
916
917   if (button->activate_timeout)
918     return;
919   
920   if (GTK_WIDGET_STATE (button) != new_state)
921     {
922       gtk_widget_set_state (GTK_WIDGET (button), new_state);
923       gtk_widget_queue_draw (GTK_WIDGET (button));
924     }
925 }
926
927 static void
928 gtk_real_button_leave (GtkButton *button)
929 {
930   g_return_if_fail (button != NULL);
931   g_return_if_fail (GTK_IS_BUTTON (button));
932   
933   if (button->activate_timeout)
934     return;
935   
936   if (GTK_WIDGET_STATE (button) != GTK_STATE_NORMAL)
937     {
938       gtk_widget_set_state (GTK_WIDGET (button), GTK_STATE_NORMAL);
939       gtk_widget_queue_draw (GTK_WIDGET (button));
940     }
941 }
942
943 static gboolean
944 button_activate_timeout (gpointer data)
945 {
946   gtk_button_finish_activate (data, TRUE);
947
948   return FALSE;
949 }
950
951 static void
952 gtk_real_button_activate (GtkButton *button)
953 {
954   GtkWidget *widget = GTK_WIDGET (button);
955   
956   g_return_if_fail (button != NULL);
957   g_return_if_fail (GTK_IS_BUTTON (button));
958
959   if (GTK_WIDGET_REALIZED (button) && !button->activate_timeout)
960     {
961       if (gdk_keyboard_grab (widget->window, TRUE,
962                              gtk_get_current_event_time ()) == 0)
963         {
964           gtk_grab_add (widget);
965           
966           button->activate_timeout = g_timeout_add (ACTIVATE_TIMEOUT,
967                                                     button_activate_timeout,
968                                                     button);
969           button->button_down = TRUE;
970           gtk_widget_set_state (widget, GTK_STATE_ACTIVE);
971         }
972     }
973 }
974
975 static void
976 gtk_button_finish_activate (GtkButton *button,
977                             gboolean   do_it)
978 {
979   GtkWidget *widget = GTK_WIDGET (button);
980   
981   g_source_remove (button->activate_timeout);
982   button->activate_timeout = 0;
983
984   gdk_keyboard_ungrab (gtk_get_current_event_time ());
985   gtk_grab_remove (widget);
986
987   button->button_down = FALSE;
988   gtk_widget_set_state (GTK_WIDGET (button),
989                         button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
990
991   if (do_it)
992     gtk_button_clicked (button);
993 }
994