1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 #include "gtkbutton.h"
23 #include "gtksignal.h"
26 #define CHILD_SPACING 1
27 #define DEFAULT_LEFT_POS 4
28 #define DEFAULT_TOP_POS 4
29 #define DEFAULT_SPACING 7
48 static void gtk_button_class_init (GtkButtonClass *klass);
49 static void gtk_button_init (GtkButton *button);
50 static void gtk_button_set_arg (GtkObject *object,
53 static void gtk_button_get_arg (GtkObject *object,
56 static void gtk_button_realize (GtkWidget *widget);
57 static void gtk_button_size_request (GtkWidget *widget,
58 GtkRequisition *requisition);
59 static void gtk_button_size_allocate (GtkWidget *widget,
60 GtkAllocation *allocation);
61 static void gtk_button_paint (GtkWidget *widget,
63 static void gtk_button_draw (GtkWidget *widget,
65 static void gtk_button_draw_focus (GtkWidget *widget);
66 static void gtk_button_draw_default (GtkWidget *widget);
67 static gint gtk_button_expose (GtkWidget *widget,
68 GdkEventExpose *event);
69 static gint gtk_button_button_press (GtkWidget *widget,
70 GdkEventButton *event);
71 static gint gtk_button_button_release (GtkWidget *widget,
72 GdkEventButton *event);
73 static gint gtk_button_enter_notify (GtkWidget *widget,
74 GdkEventCrossing *event);
75 static gint gtk_button_leave_notify (GtkWidget *widget,
76 GdkEventCrossing *event);
77 static gint gtk_button_focus_in (GtkWidget *widget,
78 GdkEventFocus *event);
79 static gint gtk_button_focus_out (GtkWidget *widget,
80 GdkEventFocus *event);
81 static void gtk_button_add (GtkContainer *container,
83 static void gtk_button_remove (GtkContainer *container,
85 static void gtk_real_button_pressed (GtkButton *button);
86 static void gtk_real_button_released (GtkButton *button);
87 static void gtk_real_button_enter (GtkButton *button);
88 static void gtk_real_button_leave (GtkButton *button);
89 static GtkType gtk_button_child_type (GtkContainer *container);
92 static GtkBinClass *parent_class = NULL;
93 static guint button_signals[LAST_SIGNAL] = { 0 };
97 gtk_button_get_type (void)
99 static GtkType button_type = 0;
103 GtkTypeInfo button_info =
107 sizeof (GtkButtonClass),
108 (GtkClassInitFunc) gtk_button_class_init,
109 (GtkObjectInitFunc) gtk_button_init,
110 /* reserved_1 */ NULL,
111 /* reserved_2 */ NULL,
112 (GtkClassInitFunc) NULL,
115 button_type = gtk_type_unique (GTK_TYPE_BIN, &button_info);
116 gtk_type_set_chunk_alloc (button_type, 16);
123 gtk_button_class_init (GtkButtonClass *klass)
125 GtkObjectClass *object_class;
126 GtkWidgetClass *widget_class;
127 GtkContainerClass *container_class;
129 object_class = (GtkObjectClass*) klass;
130 widget_class = (GtkWidgetClass*) klass;
131 container_class = (GtkContainerClass*) klass;
133 parent_class = gtk_type_class (GTK_TYPE_BIN);
135 gtk_object_add_arg_type ("GtkButton::label", GTK_TYPE_STRING, GTK_ARG_READWRITE, ARG_LABEL);
136 gtk_object_add_arg_type ("GtkButton::relief", GTK_TYPE_RELIEF_STYLE, GTK_ARG_READWRITE, ARG_RELIEF);
138 button_signals[PRESSED] =
139 gtk_signal_new ("pressed",
142 GTK_SIGNAL_OFFSET (GtkButtonClass, pressed),
143 gtk_marshal_NONE__NONE,
145 button_signals[RELEASED] =
146 gtk_signal_new ("released",
149 GTK_SIGNAL_OFFSET (GtkButtonClass, released),
150 gtk_marshal_NONE__NONE,
152 button_signals[CLICKED] =
153 gtk_signal_new ("clicked",
156 GTK_SIGNAL_OFFSET (GtkButtonClass, clicked),
157 gtk_marshal_NONE__NONE,
159 button_signals[ENTER] =
160 gtk_signal_new ("enter",
163 GTK_SIGNAL_OFFSET (GtkButtonClass, enter),
164 gtk_marshal_NONE__NONE,
166 button_signals[LEAVE] =
167 gtk_signal_new ("leave",
170 GTK_SIGNAL_OFFSET (GtkButtonClass, leave),
171 gtk_marshal_NONE__NONE,
174 gtk_object_class_add_signals (object_class, button_signals, LAST_SIGNAL);
176 object_class->set_arg = gtk_button_set_arg;
177 object_class->get_arg = gtk_button_get_arg;
179 widget_class->activate_signal = button_signals[CLICKED];
180 widget_class->realize = gtk_button_realize;
181 widget_class->draw = gtk_button_draw;
182 widget_class->draw_focus = gtk_button_draw_focus;
183 widget_class->draw_default = gtk_button_draw_default;
184 widget_class->size_request = gtk_button_size_request;
185 widget_class->size_allocate = gtk_button_size_allocate;
186 widget_class->expose_event = gtk_button_expose;
187 widget_class->button_press_event = gtk_button_button_press;
188 widget_class->button_release_event = gtk_button_button_release;
189 widget_class->enter_notify_event = gtk_button_enter_notify;
190 widget_class->leave_notify_event = gtk_button_leave_notify;
191 widget_class->focus_in_event = gtk_button_focus_in;
192 widget_class->focus_out_event = gtk_button_focus_out;
194 container_class->add = gtk_button_add;
195 container_class->remove = gtk_button_remove;
196 container_class->child_type = gtk_button_child_type;
198 klass->pressed = gtk_real_button_pressed;
199 klass->released = gtk_real_button_released;
200 klass->clicked = NULL;
201 klass->enter = gtk_real_button_enter;
202 klass->leave = gtk_real_button_leave;
206 gtk_button_init (GtkButton *button)
208 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_FOCUS);
209 GTK_WIDGET_UNSET_FLAGS (button, GTK_NO_WINDOW);
211 button->child = NULL;
212 button->in_button = FALSE;
213 button->button_down = FALSE;
214 button->relief = GTK_RELIEF_NORMAL;
218 gtk_button_child_type (GtkContainer *container)
220 if (!GTK_BIN (container)->child)
221 return GTK_TYPE_WIDGET;
223 return GTK_TYPE_NONE;
227 gtk_button_set_arg (GtkObject *object,
233 button = GTK_BUTTON (object);
240 child = GTK_BIN (button)->child;
242 child = gtk_widget_new (GTK_TYPE_LABEL,
246 if (GTK_IS_LABEL (child))
247 gtk_label_set (GTK_LABEL (child),
248 GTK_VALUE_STRING (*arg) ? GTK_VALUE_STRING (*arg) : "");
251 gtk_button_set_relief (button, GTK_VALUE_ENUM (*arg));
259 gtk_button_get_arg (GtkObject *object,
265 button = GTK_BUTTON (object);
270 if (GTK_BIN (button)->child && GTK_IS_LABEL (GTK_BIN (button)->child))
271 GTK_VALUE_STRING (*arg) = g_strdup (GTK_LABEL (GTK_BIN (button)->child)->label);
273 GTK_VALUE_STRING (*arg) = NULL;
276 GTK_VALUE_ENUM (*arg) = gtk_button_get_relief (button);
279 arg->type = GTK_TYPE_INVALID;
285 gtk_button_new (void)
287 return GTK_WIDGET (gtk_type_new (gtk_button_get_type ()));
291 gtk_button_new_with_label (const gchar *label)
294 GtkWidget *label_widget;
296 button = gtk_button_new ();
297 label_widget = gtk_label_new (label);
298 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.5, 0.5);
300 gtk_container_add (GTK_CONTAINER (button), label_widget);
301 gtk_widget_show (label_widget);
307 gtk_button_pressed (GtkButton *button)
309 gtk_signal_emit (GTK_OBJECT (button), button_signals[PRESSED]);
313 gtk_button_released (GtkButton *button)
315 gtk_signal_emit (GTK_OBJECT (button), button_signals[RELEASED]);
319 gtk_button_clicked (GtkButton *button)
321 gtk_signal_emit (GTK_OBJECT (button), button_signals[CLICKED]);
325 gtk_button_enter (GtkButton *button)
327 gtk_signal_emit (GTK_OBJECT (button), button_signals[ENTER]);
331 gtk_button_leave (GtkButton *button)
333 gtk_signal_emit (GTK_OBJECT (button), button_signals[LEAVE]);
337 gtk_button_set_relief (GtkButton *button,
338 GtkReliefStyle newrelief)
340 g_return_if_fail (button != NULL);
341 g_return_if_fail (GTK_IS_BUTTON (button));
343 button->relief = newrelief;
344 gtk_widget_queue_draw (GTK_WIDGET (button));
348 gtk_button_get_relief (GtkButton *button)
350 g_return_val_if_fail (button != NULL, GTK_RELIEF_NORMAL);
351 g_return_val_if_fail (GTK_IS_BUTTON (button), GTK_RELIEF_NORMAL);
353 return button->relief;
357 gtk_button_realize (GtkWidget *widget)
360 GdkWindowAttr attributes;
361 gint attributes_mask;
364 g_return_if_fail (widget != NULL);
365 g_return_if_fail (GTK_IS_BUTTON (widget));
367 button = GTK_BUTTON (widget);
368 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
370 border_width = GTK_CONTAINER (widget)->border_width;
372 attributes.window_type = GDK_WINDOW_CHILD;
373 attributes.x = widget->allocation.x + border_width;
374 attributes.y = widget->allocation.y + border_width;
375 attributes.width = widget->allocation.width - border_width * 2;
376 attributes.height = widget->allocation.height - border_width * 2;
377 attributes.wclass = GDK_INPUT_OUTPUT;
378 attributes.visual = gtk_widget_get_visual (widget);
379 attributes.colormap = gtk_widget_get_colormap (widget);
380 attributes.event_mask = gtk_widget_get_events (widget);
381 attributes.event_mask |= (GDK_EXPOSURE_MASK |
382 GDK_BUTTON_PRESS_MASK |
383 GDK_BUTTON_RELEASE_MASK |
384 GDK_ENTER_NOTIFY_MASK |
385 GDK_LEAVE_NOTIFY_MASK);
387 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
389 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
390 gdk_window_set_user_data (widget->window, button);
392 widget->style = gtk_style_attach (widget->style, widget->window);
393 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
397 gtk_button_size_request (GtkWidget *widget,
398 GtkRequisition *requisition)
402 g_return_if_fail (widget != NULL);
403 g_return_if_fail (GTK_IS_BUTTON (widget));
404 g_return_if_fail (requisition != NULL);
406 button = GTK_BUTTON (widget);
408 requisition->width = (GTK_CONTAINER (widget)->border_width + CHILD_SPACING +
409 GTK_WIDGET (widget)->style->klass->xthickness) * 2;
410 requisition->height = (GTK_CONTAINER (widget)->border_width + CHILD_SPACING +
411 GTK_WIDGET (widget)->style->klass->ythickness) * 2;
413 if (GTK_WIDGET_CAN_DEFAULT (widget))
415 requisition->width += (GTK_WIDGET (widget)->style->klass->xthickness * 2 +
417 requisition->height += (GTK_WIDGET (widget)->style->klass->ythickness * 2 +
421 if (GTK_BIN (button)->child && GTK_WIDGET_VISIBLE (GTK_BIN (button)->child))
423 gtk_widget_size_request (GTK_BIN (button)->child, >K_BIN (button)->child->requisition);
425 requisition->width += GTK_BIN (button)->child->requisition.width;
426 requisition->height += GTK_BIN (button)->child->requisition.height;
431 gtk_button_size_allocate (GtkWidget *widget,
432 GtkAllocation *allocation)
435 GtkAllocation child_allocation;
438 g_return_if_fail (widget != NULL);
439 g_return_if_fail (GTK_IS_BUTTON (widget));
440 g_return_if_fail (allocation != NULL);
442 widget->allocation = *allocation;
443 border_width = GTK_CONTAINER (widget)->border_width;
445 if (GTK_WIDGET_REALIZED (widget))
446 gdk_window_move_resize (widget->window,
447 widget->allocation.x + border_width,
448 widget->allocation.y + border_width,
449 widget->allocation.width - border_width * 2,
450 widget->allocation.height - border_width * 2);
452 button = GTK_BUTTON (widget);
454 if (GTK_BIN (button)->child && GTK_WIDGET_VISIBLE (GTK_BIN (button)->child))
456 child_allocation.x = (CHILD_SPACING + GTK_WIDGET (widget)->style->klass->xthickness);
457 child_allocation.y = (CHILD_SPACING + GTK_WIDGET (widget)->style->klass->ythickness);
459 child_allocation.width = MAX (1, widget->allocation.width - child_allocation.x * 2 -
461 child_allocation.height = MAX (1, widget->allocation.height - child_allocation.y * 2 -
464 if (GTK_WIDGET_CAN_DEFAULT (button))
466 child_allocation.x += (GTK_WIDGET (widget)->style->klass->xthickness +
468 child_allocation.y += (GTK_WIDGET (widget)->style->klass->ythickness +
470 child_allocation.width = MAX (1, child_allocation.width -
471 (GTK_WIDGET (widget)->style->klass->xthickness * 2 + DEFAULT_SPACING));
472 child_allocation.height = MAX (1, child_allocation.height -
473 (GTK_WIDGET (widget)->style->klass->xthickness * 2 + DEFAULT_SPACING));
476 gtk_widget_size_allocate (GTK_BIN (button)->child, &child_allocation);
481 * +------------------------------------------------+
483 * | +------------------------------------------+ |
484 * | |\\\\\\\\\\\\\\\\DEFAULT\\\\\\\\\\\\\\\\\ | |
485 * | |\\+------------------------------------+ | |
486 * | |\\| | SPACING 3 | | | |
487 * | |\\| +--------------------------------+ | | |
488 * | |\\| |########## FOCUS ###############| | | |
489 * | |\\| |#+----------------------------+#| | | |
490 * | |\\| |#| RELIEF \|#| | | |
491 * | |\\| |#| +-----------------------+\|#| | | |
492 * | |\\|1|#| + THE TEXT +\|#|2| | |
493 * | |\\| |#| +-----------------------+\|#| | | |
494 * | |\\| |#| \\\\\ ythickness \\\\\\\\\\|#| | | |
495 * | |\\| |#+----------------------------+#| | | |
496 * | |\\| |########### 1 ##################| | | |
497 * | |\\| +--------------------------------+ | | |
498 * | |\\| | default spacing 4 | | | |
499 * | |\\+------------------------------------+ | |
500 * | |\ ythickness | |
501 * | +------------------------------------------+ |
503 * +------------------------------------------------+
507 gtk_button_paint (GtkWidget *widget,
510 GdkRectangle restrict_area;
511 GdkRectangle outer_area;
512 GdkRectangle tmp_area;
513 GdkRectangle new_area;
517 g_return_if_fail (widget != NULL);
518 g_return_if_fail (GTK_IS_BUTTON (widget));
520 xthickness = widget->style->klass->xthickness;
521 ythickness = widget->style->klass->ythickness;
523 if (GTK_WIDGET_DRAWABLE (widget))
525 restrict_area.x = xthickness;
526 restrict_area.y = ythickness;
527 restrict_area.width = GTK_WIDGET (widget)->allocation.width -
528 restrict_area.x * 2 - GTK_CONTAINER (widget)->border_width * 2;
529 restrict_area.height = GTK_WIDGET (widget)->allocation.height -
530 restrict_area.y * 2 - GTK_CONTAINER (widget)->border_width * 2;
532 outer_area = restrict_area;
534 if (GTK_WIDGET_CAN_DEFAULT (widget))
536 restrict_area.x += DEFAULT_LEFT_POS;
537 restrict_area.y += DEFAULT_TOP_POS;
538 restrict_area.width -= DEFAULT_SPACING;
539 restrict_area.height -= DEFAULT_SPACING;
542 if (gdk_rectangle_intersect (area, &restrict_area, &new_area))
544 if ((GTK_WIDGET_STATE (widget) == GTK_STATE_PRELIGHT) &&
545 (GTK_BUTTON (widget)->relief != GTK_RELIEF_NORMAL))
546 gtk_style_set_background (widget->style, widget->window,
547 GTK_BUTTON (widget)->relief == GTK_RELIEF_NONE ? GTK_STATE_NORMAL : GTK_WIDGET_STATE (widget));
549 gtk_style_set_background (widget->style, widget->window, GTK_WIDGET_STATE (widget));
550 gdk_window_clear_area (widget->window,
551 new_area.x, new_area.y,
552 new_area.width, new_area.height);
555 if (GTK_WIDGET_CAN_DEFAULT (widget))
557 /* Now fill spacing area between the default border and the button */
559 /* 1 */ tmp_area = outer_area;
560 tmp_area.width = restrict_area.x - outer_area.x;
561 if (gdk_rectangle_intersect (area, &tmp_area, &new_area))
562 gdk_draw_rectangle (widget->window,
563 widget->style->bg_gc[GTK_STATE_NORMAL],
565 new_area.x, new_area.y,
566 new_area.width, new_area.height);
568 /* 2 */ tmp_area.x = restrict_area.x + restrict_area.width;
570 if (gdk_rectangle_intersect (area, &tmp_area, &new_area))
571 gdk_draw_rectangle (widget->window,
572 widget->style->bg_gc[GTK_STATE_NORMAL],
574 new_area.x, new_area.y,
575 new_area.width, new_area.height);
577 /* 3 */ tmp_area.width = restrict_area.width;
578 tmp_area.height = restrict_area.y - outer_area.y;
579 tmp_area.x = restrict_area.x;
581 if (gdk_rectangle_intersect (area, &tmp_area, &new_area))
582 gdk_draw_rectangle (widget->window,
583 widget->style->bg_gc[GTK_STATE_NORMAL],
585 new_area.x, new_area.y,
586 new_area.width, new_area.height);
588 /* 4 */ tmp_area.y = restrict_area.y + restrict_area.height;
590 if (gdk_rectangle_intersect (area, &tmp_area, &new_area))
591 gdk_draw_rectangle (widget->window,
592 widget->style->bg_gc[GTK_STATE_NORMAL],
594 new_area.x, new_area.y,
595 new_area.width, new_area.height);
601 gtk_button_draw (GtkWidget *widget,
605 GdkRectangle child_area;
606 GdkRectangle tmp_area;
608 g_return_if_fail (widget != NULL);
609 g_return_if_fail (GTK_IS_BUTTON (widget));
610 g_return_if_fail (area != NULL);
612 if (GTK_WIDGET_DRAWABLE (widget))
614 button = GTK_BUTTON (widget);
617 tmp_area.x -= GTK_CONTAINER (button)->border_width;
618 tmp_area.y -= GTK_CONTAINER (button)->border_width;
620 gtk_button_paint (widget, &tmp_area);
622 if (GTK_BIN (button)->child && gtk_widget_intersect (GTK_BIN (button)->child, &tmp_area, &child_area))
623 gtk_widget_draw (GTK_BIN (button)->child, &child_area);
625 gtk_widget_draw_default (widget);
626 gtk_widget_draw_focus (widget);
631 gtk_button_draw_focus (GtkWidget *widget)
634 GtkShadowType shadow_type;
638 g_return_if_fail (widget != NULL);
639 g_return_if_fail (GTK_IS_BUTTON (widget));
641 if (GTK_WIDGET_DRAWABLE (widget))
643 button = GTK_BUTTON (widget);
647 width = widget->allocation.width - GTK_CONTAINER (widget)->border_width * 2;
648 height = widget->allocation.height - GTK_CONTAINER (widget)->border_width * 2;
650 if (GTK_WIDGET_CAN_DEFAULT (widget))
652 x += widget->style->klass->xthickness;
653 y += widget->style->klass->ythickness;
654 width -= 2 * x + DEFAULT_SPACING;
655 height -= 2 * y + DEFAULT_SPACING;
656 x += DEFAULT_LEFT_POS;
657 y += DEFAULT_TOP_POS;
660 if (GTK_WIDGET_HAS_FOCUS (widget))
669 if (GTK_WIDGET_STATE (widget) == GTK_STATE_ACTIVE)
670 gdk_draw_rectangle (widget->window,
671 widget->style->bg_gc[GTK_WIDGET_STATE (widget)], FALSE,
672 x + 1, y + 1, width - 4, height - 4);
673 else if (button->relief == GTK_RELIEF_NORMAL)
674 gdk_draw_rectangle (widget->window,
675 widget->style->bg_gc[GTK_WIDGET_STATE (widget)], FALSE,
676 x + 2, y + 2, width - 5, height - 5);
678 gdk_draw_rectangle (widget->window,
679 widget->style->bg_gc[GTK_WIDGET_STATE (widget)], FALSE,
680 x, y, width - 1, height - 1);
683 if (GTK_WIDGET_STATE (widget) == GTK_STATE_ACTIVE)
684 shadow_type = GTK_SHADOW_IN;
686 shadow_type = GTK_SHADOW_OUT;
688 if ((button->relief == GTK_RELIEF_NORMAL) ||
689 ((GTK_WIDGET_STATE (widget) != GTK_STATE_NORMAL) &&
690 (GTK_WIDGET_STATE (widget) != GTK_STATE_INSENSITIVE)))
692 gtk_draw_shadow (widget->style, widget->window,
693 button->relief == GTK_RELIEF_NONE ? GTK_STATE_NORMAL : GTK_WIDGET_STATE (widget),
695 x, y, width, height);
698 if (GTK_WIDGET_HAS_FOCUS (widget))
705 gdk_draw_rectangle (widget->window,
706 widget->style->black_gc, FALSE,
707 x, y, width - 1, height - 1);
713 gtk_button_draw_default (GtkWidget *widget)
718 g_return_if_fail (widget != NULL);
719 g_return_if_fail (GTK_IS_BUTTON (widget));
721 if (GTK_WIDGET_DRAWABLE (widget))
725 width = widget->allocation.width - GTK_CONTAINER (widget)->border_width * 2;
726 height = widget->allocation.height - GTK_CONTAINER (widget)->border_width * 2;
728 if (GTK_WIDGET_HAS_DEFAULT (widget) &&
729 GTK_BUTTON (widget)->relief == GTK_RELIEF_NORMAL)
731 gtk_draw_shadow (widget->style, widget->window,
732 GTK_STATE_NORMAL, GTK_SHADOW_IN,
733 x, y, width, height);
737 gdk_draw_rectangle (widget->window, widget->style->bg_gc[GTK_STATE_NORMAL],
738 FALSE, x, y, width - 1, height - 1);
739 gdk_draw_rectangle (widget->window, widget->style->bg_gc[GTK_STATE_NORMAL],
740 FALSE, x + 1, y + 1, width - 3, height - 3);
746 gtk_button_expose (GtkWidget *widget,
747 GdkEventExpose *event)
750 GdkEventExpose child_event;
752 g_return_val_if_fail (widget != NULL, FALSE);
753 g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
754 g_return_val_if_fail (event != NULL, FALSE);
756 if (GTK_WIDGET_DRAWABLE (widget))
758 button = GTK_BUTTON (widget);
760 gtk_button_paint (widget, &event->area);
762 child_event = *event;
763 if (GTK_BIN (button)->child && GTK_WIDGET_NO_WINDOW (GTK_BIN (button)->child) &&
764 gtk_widget_intersect (GTK_BIN (button)->child, &event->area, &child_event.area))
765 gtk_widget_event (GTK_BIN (button)->child, (GdkEvent*) &child_event);
767 gtk_widget_draw_default (widget);
768 gtk_widget_draw_focus (widget);
775 gtk_button_button_press (GtkWidget *widget,
776 GdkEventButton *event)
780 g_return_val_if_fail (widget != NULL, FALSE);
781 g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
782 g_return_val_if_fail (event != NULL, FALSE);
784 if (event->type == GDK_BUTTON_PRESS)
786 button = GTK_BUTTON (widget);
788 if (GTK_WIDGET_CAN_DEFAULT (widget) && (event->button == 1))
789 gtk_widget_grab_default (widget);
790 if (!GTK_WIDGET_HAS_FOCUS (widget))
791 gtk_widget_grab_focus (widget);
793 if (event->button == 1)
795 gtk_grab_add (GTK_WIDGET (button));
796 gtk_button_pressed (button);
804 gtk_button_button_release (GtkWidget *widget,
805 GdkEventButton *event)
809 g_return_val_if_fail (widget != NULL, FALSE);
810 g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
811 g_return_val_if_fail (event != NULL, FALSE);
813 if (event->button == 1)
815 button = GTK_BUTTON (widget);
816 gtk_grab_remove (GTK_WIDGET (button));
817 gtk_button_released (button);
824 gtk_button_enter_notify (GtkWidget *widget,
825 GdkEventCrossing *event)
828 GtkWidget *event_widget;
830 g_return_val_if_fail (widget != NULL, FALSE);
831 g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
832 g_return_val_if_fail (event != NULL, FALSE);
834 button = GTK_BUTTON (widget);
835 event_widget = gtk_get_event_widget ((GdkEvent*) event);
837 if ((event_widget == widget) &&
838 (event->detail != GDK_NOTIFY_INFERIOR))
840 button->in_button = TRUE;
841 gtk_button_enter (button);
848 gtk_button_leave_notify (GtkWidget *widget,
849 GdkEventCrossing *event)
852 GtkWidget *event_widget;
854 g_return_val_if_fail (widget != NULL, FALSE);
855 g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
856 g_return_val_if_fail (event != NULL, FALSE);
858 button = GTK_BUTTON (widget);
859 event_widget = gtk_get_event_widget ((GdkEvent*) event);
861 if ((event_widget == widget) &&
862 (event->detail != GDK_NOTIFY_INFERIOR))
864 button->in_button = FALSE;
865 gtk_button_leave (button);
872 gtk_button_focus_in (GtkWidget *widget,
873 GdkEventFocus *event)
875 g_return_val_if_fail (widget != NULL, FALSE);
876 g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
877 g_return_val_if_fail (event != NULL, FALSE);
879 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
880 gtk_widget_draw_focus (widget);
886 gtk_button_focus_out (GtkWidget *widget,
887 GdkEventFocus *event)
889 g_return_val_if_fail (widget != NULL, FALSE);
890 g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
891 g_return_val_if_fail (event != NULL, FALSE);
893 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
894 gtk_widget_draw_focus (widget);
900 gtk_button_add (GtkContainer *container,
903 g_return_if_fail (container != NULL);
904 g_return_if_fail (widget != NULL);
906 if (GTK_CONTAINER_CLASS (parent_class)->add)
907 GTK_CONTAINER_CLASS (parent_class)->add (container, widget);
909 GTK_BUTTON (container)->child = GTK_BIN (container)->child;
913 gtk_button_remove (GtkContainer *container,
916 g_return_if_fail (container != NULL);
917 g_return_if_fail (widget != NULL);
919 if (GTK_CONTAINER_CLASS (parent_class)->remove)
920 GTK_CONTAINER_CLASS (parent_class)->remove (container, widget);
922 GTK_BUTTON (container)->child = GTK_BIN (container)->child;
926 gtk_real_button_pressed (GtkButton *button)
928 GtkStateType new_state;
930 g_return_if_fail (button != NULL);
931 g_return_if_fail (GTK_IS_BUTTON (button));
933 button->button_down = TRUE;
935 new_state = (button->in_button ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL);
937 if (GTK_WIDGET_STATE (button) != new_state)
939 gtk_widget_set_state (GTK_WIDGET (button), new_state);
940 gtk_widget_queue_draw (GTK_WIDGET (button));
945 gtk_real_button_released (GtkButton *button)
947 GtkStateType new_state;
949 g_return_if_fail (button != NULL);
950 g_return_if_fail (GTK_IS_BUTTON (button));
952 if (button->button_down)
954 button->button_down = FALSE;
956 if (button->in_button)
957 gtk_button_clicked (button);
959 new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
961 if (GTK_WIDGET_STATE (button) != new_state)
963 gtk_widget_set_state (GTK_WIDGET (button), new_state);
964 /* We _draw () instead of queue_draw so that if the operation
965 * blocks, the label doesn't vanish.
967 gtk_widget_draw (GTK_WIDGET (button), NULL);
973 gtk_real_button_enter (GtkButton *button)
975 GtkStateType new_state;
977 g_return_if_fail (button != NULL);
978 g_return_if_fail (GTK_IS_BUTTON (button));
980 new_state = (button->button_down ? GTK_STATE_ACTIVE : GTK_STATE_PRELIGHT);
982 if (GTK_WIDGET_STATE (button) != new_state)
984 gtk_widget_set_state (GTK_WIDGET (button), new_state);
985 gtk_widget_queue_draw (GTK_WIDGET (button));
990 gtk_real_button_leave (GtkButton *button)
992 g_return_if_fail (button != NULL);
993 g_return_if_fail (GTK_IS_BUTTON (button));
995 if (GTK_WIDGET_STATE (button) != GTK_STATE_NORMAL)
997 gtk_widget_set_state (GTK_WIDGET (button), GTK_STATE_NORMAL);
998 gtk_widget_queue_draw (GTK_WIDGET (button));