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