]> Pileus Git - ~andy/gtk/blob - gtk/gtkbutton.c
Added "edit_only" argument to gtk_cell_area_activate()
[~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-2001.  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 /**
28  * SECTION:gtkbutton
29  * @Short_description: A widget that creates a signal when clicked on
30  * @Title: GtkButton
31  *
32  * The #GtkButton widget is generally used to attach a function to that is
33  * called when the button is pressed.  The various signals and how to use them
34  * are outlined below.
35  *
36  * The #GtkButton widget can hold any valid child widget.  That is it can hold
37  * most any other standard #GtkWidget.  The most commonly used child is the
38  * #GtkLabel.
39  */
40
41 #include "config.h"
42
43 #include "gtkbutton.h"
44 #include "gtkbuttonprivate.h"
45
46 #include <string.h>
47 #include "gtkalignment.h"
48 #include "gtklabel.h"
49 #include "gtkmain.h"
50 #include "gtkmarshalers.h"
51 #include "gtkimage.h"
52 #include "gtkhbox.h"
53 #include "gtkvbox.h"
54 #include "gtkstock.h"
55 #include "gtkiconfactory.h"
56 #include "gtkactivatable.h"
57 #include "gtksizerequest.h"
58 #include "gtkprivate.h"
59 #include "gtkintl.h"
60
61
62 static const GtkBorder default_default_border = { 1, 1, 1, 1 };
63 static const GtkBorder default_default_outside_border = { 0, 0, 0, 0 };
64 static const GtkBorder default_inner_border = { 1, 1, 1, 1 };
65
66 /* Time out before giving up on getting a key release when animating
67  * the close button.
68  */
69 #define ACTIVATE_TIMEOUT 250
70
71
72 enum {
73   PRESSED,
74   RELEASED,
75   CLICKED,
76   ENTER,
77   LEAVE,
78   ACTIVATE,
79   LAST_SIGNAL
80 };
81
82 enum {
83   PROP_0,
84   PROP_LABEL,
85   PROP_IMAGE,
86   PROP_RELIEF,
87   PROP_USE_UNDERLINE,
88   PROP_USE_STOCK,
89   PROP_FOCUS_ON_CLICK,
90   PROP_XALIGN,
91   PROP_YALIGN,
92   PROP_IMAGE_POSITION,
93
94   /* activatable properties */
95   PROP_ACTIVATABLE_RELATED_ACTION,
96   PROP_ACTIVATABLE_USE_ACTION_APPEARANCE
97 };
98
99
100 static void gtk_button_destroy        (GtkWidget          *widget);
101 static void gtk_button_dispose        (GObject            *object);
102 static void gtk_button_set_property   (GObject            *object,
103                                        guint               prop_id,
104                                        const GValue       *value,
105                                        GParamSpec         *pspec);
106 static void gtk_button_get_property   (GObject            *object,
107                                        guint               prop_id,
108                                        GValue             *value,
109                                        GParamSpec         *pspec);
110 static void gtk_button_screen_changed (GtkWidget          *widget,
111                                        GdkScreen          *previous_screen);
112 static void gtk_button_realize (GtkWidget * widget);
113 static void gtk_button_unrealize (GtkWidget * widget);
114 static void gtk_button_map (GtkWidget * widget);
115 static void gtk_button_unmap (GtkWidget * widget);
116 static void gtk_button_style_updated (GtkWidget * widget);
117 static void gtk_button_size_allocate (GtkWidget * widget,
118                                       GtkAllocation * allocation);
119 static gint gtk_button_draw (GtkWidget * widget, cairo_t *cr);
120 static gint gtk_button_button_press (GtkWidget * widget,
121                                      GdkEventButton * event);
122 static gint gtk_button_button_release (GtkWidget * widget,
123                                        GdkEventButton * event);
124 static gint gtk_button_grab_broken (GtkWidget * widget,
125                                     GdkEventGrabBroken * event);
126 static gint gtk_button_key_release (GtkWidget * widget, GdkEventKey * event);
127 static gint gtk_button_enter_notify (GtkWidget * widget,
128                                      GdkEventCrossing * event);
129 static gint gtk_button_leave_notify (GtkWidget * widget,
130                                      GdkEventCrossing * event);
131 static void gtk_real_button_pressed (GtkButton * button);
132 static void gtk_real_button_released (GtkButton * button);
133 static void gtk_real_button_clicked (GtkButton * button);
134 static void gtk_real_button_activate  (GtkButton          *button);
135 static void gtk_button_update_state   (GtkButton          *button);
136 static void gtk_button_add            (GtkContainer       *container,
137                                        GtkWidget          *widget);
138 static GType gtk_button_child_type    (GtkContainer       *container);
139 static void gtk_button_finish_activate (GtkButton         *button,
140                                         gboolean           do_it);
141
142 static GObject* gtk_button_constructor (GType                  type,
143                                         guint                  n_construct_properties,
144                                         GObjectConstructParam *construct_params);
145 static void gtk_button_construct_child (GtkButton             *button);
146 static void gtk_button_state_changed   (GtkWidget             *widget,
147                                         GtkStateType           previous_state);
148 static void gtk_button_grab_notify     (GtkWidget             *widget,
149                                         gboolean               was_grabbed);
150
151
152 static void gtk_button_activatable_interface_init(GtkActivatableIface  *iface);
153 static void gtk_button_update                    (GtkActivatable       *activatable,
154                                                   GtkAction            *action,
155                                                   const gchar          *property_name);
156 static void gtk_button_sync_action_properties    (GtkActivatable       *activatable,
157                                                   GtkAction            *action);
158 static void gtk_button_set_related_action        (GtkButton            *button,
159                                                   GtkAction            *action);
160 static void gtk_button_set_use_action_appearance (GtkButton            *button,
161                                                   gboolean              use_appearance);
162
163 static void gtk_button_get_preferred_width       (GtkWidget           *widget,
164                                                   gint                *minimum_size,
165                                                   gint                *natural_size);
166 static void gtk_button_get_preferred_height      (GtkWidget           *widget,
167                                                   gint                *minimum_size,
168                                                   gint                *natural_size);
169   
170 static guint button_signals[LAST_SIGNAL] = { 0 };
171
172 G_DEFINE_TYPE_WITH_CODE (GtkButton, gtk_button, GTK_TYPE_BIN,
173                          G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
174                                                 gtk_button_activatable_interface_init))
175
176 static void
177 gtk_button_class_init (GtkButtonClass *klass)
178 {
179   GObjectClass *gobject_class;
180   GtkWidgetClass *widget_class;
181   GtkContainerClass *container_class;
182
183   gobject_class = G_OBJECT_CLASS (klass);
184   widget_class = (GtkWidgetClass*) klass;
185   container_class = (GtkContainerClass*) klass;
186   
187   gobject_class->constructor  = gtk_button_constructor;
188   gobject_class->dispose      = gtk_button_dispose;
189   gobject_class->set_property = gtk_button_set_property;
190   gobject_class->get_property = gtk_button_get_property;
191
192   widget_class->get_preferred_width  = gtk_button_get_preferred_width;
193   widget_class->get_preferred_height = gtk_button_get_preferred_height;
194   widget_class->destroy = gtk_button_destroy;
195   widget_class->screen_changed = gtk_button_screen_changed;
196   widget_class->realize = gtk_button_realize;
197   widget_class->unrealize = gtk_button_unrealize;
198   widget_class->map = gtk_button_map;
199   widget_class->unmap = gtk_button_unmap;
200   widget_class->style_updated = gtk_button_style_updated;
201   widget_class->size_allocate = gtk_button_size_allocate;
202   widget_class->draw = gtk_button_draw;
203   widget_class->button_press_event = gtk_button_button_press;
204   widget_class->button_release_event = gtk_button_button_release;
205   widget_class->grab_broken_event = gtk_button_grab_broken;
206   widget_class->key_release_event = gtk_button_key_release;
207   widget_class->enter_notify_event = gtk_button_enter_notify;
208   widget_class->leave_notify_event = gtk_button_leave_notify;
209   widget_class->state_changed = gtk_button_state_changed;
210   widget_class->grab_notify = gtk_button_grab_notify;
211
212   container_class->child_type = gtk_button_child_type;
213   container_class->add = gtk_button_add;
214   gtk_container_class_handle_border_width (container_class);
215
216   klass->pressed = gtk_real_button_pressed;
217   klass->released = gtk_real_button_released;
218   klass->clicked = NULL;
219   klass->enter = gtk_button_update_state;
220   klass->leave = gtk_button_update_state;
221   klass->activate = gtk_real_button_activate;
222
223   g_object_class_install_property (gobject_class,
224                                    PROP_LABEL,
225                                    g_param_spec_string ("label",
226                                                         P_("Label"),
227                                                         P_("Text of the label widget inside the button, if the button contains a label widget"),
228                                                         NULL,
229                                                         GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
230   
231   g_object_class_install_property (gobject_class,
232                                    PROP_USE_UNDERLINE,
233                                    g_param_spec_boolean ("use-underline",
234                                                          P_("Use underline"),
235                                                          P_("If set, an underline in the text indicates the next character should be used for the mnemonic accelerator key"),
236                                                         FALSE,
237                                                         GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
238   
239   g_object_class_install_property (gobject_class,
240                                    PROP_USE_STOCK,
241                                    g_param_spec_boolean ("use-stock",
242                                                          P_("Use stock"),
243                                                          P_("If set, the label is used to pick a stock item instead of being displayed"),
244                                                         FALSE,
245                                                         GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT));
246   
247   g_object_class_install_property (gobject_class,
248                                    PROP_FOCUS_ON_CLICK,
249                                    g_param_spec_boolean ("focus-on-click",
250                                                          P_("Focus on click"),
251                                                          P_("Whether the button grabs focus when it is clicked with the mouse"),
252                                                          TRUE,
253                                                          GTK_PARAM_READWRITE));
254   
255   g_object_class_install_property (gobject_class,
256                                    PROP_RELIEF,
257                                    g_param_spec_enum ("relief",
258                                                       P_("Border relief"),
259                                                       P_("The border relief style"),
260                                                       GTK_TYPE_RELIEF_STYLE,
261                                                       GTK_RELIEF_NORMAL,
262                                                       GTK_PARAM_READWRITE));
263   
264   /**
265    * GtkButton:xalign:
266    *
267    * If the child of the button is a #GtkMisc or #GtkAlignment, this property 
268    * can be used to control it's horizontal alignment. 0.0 is left aligned, 
269    * 1.0 is right aligned.
270    *
271    * Since: 2.4
272    */
273   g_object_class_install_property (gobject_class,
274                                    PROP_XALIGN,
275                                    g_param_spec_float("xalign",
276                                                       P_("Horizontal alignment for child"),
277                                                       P_("Horizontal position of child in available space. 0.0 is left aligned, 1.0 is right aligned"),
278                                                       0.0,
279                                                       1.0,
280                                                       0.5,
281                                                       GTK_PARAM_READWRITE));
282
283   /**
284    * GtkButton:yalign:
285    *
286    * If the child of the button is a #GtkMisc or #GtkAlignment, this property 
287    * can be used to control it's vertical alignment. 0.0 is top aligned, 
288    * 1.0 is bottom aligned.
289    *
290    * Since: 2.4
291    */
292   g_object_class_install_property (gobject_class,
293                                    PROP_YALIGN,
294                                    g_param_spec_float("yalign",
295                                                       P_("Vertical alignment for child"),
296                                                       P_("Vertical position of child in available space. 0.0 is top aligned, 1.0 is bottom aligned"),
297                                                       0.0,
298                                                       1.0,
299                                                       0.5,
300                                                       GTK_PARAM_READWRITE));
301
302   /**
303    * GtkButton::image:
304    *
305    * The child widget to appear next to the button text.
306    *
307    * Since: 2.6
308    */
309   g_object_class_install_property (gobject_class,
310                                    PROP_IMAGE,
311                                    g_param_spec_object ("image",
312                                                         P_("Image widget"),
313                                                         P_("Child widget to appear next to the button text"),
314                                                         GTK_TYPE_WIDGET,
315                                                         GTK_PARAM_READWRITE));
316
317   /**
318    * GtkButton:image-position:
319    *
320    * The position of the image relative to the text inside the button.
321    *
322    * Since: 2.10
323    */
324   g_object_class_install_property (gobject_class,
325                                    PROP_IMAGE_POSITION,
326                                    g_param_spec_enum ("image-position",
327                                             P_("Image position"),
328                                                       P_("The position of the image relative to the text"),
329                                                       GTK_TYPE_POSITION_TYPE,
330                                                       GTK_POS_LEFT,
331                                                       GTK_PARAM_READWRITE));
332
333   g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_RELATED_ACTION, "related-action");
334   g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_USE_ACTION_APPEARANCE, "use-action-appearance");
335
336   /**
337    * GtkButton::pressed:
338    * @button: the object that received the signal
339    *
340    * Emitted when the button is pressed.
341    *
342    * Deprecated: 2.8: Use the #GtkWidget::button-press-event signal.
343    */ 
344   button_signals[PRESSED] =
345     g_signal_new (I_("pressed"),
346                   G_OBJECT_CLASS_TYPE (gobject_class),
347                   G_SIGNAL_RUN_FIRST,
348                   G_STRUCT_OFFSET (GtkButtonClass, pressed),
349                   NULL, NULL,
350                   _gtk_marshal_VOID__VOID,
351                   G_TYPE_NONE, 0);
352
353   /**
354    * GtkButton::released:
355    * @button: the object that received the signal
356    *
357    * Emitted when the button is released.
358    *
359    * Deprecated: 2.8: Use the #GtkWidget::button-release-event signal.
360    */ 
361   button_signals[RELEASED] =
362     g_signal_new (I_("released"),
363                   G_OBJECT_CLASS_TYPE (gobject_class),
364                   G_SIGNAL_RUN_FIRST,
365                   G_STRUCT_OFFSET (GtkButtonClass, released),
366                   NULL, NULL,
367                   _gtk_marshal_VOID__VOID,
368                   G_TYPE_NONE, 0);
369
370   /**
371    * GtkButton::clicked:
372    * @button: the object that received the signal
373    *
374    * Emitted when the button has been activated (pressed and released).
375    */ 
376   button_signals[CLICKED] =
377     g_signal_new (I_("clicked"),
378                   G_OBJECT_CLASS_TYPE (gobject_class),
379                   G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
380                   G_STRUCT_OFFSET (GtkButtonClass, clicked),
381                   NULL, NULL,
382                   _gtk_marshal_VOID__VOID,
383                   G_TYPE_NONE, 0);
384
385   /**
386    * GtkButton::enter:
387    * @button: the object that received the signal
388    *
389    * Emitted when the pointer enters the button.
390    *
391    * Deprecated: 2.8: Use the #GtkWidget::enter-notify-event signal.
392    */ 
393   button_signals[ENTER] =
394     g_signal_new (I_("enter"),
395                   G_OBJECT_CLASS_TYPE (gobject_class),
396                   G_SIGNAL_RUN_FIRST,
397                   G_STRUCT_OFFSET (GtkButtonClass, enter),
398                   NULL, NULL,
399                   _gtk_marshal_VOID__VOID,
400                   G_TYPE_NONE, 0);
401
402   /**
403    * GtkButton::leave:
404    * @button: the object that received the signal
405    *
406    * Emitted when the pointer leaves the button.
407    *
408    * Deprecated: 2.8: Use the #GtkWidget::leave-notify-event signal.
409    */ 
410   button_signals[LEAVE] =
411     g_signal_new (I_("leave"),
412                   G_OBJECT_CLASS_TYPE (gobject_class),
413                   G_SIGNAL_RUN_FIRST,
414                   G_STRUCT_OFFSET (GtkButtonClass, leave),
415                   NULL, NULL,
416                   _gtk_marshal_VOID__VOID,
417                   G_TYPE_NONE, 0);
418
419   /**
420    * GtkButton::activate:
421    * @widget: the object which received the signal.
422    *
423    * The ::activate signal on GtkButton is an action signal and
424    * emitting it causes the button to animate press then release. 
425    * Applications should never connect to this signal, but use the
426    * #GtkButton::clicked signal.
427    */
428   button_signals[ACTIVATE] =
429     g_signal_new (I_("activate"),
430                   G_OBJECT_CLASS_TYPE (gobject_class),
431                   G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
432                   G_STRUCT_OFFSET (GtkButtonClass, activate),
433                   NULL, NULL,
434                   _gtk_marshal_VOID__VOID,
435                   G_TYPE_NONE, 0);
436   widget_class->activate_signal = button_signals[ACTIVATE];
437
438   /**
439    * GtkButton:default-border:
440    *
441    * The "default-border" style property defines the extra space to add
442    * around a button that can become the default widget of its window.
443    * For more information about default widgets, see gtk_widget_grab_default().
444    */
445
446   gtk_widget_class_install_style_property (widget_class,
447                                            g_param_spec_boxed ("default-border",
448                                                                P_("Default Spacing"),
449                                                                P_("Extra space to add for GTK_CAN_DEFAULT buttons"),
450                                                                GTK_TYPE_BORDER,
451                                                                GTK_PARAM_READABLE));
452
453   /**
454    * GtkButton:default-outside-border:
455    *
456    * The "default-outside-border" style property defines the extra outside
457    * space to add around a button that can become the default widget of its
458    * window. Extra outside space is always drawn outside the button border.
459    * For more information about default widgets, see gtk_widget_grab_default().
460    */
461   gtk_widget_class_install_style_property (widget_class,
462                                            g_param_spec_boxed ("default-outside-border",
463                                                                P_("Default Outside Spacing"),
464                                                                P_("Extra space to add for GTK_CAN_DEFAULT buttons that is always drawn outside the border"),
465                                                                GTK_TYPE_BORDER,
466                                                                GTK_PARAM_READABLE));
467   gtk_widget_class_install_style_property (widget_class,
468                                            g_param_spec_int ("child-displacement-x",
469                                                              P_("Child X Displacement"),
470                                                              P_("How far in the x direction to move the child when the button is depressed"),
471                                                              G_MININT,
472                                                              G_MAXINT,
473                                                              0,
474                                                              GTK_PARAM_READABLE));
475   gtk_widget_class_install_style_property (widget_class,
476                                            g_param_spec_int ("child-displacement-y",
477                                                              P_("Child Y Displacement"),
478                                                              P_("How far in the y direction to move the child when the button is depressed"),
479                                                              G_MININT,
480                                                              G_MAXINT,
481                                                              0,
482                                                              GTK_PARAM_READABLE));
483
484   /**
485    * GtkButton:displace-focus:
486    *
487    * Whether the child_displacement_x/child_displacement_y properties 
488    * should also affect the focus rectangle.
489    *
490    * Since: 2.6
491    */
492   gtk_widget_class_install_style_property (widget_class,
493                                            g_param_spec_boolean ("displace-focus",
494                                                                  P_("Displace focus"),
495                                                                  P_("Whether the child_displacement_x/_y properties should also affect the focus rectangle"),
496                                                                  FALSE,
497                                                                  GTK_PARAM_READABLE));
498
499   /**
500    * GtkButton:inner-border:
501    *
502    * Sets the border between the button edges and child.
503    *
504    * Since: 2.10
505    */
506   gtk_widget_class_install_style_property (widget_class,
507                                            g_param_spec_boxed ("inner-border",
508                                                                P_("Inner Border"),
509                                                                P_("Border between button edges and child."),
510                                                                GTK_TYPE_BORDER,
511                                                                GTK_PARAM_READABLE));
512
513   /**
514    * GtkButton::image-spacing:
515    *
516    * Spacing in pixels between the image and label.
517    *
518    * Since: 2.10
519    */
520   gtk_widget_class_install_style_property (widget_class,
521                                            g_param_spec_int ("image-spacing",
522                                                              P_("Image spacing"),
523                                                              P_("Spacing in pixels between the image and label"),
524                                                              0,
525                                                              G_MAXINT,
526                                                              2,
527                                                              GTK_PARAM_READABLE));
528
529   g_type_class_add_private (gobject_class, sizeof (GtkButtonPrivate));
530 }
531
532 static void
533 gtk_button_init (GtkButton *button)
534 {
535   GtkButtonPrivate *priv;
536   GtkStyleContext *context;
537
538   button->priv = G_TYPE_INSTANCE_GET_PRIVATE (button,
539                                               GTK_TYPE_BUTTON,
540                                               GtkButtonPrivate);
541   priv = button->priv;
542
543   gtk_widget_set_can_focus (GTK_WIDGET (button), TRUE);
544   gtk_widget_set_receives_default (GTK_WIDGET (button), TRUE);
545   gtk_widget_set_has_window (GTK_WIDGET (button), FALSE);
546
547   priv->label_text = NULL;
548
549   priv->constructed = FALSE;
550   priv->in_button = FALSE;
551   priv->button_down = FALSE;
552   priv->relief = GTK_RELIEF_NORMAL;
553   priv->use_stock = FALSE;
554   priv->use_underline = FALSE;
555   priv->depressed = FALSE;
556   priv->depress_on_activate = TRUE;
557   priv->focus_on_click = TRUE;
558
559   priv->xalign = 0.5;
560   priv->yalign = 0.5;
561   priv->align_set = 0;
562   priv->image_is_stock = TRUE;
563   priv->image_position = GTK_POS_LEFT;
564   priv->use_action_appearance = TRUE;
565
566   context = gtk_widget_get_style_context (GTK_WIDGET (button));
567   gtk_style_context_add_class (context, GTK_STYLE_CLASS_BUTTON);
568 }
569
570 static void
571 gtk_button_destroy (GtkWidget *widget)
572 {
573   GtkButton *button = GTK_BUTTON (widget);
574   GtkButtonPrivate *priv = button->priv;
575
576   if (priv->label_text)
577     {
578       g_free (priv->label_text);
579       priv->label_text = NULL;
580     }
581
582   GTK_WIDGET_CLASS (gtk_button_parent_class)->destroy (widget);
583 }
584
585 static GObject*
586 gtk_button_constructor (GType                  type,
587                         guint                  n_construct_properties,
588                         GObjectConstructParam *construct_params)
589 {
590   GObject *object;
591   GtkButton *button;
592   GtkButtonPrivate *priv;
593
594   object = G_OBJECT_CLASS (gtk_button_parent_class)->constructor (type,
595                                                                   n_construct_properties,
596                                                                   construct_params);
597
598   button = GTK_BUTTON (object);
599   priv = button->priv;
600
601   priv->constructed = TRUE;
602
603   if (priv->label_text != NULL)
604     gtk_button_construct_child (button);
605   
606   return object;
607 }
608
609
610 static GType
611 gtk_button_child_type  (GtkContainer     *container)
612 {
613   if (!gtk_bin_get_child (GTK_BIN (container)))
614     return GTK_TYPE_WIDGET;
615   else
616     return G_TYPE_NONE;
617 }
618
619 static void
620 maybe_set_alignment (GtkButton *button,
621                      GtkWidget *widget)
622 {
623   GtkButtonPrivate *priv = button->priv;
624
625   if (GTK_IS_MISC (widget))
626     {
627       GtkMisc *misc = GTK_MISC (widget);
628       
629       if (priv->align_set)
630         gtk_misc_set_alignment (misc, priv->xalign, priv->yalign);
631     }
632   else if (GTK_IS_ALIGNMENT (widget))
633     {
634       GtkAlignment *alignment = GTK_ALIGNMENT (widget);
635       gfloat xscale, yscale;
636
637       g_object_get (alignment,
638                     "xscale", &xscale,
639                     "yscale", &yscale,
640                     NULL);
641
642       if (priv->align_set)
643         gtk_alignment_set (alignment,
644                            priv->xalign, priv->yalign,
645                            xscale, yscale);
646     }
647 }
648
649 static void
650 gtk_button_add (GtkContainer *container,
651                 GtkWidget    *widget)
652 {
653   maybe_set_alignment (GTK_BUTTON (container), widget);
654
655   GTK_CONTAINER_CLASS (gtk_button_parent_class)->add (container, widget);
656 }
657
658 static void 
659 gtk_button_dispose (GObject *object)
660 {
661   GtkButton *button = GTK_BUTTON (object);
662   GtkButtonPrivate *priv = button->priv;
663
664   if (priv->action)
665     {
666       gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (button), NULL);
667       priv->action = NULL;
668     }
669   G_OBJECT_CLASS (gtk_button_parent_class)->dispose (object);
670 }
671
672 static void
673 gtk_button_set_property (GObject         *object,
674                          guint            prop_id,
675                          const GValue    *value,
676                          GParamSpec      *pspec)
677 {
678   GtkButton *button = GTK_BUTTON (object);
679   GtkButtonPrivate *priv = button->priv;
680
681   switch (prop_id)
682     {
683     case PROP_LABEL:
684       gtk_button_set_label (button, g_value_get_string (value));
685       break;
686     case PROP_IMAGE:
687       gtk_button_set_image (button, (GtkWidget *) g_value_get_object (value));
688       break;
689     case PROP_RELIEF:
690       gtk_button_set_relief (button, g_value_get_enum (value));
691       break;
692     case PROP_USE_UNDERLINE:
693       gtk_button_set_use_underline (button, g_value_get_boolean (value));
694       break;
695     case PROP_USE_STOCK:
696       gtk_button_set_use_stock (button, g_value_get_boolean (value));
697       break;
698     case PROP_FOCUS_ON_CLICK:
699       gtk_button_set_focus_on_click (button, g_value_get_boolean (value));
700       break;
701     case PROP_XALIGN:
702       gtk_button_set_alignment (button, g_value_get_float (value), priv->yalign);
703       break;
704     case PROP_YALIGN:
705       gtk_button_set_alignment (button, priv->xalign, g_value_get_float (value));
706       break;
707     case PROP_IMAGE_POSITION:
708       gtk_button_set_image_position (button, g_value_get_enum (value));
709       break;
710     case PROP_ACTIVATABLE_RELATED_ACTION:
711       gtk_button_set_related_action (button, g_value_get_object (value));
712       break;
713     case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
714       gtk_button_set_use_action_appearance (button, g_value_get_boolean (value));
715       break;
716     default:
717       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
718       break;
719     }
720 }
721
722 static void
723 gtk_button_get_property (GObject         *object,
724                          guint            prop_id,
725                          GValue          *value,
726                          GParamSpec      *pspec)
727 {
728   GtkButton *button = GTK_BUTTON (object);
729   GtkButtonPrivate *priv = button->priv;
730
731   switch (prop_id)
732     {
733     case PROP_LABEL:
734       g_value_set_string (value, priv->label_text);
735       break;
736     case PROP_IMAGE:
737       g_value_set_object (value, (GObject *)priv->image);
738       break;
739     case PROP_RELIEF:
740       g_value_set_enum (value, priv->relief);
741       break;
742     case PROP_USE_UNDERLINE:
743       g_value_set_boolean (value, priv->use_underline);
744       break;
745     case PROP_USE_STOCK:
746       g_value_set_boolean (value, priv->use_stock);
747       break;
748     case PROP_FOCUS_ON_CLICK:
749       g_value_set_boolean (value, priv->focus_on_click);
750       break;
751     case PROP_XALIGN:
752       g_value_set_float (value, priv->xalign);
753       break;
754     case PROP_YALIGN:
755       g_value_set_float (value, priv->yalign);
756       break;
757     case PROP_IMAGE_POSITION:
758       g_value_set_enum (value, priv->image_position);
759       break;
760     case PROP_ACTIVATABLE_RELATED_ACTION:
761       g_value_set_object (value, priv->action);
762       break;
763     case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
764       g_value_set_boolean (value, priv->use_action_appearance);
765       break;
766     default:
767       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
768       break;
769     }
770 }
771
772 static void 
773 gtk_button_activatable_interface_init (GtkActivatableIface  *iface)
774 {
775   iface->update = gtk_button_update;
776   iface->sync_action_properties = gtk_button_sync_action_properties;
777 }
778
779 static void
780 activatable_update_stock_id (GtkButton *button,
781                              GtkAction *action)
782 {
783   if (!gtk_button_get_use_stock (button))
784     return;
785
786   gtk_button_set_label (button, gtk_action_get_stock_id (action));
787 }
788
789 static void
790 activatable_update_short_label (GtkButton *button,
791                                 GtkAction *action)
792 {
793   GtkWidget *child;
794   GtkWidget *image;
795
796   if (gtk_button_get_use_stock (button))
797     return;
798
799   image = gtk_button_get_image (button);
800
801   /* Dont touch custom child... */
802   child = gtk_bin_get_child (GTK_BIN (button));
803   if (GTK_IS_IMAGE (image) ||
804       child == NULL ||
805       GTK_IS_LABEL (child))
806     {
807       gtk_button_set_label (button, gtk_action_get_short_label (action));
808       gtk_button_set_use_underline (button, TRUE);
809     }
810 }
811
812 static void
813 activatable_update_icon_name (GtkButton *button,
814                               GtkAction *action)
815 {
816   GtkWidget *image;
817               
818   if (gtk_button_get_use_stock (button))
819     return;
820
821   image = gtk_button_get_image (button);
822
823   if (GTK_IS_IMAGE (image) &&
824       (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
825        gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME))
826     gtk_image_set_from_icon_name (GTK_IMAGE (image),
827                                   gtk_action_get_icon_name (action), GTK_ICON_SIZE_MENU);
828 }
829
830 static void
831 activatable_update_gicon (GtkButton *button,
832                           GtkAction *action)
833 {
834   GtkWidget *image = gtk_button_get_image (button);
835   GIcon *icon = gtk_action_get_gicon (action);
836   
837   if (GTK_IS_IMAGE (image) &&
838       (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
839        gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_GICON))
840     gtk_image_set_from_gicon (GTK_IMAGE (image), icon, GTK_ICON_SIZE_BUTTON);
841 }
842
843 static void 
844 gtk_button_update (GtkActivatable *activatable,
845                    GtkAction      *action,
846                    const gchar    *property_name)
847 {
848   GtkButton *button = GTK_BUTTON (activatable);
849   GtkButtonPrivate *priv = button->priv;
850
851   if (strcmp (property_name, "visible") == 0)
852     {
853       if (gtk_action_is_visible (action))
854         gtk_widget_show (GTK_WIDGET (activatable));
855       else
856         gtk_widget_hide (GTK_WIDGET (activatable));
857     }
858   else if (strcmp (property_name, "sensitive") == 0)
859     gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
860
861   if (!priv->use_action_appearance)
862     return;
863
864   if (strcmp (property_name, "stock-id") == 0)
865     activatable_update_stock_id (GTK_BUTTON (activatable), action);
866   else if (strcmp (property_name, "gicon") == 0)
867     activatable_update_gicon (GTK_BUTTON (activatable), action);
868   else if (strcmp (property_name, "short-label") == 0)
869     activatable_update_short_label (GTK_BUTTON (activatable), action);
870   else if (strcmp (property_name, "icon-name") == 0)
871     activatable_update_icon_name (GTK_BUTTON (activatable), action);
872 }
873
874 static void
875 gtk_button_sync_action_properties (GtkActivatable *activatable,
876                                    GtkAction      *action)
877 {
878   GtkButton *button = GTK_BUTTON (activatable);
879   GtkButtonPrivate *priv = button->priv;
880
881   if (!action)
882     return;
883
884   if (gtk_action_is_visible (action))
885     gtk_widget_show (GTK_WIDGET (activatable));
886   else
887     gtk_widget_hide (GTK_WIDGET (activatable));
888   
889   gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
890   
891   if (priv->use_action_appearance)
892     {
893       activatable_update_stock_id (GTK_BUTTON (activatable), action);
894       activatable_update_short_label (GTK_BUTTON (activatable), action);
895       activatable_update_gicon (GTK_BUTTON (activatable), action);
896       activatable_update_icon_name (GTK_BUTTON (activatable), action);
897     }
898 }
899
900 static void
901 gtk_button_set_related_action (GtkButton *button,
902                                GtkAction *action)
903 {
904   GtkButtonPrivate *priv = button->priv;
905
906   if (priv->action == action)
907     return;
908
909   /* This should be a default handler, but for compatibility reasons
910    * we need to support derived classes that don't chain up their
911    * clicked handler.
912    */
913   g_signal_handlers_disconnect_by_func (button, gtk_real_button_clicked, NULL);
914   if (action)
915     g_signal_connect_after (button, "clicked",
916                             G_CALLBACK (gtk_real_button_clicked), NULL);
917
918   gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (button), action);
919
920   priv->action = action;
921 }
922
923 static void
924 gtk_button_set_use_action_appearance (GtkButton *button,
925                                       gboolean   use_appearance)
926 {
927   GtkButtonPrivate *priv = button->priv;
928
929   if (priv->use_action_appearance != use_appearance)
930     {
931       priv->use_action_appearance = use_appearance;
932
933       gtk_activatable_sync_action_properties (GTK_ACTIVATABLE (button), priv->action);
934     }
935 }
936
937 /**
938  * gtk_button_new:
939  *
940  * Creates a new #GtkButton widget. To add a child widget to the button,
941  * use gtk_container_add().
942  *
943  * Returns: The newly created #GtkButton widget.
944  */
945 GtkWidget*
946 gtk_button_new (void)
947 {
948   return g_object_new (GTK_TYPE_BUTTON, NULL);
949 }
950
951 static gboolean
952 show_image (GtkButton *button)
953 {
954   GtkButtonPrivate *priv = button->priv;
955   gboolean show;
956
957   if (priv->label_text)
958     {
959       GtkSettings *settings;
960
961       settings = gtk_widget_get_settings (GTK_WIDGET (button));        
962       g_object_get (settings, "gtk-button-images", &show, NULL);
963     }
964   else
965     show = TRUE;
966
967   return show;
968 }
969
970 static void
971 gtk_button_construct_child (GtkButton *button)
972 {
973   GtkButtonPrivate *priv = button->priv;
974   GtkStyleContext *context;
975   GtkStockItem item;
976   GtkWidget *child;
977   GtkWidget *label;
978   GtkWidget *box;
979   GtkWidget *align;
980   GtkWidget *image = NULL;
981   gchar *label_text = NULL;
982   gint image_spacing;
983
984   if (!priv->constructed)
985     return;
986
987   if (!priv->label_text && !priv->image)
988     return;
989
990   context = gtk_widget_get_style_context (GTK_WIDGET (button));
991
992   gtk_style_context_get_style (context,
993                                "image-spacing", &image_spacing,
994                                NULL);
995
996   if (priv->image && !priv->image_is_stock)
997     {
998       GtkWidget *parent;
999
1000       image = g_object_ref (priv->image);
1001
1002       parent = gtk_widget_get_parent (image);
1003       if (parent)
1004         gtk_container_remove (GTK_CONTAINER (parent), image);
1005     }
1006
1007   priv->image = NULL;
1008
1009   child = gtk_bin_get_child (GTK_BIN (button));
1010   if (child)
1011     gtk_container_remove (GTK_CONTAINER (button), child);
1012
1013   if (priv->use_stock &&
1014       priv->label_text &&
1015       gtk_stock_lookup (priv->label_text, &item))
1016     {
1017       if (!image)
1018         image = g_object_ref (gtk_image_new_from_stock (priv->label_text, GTK_ICON_SIZE_BUTTON));
1019
1020       label_text = item.label;
1021     }
1022   else
1023     label_text = priv->label_text;
1024
1025   if (image)
1026     {
1027       priv->image = image;
1028       g_object_set (priv->image,
1029                     "visible", show_image (button),
1030                     "no-show-all", TRUE,
1031                     NULL);
1032
1033       if (priv->image_position == GTK_POS_LEFT ||
1034           priv->image_position == GTK_POS_RIGHT)
1035         box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, image_spacing);
1036       else
1037         box = gtk_box_new (GTK_ORIENTATION_VERTICAL, image_spacing);
1038
1039       if (priv->align_set)
1040         align = gtk_alignment_new (priv->xalign, priv->yalign, 0.0, 0.0);
1041       else
1042         align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
1043
1044       if (priv->image_position == GTK_POS_LEFT ||
1045           priv->image_position == GTK_POS_TOP)
1046         gtk_box_pack_start (GTK_BOX (box), priv->image, FALSE, FALSE, 0);
1047       else
1048         gtk_box_pack_end (GTK_BOX (box), priv->image, FALSE, FALSE, 0);
1049
1050       if (label_text)
1051         {
1052           if (priv->use_underline || priv->use_stock)
1053             {
1054               label = gtk_label_new_with_mnemonic (label_text);
1055               gtk_label_set_mnemonic_widget (GTK_LABEL (label),
1056                                              GTK_WIDGET (button));
1057             }
1058           else
1059             label = gtk_label_new (label_text);
1060
1061           if (priv->image_position == GTK_POS_RIGHT ||
1062               priv->image_position == GTK_POS_BOTTOM)
1063             gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
1064           else
1065             gtk_box_pack_end (GTK_BOX (box), label, FALSE, FALSE, 0);
1066         }
1067
1068       gtk_container_add (GTK_CONTAINER (button), align);
1069       gtk_container_add (GTK_CONTAINER (align), box);
1070       gtk_widget_show_all (align);
1071
1072       g_object_unref (image);
1073
1074       return;
1075     }
1076
1077   if (priv->use_underline || priv->use_stock)
1078     {
1079       label = gtk_label_new_with_mnemonic (priv->label_text);
1080       gtk_label_set_mnemonic_widget (GTK_LABEL (label), GTK_WIDGET (button));
1081     }
1082   else
1083     label = gtk_label_new (priv->label_text);
1084
1085   if (priv->align_set)
1086     gtk_misc_set_alignment (GTK_MISC (label), priv->xalign, priv->yalign);
1087
1088   gtk_widget_show (label);
1089   gtk_container_add (GTK_CONTAINER (button), label);
1090 }
1091
1092
1093 /**
1094  * gtk_button_new_with_label:
1095  * @label: The text you want the #GtkLabel to hold.
1096  *
1097  * Creates a #GtkButton widget with a #GtkLabel child containing the given
1098  * text.
1099  *
1100  * Returns: The newly created #GtkButton widget.
1101  */
1102 GtkWidget*
1103 gtk_button_new_with_label (const gchar *label)
1104 {
1105   return g_object_new (GTK_TYPE_BUTTON, "label", label, NULL);
1106 }
1107
1108 /**
1109  * gtk_button_new_from_stock:
1110  * @stock_id: the name of the stock item 
1111  *
1112  * Creates a new #GtkButton containing the image and text from a stock item.
1113  * Some stock ids have preprocessor macros like #GTK_STOCK_OK and
1114  * #GTK_STOCK_APPLY.
1115  *
1116  * If @stock_id is unknown, then it will be treated as a mnemonic
1117  * label (as for gtk_button_new_with_mnemonic()).
1118  *
1119  * Returns: a new #GtkButton
1120  **/
1121 GtkWidget*
1122 gtk_button_new_from_stock (const gchar *stock_id)
1123 {
1124   return g_object_new (GTK_TYPE_BUTTON,
1125                        "label", stock_id,
1126                        "use-stock", TRUE,
1127                        "use-underline", TRUE,
1128                        NULL);
1129 }
1130
1131 /**
1132  * gtk_button_new_with_mnemonic:
1133  * @label: The text of the button, with an underscore in front of the
1134  *         mnemonic character
1135  * @returns: a new #GtkButton
1136  *
1137  * Creates a new #GtkButton containing a label.
1138  * If characters in @label are preceded by an underscore, they are underlined.
1139  * If you need a literal underscore character in a label, use '__' (two 
1140  * underscores). The first underlined character represents a keyboard 
1141  * accelerator called a mnemonic.
1142  * Pressing Alt and that key activates the button.
1143  **/
1144 GtkWidget*
1145 gtk_button_new_with_mnemonic (const gchar *label)
1146 {
1147   return g_object_new (GTK_TYPE_BUTTON, "label", label, "use-underline", TRUE,  NULL);
1148 }
1149
1150 /**
1151  * gtk_button_pressed:
1152  * @button: The #GtkButton you want to send the signal to.
1153  *
1154  * Emits a #GtkButton::pressed signal to the given #GtkButton.
1155  *
1156  * Deprecated: 2.20: Use the #GtkWidget::button-press-event signal.
1157  */
1158 void
1159 gtk_button_pressed (GtkButton *button)
1160 {
1161   g_return_if_fail (GTK_IS_BUTTON (button));
1162
1163   g_signal_emit (button, button_signals[PRESSED], 0);
1164 }
1165
1166 /**
1167  * gtk_button_released:
1168  * @button: The #GtkButton you want to send the signal to.
1169  *
1170  * Emits a #GtkButton::released signal to the given #GtkButton.
1171  *
1172  * Deprecated: 2.20: Use the #GtkWidget::button-release-event signal.
1173  */
1174 void
1175 gtk_button_released (GtkButton *button)
1176 {
1177   g_return_if_fail (GTK_IS_BUTTON (button));
1178
1179   g_signal_emit (button, button_signals[RELEASED], 0);
1180 }
1181
1182 /**
1183  * gtk_button_clicked:
1184  * @button: The #GtkButton you want to send the signal to.
1185  *
1186  * Emits a #GtkButton::clicked signal to the given #GtkButton.
1187  */
1188 void
1189 gtk_button_clicked (GtkButton *button)
1190 {
1191   g_return_if_fail (GTK_IS_BUTTON (button));
1192
1193   g_signal_emit (button, button_signals[CLICKED], 0);
1194 }
1195
1196 /**
1197  * gtk_button_enter:
1198  * @button: The #GtkButton you want to send the signal to.
1199  *
1200  * Emits a #GtkButton::enter signal to the given #GtkButton.
1201  *
1202  * Deprecated: 2.20: Use the #GtkWidget::enter-notify-event signal.
1203  */
1204 void
1205 gtk_button_enter (GtkButton *button)
1206 {
1207   g_return_if_fail (GTK_IS_BUTTON (button));
1208
1209   g_signal_emit (button, button_signals[ENTER], 0);
1210 }
1211
1212 /**
1213  * gtk_button_leave:
1214  * @button: The #GtkButton you want to send the signal to.
1215  *
1216  * Emits a #GtkButton::leave signal to the given #GtkButton.
1217  *
1218  * Deprecated: 2.20: Use the #GtkWidget::leave-notify-event signal.
1219  */
1220 void
1221 gtk_button_leave (GtkButton *button)
1222 {
1223   g_return_if_fail (GTK_IS_BUTTON (button));
1224
1225   g_signal_emit (button, button_signals[LEAVE], 0);
1226 }
1227
1228 /**
1229  * gtk_button_set_relief:
1230  * @button: The #GtkButton you want to set relief styles of.
1231  * @newstyle: The GtkReliefStyle as described above.
1232  *
1233  * Sets the relief style of the edges of the given #GtkButton widget.
1234  * Three styles exist, GTK_RELIEF_NORMAL, GTK_RELIEF_HALF, GTK_RELIEF_NONE.
1235  * The default style is, as one can guess, GTK_RELIEF_NORMAL.
1236  *
1237  * <!-- FIXME: put pictures of each style -->
1238  */
1239 void
1240 gtk_button_set_relief (GtkButton *button,
1241                        GtkReliefStyle newrelief)
1242 {
1243   GtkButtonPrivate *priv;
1244
1245   g_return_if_fail (GTK_IS_BUTTON (button));
1246
1247   priv = button->priv;
1248
1249   if (newrelief != priv->relief)
1250     {
1251        priv->relief = newrelief;
1252        g_object_notify (G_OBJECT (button), "relief");
1253        gtk_widget_queue_draw (GTK_WIDGET (button));
1254     }
1255 }
1256
1257 /**
1258  * gtk_button_get_relief:
1259  * @button: The #GtkButton you want the #GtkReliefStyle from.
1260  *
1261  * Returns the current relief style of the given #GtkButton.
1262  *
1263  * Returns: The current #GtkReliefStyle
1264  */
1265 GtkReliefStyle
1266 gtk_button_get_relief (GtkButton *button)
1267 {
1268   g_return_val_if_fail (GTK_IS_BUTTON (button), GTK_RELIEF_NORMAL);
1269
1270   return button->priv->relief;
1271 }
1272
1273 static void
1274 gtk_button_realize (GtkWidget *widget)
1275 {
1276   GtkButton *button = GTK_BUTTON (widget);
1277   GtkButtonPrivate *priv = button->priv;
1278   GtkAllocation allocation;
1279   GdkWindow *window;
1280   GdkWindowAttr attributes;
1281   gint attributes_mask;
1282
1283   gtk_widget_get_allocation (widget, &allocation);
1284
1285   gtk_widget_set_realized (widget, TRUE);
1286
1287   attributes.window_type = GDK_WINDOW_CHILD;
1288   attributes.x = allocation.x;
1289   attributes.y = allocation.y;
1290   attributes.width = allocation.width;
1291   attributes.height = allocation.height;
1292   attributes.wclass = GDK_INPUT_ONLY;
1293   attributes.event_mask = gtk_widget_get_events (widget);
1294   attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
1295                             GDK_BUTTON_RELEASE_MASK |
1296                             GDK_ENTER_NOTIFY_MASK |
1297                             GDK_LEAVE_NOTIFY_MASK);
1298
1299   attributes_mask = GDK_WA_X | GDK_WA_Y;
1300
1301   window = gtk_widget_get_parent_window (widget);
1302   gtk_widget_set_window (widget, window);
1303   g_object_ref (window);
1304
1305   priv->event_window = gdk_window_new (window,
1306                                        &attributes, attributes_mask);
1307   gdk_window_set_user_data (priv->event_window, button);
1308 }
1309
1310 static void
1311 gtk_button_unrealize (GtkWidget *widget)
1312 {
1313   GtkButton *button = GTK_BUTTON (widget);
1314   GtkButtonPrivate *priv = button->priv;
1315
1316   if (priv->activate_timeout)
1317     gtk_button_finish_activate (button, FALSE);
1318
1319   if (priv->event_window)
1320     {
1321       gdk_window_set_user_data (priv->event_window, NULL);
1322       gdk_window_destroy (priv->event_window);
1323       priv->event_window = NULL;
1324     }
1325
1326   GTK_WIDGET_CLASS (gtk_button_parent_class)->unrealize (widget);
1327 }
1328
1329 static void
1330 gtk_button_map (GtkWidget *widget)
1331 {
1332   GtkButton *button = GTK_BUTTON (widget);
1333   GtkButtonPrivate *priv = button->priv;
1334
1335   GTK_WIDGET_CLASS (gtk_button_parent_class)->map (widget);
1336
1337   if (priv->event_window)
1338     gdk_window_show (priv->event_window);
1339 }
1340
1341 static void
1342 gtk_button_unmap (GtkWidget *widget)
1343 {
1344   GtkButton *button = GTK_BUTTON (widget);
1345   GtkButtonPrivate *priv = button->priv;
1346
1347   if (priv->event_window)
1348     gdk_window_hide (priv->event_window);
1349
1350   GTK_WIDGET_CLASS (gtk_button_parent_class)->unmap (widget);
1351 }
1352
1353 static void
1354 gtk_button_update_image_spacing (GtkButton       *button,
1355                                  GtkStyleContext *context)
1356 {
1357   GtkButtonPrivate *priv = button->priv;
1358   GtkWidget *child; 
1359   gint spacing;
1360
1361   /* Keep in sync with gtk_button_construct_child,
1362    * we only want to update the spacing if the box 
1363    * was constructed there.
1364    */
1365   if (!priv->constructed || !priv->image)
1366     return;
1367
1368   child = gtk_bin_get_child (GTK_BIN (button));
1369   if (GTK_IS_ALIGNMENT (child))
1370     {
1371       child = gtk_bin_get_child (GTK_BIN (child));
1372       if (GTK_IS_BOX (child))
1373         {
1374           gtk_style_context_get_style (context,
1375                                        "image-spacing", &spacing,
1376                                        NULL);
1377
1378           gtk_box_set_spacing (GTK_BOX (child), spacing);
1379         }
1380     }
1381 }
1382
1383 static void
1384 gtk_button_style_updated (GtkWidget *widget)
1385 {
1386   GtkStyleContext *context;
1387
1388   context = gtk_widget_get_style_context (widget);
1389
1390   gtk_button_update_image_spacing (GTK_BUTTON (widget), context);
1391 }
1392
1393 static void
1394 gtk_button_get_props (GtkButton *button,
1395                       GtkBorder *default_border,
1396                       GtkBorder *default_outside_border,
1397                       GtkBorder *inner_border,
1398                       gboolean  *interior_focus)
1399 {
1400   GtkStyleContext *context;
1401   GtkBorder *tmp_border;
1402
1403   context = gtk_widget_get_style_context (GTK_WIDGET (button));
1404
1405   if (default_border)
1406     {
1407       gtk_style_context_get_style (context,
1408                                    "default-border", &tmp_border,
1409                                    NULL);
1410
1411       if (tmp_border)
1412         {
1413           *default_border = *tmp_border;
1414           gtk_border_free (tmp_border);
1415         }
1416       else
1417         *default_border = default_default_border;
1418     }
1419
1420   if (default_outside_border)
1421     {
1422       gtk_style_context_get_style (context,
1423                                    "default-outside-border", &tmp_border,
1424                                    NULL);
1425
1426       if (tmp_border)
1427         {
1428           *default_outside_border = *tmp_border;
1429           gtk_border_free (tmp_border);
1430         }
1431       else
1432         *default_outside_border = default_default_outside_border;
1433     }
1434
1435   if (inner_border)
1436     {
1437       gtk_style_context_get_style (context,
1438                                    "inner-border", &tmp_border,
1439                                    NULL);
1440
1441       if (tmp_border)
1442         {
1443           *inner_border = *tmp_border;
1444           gtk_border_free (tmp_border);
1445         }
1446       else
1447         *inner_border = default_inner_border;
1448     }
1449
1450   if (interior_focus)
1451     {
1452       gtk_style_context_get_style (context,
1453                                    "interior-focus", interior_focus,
1454                                    NULL);
1455     }
1456 }
1457
1458 static void
1459 gtk_button_size_allocate (GtkWidget     *widget,
1460                           GtkAllocation *allocation)
1461 {
1462   GtkButton *button = GTK_BUTTON (widget);
1463   GtkButtonPrivate *priv = button->priv;
1464   GtkAllocation child_allocation;
1465   GtkStyleContext *context;
1466   GtkStateFlags state;
1467   GtkWidget *child;
1468   GtkBorder default_border;
1469   GtkBorder inner_border;
1470   GtkBorder *border;
1471   gint focus_width;
1472   gint focus_pad;
1473
1474   context = gtk_widget_get_style_context (widget);
1475   state = gtk_widget_get_state_flags (widget);
1476
1477   gtk_button_get_props (button, &default_border, NULL, &inner_border, NULL);
1478   gtk_style_context_get_style (context,
1479                               "focus-line-width", &focus_width,
1480                               "focus-padding", &focus_pad,
1481                               NULL);
1482
1483   gtk_style_context_get (context, state,
1484                          "border-width", &border,
1485                          NULL);
1486
1487   gtk_widget_set_allocation (widget, allocation);
1488
1489   if (gtk_widget_get_realized (widget))
1490     gdk_window_move_resize (priv->event_window,
1491                             allocation->x,
1492                             allocation->y,
1493                             allocation->width,
1494                             allocation->height);
1495
1496   child = gtk_bin_get_child (GTK_BIN (button));
1497   if (child && gtk_widget_get_visible (child))
1498     {
1499       child_allocation.x = allocation->x + inner_border.left + border->left;
1500       child_allocation.y = allocation->y + inner_border.top + border->top;
1501
1502       child_allocation.width =
1503         allocation->width -
1504         (border->left + border->right) -
1505         inner_border.left -
1506         inner_border.right;
1507
1508       child_allocation.height = 
1509         allocation->height -
1510         (border->top + border->bottom) -
1511         inner_border.top -
1512         inner_border.bottom;
1513
1514       if (gtk_widget_get_can_default (GTK_WIDGET (button)))
1515         {
1516           child_allocation.x += default_border.left;
1517           child_allocation.y += default_border.top;
1518           child_allocation.width =  child_allocation.width - default_border.left - default_border.right;
1519           child_allocation.height = child_allocation.height - default_border.top - default_border.bottom;
1520         }
1521
1522       if (gtk_widget_get_can_focus (GTK_WIDGET (button)))
1523         {
1524           child_allocation.x += focus_width + focus_pad;
1525           child_allocation.y += focus_width + focus_pad;
1526           child_allocation.width =  child_allocation.width - (focus_width + focus_pad) * 2;
1527           child_allocation.height = child_allocation.height - (focus_width + focus_pad) * 2;
1528         }
1529
1530       if (priv->depressed)
1531         {
1532           gint child_displacement_x;
1533           gint child_displacement_y;
1534
1535           gtk_style_context_get_style (context,
1536                                        "child-displacement-x", &child_displacement_x,
1537                                        "child-displacement-y", &child_displacement_y,
1538                                        NULL);
1539           child_allocation.x += child_displacement_x;
1540           child_allocation.y += child_displacement_y;
1541         }
1542
1543       child_allocation.width  = MAX (1, child_allocation.width);
1544       child_allocation.height = MAX (1, child_allocation.height);
1545
1546       gtk_widget_size_allocate (child, &child_allocation);
1547     }
1548
1549   gtk_border_free (border);
1550 }
1551
1552 void
1553 _gtk_button_paint (GtkButton          *button,
1554                    cairo_t            *cr,
1555                    int                 width,
1556                    int                 height,
1557                    GtkStateType        state_type,
1558                    GtkShadowType       shadow_type,
1559                    const gchar        *main_detail,
1560                    const gchar        *default_detail)
1561 {
1562   GtkButtonPrivate *priv = button->priv;
1563   GtkWidget *widget;
1564   gint x, y;
1565   GtkBorder default_border;
1566   GtkBorder default_outside_border;
1567   gboolean interior_focus;
1568   gint focus_width;
1569   gint focus_pad;
1570   GtkAllocation allocation;
1571   GdkWindow *window;
1572   GtkStyleContext *context;
1573   GtkStateFlags state;
1574
1575   widget = GTK_WIDGET (button);
1576
1577   context = gtk_widget_get_style_context (widget);
1578   state = gtk_widget_get_state_flags (widget);
1579
1580   gtk_button_get_props (button, &default_border, &default_outside_border, NULL, &interior_focus);
1581   gtk_style_context_get_style (context,
1582                                "focus-line-width", &focus_width,
1583                                "focus-padding", &focus_pad,
1584                                NULL);
1585
1586   gtk_widget_get_allocation (widget, &allocation);
1587   window = gtk_widget_get_window (widget);
1588
1589   x = 0;
1590   y = 0;
1591
1592   if (gtk_widget_has_default (widget) &&
1593       priv->relief == GTK_RELIEF_NORMAL)
1594     {
1595       x += default_border.left;
1596       y += default_border.top;
1597       width -= default_border.left + default_border.right;
1598       height -= default_border.top + default_border.bottom;
1599
1600       gtk_style_context_add_class (context, GTK_STYLE_CLASS_DEFAULT);
1601     }
1602   else if (gtk_widget_get_can_default (widget))
1603     {
1604       x += default_outside_border.left;
1605       y += default_outside_border.top;
1606       width -= default_outside_border.left + default_outside_border.right;
1607       height -= default_outside_border.top + default_outside_border.bottom;
1608     }
1609    
1610   if (!interior_focus && gtk_widget_has_focus (widget))
1611     {
1612       x += focus_width + focus_pad;
1613       y += focus_width + focus_pad;
1614       width -= 2 * (focus_width + focus_pad);
1615       height -= 2 * (focus_width + focus_pad);
1616     }
1617
1618   state = gtk_widget_get_state_flags (widget);
1619   gtk_style_context_set_state (context, state);
1620
1621   if (priv->relief != GTK_RELIEF_NONE || priv->depressed ||
1622       state & GTK_STATE_FLAG_PRELIGHT)
1623     {
1624       gtk_render_background (context, cr,
1625                              x, y, width, height);
1626       gtk_render_frame (context, cr,
1627                         x, y, width, height);
1628     }
1629
1630   if (gtk_widget_has_focus (widget))
1631     {
1632       gint child_displacement_x;
1633       gint child_displacement_y;
1634       gboolean displace_focus;
1635       GtkBorder *border;
1636
1637       gtk_style_context_get_style (context,
1638                                    "child-displacement-y", &child_displacement_y,
1639                                    "child-displacement-x", &child_displacement_x,
1640                                    "displace-focus", &displace_focus,
1641                                    NULL);
1642
1643       gtk_style_context_get (context, state,
1644                              "border-width", &border,
1645                              NULL);
1646
1647       if (interior_focus)
1648         {
1649           x += border->left + focus_pad;
1650           y += border->top + focus_pad;
1651           width -= (2 * focus_pad) + border->left + border->right;
1652           height -=  (2 * focus_pad) + border->top + border->bottom;
1653         }
1654       else
1655         {
1656           x -= focus_width + focus_pad;
1657           y -= focus_width + focus_pad;
1658           width += 2 * (focus_width + focus_pad);
1659           height += 2 * (focus_width + focus_pad);
1660         }
1661
1662       if (priv->depressed && displace_focus)
1663         {
1664           x += child_displacement_x;
1665           y += child_displacement_y;
1666         }
1667
1668       gtk_render_focus (context, cr,
1669                         x, y, width, height);
1670
1671       gtk_border_free (border);
1672     }
1673 }
1674
1675 static gboolean
1676 gtk_button_draw (GtkWidget *widget,
1677                  cairo_t   *cr)
1678 {
1679   GtkButton *button = GTK_BUTTON (widget);
1680   GtkButtonPrivate *priv = button->priv;
1681
1682   _gtk_button_paint (button, cr, 
1683                      gtk_widget_get_allocated_width (widget),
1684                      gtk_widget_get_allocated_height (widget),
1685                      gtk_widget_get_state (widget),
1686                      priv->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
1687                      "button", "buttondefault");
1688
1689   GTK_WIDGET_CLASS (gtk_button_parent_class)->draw (widget, cr);
1690
1691   return FALSE;
1692 }
1693
1694 static gboolean
1695 gtk_button_button_press (GtkWidget      *widget,
1696                          GdkEventButton *event)
1697 {
1698   GtkButton *button;
1699   GtkButtonPrivate *priv;
1700
1701   if (event->type == GDK_BUTTON_PRESS)
1702     {
1703       button = GTK_BUTTON (widget);
1704       priv = button->priv;
1705
1706       if (priv->focus_on_click && !gtk_widget_has_focus (widget))
1707         gtk_widget_grab_focus (widget);
1708
1709       if (event->button == 1)
1710         gtk_button_pressed (button);
1711     }
1712
1713   return TRUE;
1714 }
1715
1716 static gboolean
1717 gtk_button_button_release (GtkWidget      *widget,
1718                            GdkEventButton *event)
1719 {
1720   GtkButton *button;
1721
1722   if (event->button == 1)
1723     {
1724       button = GTK_BUTTON (widget);
1725       gtk_button_released (button);
1726     }
1727
1728   return TRUE;
1729 }
1730
1731 static gboolean
1732 gtk_button_grab_broken (GtkWidget          *widget,
1733                         GdkEventGrabBroken *event)
1734 {
1735   GtkButton *button = GTK_BUTTON (widget);
1736   GtkButtonPrivate *priv = button->priv;
1737   gboolean save_in;
1738   
1739   /* Simulate a button release without the pointer in the button */
1740   if (priv->button_down)
1741     {
1742       save_in = priv->in_button;
1743       priv->in_button = FALSE;
1744       gtk_button_released (button);
1745       if (save_in != priv->in_button)
1746         {
1747           priv->in_button = save_in;
1748           gtk_button_update_state (button);
1749         }
1750     }
1751
1752   return TRUE;
1753 }
1754
1755 static gboolean
1756 gtk_button_key_release (GtkWidget   *widget,
1757                         GdkEventKey *event)
1758 {
1759   GtkButton *button = GTK_BUTTON (widget);
1760   GtkButtonPrivate *priv = button->priv;
1761
1762   if (priv->activate_timeout)
1763     {
1764       gtk_button_finish_activate (button, TRUE);
1765       return TRUE;
1766     }
1767   else if (GTK_WIDGET_CLASS (gtk_button_parent_class)->key_release_event)
1768     return GTK_WIDGET_CLASS (gtk_button_parent_class)->key_release_event (widget, event);
1769   else
1770     return FALSE;
1771 }
1772
1773 static gboolean
1774 gtk_button_enter_notify (GtkWidget        *widget,
1775                          GdkEventCrossing *event)
1776 {
1777   GtkButton *button = GTK_BUTTON (widget);
1778   GtkButtonPrivate *priv = button->priv;
1779
1780   if ((event->window == button->priv->event_window) &&
1781       (event->detail != GDK_NOTIFY_INFERIOR))
1782     {
1783       priv->in_button = TRUE;
1784       gtk_button_enter (button);
1785     }
1786
1787   return FALSE;
1788 }
1789
1790 static gboolean
1791 gtk_button_leave_notify (GtkWidget        *widget,
1792                          GdkEventCrossing *event)
1793 {
1794   GtkButton *button = GTK_BUTTON (widget);
1795   GtkButtonPrivate *priv = button->priv;
1796
1797   if ((event->window == button->priv->event_window) &&
1798       (event->detail != GDK_NOTIFY_INFERIOR) &&
1799       (gtk_widget_get_sensitive (widget)))
1800     {
1801       priv->in_button = FALSE;
1802       gtk_button_leave (button);
1803     }
1804
1805   return FALSE;
1806 }
1807
1808 static void
1809 gtk_real_button_pressed (GtkButton *button)
1810 {
1811   GtkButtonPrivate *priv = button->priv;
1812
1813   if (priv->activate_timeout)
1814     return;
1815
1816   priv->button_down = TRUE;
1817   gtk_button_update_state (button);
1818 }
1819
1820 static void
1821 gtk_real_button_released (GtkButton *button)
1822 {
1823   GtkButtonPrivate *priv = button->priv;
1824
1825   if (priv->button_down)
1826     {
1827       priv->button_down = FALSE;
1828
1829       if (priv->activate_timeout)
1830         return;
1831
1832       if (priv->in_button)
1833         gtk_button_clicked (button);
1834
1835       gtk_button_update_state (button);
1836     }
1837 }
1838
1839 static void 
1840 gtk_real_button_clicked (GtkButton *button)
1841 {
1842   GtkButtonPrivate *priv = button->priv;
1843
1844   if (priv->action)
1845     gtk_action_activate (priv->action);
1846 }
1847
1848 static gboolean
1849 button_activate_timeout (gpointer data)
1850 {
1851   gtk_button_finish_activate (data, TRUE);
1852
1853   return FALSE;
1854 }
1855
1856 static void
1857 gtk_real_button_activate (GtkButton *button)
1858 {
1859   GtkWidget *widget = GTK_WIDGET (button);
1860   GtkButtonPrivate *priv = button->priv;
1861   GdkDevice *device;
1862   guint32 time;
1863
1864   device = gtk_get_current_event_device ();
1865
1866   if (device && gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
1867     device = gdk_device_get_associated_device (device);
1868
1869   g_return_if_fail (device && gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD);
1870
1871   if (gtk_widget_get_realized (widget) && !priv->activate_timeout)
1872     {
1873       time = gtk_get_current_event_time ();
1874
1875       if (gdk_device_grab (device, priv->event_window,
1876                            GDK_OWNERSHIP_WINDOW, TRUE,
1877                            GDK_KEY_PRESS | GDK_KEY_RELEASE,
1878                            NULL, time) == GDK_GRAB_SUCCESS)
1879         {
1880           gtk_device_grab_add (widget, device, TRUE);
1881           priv->grab_keyboard = device;
1882           priv->grab_time = time;
1883         }
1884
1885       priv->activate_timeout = gdk_threads_add_timeout (ACTIVATE_TIMEOUT,
1886                                                 button_activate_timeout,
1887                                                 button);
1888       priv->button_down = TRUE;
1889       gtk_button_update_state (button);
1890       gtk_widget_queue_draw (GTK_WIDGET (button));
1891     }
1892 }
1893
1894 static void
1895 gtk_button_finish_activate (GtkButton *button,
1896                             gboolean   do_it)
1897 {
1898   GtkWidget *widget = GTK_WIDGET (button);
1899   GtkButtonPrivate *priv = button->priv;
1900
1901   g_source_remove (priv->activate_timeout);
1902   priv->activate_timeout = 0;
1903
1904   if (priv->grab_keyboard)
1905     {
1906       gdk_device_ungrab (priv->grab_keyboard, priv->grab_time);
1907       gtk_device_grab_remove (widget, priv->grab_keyboard);
1908       priv->grab_keyboard = NULL;
1909     }
1910
1911   priv->button_down = FALSE;
1912
1913   gtk_button_update_state (button);
1914   gtk_widget_queue_draw (GTK_WIDGET (button));
1915
1916   if (do_it)
1917     gtk_button_clicked (button);
1918 }
1919
1920
1921 static void
1922 gtk_button_get_size (GtkWidget      *widget,
1923                      GtkOrientation  orientation,
1924                      gint           *minimum_size,
1925                      gint           *natural_size)
1926 {
1927   GtkButton *button = GTK_BUTTON (widget);
1928   GtkStyleContext *context;
1929   GtkStateFlags state;
1930   GtkWidget *child;
1931   GtkBorder default_border;
1932   GtkBorder inner_border;
1933   GtkBorder *border;
1934   gint focus_width;
1935   gint focus_pad;
1936   gint minimum, natural;
1937
1938   context = gtk_widget_get_style_context (widget);
1939   state = gtk_widget_get_state_flags (widget);
1940
1941   gtk_button_get_props (button, &default_border, NULL, &inner_border, NULL);
1942   gtk_style_context_get_style (context,
1943                                "focus-line-width", &focus_width,
1944                                "focus-padding", &focus_pad,
1945                                NULL);
1946
1947   gtk_style_context_get (context, state,
1948                          "border-width", &border,
1949                          NULL);
1950
1951   if (orientation == GTK_ORIENTATION_HORIZONTAL)
1952     {
1953       minimum = (border->left + border->right +
1954                  inner_border.left + inner_border.right);
1955
1956       if (gtk_widget_get_can_default (GTK_WIDGET (widget)))
1957         minimum += default_border.left + default_border.right;
1958     }
1959   else
1960     {
1961       minimum = (border->top + border->bottom +
1962                  inner_border.top + inner_border.bottom);
1963
1964       if (gtk_widget_get_can_default (GTK_WIDGET (widget)))
1965         minimum += default_border.top + default_border.bottom;
1966     }  
1967
1968   minimum += 2 * (focus_width + focus_pad);
1969   natural = minimum;
1970
1971   if ((child = gtk_bin_get_child (GTK_BIN (button))) && 
1972       gtk_widget_get_visible (child))
1973     {
1974       gint child_min, child_nat;
1975
1976       if (orientation == GTK_ORIENTATION_HORIZONTAL)
1977         gtk_widget_get_preferred_width (child, &child_min, &child_nat);
1978       else
1979         gtk_widget_get_preferred_height (child, &child_min, &child_nat);
1980
1981       minimum += child_min;
1982       natural += child_nat;
1983     }
1984
1985   if (minimum_size)
1986     *minimum_size = minimum;
1987
1988   if (natural_size)
1989     *natural_size = natural;
1990
1991   gtk_border_free (border);
1992 }
1993
1994 static void 
1995 gtk_button_get_preferred_width (GtkWidget *widget,
1996                                 gint      *minimum_size,
1997                                 gint      *natural_size)
1998 {
1999   gtk_button_get_size (widget, GTK_ORIENTATION_HORIZONTAL, minimum_size, natural_size);
2000 }
2001
2002 static void 
2003 gtk_button_get_preferred_height (GtkWidget *widget,
2004                                  gint      *minimum_size,
2005                                  gint      *natural_size)
2006 {
2007   gtk_button_get_size (widget, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size);
2008 }
2009
2010 /**
2011  * gtk_button_set_label:
2012  * @button: a #GtkButton
2013  * @label: a string
2014  *
2015  * Sets the text of the label of the button to @str. This text is
2016  * also used to select the stock item if gtk_button_set_use_stock()
2017  * is used.
2018  *
2019  * This will also clear any previously set labels.
2020  **/
2021 void
2022 gtk_button_set_label (GtkButton   *button,
2023                       const gchar *label)
2024 {
2025   GtkButtonPrivate *priv;
2026   gchar *new_label;
2027
2028   g_return_if_fail (GTK_IS_BUTTON (button));
2029
2030   priv = button->priv;
2031
2032   new_label = g_strdup (label);
2033   g_free (priv->label_text);
2034   priv->label_text = new_label;
2035
2036   gtk_button_construct_child (button);
2037   
2038   g_object_notify (G_OBJECT (button), "label");
2039 }
2040
2041 /**
2042  * gtk_button_get_label:
2043  * @button: a #GtkButton
2044  *
2045  * Fetches the text from the label of the button, as set by
2046  * gtk_button_set_label(). If the label text has not 
2047  * been set the return value will be %NULL. This will be the 
2048  * case if you create an empty button with gtk_button_new() to 
2049  * use as a container.
2050  *
2051  * Return value: The text of the label widget. This string is owned
2052  * by the widget and must not be modified or freed.
2053  **/
2054 G_CONST_RETURN gchar *
2055 gtk_button_get_label (GtkButton *button)
2056 {
2057   g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
2058
2059   return button->priv->label_text;
2060 }
2061
2062 /**
2063  * gtk_button_set_use_underline:
2064  * @button: a #GtkButton
2065  * @use_underline: %TRUE if underlines in the text indicate mnemonics
2066  *
2067  * If true, an underline in the text of the button label indicates
2068  * the next character should be used for the mnemonic accelerator key.
2069  */
2070 void
2071 gtk_button_set_use_underline (GtkButton *button,
2072                               gboolean   use_underline)
2073 {
2074   GtkButtonPrivate *priv;
2075
2076   g_return_if_fail (GTK_IS_BUTTON (button));
2077
2078   priv = button->priv;
2079
2080   use_underline = use_underline != FALSE;
2081
2082   if (use_underline != priv->use_underline)
2083     {
2084       priv->use_underline = use_underline;
2085
2086       gtk_button_construct_child (button);
2087       
2088       g_object_notify (G_OBJECT (button), "use-underline");
2089     }
2090 }
2091
2092 /**
2093  * gtk_button_get_use_underline:
2094  * @button: a #GtkButton
2095  *
2096  * Returns whether an embedded underline in the button label indicates a
2097  * mnemonic. See gtk_button_set_use_underline ().
2098  *
2099  * Return value: %TRUE if an embedded underline in the button label
2100  *               indicates the mnemonic accelerator keys.
2101  **/
2102 gboolean
2103 gtk_button_get_use_underline (GtkButton *button)
2104 {
2105   g_return_val_if_fail (GTK_IS_BUTTON (button), FALSE);
2106
2107   return button->priv->use_underline;
2108 }
2109
2110 /**
2111  * gtk_button_set_use_stock:
2112  * @button: a #GtkButton
2113  * @use_stock: %TRUE if the button should use a stock item
2114  *
2115  * If %TRUE, the label set on the button is used as a
2116  * stock id to select the stock item for the button.
2117  */
2118 void
2119 gtk_button_set_use_stock (GtkButton *button,
2120                           gboolean   use_stock)
2121 {
2122   GtkButtonPrivate *priv;
2123
2124   g_return_if_fail (GTK_IS_BUTTON (button));
2125
2126   priv = button->priv;
2127
2128   use_stock = use_stock != FALSE;
2129
2130   if (use_stock != priv->use_stock)
2131     {
2132       priv->use_stock = use_stock;
2133
2134       gtk_button_construct_child (button);
2135       
2136       g_object_notify (G_OBJECT (button), "use-stock");
2137     }
2138 }
2139
2140 /**
2141  * gtk_button_get_use_stock:
2142  * @button: a #GtkButton
2143  *
2144  * Returns whether the button label is a stock item.
2145  *
2146  * Return value: %TRUE if the button label is used to
2147  *               select a stock item instead of being
2148  *               used directly as the label text.
2149  */
2150 gboolean
2151 gtk_button_get_use_stock (GtkButton *button)
2152 {
2153   g_return_val_if_fail (GTK_IS_BUTTON (button), FALSE);
2154
2155   return button->priv->use_stock;
2156 }
2157
2158 /**
2159  * gtk_button_set_focus_on_click:
2160  * @button: a #GtkButton
2161  * @focus_on_click: whether the button grabs focus when clicked with the mouse
2162  *
2163  * Sets whether the button will grab focus when it is clicked with the mouse.
2164  * Making mouse clicks not grab focus is useful in places like toolbars where
2165  * you don't want the keyboard focus removed from the main area of the
2166  * application.
2167  *
2168  * Since: 2.4
2169  **/
2170 void
2171 gtk_button_set_focus_on_click (GtkButton *button,
2172                                gboolean   focus_on_click)
2173 {
2174   GtkButtonPrivate *priv;
2175
2176   g_return_if_fail (GTK_IS_BUTTON (button));
2177
2178   priv = button->priv;
2179
2180   focus_on_click = focus_on_click != FALSE;
2181
2182   if (priv->focus_on_click != focus_on_click)
2183     {
2184       priv->focus_on_click = focus_on_click;
2185       
2186       g_object_notify (G_OBJECT (button), "focus-on-click");
2187     }
2188 }
2189
2190 /**
2191  * gtk_button_get_focus_on_click:
2192  * @button: a #GtkButton
2193  *
2194  * Returns whether the button grabs focus when it is clicked with the mouse.
2195  * See gtk_button_set_focus_on_click().
2196  *
2197  * Return value: %TRUE if the button grabs focus when it is clicked with
2198  *               the mouse.
2199  *
2200  * Since: 2.4
2201  **/
2202 gboolean
2203 gtk_button_get_focus_on_click (GtkButton *button)
2204 {
2205   g_return_val_if_fail (GTK_IS_BUTTON (button), FALSE);
2206   
2207   return button->priv->focus_on_click;
2208 }
2209
2210 /**
2211  * gtk_button_set_alignment:
2212  * @button: a #GtkButton
2213  * @xalign: the horizontal position of the child, 0.0 is left aligned, 
2214  *   1.0 is right aligned
2215  * @yalign: the vertical position of the child, 0.0 is top aligned, 
2216  *   1.0 is bottom aligned
2217  *
2218  * Sets the alignment of the child. This property has no effect unless 
2219  * the child is a #GtkMisc or a #GtkAlignment.
2220  *
2221  * Since: 2.4
2222  */
2223 void
2224 gtk_button_set_alignment (GtkButton *button,
2225                           gfloat     xalign,
2226                           gfloat     yalign)
2227 {
2228   GtkButtonPrivate *priv;
2229
2230   g_return_if_fail (GTK_IS_BUTTON (button));
2231   
2232   priv = button->priv;
2233
2234   priv->xalign = xalign;
2235   priv->yalign = yalign;
2236   priv->align_set = 1;
2237
2238   maybe_set_alignment (button, gtk_bin_get_child (GTK_BIN (button)));
2239
2240   g_object_freeze_notify (G_OBJECT (button));
2241   g_object_notify (G_OBJECT (button), "xalign");
2242   g_object_notify (G_OBJECT (button), "yalign");
2243   g_object_thaw_notify (G_OBJECT (button));
2244 }
2245
2246 /**
2247  * gtk_button_get_alignment:
2248  * @button: a #GtkButton
2249  * @xalign: return location for horizontal alignment
2250  * @yalign: return location for vertical alignment
2251  *
2252  * Gets the alignment of the child in the button.
2253  *
2254  * Since: 2.4
2255  */
2256 void
2257 gtk_button_get_alignment (GtkButton *button,
2258                           gfloat    *xalign,
2259                           gfloat    *yalign)
2260 {
2261   GtkButtonPrivate *priv;
2262
2263   g_return_if_fail (GTK_IS_BUTTON (button));
2264   
2265   priv = button->priv;
2266  
2267   if (xalign) 
2268     *xalign = priv->xalign;
2269
2270   if (yalign)
2271     *yalign = priv->yalign;
2272 }
2273
2274 /**
2275  * _gtk_button_set_depressed:
2276  * @button: a #GtkButton
2277  * @depressed: %TRUE if the button should be drawn with a recessed shadow.
2278  *
2279  * Sets whether the button is currently drawn as down or not. This is 
2280  * purely a visual setting, and is meant only for use by derived widgets
2281  * such as #GtkToggleButton.
2282  **/
2283 void
2284 _gtk_button_set_depressed (GtkButton *button,
2285                            gboolean   depressed)
2286 {
2287   GtkWidget *widget = GTK_WIDGET (button);
2288   GtkButtonPrivate *priv = button->priv;
2289
2290   depressed = depressed != FALSE;
2291
2292   if (depressed != priv->depressed)
2293     {
2294       priv->depressed = depressed;
2295       gtk_widget_queue_resize (widget);
2296     }
2297 }
2298
2299 static void
2300 gtk_button_update_state (GtkButton *button)
2301 {
2302   GtkButtonPrivate *priv = button->priv;
2303   GtkStateFlags new_state = 0;
2304   gboolean depressed;
2305
2306   if (priv->activate_timeout)
2307     depressed = priv->depress_on_activate;
2308   else
2309     depressed = priv->in_button && priv->button_down;
2310
2311   if (priv->in_button)
2312     new_state |= GTK_STATE_FLAG_PRELIGHT;
2313
2314   if (priv->button_down || depressed)
2315     new_state |= GTK_STATE_FLAG_ACTIVE;
2316
2317   _gtk_button_set_depressed (button, depressed);
2318   gtk_widget_set_state_flags (GTK_WIDGET (button), new_state, TRUE);
2319 }
2320
2321 static void 
2322 show_image_change_notify (GtkButton *button)
2323 {
2324   GtkButtonPrivate *priv = button->priv;
2325
2326   if (priv->image) 
2327     {
2328       if (show_image (button))
2329         gtk_widget_show (priv->image);
2330       else
2331         gtk_widget_hide (priv->image);
2332     }
2333 }
2334
2335 static void
2336 traverse_container (GtkWidget *widget,
2337                     gpointer   data)
2338 {
2339   if (GTK_IS_BUTTON (widget))
2340     show_image_change_notify (GTK_BUTTON (widget));
2341   else if (GTK_IS_CONTAINER (widget))
2342     gtk_container_forall (GTK_CONTAINER (widget), traverse_container, NULL);
2343 }
2344
2345 static void
2346 gtk_button_setting_changed (GtkSettings *settings)
2347 {
2348   GList *list, *l;
2349
2350   list = gtk_window_list_toplevels ();
2351
2352   for (l = list; l; l = l->next)
2353     gtk_container_forall (GTK_CONTAINER (l->data), 
2354                           traverse_container, NULL);
2355
2356   g_list_free (list);
2357 }
2358
2359
2360 static void
2361 gtk_button_screen_changed (GtkWidget *widget,
2362                            GdkScreen *previous_screen)
2363 {
2364   GtkButton *button;
2365   GtkButtonPrivate *priv;
2366   GtkSettings *settings;
2367   gulong show_image_connection;
2368
2369   if (!gtk_widget_has_screen (widget))
2370     return;
2371
2372   button = GTK_BUTTON (widget);
2373   priv = button->priv;
2374
2375   /* If the button is being pressed while the screen changes the
2376     release might never occur, so we reset the state. */
2377   if (priv->button_down)
2378     {
2379       priv->button_down = FALSE;
2380       gtk_button_update_state (button);
2381     }
2382
2383   settings = gtk_widget_get_settings (widget);
2384
2385   show_image_connection = 
2386     g_signal_handler_find (settings, G_SIGNAL_MATCH_FUNC, 0, 0,
2387                            NULL, gtk_button_setting_changed, NULL);
2388   
2389   if (show_image_connection)
2390     return;
2391
2392   g_signal_connect (settings, "notify::gtk-button-images",
2393                     G_CALLBACK (gtk_button_setting_changed), NULL);
2394
2395   show_image_change_notify (button);
2396 }
2397
2398 static void
2399 gtk_button_state_changed (GtkWidget    *widget,
2400                           GtkStateType  previous_state)
2401 {
2402   GtkButton *button = GTK_BUTTON (widget);
2403   GtkButtonPrivate *priv = button->priv;
2404
2405   if (!gtk_widget_is_sensitive (widget))
2406     {
2407       priv->in_button = FALSE;
2408       gtk_real_button_released (button);
2409     }
2410 }
2411
2412 static void
2413 gtk_button_grab_notify (GtkWidget *widget,
2414                         gboolean   was_grabbed)
2415 {
2416   GtkButton *button = GTK_BUTTON (widget);
2417   GtkButtonPrivate *priv = button->priv;
2418   gboolean save_in;
2419
2420   if (priv->activate_timeout &&
2421       priv->grab_keyboard &&
2422       gtk_widget_device_is_shadowed (widget, priv->grab_keyboard))
2423     gtk_button_finish_activate (button, FALSE);
2424
2425   if (!was_grabbed)
2426     {
2427       save_in = priv->in_button;
2428       priv->in_button = FALSE;
2429       gtk_real_button_released (button);
2430       if (save_in != priv->in_button)
2431         {
2432           priv->in_button = save_in;
2433           gtk_button_update_state (button);
2434         }
2435     }
2436 }
2437
2438 /**
2439  * gtk_button_set_image:
2440  * @button: a #GtkButton
2441  * @image: a widget to set as the image for the button
2442  *
2443  * Set the image of @button to the given widget. Note that
2444  * it depends on the #GtkSettings:gtk-button-images setting whether the
2445  * image will be displayed or not, you don't have to call
2446  * gtk_widget_show() on @image yourself.
2447  *
2448  * Since: 2.6
2449  */ 
2450 void
2451 gtk_button_set_image (GtkButton *button,
2452                       GtkWidget *image)
2453 {
2454   GtkButtonPrivate *priv;
2455   GtkWidget *parent;
2456
2457   g_return_if_fail (GTK_IS_BUTTON (button));
2458   g_return_if_fail (image == NULL || GTK_IS_WIDGET (image));
2459
2460   priv = button->priv;
2461
2462   if (priv->image)
2463     {
2464       parent = gtk_widget_get_parent (priv->image);
2465       if (parent)
2466         gtk_container_remove (GTK_CONTAINER (parent), priv->image);
2467     }
2468
2469   priv->image = image;
2470   priv->image_is_stock = (image == NULL);
2471
2472   gtk_button_construct_child (button);
2473
2474   g_object_notify (G_OBJECT (button), "image");
2475 }
2476
2477 /**
2478  * gtk_button_get_image:
2479  * @button: a #GtkButton
2480  *
2481  * Gets the widget that is currenty set as the image of @button.
2482  * This may have been explicitly set by gtk_button_set_image()
2483  * or constructed by gtk_button_new_from_stock().
2484  *
2485  * Return value: (transfer none): a #GtkWidget or %NULL in case there is no image
2486  *
2487  * Since: 2.6
2488  */
2489 GtkWidget *
2490 gtk_button_get_image (GtkButton *button)
2491 {
2492   g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
2493   
2494   return button->priv->image;
2495 }
2496
2497 /**
2498  * gtk_button_set_image_position:
2499  * @button: a #GtkButton
2500  * @position: the position
2501  *
2502  * Sets the position of the image relative to the text 
2503  * inside the button.
2504  *
2505  * Since: 2.10
2506  */ 
2507 void
2508 gtk_button_set_image_position (GtkButton       *button,
2509                                GtkPositionType  position)
2510 {
2511   GtkButtonPrivate *priv;
2512
2513   g_return_if_fail (GTK_IS_BUTTON (button));
2514   g_return_if_fail (position >= GTK_POS_LEFT && position <= GTK_POS_BOTTOM);
2515   
2516   priv = button->priv;
2517
2518   if (priv->image_position != position)
2519     {
2520       priv->image_position = position;
2521
2522       gtk_button_construct_child (button);
2523
2524       g_object_notify (G_OBJECT (button), "image-position");
2525     }
2526 }
2527
2528 /**
2529  * gtk_button_get_image_position:
2530  * @button: a #GtkButton
2531  *
2532  * Gets the position of the image relative to the text 
2533  * inside the button.
2534  *
2535  * Return value: the position
2536  *
2537  * Since: 2.10
2538  */
2539 GtkPositionType
2540 gtk_button_get_image_position (GtkButton *button)
2541 {
2542   g_return_val_if_fail (GTK_IS_BUTTON (button), GTK_POS_LEFT);
2543   
2544   return button->priv->image_position;
2545 }
2546
2547
2548 /**
2549  * gtk_button_get_event_window:
2550  * @button: a #GtkButton
2551  *
2552  * Returns the button's event window if it is realized, %NULL otherwise.
2553  * This function should be rarely needed.
2554  *
2555  * Return value: (transfer none): @button's event window.
2556  *
2557  * Since: 2.22
2558  */
2559 GdkWindow*
2560 gtk_button_get_event_window (GtkButton *button)
2561 {
2562   g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
2563
2564   return button->priv->event_window;
2565 }