]> Pileus Git - ~andy/gtk/blob - gtk/gtkbutton.c
Move all GdkDevice members to private and add one missing accessor
[~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_set (GtkWidget * widget, GtkStyle * prev_style);
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_set = gtk_button_style_set;
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
537   button->priv = G_TYPE_INSTANCE_GET_PRIVATE (button,
538                                               GTK_TYPE_BUTTON,
539                                               GtkButtonPrivate);
540   priv = button->priv;
541
542   gtk_widget_set_can_focus (GTK_WIDGET (button), TRUE);
543   gtk_widget_set_receives_default (GTK_WIDGET (button), TRUE);
544   gtk_widget_set_has_window (GTK_WIDGET (button), FALSE);
545
546   priv->label_text = NULL;
547
548   priv->constructed = FALSE;
549   priv->in_button = FALSE;
550   priv->button_down = FALSE;
551   priv->relief = GTK_RELIEF_NORMAL;
552   priv->use_stock = FALSE;
553   priv->use_underline = FALSE;
554   priv->depressed = FALSE;
555   priv->depress_on_activate = TRUE;
556   priv->focus_on_click = TRUE;
557
558   priv->xalign = 0.5;
559   priv->yalign = 0.5;
560   priv->align_set = 0;
561   priv->image_is_stock = TRUE;
562   priv->image_position = GTK_POS_LEFT;
563   priv->use_action_appearance = TRUE;
564 }
565
566 static void
567 gtk_button_destroy (GtkWidget *widget)
568 {
569   GtkButton *button = GTK_BUTTON (widget);
570   GtkButtonPrivate *priv = button->priv;
571
572   if (priv->label_text)
573     {
574       g_free (priv->label_text);
575       priv->label_text = NULL;
576     }
577
578   GTK_WIDGET_CLASS (gtk_button_parent_class)->destroy (widget);
579 }
580
581 static GObject*
582 gtk_button_constructor (GType                  type,
583                         guint                  n_construct_properties,
584                         GObjectConstructParam *construct_params)
585 {
586   GObject *object;
587   GtkButton *button;
588   GtkButtonPrivate *priv;
589
590   object = G_OBJECT_CLASS (gtk_button_parent_class)->constructor (type,
591                                                                   n_construct_properties,
592                                                                   construct_params);
593
594   button = GTK_BUTTON (object);
595   priv = button->priv;
596
597   priv->constructed = TRUE;
598
599   if (priv->label_text != NULL)
600     gtk_button_construct_child (button);
601   
602   return object;
603 }
604
605
606 static GType
607 gtk_button_child_type  (GtkContainer     *container)
608 {
609   if (!gtk_bin_get_child (GTK_BIN (container)))
610     return GTK_TYPE_WIDGET;
611   else
612     return G_TYPE_NONE;
613 }
614
615 static void
616 maybe_set_alignment (GtkButton *button,
617                      GtkWidget *widget)
618 {
619   GtkButtonPrivate *priv = button->priv;
620
621   if (GTK_IS_MISC (widget))
622     {
623       GtkMisc *misc = GTK_MISC (widget);
624       
625       if (priv->align_set)
626         gtk_misc_set_alignment (misc, priv->xalign, priv->yalign);
627     }
628   else if (GTK_IS_ALIGNMENT (widget))
629     {
630       GtkAlignment *alignment = GTK_ALIGNMENT (widget);
631       gfloat xscale, yscale;
632
633       g_object_get (alignment,
634                     "xscale", &xscale,
635                     "yscale", &yscale,
636                     NULL);
637
638       if (priv->align_set)
639         gtk_alignment_set (alignment,
640                            priv->xalign, priv->yalign,
641                            xscale, yscale);
642     }
643 }
644
645 static void
646 gtk_button_add (GtkContainer *container,
647                 GtkWidget    *widget)
648 {
649   maybe_set_alignment (GTK_BUTTON (container), widget);
650
651   GTK_CONTAINER_CLASS (gtk_button_parent_class)->add (container, widget);
652 }
653
654 static void 
655 gtk_button_dispose (GObject *object)
656 {
657   GtkButton *button = GTK_BUTTON (object);
658   GtkButtonPrivate *priv = button->priv;
659
660   if (priv->action)
661     {
662       gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (button), NULL);
663       priv->action = NULL;
664     }
665   G_OBJECT_CLASS (gtk_button_parent_class)->dispose (object);
666 }
667
668 static void
669 gtk_button_set_property (GObject         *object,
670                          guint            prop_id,
671                          const GValue    *value,
672                          GParamSpec      *pspec)
673 {
674   GtkButton *button = GTK_BUTTON (object);
675   GtkButtonPrivate *priv = button->priv;
676
677   switch (prop_id)
678     {
679     case PROP_LABEL:
680       gtk_button_set_label (button, g_value_get_string (value));
681       break;
682     case PROP_IMAGE:
683       gtk_button_set_image (button, (GtkWidget *) g_value_get_object (value));
684       break;
685     case PROP_RELIEF:
686       gtk_button_set_relief (button, g_value_get_enum (value));
687       break;
688     case PROP_USE_UNDERLINE:
689       gtk_button_set_use_underline (button, g_value_get_boolean (value));
690       break;
691     case PROP_USE_STOCK:
692       gtk_button_set_use_stock (button, g_value_get_boolean (value));
693       break;
694     case PROP_FOCUS_ON_CLICK:
695       gtk_button_set_focus_on_click (button, g_value_get_boolean (value));
696       break;
697     case PROP_XALIGN:
698       gtk_button_set_alignment (button, g_value_get_float (value), priv->yalign);
699       break;
700     case PROP_YALIGN:
701       gtk_button_set_alignment (button, priv->xalign, g_value_get_float (value));
702       break;
703     case PROP_IMAGE_POSITION:
704       gtk_button_set_image_position (button, g_value_get_enum (value));
705       break;
706     case PROP_ACTIVATABLE_RELATED_ACTION:
707       gtk_button_set_related_action (button, g_value_get_object (value));
708       break;
709     case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
710       gtk_button_set_use_action_appearance (button, g_value_get_boolean (value));
711       break;
712     default:
713       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
714       break;
715     }
716 }
717
718 static void
719 gtk_button_get_property (GObject         *object,
720                          guint            prop_id,
721                          GValue          *value,
722                          GParamSpec      *pspec)
723 {
724   GtkButton *button = GTK_BUTTON (object);
725   GtkButtonPrivate *priv = button->priv;
726
727   switch (prop_id)
728     {
729     case PROP_LABEL:
730       g_value_set_string (value, priv->label_text);
731       break;
732     case PROP_IMAGE:
733       g_value_set_object (value, (GObject *)priv->image);
734       break;
735     case PROP_RELIEF:
736       g_value_set_enum (value, priv->relief);
737       break;
738     case PROP_USE_UNDERLINE:
739       g_value_set_boolean (value, priv->use_underline);
740       break;
741     case PROP_USE_STOCK:
742       g_value_set_boolean (value, priv->use_stock);
743       break;
744     case PROP_FOCUS_ON_CLICK:
745       g_value_set_boolean (value, priv->focus_on_click);
746       break;
747     case PROP_XALIGN:
748       g_value_set_float (value, priv->xalign);
749       break;
750     case PROP_YALIGN:
751       g_value_set_float (value, priv->yalign);
752       break;
753     case PROP_IMAGE_POSITION:
754       g_value_set_enum (value, priv->image_position);
755       break;
756     case PROP_ACTIVATABLE_RELATED_ACTION:
757       g_value_set_object (value, priv->action);
758       break;
759     case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
760       g_value_set_boolean (value, priv->use_action_appearance);
761       break;
762     default:
763       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
764       break;
765     }
766 }
767
768 static void 
769 gtk_button_activatable_interface_init (GtkActivatableIface  *iface)
770 {
771   iface->update = gtk_button_update;
772   iface->sync_action_properties = gtk_button_sync_action_properties;
773 }
774
775 static void
776 activatable_update_stock_id (GtkButton *button,
777                              GtkAction *action)
778 {
779   if (!gtk_button_get_use_stock (button))
780     return;
781
782   gtk_button_set_label (button, gtk_action_get_stock_id (action));
783 }
784
785 static void
786 activatable_update_short_label (GtkButton *button,
787                                 GtkAction *action)
788 {
789   GtkWidget *child;
790   GtkWidget *image;
791
792   if (gtk_button_get_use_stock (button))
793     return;
794
795   image = gtk_button_get_image (button);
796
797   /* Dont touch custom child... */
798   child = gtk_bin_get_child (GTK_BIN (button));
799   if (GTK_IS_IMAGE (image) ||
800       child == NULL ||
801       GTK_IS_LABEL (child))
802     {
803       gtk_button_set_label (button, gtk_action_get_short_label (action));
804       gtk_button_set_use_underline (button, TRUE);
805     }
806 }
807
808 static void
809 activatable_update_icon_name (GtkButton *button,
810                               GtkAction *action)
811 {
812   GtkWidget *image;
813               
814   if (gtk_button_get_use_stock (button))
815     return;
816
817   image = gtk_button_get_image (button);
818
819   if (GTK_IS_IMAGE (image) &&
820       (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
821        gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME))
822     gtk_image_set_from_icon_name (GTK_IMAGE (image),
823                                   gtk_action_get_icon_name (action), GTK_ICON_SIZE_MENU);
824 }
825
826 static void
827 activatable_update_gicon (GtkButton *button,
828                           GtkAction *action)
829 {
830   GtkWidget *image = gtk_button_get_image (button);
831   GIcon *icon = gtk_action_get_gicon (action);
832   
833   if (GTK_IS_IMAGE (image) &&
834       (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY ||
835        gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_GICON))
836     gtk_image_set_from_gicon (GTK_IMAGE (image), icon, GTK_ICON_SIZE_BUTTON);
837 }
838
839 static void 
840 gtk_button_update (GtkActivatable *activatable,
841                    GtkAction      *action,
842                    const gchar    *property_name)
843 {
844   GtkButton *button = GTK_BUTTON (activatable);
845   GtkButtonPrivate *priv = button->priv;
846
847   if (strcmp (property_name, "visible") == 0)
848     {
849       if (gtk_action_is_visible (action))
850         gtk_widget_show (GTK_WIDGET (activatable));
851       else
852         gtk_widget_hide (GTK_WIDGET (activatable));
853     }
854   else if (strcmp (property_name, "sensitive") == 0)
855     gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
856
857   if (!priv->use_action_appearance)
858     return;
859
860   if (strcmp (property_name, "stock-id") == 0)
861     activatable_update_stock_id (GTK_BUTTON (activatable), action);
862   else if (strcmp (property_name, "gicon") == 0)
863     activatable_update_gicon (GTK_BUTTON (activatable), action);
864   else if (strcmp (property_name, "short-label") == 0)
865     activatable_update_short_label (GTK_BUTTON (activatable), action);
866   else if (strcmp (property_name, "icon-name") == 0)
867     activatable_update_icon_name (GTK_BUTTON (activatable), action);
868 }
869
870 static void
871 gtk_button_sync_action_properties (GtkActivatable *activatable,
872                                    GtkAction      *action)
873 {
874   GtkButton *button = GTK_BUTTON (activatable);
875   GtkButtonPrivate *priv = button->priv;
876
877   if (!action)
878     return;
879
880   if (gtk_action_is_visible (action))
881     gtk_widget_show (GTK_WIDGET (activatable));
882   else
883     gtk_widget_hide (GTK_WIDGET (activatable));
884   
885   gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
886   
887   if (priv->use_action_appearance)
888     {
889       activatable_update_stock_id (GTK_BUTTON (activatable), action);
890       activatable_update_short_label (GTK_BUTTON (activatable), action);
891       activatable_update_gicon (GTK_BUTTON (activatable), action);
892       activatable_update_icon_name (GTK_BUTTON (activatable), action);
893     }
894 }
895
896 static void
897 gtk_button_set_related_action (GtkButton *button,
898                                GtkAction *action)
899 {
900   GtkButtonPrivate *priv = button->priv;
901
902   if (priv->action == action)
903     return;
904
905   /* This should be a default handler, but for compatibility reasons
906    * we need to support derived classes that don't chain up their
907    * clicked handler.
908    */
909   g_signal_handlers_disconnect_by_func (button, gtk_real_button_clicked, NULL);
910   if (action)
911     g_signal_connect_after (button, "clicked",
912                             G_CALLBACK (gtk_real_button_clicked), NULL);
913
914   gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (button), action);
915
916   priv->action = action;
917 }
918
919 static void
920 gtk_button_set_use_action_appearance (GtkButton *button,
921                                       gboolean   use_appearance)
922 {
923   GtkButtonPrivate *priv = button->priv;
924
925   if (priv->use_action_appearance != use_appearance)
926     {
927       priv->use_action_appearance = use_appearance;
928
929       gtk_activatable_sync_action_properties (GTK_ACTIVATABLE (button), priv->action);
930     }
931 }
932
933 /**
934  * gtk_button_new:
935  *
936  * Creates a new #GtkButton widget. To add a child widget to the button,
937  * use gtk_container_add().
938  *
939  * Returns: The newly created #GtkButton widget.
940  */
941 GtkWidget*
942 gtk_button_new (void)
943 {
944   return g_object_new (GTK_TYPE_BUTTON, NULL);
945 }
946
947 static gboolean
948 show_image (GtkButton *button)
949 {
950   GtkButtonPrivate *priv = button->priv;
951   gboolean show;
952
953   if (priv->label_text)
954     {
955       GtkSettings *settings;
956
957       settings = gtk_widget_get_settings (GTK_WIDGET (button));        
958       g_object_get (settings, "gtk-button-images", &show, NULL);
959     }
960   else
961     show = TRUE;
962
963   return show;
964 }
965
966 static void
967 gtk_button_construct_child (GtkButton *button)
968 {
969   GtkButtonPrivate *priv = button->priv;
970   GtkStockItem item;
971   GtkWidget *child;
972   GtkWidget *label;
973   GtkWidget *box;
974   GtkWidget *align;
975   GtkWidget *image = NULL;
976   gchar *label_text = NULL;
977   gint image_spacing;
978
979   if (!priv->constructed)
980     return;
981
982   if (!priv->label_text && !priv->image)
983     return;
984
985   gtk_widget_style_get (GTK_WIDGET (button),
986                         "image-spacing", &image_spacing,
987                         NULL);
988
989   if (priv->image && !priv->image_is_stock)
990     {
991       GtkWidget *parent;
992
993       image = g_object_ref (priv->image);
994
995       parent = gtk_widget_get_parent (image);
996       if (parent)
997         gtk_container_remove (GTK_CONTAINER (parent), image);
998     }
999
1000   priv->image = NULL;
1001
1002   child = gtk_bin_get_child (GTK_BIN (button));
1003   if (child)
1004     gtk_container_remove (GTK_CONTAINER (button), child);
1005
1006   if (priv->use_stock &&
1007       priv->label_text &&
1008       gtk_stock_lookup (priv->label_text, &item))
1009     {
1010       if (!image)
1011         image = g_object_ref (gtk_image_new_from_stock (priv->label_text, GTK_ICON_SIZE_BUTTON));
1012
1013       label_text = item.label;
1014     }
1015   else
1016     label_text = priv->label_text;
1017
1018   if (image)
1019     {
1020       priv->image = image;
1021       g_object_set (priv->image,
1022                     "visible", show_image (button),
1023                     "no-show-all", TRUE,
1024                     NULL);
1025
1026       if (priv->image_position == GTK_POS_LEFT ||
1027           priv->image_position == GTK_POS_RIGHT)
1028         box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, image_spacing);
1029       else
1030         box = gtk_box_new (GTK_ORIENTATION_VERTICAL, image_spacing);
1031
1032       if (priv->align_set)
1033         align = gtk_alignment_new (priv->xalign, priv->yalign, 0.0, 0.0);
1034       else
1035         align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
1036
1037       if (priv->image_position == GTK_POS_LEFT ||
1038           priv->image_position == GTK_POS_TOP)
1039         gtk_box_pack_start (GTK_BOX (box), priv->image, FALSE, FALSE, 0);
1040       else
1041         gtk_box_pack_end (GTK_BOX (box), priv->image, FALSE, FALSE, 0);
1042
1043       if (label_text)
1044         {
1045           if (priv->use_underline || priv->use_stock)
1046             {
1047               label = gtk_label_new_with_mnemonic (label_text);
1048               gtk_label_set_mnemonic_widget (GTK_LABEL (label),
1049                                              GTK_WIDGET (button));
1050             }
1051           else
1052             label = gtk_label_new (label_text);
1053
1054           if (priv->image_position == GTK_POS_RIGHT ||
1055               priv->image_position == GTK_POS_BOTTOM)
1056             gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
1057           else
1058             gtk_box_pack_end (GTK_BOX (box), label, FALSE, FALSE, 0);
1059         }
1060
1061       gtk_container_add (GTK_CONTAINER (button), align);
1062       gtk_container_add (GTK_CONTAINER (align), box);
1063       gtk_widget_show_all (align);
1064
1065       g_object_unref (image);
1066
1067       return;
1068     }
1069
1070   if (priv->use_underline || priv->use_stock)
1071     {
1072       label = gtk_label_new_with_mnemonic (priv->label_text);
1073       gtk_label_set_mnemonic_widget (GTK_LABEL (label), GTK_WIDGET (button));
1074     }
1075   else
1076     label = gtk_label_new (priv->label_text);
1077
1078   if (priv->align_set)
1079     gtk_misc_set_alignment (GTK_MISC (label), priv->xalign, priv->yalign);
1080
1081   gtk_widget_show (label);
1082   gtk_container_add (GTK_CONTAINER (button), label);
1083 }
1084
1085
1086 /**
1087  * gtk_button_new_with_label:
1088  * @label: The text you want the #GtkLabel to hold.
1089  *
1090  * Creates a #GtkButton widget with a #GtkLabel child containing the given
1091  * text.
1092  *
1093  * Returns: The newly created #GtkButton widget.
1094  */
1095 GtkWidget*
1096 gtk_button_new_with_label (const gchar *label)
1097 {
1098   return g_object_new (GTK_TYPE_BUTTON, "label", label, NULL);
1099 }
1100
1101 /**
1102  * gtk_button_new_from_stock:
1103  * @stock_id: the name of the stock item 
1104  *
1105  * Creates a new #GtkButton containing the image and text from a stock item.
1106  * Some stock ids have preprocessor macros like #GTK_STOCK_OK and
1107  * #GTK_STOCK_APPLY.
1108  *
1109  * If @stock_id is unknown, then it will be treated as a mnemonic
1110  * label (as for gtk_button_new_with_mnemonic()).
1111  *
1112  * Returns: a new #GtkButton
1113  **/
1114 GtkWidget*
1115 gtk_button_new_from_stock (const gchar *stock_id)
1116 {
1117   return g_object_new (GTK_TYPE_BUTTON,
1118                        "label", stock_id,
1119                        "use-stock", TRUE,
1120                        "use-underline", TRUE,
1121                        NULL);
1122 }
1123
1124 /**
1125  * gtk_button_new_with_mnemonic:
1126  * @label: The text of the button, with an underscore in front of the
1127  *         mnemonic character
1128  * @returns: a new #GtkButton
1129  *
1130  * Creates a new #GtkButton containing a label.
1131  * If characters in @label are preceded by an underscore, they are underlined.
1132  * If you need a literal underscore character in a label, use '__' (two 
1133  * underscores). The first underlined character represents a keyboard 
1134  * accelerator called a mnemonic.
1135  * Pressing Alt and that key activates the button.
1136  **/
1137 GtkWidget*
1138 gtk_button_new_with_mnemonic (const gchar *label)
1139 {
1140   return g_object_new (GTK_TYPE_BUTTON, "label", label, "use-underline", TRUE,  NULL);
1141 }
1142
1143 /**
1144  * gtk_button_pressed:
1145  * @button: The #GtkButton you want to send the signal to.
1146  *
1147  * Emits a #GtkButton::pressed signal to the given #GtkButton.
1148  *
1149  * Deprecated: 2.20: Use the #GtkWidget::button-press-event signal.
1150  */
1151 void
1152 gtk_button_pressed (GtkButton *button)
1153 {
1154   g_return_if_fail (GTK_IS_BUTTON (button));
1155
1156   g_signal_emit (button, button_signals[PRESSED], 0);
1157 }
1158
1159 /**
1160  * gtk_button_released:
1161  * @button: The #GtkButton you want to send the signal to.
1162  *
1163  * Emits a #GtkButton::released signal to the given #GtkButton.
1164  *
1165  * Deprecated: 2.20: Use the #GtkWidget::button-release-event signal.
1166  */
1167 void
1168 gtk_button_released (GtkButton *button)
1169 {
1170   g_return_if_fail (GTK_IS_BUTTON (button));
1171
1172   g_signal_emit (button, button_signals[RELEASED], 0);
1173 }
1174
1175 /**
1176  * gtk_button_clicked:
1177  * @button: The #GtkButton you want to send the signal to.
1178  *
1179  * Emits a #GtkButton::clicked signal to the given #GtkButton.
1180  */
1181 void
1182 gtk_button_clicked (GtkButton *button)
1183 {
1184   g_return_if_fail (GTK_IS_BUTTON (button));
1185
1186   g_signal_emit (button, button_signals[CLICKED], 0);
1187 }
1188
1189 /**
1190  * gtk_button_enter:
1191  * @button: The #GtkButton you want to send the signal to.
1192  *
1193  * Emits a #GtkButton::enter signal to the given #GtkButton.
1194  *
1195  * Deprecated: 2.20: Use the #GtkWidget::enter-notify-event signal.
1196  */
1197 void
1198 gtk_button_enter (GtkButton *button)
1199 {
1200   g_return_if_fail (GTK_IS_BUTTON (button));
1201
1202   g_signal_emit (button, button_signals[ENTER], 0);
1203 }
1204
1205 /**
1206  * gtk_button_leave:
1207  * @button: The #GtkButton you want to send the signal to.
1208  *
1209  * Emits a #GtkButton::leave signal to the given #GtkButton.
1210  *
1211  * Deprecated: 2.20: Use the #GtkWidget::leave-notify-event signal.
1212  */
1213 void
1214 gtk_button_leave (GtkButton *button)
1215 {
1216   g_return_if_fail (GTK_IS_BUTTON (button));
1217
1218   g_signal_emit (button, button_signals[LEAVE], 0);
1219 }
1220
1221 /**
1222  * gtk_button_set_relief:
1223  * @button: The #GtkButton you want to set relief styles of.
1224  * @newstyle: The GtkReliefStyle as described above.
1225  *
1226  * Sets the relief style of the edges of the given #GtkButton widget.
1227  * Three styles exist, GTK_RELIEF_NORMAL, GTK_RELIEF_HALF, GTK_RELIEF_NONE.
1228  * The default style is, as one can guess, GTK_RELIEF_NORMAL.
1229  *
1230  * <!-- FIXME: put pictures of each style -->
1231  */
1232 void
1233 gtk_button_set_relief (GtkButton *button,
1234                        GtkReliefStyle newrelief)
1235 {
1236   GtkButtonPrivate *priv;
1237
1238   g_return_if_fail (GTK_IS_BUTTON (button));
1239
1240   priv = button->priv;
1241
1242   if (newrelief != priv->relief)
1243     {
1244        priv->relief = newrelief;
1245        g_object_notify (G_OBJECT (button), "relief");
1246        gtk_widget_queue_draw (GTK_WIDGET (button));
1247     }
1248 }
1249
1250 /**
1251  * gtk_button_get_relief:
1252  * @button: The #GtkButton you want the #GtkReliefStyle from.
1253  *
1254  * Returns the current relief style of the given #GtkButton.
1255  *
1256  * Returns: The current #GtkReliefStyle
1257  */
1258 GtkReliefStyle
1259 gtk_button_get_relief (GtkButton *button)
1260 {
1261   g_return_val_if_fail (GTK_IS_BUTTON (button), GTK_RELIEF_NORMAL);
1262
1263   return button->priv->relief;
1264 }
1265
1266 static void
1267 gtk_button_realize (GtkWidget *widget)
1268 {
1269   GtkButton *button = GTK_BUTTON (widget);
1270   GtkButtonPrivate *priv = button->priv;
1271   GtkAllocation allocation;
1272   GdkWindow *window;
1273   GdkWindowAttr attributes;
1274   gint attributes_mask;
1275
1276   gtk_widget_get_allocation (widget, &allocation);
1277
1278   gtk_widget_set_realized (widget, TRUE);
1279
1280   attributes.window_type = GDK_WINDOW_CHILD;
1281   attributes.x = allocation.x;
1282   attributes.y = allocation.y;
1283   attributes.width = allocation.width;
1284   attributes.height = allocation.height;
1285   attributes.wclass = GDK_INPUT_ONLY;
1286   attributes.event_mask = gtk_widget_get_events (widget);
1287   attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
1288                             GDK_BUTTON_RELEASE_MASK |
1289                             GDK_ENTER_NOTIFY_MASK |
1290                             GDK_LEAVE_NOTIFY_MASK);
1291
1292   attributes_mask = GDK_WA_X | GDK_WA_Y;
1293
1294   window = gtk_widget_get_parent_window (widget);
1295   gtk_widget_set_window (widget, window);
1296   g_object_ref (window);
1297
1298   priv->event_window = gdk_window_new (window,
1299                                        &attributes, attributes_mask);
1300   gdk_window_set_user_data (priv->event_window, button);
1301
1302   gtk_widget_style_attach (widget);
1303 }
1304
1305 static void
1306 gtk_button_unrealize (GtkWidget *widget)
1307 {
1308   GtkButton *button = GTK_BUTTON (widget);
1309   GtkButtonPrivate *priv = button->priv;
1310
1311   if (priv->activate_timeout)
1312     gtk_button_finish_activate (button, FALSE);
1313
1314   if (priv->event_window)
1315     {
1316       gdk_window_set_user_data (priv->event_window, NULL);
1317       gdk_window_destroy (priv->event_window);
1318       priv->event_window = NULL;
1319     }
1320
1321   GTK_WIDGET_CLASS (gtk_button_parent_class)->unrealize (widget);
1322 }
1323
1324 static void
1325 gtk_button_map (GtkWidget *widget)
1326 {
1327   GtkButton *button = GTK_BUTTON (widget);
1328   GtkButtonPrivate *priv = button->priv;
1329
1330   GTK_WIDGET_CLASS (gtk_button_parent_class)->map (widget);
1331
1332   if (priv->event_window)
1333     gdk_window_show (priv->event_window);
1334 }
1335
1336 static void
1337 gtk_button_unmap (GtkWidget *widget)
1338 {
1339   GtkButton *button = GTK_BUTTON (widget);
1340   GtkButtonPrivate *priv = button->priv;
1341
1342   if (priv->event_window)
1343     gdk_window_hide (priv->event_window);
1344
1345   GTK_WIDGET_CLASS (gtk_button_parent_class)->unmap (widget);
1346 }
1347
1348 static void
1349 gtk_button_update_image_spacing (GtkButton *button)
1350 {
1351   GtkButtonPrivate *priv = button->priv;
1352   GtkWidget *child; 
1353   gint spacing;
1354
1355   /* Keep in sync with gtk_button_construct_child,
1356    * we only want to update the spacing if the box 
1357    * was constructed there.
1358    */
1359   if (!priv->constructed || !priv->image)
1360     return;
1361
1362   child = gtk_bin_get_child (GTK_BIN (button));
1363   if (GTK_IS_ALIGNMENT (child))
1364     {
1365       child = gtk_bin_get_child (GTK_BIN (child));
1366       if (GTK_IS_BOX (child))
1367         {
1368           gtk_widget_style_get (GTK_WIDGET (button),
1369                                 "image-spacing", &spacing,
1370                                 NULL);
1371
1372           gtk_box_set_spacing (GTK_BOX (child), spacing);
1373         }
1374     }   
1375 }
1376
1377 static void
1378 gtk_button_style_set (GtkWidget *widget,
1379                       GtkStyle  *prev_style)
1380 {
1381   gtk_button_update_image_spacing (GTK_BUTTON (widget));
1382 }
1383
1384 static void
1385 gtk_button_get_props (GtkButton *button,
1386                       GtkBorder *default_border,
1387                       GtkBorder *default_outside_border,
1388                       GtkBorder *inner_border,
1389                       gboolean  *interior_focus)
1390 {
1391   GtkWidget *widget =  GTK_WIDGET (button);
1392   GtkBorder *tmp_border;
1393
1394   if (default_border)
1395     {
1396       gtk_widget_style_get (widget, "default-border", &tmp_border, NULL);
1397
1398       if (tmp_border)
1399         {
1400           *default_border = *tmp_border;
1401           gtk_border_free (tmp_border);
1402         }
1403       else
1404         *default_border = default_default_border;
1405     }
1406
1407   if (default_outside_border)
1408     {
1409       gtk_widget_style_get (widget, "default-outside-border", &tmp_border, NULL);
1410
1411       if (tmp_border)
1412         {
1413           *default_outside_border = *tmp_border;
1414           gtk_border_free (tmp_border);
1415         }
1416       else
1417         *default_outside_border = default_default_outside_border;
1418     }
1419
1420   if (inner_border)
1421     {
1422       gtk_widget_style_get (widget, "inner-border", &tmp_border, NULL);
1423
1424       if (tmp_border)
1425         {
1426           *inner_border = *tmp_border;
1427           gtk_border_free (tmp_border);
1428         }
1429       else
1430         *inner_border = default_inner_border;
1431     }
1432
1433   if (interior_focus)
1434     gtk_widget_style_get (widget, "interior-focus", interior_focus, NULL);
1435 }
1436
1437 static void
1438 gtk_button_size_allocate (GtkWidget     *widget,
1439                           GtkAllocation *allocation)
1440 {
1441   GtkButton *button = GTK_BUTTON (widget);
1442   GtkButtonPrivate *priv = button->priv;
1443   GtkAllocation child_allocation;
1444   GtkStyle *style;
1445   GtkWidget *child;
1446
1447   gint xthickness, ythickness;
1448   GtkBorder default_border;
1449   GtkBorder inner_border;
1450   gint focus_width;
1451   gint focus_pad;
1452
1453   style = gtk_widget_get_style (widget);
1454   xthickness = style->xthickness;
1455   ythickness = style->ythickness;
1456
1457   gtk_button_get_props (button, &default_border, NULL, &inner_border, NULL);
1458   gtk_widget_style_get (GTK_WIDGET (widget),
1459                         "focus-line-width", &focus_width,
1460                         "focus-padding", &focus_pad,
1461                         NULL);
1462
1463   gtk_widget_set_allocation (widget, allocation);
1464
1465   if (gtk_widget_get_realized (widget))
1466     gdk_window_move_resize (priv->event_window,
1467                             allocation->x,
1468                             allocation->y,
1469                             allocation->width,
1470                             allocation->height);
1471
1472   child = gtk_bin_get_child (GTK_BIN (button));
1473   if (child && gtk_widget_get_visible (child))
1474     {
1475       child_allocation.x = allocation->x + inner_border.left + xthickness;
1476       child_allocation.y = allocation->y + inner_border.top + ythickness;
1477
1478       child_allocation.width =
1479         allocation->width -
1480         xthickness * 2 -
1481         inner_border.left -
1482         inner_border.right;
1483
1484       child_allocation.height = 
1485         allocation->height -
1486         ythickness * 2 -
1487         inner_border.top -
1488         inner_border.bottom;
1489
1490       if (gtk_widget_get_can_default (GTK_WIDGET (button)))
1491         {
1492           child_allocation.x += default_border.left;
1493           child_allocation.y += default_border.top;
1494           child_allocation.width =  child_allocation.width - default_border.left - default_border.right;
1495           child_allocation.height = child_allocation.height - default_border.top - default_border.bottom;
1496         }
1497
1498       if (gtk_widget_get_can_focus (GTK_WIDGET (button)))
1499         {
1500           child_allocation.x += focus_width + focus_pad;
1501           child_allocation.y += focus_width + focus_pad;
1502           child_allocation.width =  child_allocation.width - (focus_width + focus_pad) * 2;
1503           child_allocation.height = child_allocation.height - (focus_width + focus_pad) * 2;
1504         }
1505
1506       if (priv->depressed)
1507         {
1508           gint child_displacement_x;
1509           gint child_displacement_y;
1510           
1511           gtk_widget_style_get (widget,
1512                                 "child-displacement-x", &child_displacement_x, 
1513                                 "child-displacement-y", &child_displacement_y,
1514                                 NULL);
1515           child_allocation.x += child_displacement_x;
1516           child_allocation.y += child_displacement_y;
1517         }
1518
1519       child_allocation.width  = MAX (1, child_allocation.width);
1520       child_allocation.height = MAX (1, child_allocation.height);
1521
1522       gtk_widget_size_allocate (child, &child_allocation);
1523     }
1524 }
1525
1526 void
1527 _gtk_button_paint (GtkButton          *button,
1528                    cairo_t            *cr,
1529                    int                 width,
1530                    int                 height,
1531                    GtkStateType        state_type,
1532                    GtkShadowType       shadow_type,
1533                    const gchar        *main_detail,
1534                    const gchar        *default_detail)
1535 {
1536   GtkButtonPrivate *priv = button->priv;
1537   GtkWidget *widget;
1538   gint x, y;
1539   GtkBorder default_border;
1540   GtkBorder default_outside_border;
1541   gboolean interior_focus;
1542   gint focus_width;
1543   gint focus_pad;
1544   GtkAllocation allocation;
1545   GdkWindow *window;
1546   GtkStyle *style;
1547
1548   widget = GTK_WIDGET (button);
1549
1550   gtk_button_get_props (button, &default_border, &default_outside_border, NULL, &interior_focus);
1551   gtk_widget_style_get (widget,
1552                         "focus-line-width", &focus_width,
1553                         "focus-padding", &focus_pad,
1554                         NULL); 
1555
1556   gtk_widget_get_allocation (widget, &allocation);
1557   style = gtk_widget_get_style (widget);
1558   window = gtk_widget_get_window (widget);
1559
1560   x = 0;
1561   y = 0;
1562
1563   if (gtk_widget_has_default (widget) &&
1564       priv->relief == GTK_RELIEF_NORMAL)
1565     {
1566       gtk_paint_box (style, cr,
1567                      GTK_STATE_NORMAL, GTK_SHADOW_IN,
1568                      widget, "buttondefault",
1569                      x, y, width, height);
1570
1571       x += default_border.left;
1572       y += default_border.top;
1573       width -= default_border.left + default_border.right;
1574       height -= default_border.top + default_border.bottom;
1575     }
1576   else if (gtk_widget_get_can_default (widget))
1577     {
1578       x += default_outside_border.left;
1579       y += default_outside_border.top;
1580       width -= default_outside_border.left + default_outside_border.right;
1581       height -= default_outside_border.top + default_outside_border.bottom;
1582     }
1583    
1584   if (!interior_focus && gtk_widget_has_focus (widget))
1585     {
1586       x += focus_width + focus_pad;
1587       y += focus_width + focus_pad;
1588       width -= 2 * (focus_width + focus_pad);
1589       height -= 2 * (focus_width + focus_pad);
1590     }
1591
1592   if (priv->relief != GTK_RELIEF_NONE || priv->depressed ||
1593       gtk_widget_get_state(widget) == GTK_STATE_PRELIGHT)
1594     gtk_paint_box (style, cr,
1595                    state_type,
1596                    shadow_type, widget, "button",
1597                    x, y, width, height);
1598    
1599   if (gtk_widget_has_focus (widget))
1600     {
1601       gint child_displacement_x;
1602       gint child_displacement_y;
1603       gboolean displace_focus;
1604       
1605       gtk_widget_style_get (widget,
1606                             "child-displacement-y", &child_displacement_y,
1607                             "child-displacement-x", &child_displacement_x,
1608                             "displace-focus", &displace_focus,
1609                             NULL);
1610
1611       if (interior_focus)
1612         {
1613           x += style->xthickness + focus_pad;
1614           y += style->ythickness + focus_pad;
1615           width -= 2 * (style->xthickness + focus_pad);
1616           height -=  2 * (style->ythickness + focus_pad);
1617         }
1618       else
1619         {
1620           x -= focus_width + focus_pad;
1621           y -= focus_width + focus_pad;
1622           width += 2 * (focus_width + focus_pad);
1623           height += 2 * (focus_width + focus_pad);
1624         }
1625
1626       if (priv->depressed && displace_focus)
1627         {
1628           x += child_displacement_x;
1629           y += child_displacement_y;
1630         }
1631
1632       gtk_paint_focus (style, cr,
1633                        gtk_widget_get_state (widget),
1634                        widget, "button",
1635                        x, y, width, height);
1636     }
1637 }
1638
1639 static gboolean
1640 gtk_button_draw (GtkWidget *widget,
1641                  cairo_t   *cr)
1642 {
1643   GtkButton *button = GTK_BUTTON (widget);
1644   GtkButtonPrivate *priv = button->priv;
1645
1646   _gtk_button_paint (button, cr, 
1647                      gtk_widget_get_allocated_width (widget),
1648                      gtk_widget_get_allocated_height (widget),
1649                      gtk_widget_get_state (widget),
1650                      priv->depressed ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
1651                      "button", "buttondefault");
1652
1653   GTK_WIDGET_CLASS (gtk_button_parent_class)->draw (widget, cr);
1654
1655   return FALSE;
1656 }
1657
1658 static gboolean
1659 gtk_button_button_press (GtkWidget      *widget,
1660                          GdkEventButton *event)
1661 {
1662   GtkButton *button;
1663   GtkButtonPrivate *priv;
1664
1665   if (event->type == GDK_BUTTON_PRESS)
1666     {
1667       button = GTK_BUTTON (widget);
1668       priv = button->priv;
1669
1670       if (priv->focus_on_click && !gtk_widget_has_focus (widget))
1671         gtk_widget_grab_focus (widget);
1672
1673       if (event->button == 1)
1674         gtk_button_pressed (button);
1675     }
1676
1677   return TRUE;
1678 }
1679
1680 static gboolean
1681 gtk_button_button_release (GtkWidget      *widget,
1682                            GdkEventButton *event)
1683 {
1684   GtkButton *button;
1685
1686   if (event->button == 1)
1687     {
1688       button = GTK_BUTTON (widget);
1689       gtk_button_released (button);
1690     }
1691
1692   return TRUE;
1693 }
1694
1695 static gboolean
1696 gtk_button_grab_broken (GtkWidget          *widget,
1697                         GdkEventGrabBroken *event)
1698 {
1699   GtkButton *button = GTK_BUTTON (widget);
1700   GtkButtonPrivate *priv = button->priv;
1701   gboolean save_in;
1702   
1703   /* Simulate a button release without the pointer in the button */
1704   if (priv->button_down)
1705     {
1706       save_in = priv->in_button;
1707       priv->in_button = FALSE;
1708       gtk_button_released (button);
1709       if (save_in != priv->in_button)
1710         {
1711           priv->in_button = save_in;
1712           gtk_button_update_state (button);
1713         }
1714     }
1715
1716   return TRUE;
1717 }
1718
1719 static gboolean
1720 gtk_button_key_release (GtkWidget   *widget,
1721                         GdkEventKey *event)
1722 {
1723   GtkButton *button = GTK_BUTTON (widget);
1724   GtkButtonPrivate *priv = button->priv;
1725
1726   if (priv->activate_timeout)
1727     {
1728       gtk_button_finish_activate (button, TRUE);
1729       return TRUE;
1730     }
1731   else if (GTK_WIDGET_CLASS (gtk_button_parent_class)->key_release_event)
1732     return GTK_WIDGET_CLASS (gtk_button_parent_class)->key_release_event (widget, event);
1733   else
1734     return FALSE;
1735 }
1736
1737 static gboolean
1738 gtk_button_enter_notify (GtkWidget        *widget,
1739                          GdkEventCrossing *event)
1740 {
1741   GtkButton *button = GTK_BUTTON (widget);
1742   GtkButtonPrivate *priv = button->priv;
1743
1744   if ((event->window == button->priv->event_window) &&
1745       (event->detail != GDK_NOTIFY_INFERIOR))
1746     {
1747       priv->in_button = TRUE;
1748       gtk_button_enter (button);
1749     }
1750
1751   return FALSE;
1752 }
1753
1754 static gboolean
1755 gtk_button_leave_notify (GtkWidget        *widget,
1756                          GdkEventCrossing *event)
1757 {
1758   GtkButton *button = GTK_BUTTON (widget);
1759   GtkButtonPrivate *priv = button->priv;
1760
1761   if ((event->window == button->priv->event_window) &&
1762       (event->detail != GDK_NOTIFY_INFERIOR) &&
1763       (gtk_widget_get_sensitive (widget)))
1764     {
1765       priv->in_button = FALSE;
1766       gtk_button_leave (button);
1767     }
1768
1769   return FALSE;
1770 }
1771
1772 static void
1773 gtk_real_button_pressed (GtkButton *button)
1774 {
1775   GtkButtonPrivate *priv = button->priv;
1776
1777   if (priv->activate_timeout)
1778     return;
1779
1780   priv->button_down = TRUE;
1781   gtk_button_update_state (button);
1782 }
1783
1784 static void
1785 gtk_real_button_released (GtkButton *button)
1786 {
1787   GtkButtonPrivate *priv = button->priv;
1788
1789   if (priv->button_down)
1790     {
1791       priv->button_down = FALSE;
1792
1793       if (priv->activate_timeout)
1794         return;
1795
1796       if (priv->in_button)
1797         gtk_button_clicked (button);
1798
1799       gtk_button_update_state (button);
1800     }
1801 }
1802
1803 static void 
1804 gtk_real_button_clicked (GtkButton *button)
1805 {
1806   GtkButtonPrivate *priv = button->priv;
1807
1808   if (priv->action)
1809     gtk_action_activate (priv->action);
1810 }
1811
1812 static gboolean
1813 button_activate_timeout (gpointer data)
1814 {
1815   gtk_button_finish_activate (data, TRUE);
1816
1817   return FALSE;
1818 }
1819
1820 static void
1821 gtk_real_button_activate (GtkButton *button)
1822 {
1823   GtkWidget *widget = GTK_WIDGET (button);
1824   GtkButtonPrivate *priv = button->priv;
1825   GdkDevice *device;
1826   guint32 time;
1827
1828   device = gtk_get_current_event_device ();
1829
1830   if (device && gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
1831     device = gdk_device_get_associated_device (device);
1832
1833   g_return_if_fail (device && gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD);
1834
1835   if (gtk_widget_get_realized (widget) && !priv->activate_timeout)
1836     {
1837       time = gtk_get_current_event_time ();
1838
1839       if (gdk_device_grab (device, priv->event_window,
1840                            GDK_OWNERSHIP_WINDOW, TRUE,
1841                            GDK_KEY_PRESS | GDK_KEY_RELEASE,
1842                            NULL, time) == GDK_GRAB_SUCCESS)
1843         {
1844           gtk_device_grab_add (widget, device, TRUE);
1845           priv->grab_keyboard = device;
1846           priv->grab_time = time;
1847         }
1848
1849       priv->activate_timeout = gdk_threads_add_timeout (ACTIVATE_TIMEOUT,
1850                                                 button_activate_timeout,
1851                                                 button);
1852       priv->button_down = TRUE;
1853       gtk_button_update_state (button);
1854       gtk_widget_queue_draw (GTK_WIDGET (button));
1855     }
1856 }
1857
1858 static void
1859 gtk_button_finish_activate (GtkButton *button,
1860                             gboolean   do_it)
1861 {
1862   GtkWidget *widget = GTK_WIDGET (button);
1863   GtkButtonPrivate *priv = button->priv;
1864
1865   g_source_remove (priv->activate_timeout);
1866   priv->activate_timeout = 0;
1867
1868   if (priv->grab_keyboard)
1869     {
1870       gdk_device_ungrab (priv->grab_keyboard, priv->grab_time);
1871       gtk_device_grab_remove (widget, priv->grab_keyboard);
1872       priv->grab_keyboard = NULL;
1873     }
1874
1875   priv->button_down = FALSE;
1876
1877   gtk_button_update_state (button);
1878   gtk_widget_queue_draw (GTK_WIDGET (button));
1879
1880   if (do_it)
1881     gtk_button_clicked (button);
1882 }
1883
1884
1885 static void
1886 gtk_button_get_size (GtkWidget      *widget,
1887                      GtkOrientation  orientation,
1888                      gint           *minimum_size,
1889                      gint           *natural_size)
1890 {
1891   GtkButton *button = GTK_BUTTON (widget);
1892   GtkStyle *style;
1893   GtkWidget *child;
1894   GtkBorder default_border;
1895   GtkBorder inner_border;
1896   gint focus_width;
1897   gint focus_pad;
1898   gint minimum, natural;
1899
1900   gtk_button_get_props (button, &default_border, NULL, &inner_border, NULL);
1901   gtk_widget_style_get (GTK_WIDGET (widget),
1902                         "focus-line-width", &focus_width,
1903                         "focus-padding", &focus_pad,
1904                         NULL);
1905
1906   style = gtk_widget_get_style (GTK_WIDGET (widget));
1907
1908   if (orientation == GTK_ORIENTATION_HORIZONTAL)
1909     {
1910       minimum = (style->xthickness * 2 +
1911                  inner_border.left + inner_border.right);
1912
1913       if (gtk_widget_get_can_default (GTK_WIDGET (widget)))
1914         minimum += default_border.left + default_border.right;
1915     }
1916   else
1917     {
1918       minimum = (style->ythickness * 2 +
1919                  inner_border.top + inner_border.bottom);
1920
1921       if (gtk_widget_get_can_default (GTK_WIDGET (widget)))
1922         minimum += default_border.top + default_border.bottom;
1923     }  
1924
1925   minimum += 2 * (focus_width + focus_pad);
1926   natural = minimum;
1927
1928   if ((child = gtk_bin_get_child (GTK_BIN (button))) && 
1929       gtk_widget_get_visible (child))
1930     {
1931       gint child_min, child_nat;
1932
1933       if (orientation == GTK_ORIENTATION_HORIZONTAL)
1934         gtk_widget_get_preferred_width (child, &child_min, &child_nat);
1935       else
1936         gtk_widget_get_preferred_height (child, &child_min, &child_nat);
1937
1938       minimum += child_min;
1939       natural += child_nat;
1940     }
1941
1942   if (minimum_size)
1943     *minimum_size = minimum;
1944
1945   if (natural_size)
1946     *natural_size = natural;
1947 }
1948
1949 static void 
1950 gtk_button_get_preferred_width (GtkWidget *widget,
1951                                 gint      *minimum_size,
1952                                 gint      *natural_size)
1953 {
1954   gtk_button_get_size (widget, GTK_ORIENTATION_HORIZONTAL, minimum_size, natural_size);
1955 }
1956
1957 static void 
1958 gtk_button_get_preferred_height (GtkWidget *widget,
1959                                  gint      *minimum_size,
1960                                  gint      *natural_size)
1961 {
1962   gtk_button_get_size (widget, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size);
1963 }
1964
1965 /**
1966  * gtk_button_set_label:
1967  * @button: a #GtkButton
1968  * @label: a string
1969  *
1970  * Sets the text of the label of the button to @str. This text is
1971  * also used to select the stock item if gtk_button_set_use_stock()
1972  * is used.
1973  *
1974  * This will also clear any previously set labels.
1975  **/
1976 void
1977 gtk_button_set_label (GtkButton   *button,
1978                       const gchar *label)
1979 {
1980   GtkButtonPrivate *priv;
1981   gchar *new_label;
1982
1983   g_return_if_fail (GTK_IS_BUTTON (button));
1984
1985   priv = button->priv;
1986
1987   new_label = g_strdup (label);
1988   g_free (priv->label_text);
1989   priv->label_text = new_label;
1990
1991   gtk_button_construct_child (button);
1992   
1993   g_object_notify (G_OBJECT (button), "label");
1994 }
1995
1996 /**
1997  * gtk_button_get_label:
1998  * @button: a #GtkButton
1999  *
2000  * Fetches the text from the label of the button, as set by
2001  * gtk_button_set_label(). If the label text has not 
2002  * been set the return value will be %NULL. This will be the 
2003  * case if you create an empty button with gtk_button_new() to 
2004  * use as a container.
2005  *
2006  * Return value: The text of the label widget. This string is owned
2007  * by the widget and must not be modified or freed.
2008  **/
2009 G_CONST_RETURN gchar *
2010 gtk_button_get_label (GtkButton *button)
2011 {
2012   g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
2013
2014   return button->priv->label_text;
2015 }
2016
2017 /**
2018  * gtk_button_set_use_underline:
2019  * @button: a #GtkButton
2020  * @use_underline: %TRUE if underlines in the text indicate mnemonics
2021  *
2022  * If true, an underline in the text of the button label indicates
2023  * the next character should be used for the mnemonic accelerator key.
2024  */
2025 void
2026 gtk_button_set_use_underline (GtkButton *button,
2027                               gboolean   use_underline)
2028 {
2029   GtkButtonPrivate *priv;
2030
2031   g_return_if_fail (GTK_IS_BUTTON (button));
2032
2033   priv = button->priv;
2034
2035   use_underline = use_underline != FALSE;
2036
2037   if (use_underline != priv->use_underline)
2038     {
2039       priv->use_underline = use_underline;
2040
2041       gtk_button_construct_child (button);
2042       
2043       g_object_notify (G_OBJECT (button), "use-underline");
2044     }
2045 }
2046
2047 /**
2048  * gtk_button_get_use_underline:
2049  * @button: a #GtkButton
2050  *
2051  * Returns whether an embedded underline in the button label indicates a
2052  * mnemonic. See gtk_button_set_use_underline ().
2053  *
2054  * Return value: %TRUE if an embedded underline in the button label
2055  *               indicates the mnemonic accelerator keys.
2056  **/
2057 gboolean
2058 gtk_button_get_use_underline (GtkButton *button)
2059 {
2060   g_return_val_if_fail (GTK_IS_BUTTON (button), FALSE);
2061
2062   return button->priv->use_underline;
2063 }
2064
2065 /**
2066  * gtk_button_set_use_stock:
2067  * @button: a #GtkButton
2068  * @use_stock: %TRUE if the button should use a stock item
2069  *
2070  * If %TRUE, the label set on the button is used as a
2071  * stock id to select the stock item for the button.
2072  */
2073 void
2074 gtk_button_set_use_stock (GtkButton *button,
2075                           gboolean   use_stock)
2076 {
2077   GtkButtonPrivate *priv;
2078
2079   g_return_if_fail (GTK_IS_BUTTON (button));
2080
2081   priv = button->priv;
2082
2083   use_stock = use_stock != FALSE;
2084
2085   if (use_stock != priv->use_stock)
2086     {
2087       priv->use_stock = use_stock;
2088
2089       gtk_button_construct_child (button);
2090       
2091       g_object_notify (G_OBJECT (button), "use-stock");
2092     }
2093 }
2094
2095 /**
2096  * gtk_button_get_use_stock:
2097  * @button: a #GtkButton
2098  *
2099  * Returns whether the button label is a stock item.
2100  *
2101  * Return value: %TRUE if the button label is used to
2102  *               select a stock item instead of being
2103  *               used directly as the label text.
2104  */
2105 gboolean
2106 gtk_button_get_use_stock (GtkButton *button)
2107 {
2108   g_return_val_if_fail (GTK_IS_BUTTON (button), FALSE);
2109
2110   return button->priv->use_stock;
2111 }
2112
2113 /**
2114  * gtk_button_set_focus_on_click:
2115  * @button: a #GtkButton
2116  * @focus_on_click: whether the button grabs focus when clicked with the mouse
2117  *
2118  * Sets whether the button will grab focus when it is clicked with the mouse.
2119  * Making mouse clicks not grab focus is useful in places like toolbars where
2120  * you don't want the keyboard focus removed from the main area of the
2121  * application.
2122  *
2123  * Since: 2.4
2124  **/
2125 void
2126 gtk_button_set_focus_on_click (GtkButton *button,
2127                                gboolean   focus_on_click)
2128 {
2129   GtkButtonPrivate *priv;
2130
2131   g_return_if_fail (GTK_IS_BUTTON (button));
2132
2133   priv = button->priv;
2134
2135   focus_on_click = focus_on_click != FALSE;
2136
2137   if (priv->focus_on_click != focus_on_click)
2138     {
2139       priv->focus_on_click = focus_on_click;
2140       
2141       g_object_notify (G_OBJECT (button), "focus-on-click");
2142     }
2143 }
2144
2145 /**
2146  * gtk_button_get_focus_on_click:
2147  * @button: a #GtkButton
2148  *
2149  * Returns whether the button grabs focus when it is clicked with the mouse.
2150  * See gtk_button_set_focus_on_click().
2151  *
2152  * Return value: %TRUE if the button grabs focus when it is clicked with
2153  *               the mouse.
2154  *
2155  * Since: 2.4
2156  **/
2157 gboolean
2158 gtk_button_get_focus_on_click (GtkButton *button)
2159 {
2160   g_return_val_if_fail (GTK_IS_BUTTON (button), FALSE);
2161   
2162   return button->priv->focus_on_click;
2163 }
2164
2165 /**
2166  * gtk_button_set_alignment:
2167  * @button: a #GtkButton
2168  * @xalign: the horizontal position of the child, 0.0 is left aligned, 
2169  *   1.0 is right aligned
2170  * @yalign: the vertical position of the child, 0.0 is top aligned, 
2171  *   1.0 is bottom aligned
2172  *
2173  * Sets the alignment of the child. This property has no effect unless 
2174  * the child is a #GtkMisc or a #GtkAlignment.
2175  *
2176  * Since: 2.4
2177  */
2178 void
2179 gtk_button_set_alignment (GtkButton *button,
2180                           gfloat     xalign,
2181                           gfloat     yalign)
2182 {
2183   GtkButtonPrivate *priv;
2184
2185   g_return_if_fail (GTK_IS_BUTTON (button));
2186   
2187   priv = button->priv;
2188
2189   priv->xalign = xalign;
2190   priv->yalign = yalign;
2191   priv->align_set = 1;
2192
2193   maybe_set_alignment (button, gtk_bin_get_child (GTK_BIN (button)));
2194
2195   g_object_freeze_notify (G_OBJECT (button));
2196   g_object_notify (G_OBJECT (button), "xalign");
2197   g_object_notify (G_OBJECT (button), "yalign");
2198   g_object_thaw_notify (G_OBJECT (button));
2199 }
2200
2201 /**
2202  * gtk_button_get_alignment:
2203  * @button: a #GtkButton
2204  * @xalign: return location for horizontal alignment
2205  * @yalign: return location for vertical alignment
2206  *
2207  * Gets the alignment of the child in the button.
2208  *
2209  * Since: 2.4
2210  */
2211 void
2212 gtk_button_get_alignment (GtkButton *button,
2213                           gfloat    *xalign,
2214                           gfloat    *yalign)
2215 {
2216   GtkButtonPrivate *priv;
2217
2218   g_return_if_fail (GTK_IS_BUTTON (button));
2219   
2220   priv = button->priv;
2221  
2222   if (xalign) 
2223     *xalign = priv->xalign;
2224
2225   if (yalign)
2226     *yalign = priv->yalign;
2227 }
2228
2229 /**
2230  * _gtk_button_set_depressed:
2231  * @button: a #GtkButton
2232  * @depressed: %TRUE if the button should be drawn with a recessed shadow.
2233  *
2234  * Sets whether the button is currently drawn as down or not. This is 
2235  * purely a visual setting, and is meant only for use by derived widgets
2236  * such as #GtkToggleButton.
2237  **/
2238 void
2239 _gtk_button_set_depressed (GtkButton *button,
2240                            gboolean   depressed)
2241 {
2242   GtkWidget *widget = GTK_WIDGET (button);
2243   GtkButtonPrivate *priv = button->priv;
2244
2245   depressed = depressed != FALSE;
2246
2247   if (depressed != priv->depressed)
2248     {
2249       priv->depressed = depressed;
2250       gtk_widget_queue_resize (widget);
2251     }
2252 }
2253
2254 static void
2255 gtk_button_update_state (GtkButton *button)
2256 {
2257   GtkButtonPrivate *priv = button->priv;
2258   GtkStateType new_state;
2259   gboolean depressed;
2260
2261   if (priv->activate_timeout)
2262     depressed = priv->depress_on_activate;
2263   else
2264     depressed = priv->in_button && priv->button_down;
2265
2266   if (priv->in_button && (!priv->button_down || !depressed))
2267     new_state = GTK_STATE_PRELIGHT;
2268   else
2269     new_state = depressed ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL;
2270
2271   _gtk_button_set_depressed (button, depressed); 
2272   gtk_widget_set_state (GTK_WIDGET (button), new_state);
2273 }
2274
2275 static void 
2276 show_image_change_notify (GtkButton *button)
2277 {
2278   GtkButtonPrivate *priv = button->priv;
2279
2280   if (priv->image) 
2281     {
2282       if (show_image (button))
2283         gtk_widget_show (priv->image);
2284       else
2285         gtk_widget_hide (priv->image);
2286     }
2287 }
2288
2289 static void
2290 traverse_container (GtkWidget *widget,
2291                     gpointer   data)
2292 {
2293   if (GTK_IS_BUTTON (widget))
2294     show_image_change_notify (GTK_BUTTON (widget));
2295   else if (GTK_IS_CONTAINER (widget))
2296     gtk_container_forall (GTK_CONTAINER (widget), traverse_container, NULL);
2297 }
2298
2299 static void
2300 gtk_button_setting_changed (GtkSettings *settings)
2301 {
2302   GList *list, *l;
2303
2304   list = gtk_window_list_toplevels ();
2305
2306   for (l = list; l; l = l->next)
2307     gtk_container_forall (GTK_CONTAINER (l->data), 
2308                           traverse_container, NULL);
2309
2310   g_list_free (list);
2311 }
2312
2313
2314 static void
2315 gtk_button_screen_changed (GtkWidget *widget,
2316                            GdkScreen *previous_screen)
2317 {
2318   GtkButton *button;
2319   GtkButtonPrivate *priv;
2320   GtkSettings *settings;
2321   gulong show_image_connection;
2322
2323   if (!gtk_widget_has_screen (widget))
2324     return;
2325
2326   button = GTK_BUTTON (widget);
2327   priv = button->priv;
2328
2329   /* If the button is being pressed while the screen changes the
2330     release might never occur, so we reset the state. */
2331   if (priv->button_down)
2332     {
2333       priv->button_down = FALSE;
2334       gtk_button_update_state (button);
2335     }
2336
2337   settings = gtk_widget_get_settings (widget);
2338
2339   show_image_connection = 
2340     g_signal_handler_find (settings, G_SIGNAL_MATCH_FUNC, 0, 0,
2341                            NULL, gtk_button_setting_changed, NULL);
2342   
2343   if (show_image_connection)
2344     return;
2345
2346   g_signal_connect (settings, "notify::gtk-button-images",
2347                     G_CALLBACK (gtk_button_setting_changed), NULL);
2348
2349   show_image_change_notify (button);
2350 }
2351
2352 static void
2353 gtk_button_state_changed (GtkWidget    *widget,
2354                           GtkStateType  previous_state)
2355 {
2356   GtkButton *button = GTK_BUTTON (widget);
2357   GtkButtonPrivate *priv = button->priv;
2358
2359   if (!gtk_widget_is_sensitive (widget))
2360     {
2361       priv->in_button = FALSE;
2362       gtk_real_button_released (button);
2363     }
2364 }
2365
2366 static void
2367 gtk_button_grab_notify (GtkWidget *widget,
2368                         gboolean   was_grabbed)
2369 {
2370   GtkButton *button = GTK_BUTTON (widget);
2371   GtkButtonPrivate *priv = button->priv;
2372   gboolean save_in;
2373
2374   if (priv->activate_timeout &&
2375       priv->grab_keyboard &&
2376       gtk_widget_device_is_shadowed (widget, priv->grab_keyboard))
2377     gtk_button_finish_activate (button, FALSE);
2378
2379   if (!was_grabbed)
2380     {
2381       save_in = priv->in_button;
2382       priv->in_button = FALSE;
2383       gtk_real_button_released (button);
2384       if (save_in != priv->in_button)
2385         {
2386           priv->in_button = save_in;
2387           gtk_button_update_state (button);
2388         }
2389     }
2390 }
2391
2392 /**
2393  * gtk_button_set_image:
2394  * @button: a #GtkButton
2395  * @image: a widget to set as the image for the button
2396  *
2397  * Set the image of @button to the given widget. Note that
2398  * it depends on the #GtkSettings:gtk-button-images setting whether the
2399  * image will be displayed or not, you don't have to call
2400  * gtk_widget_show() on @image yourself.
2401  *
2402  * Since: 2.6
2403  */ 
2404 void
2405 gtk_button_set_image (GtkButton *button,
2406                       GtkWidget *image)
2407 {
2408   GtkButtonPrivate *priv;
2409   GtkWidget *parent;
2410
2411   g_return_if_fail (GTK_IS_BUTTON (button));
2412   g_return_if_fail (image == NULL || GTK_IS_WIDGET (image));
2413
2414   priv = button->priv;
2415
2416   if (priv->image)
2417     {
2418       parent = gtk_widget_get_parent (priv->image);
2419       if (parent)
2420         gtk_container_remove (GTK_CONTAINER (parent), priv->image);
2421     }
2422
2423   priv->image = image;
2424   priv->image_is_stock = (image == NULL);
2425
2426   gtk_button_construct_child (button);
2427
2428   g_object_notify (G_OBJECT (button), "image");
2429 }
2430
2431 /**
2432  * gtk_button_get_image:
2433  * @button: a #GtkButton
2434  *
2435  * Gets the widget that is currenty set as the image of @button.
2436  * This may have been explicitly set by gtk_button_set_image()
2437  * or constructed by gtk_button_new_from_stock().
2438  *
2439  * Return value: (transfer none): a #GtkWidget or %NULL in case there is no image
2440  *
2441  * Since: 2.6
2442  */
2443 GtkWidget *
2444 gtk_button_get_image (GtkButton *button)
2445 {
2446   g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
2447   
2448   return button->priv->image;
2449 }
2450
2451 /**
2452  * gtk_button_set_image_position:
2453  * @button: a #GtkButton
2454  * @position: the position
2455  *
2456  * Sets the position of the image relative to the text 
2457  * inside the button.
2458  *
2459  * Since: 2.10
2460  */ 
2461 void
2462 gtk_button_set_image_position (GtkButton       *button,
2463                                GtkPositionType  position)
2464 {
2465   GtkButtonPrivate *priv;
2466
2467   g_return_if_fail (GTK_IS_BUTTON (button));
2468   g_return_if_fail (position >= GTK_POS_LEFT && position <= GTK_POS_BOTTOM);
2469   
2470   priv = button->priv;
2471
2472   if (priv->image_position != position)
2473     {
2474       priv->image_position = position;
2475
2476       gtk_button_construct_child (button);
2477
2478       g_object_notify (G_OBJECT (button), "image-position");
2479     }
2480 }
2481
2482 /**
2483  * gtk_button_get_image_position:
2484  * @button: a #GtkButton
2485  *
2486  * Gets the position of the image relative to the text 
2487  * inside the button.
2488  *
2489  * Return value: the position
2490  *
2491  * Since: 2.10
2492  */
2493 GtkPositionType
2494 gtk_button_get_image_position (GtkButton *button)
2495 {
2496   g_return_val_if_fail (GTK_IS_BUTTON (button), GTK_POS_LEFT);
2497   
2498   return button->priv->image_position;
2499 }
2500
2501
2502 /**
2503  * gtk_button_get_event_window:
2504  * @button: a #GtkButton
2505  *
2506  * Returns the button's event window if it is realized, %NULL otherwise.
2507  * This function should be rarely needed.
2508  *
2509  * Return value: (transfer none): @button's event window.
2510  *
2511  * Since: 2.22
2512  */
2513 GdkWindow*
2514 gtk_button_get_event_window (GtkButton *button)
2515 {
2516   g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
2517
2518   return button->priv->event_window;
2519 }