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
47 static void gtk_button_class_init (GtkButtonClass *klass);
48 static void gtk_button_init (GtkButton *button);
49 static void gtk_button_set_arg (GtkButton *button,
52 static void gtk_button_map (GtkWidget *widget);
53 static void gtk_button_unmap (GtkWidget *widget);
54 static void gtk_button_realize (GtkWidget *widget);
55 static void gtk_button_size_request (GtkWidget *widget,
56 GtkRequisition *requisition);
57 static void gtk_button_size_allocate (GtkWidget *widget,
58 GtkAllocation *allocation);
59 static void gtk_button_paint (GtkWidget *widget,
61 static void gtk_button_draw (GtkWidget *widget,
63 static void gtk_button_draw_focus (GtkWidget *widget);
64 static void gtk_button_draw_default (GtkWidget *widget);
65 static gint gtk_button_expose (GtkWidget *widget,
66 GdkEventExpose *event);
67 static gint gtk_button_button_press (GtkWidget *widget,
68 GdkEventButton *event);
69 static gint gtk_button_button_release (GtkWidget *widget,
70 GdkEventButton *event);
71 static gint gtk_button_enter_notify (GtkWidget *widget,
72 GdkEventCrossing *event);
73 static gint gtk_button_leave_notify (GtkWidget *widget,
74 GdkEventCrossing *event);
75 static gint gtk_button_focus_in (GtkWidget *widget,
76 GdkEventFocus *event);
77 static gint gtk_button_focus_out (GtkWidget *widget,
78 GdkEventFocus *event);
79 static void gtk_button_add (GtkContainer *container,
81 static void gtk_button_remove (GtkContainer *container,
83 static void gtk_button_foreach (GtkContainer *container,
85 gpointer callback_data);
86 static void gtk_real_button_pressed (GtkButton *button);
87 static void gtk_real_button_released (GtkButton *button);
88 static void gtk_real_button_enter (GtkButton *button);
89 static void gtk_real_button_leave (GtkButton *button);
92 static GtkContainerClass *parent_class;
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 (GtkArgSetFunc) gtk_button_set_arg,
111 (GtkArgGetFunc) NULL,
114 button_type = gtk_type_unique (gtk_container_get_type (), &button_info);
115 gtk_type_set_chunk_alloc (button_type, 16);
122 gtk_button_class_init (GtkButtonClass *klass)
124 GtkObjectClass *object_class;
125 GtkWidgetClass *widget_class;
126 GtkContainerClass *container_class;
128 object_class = (GtkObjectClass*) klass;
129 widget_class = (GtkWidgetClass*) klass;
130 container_class = (GtkContainerClass*) klass;
132 parent_class = gtk_type_class (gtk_container_get_type ());
134 gtk_object_add_arg_type ("GtkButton::label", GTK_TYPE_STRING, GTK_ARG_WRITABLE, ARG_LABEL);
136 button_signals[PRESSED] =
137 gtk_signal_new ("pressed",
140 GTK_SIGNAL_OFFSET (GtkButtonClass, pressed),
141 gtk_signal_default_marshaller,
143 button_signals[RELEASED] =
144 gtk_signal_new ("released",
147 GTK_SIGNAL_OFFSET (GtkButtonClass, released),
148 gtk_signal_default_marshaller,
150 button_signals[CLICKED] =
151 gtk_signal_new ("clicked",
154 GTK_SIGNAL_OFFSET (GtkButtonClass, clicked),
155 gtk_signal_default_marshaller,
157 button_signals[ENTER] =
158 gtk_signal_new ("enter",
161 GTK_SIGNAL_OFFSET (GtkButtonClass, enter),
162 gtk_signal_default_marshaller,
164 button_signals[LEAVE] =
165 gtk_signal_new ("leave",
168 GTK_SIGNAL_OFFSET (GtkButtonClass, leave),
169 gtk_signal_default_marshaller,
172 gtk_object_class_add_signals (object_class, button_signals, LAST_SIGNAL);
174 widget_class->activate_signal = button_signals[CLICKED];
175 widget_class->map = gtk_button_map;
176 widget_class->unmap = gtk_button_unmap;
177 widget_class->realize = gtk_button_realize;
178 widget_class->draw = gtk_button_draw;
179 widget_class->draw_focus = gtk_button_draw_focus;
180 widget_class->draw_default = gtk_button_draw_default;
181 widget_class->size_request = gtk_button_size_request;
182 widget_class->size_allocate = gtk_button_size_allocate;
183 widget_class->expose_event = gtk_button_expose;
184 widget_class->button_press_event = gtk_button_button_press;
185 widget_class->button_release_event = gtk_button_button_release;
186 widget_class->enter_notify_event = gtk_button_enter_notify;
187 widget_class->leave_notify_event = gtk_button_leave_notify;
188 widget_class->focus_in_event = gtk_button_focus_in;
189 widget_class->focus_out_event = gtk_button_focus_out;
191 container_class->add = gtk_button_add;
192 container_class->remove = gtk_button_remove;
193 container_class->foreach = gtk_button_foreach;
195 klass->pressed = gtk_real_button_pressed;
196 klass->released = gtk_real_button_released;
197 klass->clicked = NULL;
198 klass->enter = gtk_real_button_enter;
199 klass->leave = gtk_real_button_leave;
203 gtk_button_init (GtkButton *button)
205 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_FOCUS);
207 button->child = NULL;
208 button->in_button = FALSE;
209 button->button_down = FALSE;
210 button->relief = GTK_RELIEF_NORMAL;
214 gtk_button_set_arg (GtkButton *button,
223 gtk_container_disable_resize (GTK_CONTAINER (button));
227 gtk_widget_unparent (button->child);
228 button->child = NULL;
231 label = gtk_label_new (GTK_VALUE_STRING(*arg));
232 gtk_widget_show (label);
234 gtk_container_add (GTK_CONTAINER (button), label);
235 gtk_container_enable_resize (GTK_CONTAINER (button));
238 arg->type = GTK_TYPE_INVALID;
244 gtk_button_new (void)
246 return GTK_WIDGET (gtk_type_new (gtk_button_get_type ()));
250 gtk_button_new_with_label (const gchar *label)
253 GtkWidget *label_widget;
255 button = gtk_button_new ();
256 label_widget = gtk_label_new (label);
257 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.5, 0.5);
259 gtk_container_add (GTK_CONTAINER (button), label_widget);
260 gtk_widget_show (label_widget);
266 gtk_button_pressed (GtkButton *button)
268 gtk_signal_emit (GTK_OBJECT (button), button_signals[PRESSED]);
272 gtk_button_released (GtkButton *button)
274 gtk_signal_emit (GTK_OBJECT (button), button_signals[RELEASED]);
278 gtk_button_clicked (GtkButton *button)
280 gtk_signal_emit (GTK_OBJECT (button), button_signals[CLICKED]);
284 gtk_button_enter (GtkButton *button)
286 gtk_signal_emit (GTK_OBJECT (button), button_signals[ENTER]);
290 gtk_button_leave (GtkButton *button)
292 gtk_signal_emit (GTK_OBJECT (button), button_signals[LEAVE]);
296 gtk_button_set_relief (GtkButton *button,
297 GtkReliefStyle newrelief)
299 g_return_if_fail (button != NULL);
300 g_return_if_fail (GTK_IS_BUTTON (button));
302 button->relief = newrelief;
306 gtk_button_get_relief(GtkButton *button)
308 g_return_val_if_fail (button != NULL, GTK_RELIEF_NORMAL);
309 g_return_val_if_fail (GTK_IS_BUTTON (button), GTK_RELIEF_NORMAL);
311 return button->relief;
315 gtk_button_map (GtkWidget *widget)
319 g_return_if_fail (widget != NULL);
320 g_return_if_fail (GTK_IS_BUTTON (widget));
322 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
323 gdk_window_show (widget->window);
325 button = GTK_BUTTON (widget);
328 GTK_WIDGET_VISIBLE (button->child) &&
329 !GTK_WIDGET_MAPPED (button->child))
330 gtk_widget_map (button->child);
334 gtk_button_unmap (GtkWidget *widget)
336 g_return_if_fail (widget != NULL);
337 g_return_if_fail (GTK_IS_BUTTON (widget));
339 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
340 gdk_window_hide (widget->window);
344 gtk_button_realize (GtkWidget *widget)
347 GdkWindowAttr attributes;
348 gint attributes_mask;
351 g_return_if_fail (widget != NULL);
352 g_return_if_fail (GTK_IS_BUTTON (widget));
354 button = GTK_BUTTON (widget);
355 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
357 border_width = GTK_CONTAINER (widget)->border_width;
359 attributes.window_type = GDK_WINDOW_CHILD;
360 attributes.x = widget->allocation.x + border_width;
361 attributes.y = widget->allocation.y + border_width;
362 attributes.width = widget->allocation.width - border_width * 2;
363 attributes.height = widget->allocation.height - border_width * 2;
364 attributes.wclass = GDK_INPUT_OUTPUT;
365 attributes.visual = gtk_widget_get_visual (widget);
366 attributes.colormap = gtk_widget_get_colormap (widget);
367 attributes.event_mask = gtk_widget_get_events (widget);
368 attributes.event_mask |= (GDK_EXPOSURE_MASK |
369 GDK_BUTTON_PRESS_MASK |
370 GDK_BUTTON_RELEASE_MASK |
371 GDK_ENTER_NOTIFY_MASK |
372 GDK_LEAVE_NOTIFY_MASK);
374 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
376 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
377 gdk_window_set_user_data (widget->window, button);
379 widget->style = gtk_style_attach (widget->style, widget->window);
380 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
384 gtk_button_size_request (GtkWidget *widget,
385 GtkRequisition *requisition)
389 g_return_if_fail (widget != NULL);
390 g_return_if_fail (GTK_IS_BUTTON (widget));
391 g_return_if_fail (requisition != NULL);
393 button = GTK_BUTTON (widget);
395 requisition->width = (GTK_CONTAINER (widget)->border_width + CHILD_SPACING +
396 GTK_WIDGET (widget)->style->klass->xthickness) * 2;
397 requisition->height = (GTK_CONTAINER (widget)->border_width + CHILD_SPACING +
398 GTK_WIDGET (widget)->style->klass->ythickness) * 2;
400 if (GTK_WIDGET_CAN_DEFAULT (widget))
402 requisition->width += (GTK_WIDGET (widget)->style->klass->xthickness * 2 +
404 requisition->height += (GTK_WIDGET (widget)->style->klass->ythickness * 2 +
408 if (button->child && GTK_WIDGET_VISIBLE (button->child))
410 gtk_widget_size_request (button->child, &button->child->requisition);
412 requisition->width += button->child->requisition.width;
413 requisition->height += button->child->requisition.height;
418 gtk_button_size_allocate (GtkWidget *widget,
419 GtkAllocation *allocation)
422 GtkAllocation child_allocation;
425 g_return_if_fail (widget != NULL);
426 g_return_if_fail (GTK_IS_BUTTON (widget));
427 g_return_if_fail (allocation != NULL);
429 widget->allocation = *allocation;
430 border_width = GTK_CONTAINER (widget)->border_width;
432 if (GTK_WIDGET_REALIZED (widget))
433 gdk_window_move_resize (widget->window,
434 widget->allocation.x + border_width,
435 widget->allocation.y + border_width,
436 widget->allocation.width - border_width * 2,
437 widget->allocation.height - border_width * 2);
439 button = GTK_BUTTON (widget);
441 if (button->child && GTK_WIDGET_VISIBLE (button->child))
443 child_allocation.x = (CHILD_SPACING + GTK_WIDGET (widget)->style->klass->xthickness);
444 child_allocation.y = (CHILD_SPACING + GTK_WIDGET (widget)->style->klass->ythickness);
446 child_allocation.width = MAX (1, widget->allocation.width - child_allocation.x * 2 -
448 child_allocation.height = MAX (1, widget->allocation.height - child_allocation.y * 2 -
451 if (GTK_WIDGET_CAN_DEFAULT (button))
453 child_allocation.x += (GTK_WIDGET (widget)->style->klass->xthickness +
455 child_allocation.y += (GTK_WIDGET (widget)->style->klass->ythickness +
457 child_allocation.width = MAX (1, child_allocation.width -
458 (GTK_WIDGET (widget)->style->klass->xthickness * 2 + DEFAULT_SPACING));
459 child_allocation.height = MAX (1, child_allocation.height -
460 (GTK_WIDGET (widget)->style->klass->xthickness * 2 + DEFAULT_SPACING));
463 gtk_widget_size_allocate (button->child, &child_allocation);
468 * +------------------------------------------------+
470 * | +------------------------------------------+ |
471 * | |\\\\\\\\\\\\\\\\DEFAULT\\\\\\\\\\\\\\\\\ | |
472 * | |\\+------------------------------------+ | |
473 * | |\\| | SPACING 3 | | | |
474 * | |\\| +--------------------------------+ | | |
475 * | |\\| |########## FOCUS ###############| | | |
476 * | |\\| |#+----------------------------+#| | | |
477 * | |\\| |#| RELIEF \|#| | | |
478 * | |\\| |#| +-----------------------+\|#| | | |
479 * | |\\|1|#| + THE TEXT +\|#|2| | |
480 * | |\\| |#| +-----------------------+\|#| | | |
481 * | |\\| |#| \\\\\ ythickness \\\\\\\\\\|#| | | |
482 * | |\\| |#+----------------------------+#| | | |
483 * | |\\| |########### 1 ##################| | | |
484 * | |\\| +--------------------------------+ | | |
485 * | |\\| | default spacing 4 | | | |
486 * | |\\+------------------------------------+ | |
487 * | |\ ythickness | |
488 * | +------------------------------------------+ |
490 * +------------------------------------------------+
494 gtk_button_paint (GtkWidget *widget,
497 GdkRectangle restrict_area;
498 GdkRectangle outer_area;
499 GdkRectangle tmp_area;
500 GdkRectangle new_area;
504 g_return_if_fail (widget != NULL);
505 g_return_if_fail (GTK_IS_BUTTON (widget));
507 xthickness = widget->style->klass->xthickness;
508 ythickness = widget->style->klass->ythickness;
510 if (GTK_WIDGET_DRAWABLE (widget))
512 restrict_area.x = xthickness;
513 restrict_area.y = ythickness;
514 restrict_area.width = GTK_WIDGET (widget)->allocation.width -
515 restrict_area.x * 2 - GTK_CONTAINER (widget)->border_width * 2;
516 restrict_area.height = GTK_WIDGET (widget)->allocation.height -
517 restrict_area.y * 2 - GTK_CONTAINER (widget)->border_width * 2;
519 outer_area = restrict_area;
521 if (GTK_WIDGET_CAN_DEFAULT (widget))
523 restrict_area.x += DEFAULT_LEFT_POS;
524 restrict_area.y += DEFAULT_TOP_POS;
525 restrict_area.width -= DEFAULT_SPACING;
526 restrict_area.height -= DEFAULT_SPACING;
529 if (gdk_rectangle_intersect (area, &restrict_area, &new_area))
531 if ((GTK_WIDGET_STATE (widget) == GTK_STATE_PRELIGHT) &&
532 (GTK_BUTTON (widget)->relief == GTK_RELIEF_NONE))
533 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
535 gtk_style_set_background (widget->style, widget->window, GTK_WIDGET_STATE (widget));
536 gdk_window_clear_area (widget->window,
537 new_area.x, new_area.y,
538 new_area.width, new_area.height);
541 if (GTK_WIDGET_CAN_DEFAULT (widget))
543 /* Now fill spacing area between the default border and the button */
545 /* 1 */ tmp_area = outer_area;
546 tmp_area.width = restrict_area.x - outer_area.x;
547 if (gdk_rectangle_intersect (area, &tmp_area, &new_area))
548 gdk_draw_rectangle (widget->window,
549 widget->style->bg_gc[GTK_STATE_NORMAL],
551 new_area.x, new_area.y,
552 new_area.width, new_area.height);
554 /* 2 */ tmp_area.x = restrict_area.x + restrict_area.width;
556 if (gdk_rectangle_intersect (area, &tmp_area, &new_area))
557 gdk_draw_rectangle (widget->window,
558 widget->style->bg_gc[GTK_STATE_NORMAL],
560 new_area.x, new_area.y,
561 new_area.width, new_area.height);
563 /* 3 */ tmp_area.width = restrict_area.width;
564 tmp_area.height = restrict_area.y - outer_area.y;
565 tmp_area.x = restrict_area.x;
567 if (gdk_rectangle_intersect (area, &tmp_area, &new_area))
568 gdk_draw_rectangle (widget->window,
569 widget->style->bg_gc[GTK_STATE_NORMAL],
571 new_area.x, new_area.y,
572 new_area.width, new_area.height);
574 /* 4 */ tmp_area.y = restrict_area.y + restrict_area.height;
576 if (gdk_rectangle_intersect (area, &tmp_area, &new_area))
577 gdk_draw_rectangle (widget->window,
578 widget->style->bg_gc[GTK_STATE_NORMAL],
580 new_area.x, new_area.y,
581 new_area.width, new_area.height);
587 gtk_button_draw (GtkWidget *widget,
591 GdkRectangle child_area;
592 GdkRectangle tmp_area;
594 g_return_if_fail (widget != NULL);
595 g_return_if_fail (GTK_IS_BUTTON (widget));
596 g_return_if_fail (area != NULL);
598 if (GTK_WIDGET_DRAWABLE (widget))
600 button = GTK_BUTTON (widget);
603 tmp_area.x -= GTK_CONTAINER (button)->border_width;
604 tmp_area.y -= GTK_CONTAINER (button)->border_width;
606 gtk_button_paint (widget, &tmp_area);
608 if (button->child && gtk_widget_intersect (button->child, &tmp_area, &child_area))
609 gtk_widget_draw (button->child, &child_area);
611 gtk_widget_draw_default (widget);
612 gtk_widget_draw_focus (widget);
617 gtk_button_draw_focus (GtkWidget *widget)
620 GtkShadowType shadow_type;
624 g_return_if_fail (widget != NULL);
625 g_return_if_fail (GTK_IS_BUTTON (widget));
627 if (GTK_WIDGET_DRAWABLE (widget))
629 button = GTK_BUTTON (widget);
633 width = widget->allocation.width - GTK_CONTAINER (widget)->border_width * 2;
634 height = widget->allocation.height - GTK_CONTAINER (widget)->border_width * 2;
636 if (GTK_WIDGET_CAN_DEFAULT (widget))
638 x += widget->style->klass->xthickness;
639 y += widget->style->klass->ythickness;
640 width -= 2 * x + DEFAULT_SPACING;
641 height -= 2 * y + DEFAULT_SPACING;
642 x += DEFAULT_LEFT_POS;
643 y += DEFAULT_TOP_POS;
646 if (GTK_WIDGET_HAS_FOCUS (widget))
655 if (GTK_WIDGET_STATE (widget) == GTK_STATE_ACTIVE)
656 gdk_draw_rectangle (widget->window,
657 widget->style->bg_gc[GTK_WIDGET_STATE (widget)], FALSE,
658 x + 1, y + 1, width - 4, height - 4);
659 else if (button->relief == GTK_RELIEF_NORMAL)
660 gdk_draw_rectangle (widget->window,
661 widget->style->bg_gc[GTK_WIDGET_STATE (widget)], FALSE,
662 x + 2, y + 2, width - 5, height - 5);
664 gdk_draw_rectangle (widget->window,
665 widget->style->bg_gc[GTK_WIDGET_STATE (widget)], FALSE,
666 x, y, width - 1, height - 1);
669 if (GTK_WIDGET_STATE (widget) == GTK_STATE_ACTIVE)
670 shadow_type = GTK_SHADOW_IN;
672 shadow_type = GTK_SHADOW_OUT;
674 if ((button->relief == GTK_RELIEF_NORMAL) ||
675 ((GTK_WIDGET_STATE (widget) != GTK_STATE_NORMAL) &&
676 (GTK_WIDGET_STATE (widget) != GTK_STATE_INSENSITIVE)))
678 gtk_draw_shadow (widget->style, widget->window,
679 GTK_WIDGET_STATE (widget), shadow_type,
680 x, y, width, height);
683 if (GTK_WIDGET_HAS_FOCUS (widget))
690 gdk_draw_rectangle (widget->window,
691 widget->style->black_gc, FALSE,
692 x, y, width - 1, height - 1);
698 gtk_button_draw_default (GtkWidget *widget)
703 g_return_if_fail (widget != NULL);
704 g_return_if_fail (GTK_IS_BUTTON (widget));
706 if (GTK_WIDGET_DRAWABLE (widget))
710 width = widget->allocation.width - GTK_CONTAINER (widget)->border_width * 2;
711 height = widget->allocation.height - GTK_CONTAINER (widget)->border_width * 2;
713 if (GTK_WIDGET_HAS_DEFAULT (widget) && gtk_button_get_relief (GTK_BUTTON (widget)) == GTK_RELIEF_NORMAL)
715 gtk_draw_shadow (widget->style, widget->window,
716 GTK_STATE_NORMAL, GTK_SHADOW_IN,
717 x, y, width, height);
721 gdk_draw_rectangle (widget->window, widget->style->bg_gc[GTK_STATE_NORMAL],
722 FALSE, x, y, width - 1, height - 1);
723 gdk_draw_rectangle (widget->window, widget->style->bg_gc[GTK_STATE_NORMAL],
724 FALSE, x + 1, y + 1, width - 3, height - 3);
730 gtk_button_expose (GtkWidget *widget,
731 GdkEventExpose *event)
734 GdkEventExpose child_event;
736 g_return_val_if_fail (widget != NULL, FALSE);
737 g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
738 g_return_val_if_fail (event != NULL, FALSE);
740 if (GTK_WIDGET_DRAWABLE (widget))
742 button = GTK_BUTTON (widget);
744 gtk_button_paint (widget, &event->area);
746 child_event = *event;
747 if (button->child && GTK_WIDGET_NO_WINDOW (button->child) &&
748 gtk_widget_intersect (button->child, &event->area, &child_event.area))
749 gtk_widget_event (button->child, (GdkEvent*) &child_event);
751 gtk_widget_draw_default (widget);
752 gtk_widget_draw_focus (widget);
759 gtk_button_button_press (GtkWidget *widget,
760 GdkEventButton *event)
764 g_return_val_if_fail (widget != NULL, FALSE);
765 g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
766 g_return_val_if_fail (event != NULL, FALSE);
768 if (event->type == GDK_BUTTON_PRESS)
770 button = GTK_BUTTON (widget);
772 if (GTK_WIDGET_CAN_DEFAULT (widget) && (event->button == 1))
773 gtk_widget_grab_default (widget);
774 if (!GTK_WIDGET_HAS_FOCUS (widget))
775 gtk_widget_grab_focus (widget);
777 if (event->button == 1)
779 gtk_grab_add (GTK_WIDGET (button));
780 gtk_button_pressed (button);
788 gtk_button_button_release (GtkWidget *widget,
789 GdkEventButton *event)
793 g_return_val_if_fail (widget != NULL, FALSE);
794 g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
795 g_return_val_if_fail (event != NULL, FALSE);
797 if (event->button == 1)
799 button = GTK_BUTTON (widget);
800 gtk_grab_remove (GTK_WIDGET (button));
801 gtk_button_released (button);
808 gtk_button_enter_notify (GtkWidget *widget,
809 GdkEventCrossing *event)
812 GtkWidget *event_widget;
814 g_return_val_if_fail (widget != NULL, FALSE);
815 g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
816 g_return_val_if_fail (event != NULL, FALSE);
818 button = GTK_BUTTON (widget);
819 event_widget = gtk_get_event_widget ((GdkEvent*) event);
821 if ((event_widget == widget) &&
822 (event->detail != GDK_NOTIFY_INFERIOR))
824 button->in_button = TRUE;
825 gtk_button_enter (button);
832 gtk_button_leave_notify (GtkWidget *widget,
833 GdkEventCrossing *event)
836 GtkWidget *event_widget;
838 g_return_val_if_fail (widget != NULL, FALSE);
839 g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
840 g_return_val_if_fail (event != NULL, FALSE);
842 button = GTK_BUTTON (widget);
843 event_widget = gtk_get_event_widget ((GdkEvent*) event);
845 if ((event_widget == widget) &&
846 (event->detail != GDK_NOTIFY_INFERIOR))
848 button->in_button = FALSE;
849 gtk_button_leave (button);
856 gtk_button_focus_in (GtkWidget *widget,
857 GdkEventFocus *event)
859 g_return_val_if_fail (widget != NULL, FALSE);
860 g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
861 g_return_val_if_fail (event != NULL, FALSE);
863 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
864 gtk_widget_draw_focus (widget);
870 gtk_button_focus_out (GtkWidget *widget,
871 GdkEventFocus *event)
873 g_return_val_if_fail (widget != NULL, FALSE);
874 g_return_val_if_fail (GTK_IS_BUTTON (widget), FALSE);
875 g_return_val_if_fail (event != NULL, FALSE);
877 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
878 gtk_widget_draw_focus (widget);
884 gtk_button_add (GtkContainer *container,
889 g_return_if_fail (container != NULL);
890 g_return_if_fail (GTK_IS_BUTTON (container));
891 g_return_if_fail (widget != NULL);
892 g_return_if_fail (gtk_widget_basic (widget));
894 button = GTK_BUTTON (container);
898 gtk_widget_set_parent (widget, GTK_WIDGET (container));
900 if (GTK_WIDGET_VISIBLE (widget->parent))
902 if (GTK_WIDGET_REALIZED (widget->parent) &&
903 !GTK_WIDGET_REALIZED (widget))
904 gtk_widget_realize (widget);
906 if (GTK_WIDGET_MAPPED (widget->parent) &&
907 !GTK_WIDGET_MAPPED (widget))
908 gtk_widget_map (widget);
911 button->child = widget;
913 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
914 gtk_widget_queue_resize (widget);
919 gtk_button_remove (GtkContainer *container,
924 g_return_if_fail (container != NULL);
925 g_return_if_fail (GTK_IS_BUTTON (container));
926 g_return_if_fail (widget != NULL);
928 button = GTK_BUTTON (container);
930 if (button->child == widget)
932 gboolean widget_was_visible = GTK_WIDGET_VISIBLE(widget);
934 gtk_widget_unparent (widget);
936 button->child = NULL;
938 if (widget_was_visible && GTK_WIDGET_VISIBLE (container))
939 gtk_widget_queue_resize (GTK_WIDGET (container));
945 gtk_button_foreach (GtkContainer *container,
946 GtkCallback callback,
947 gpointer callback_data)
951 g_return_if_fail (container != NULL);
952 g_return_if_fail (GTK_IS_BUTTON (container));
953 g_return_if_fail (callback != NULL);
955 button = GTK_BUTTON (container);
958 (* callback) (button->child, callback_data);
962 gtk_real_button_pressed (GtkButton *button)
964 GtkStateType new_state;
966 g_return_if_fail (button != NULL);
967 g_return_if_fail (GTK_IS_BUTTON (button));
969 button->button_down = TRUE;
971 new_state = (button->in_button ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL);
973 if (GTK_WIDGET_STATE (button) != new_state)
975 gtk_widget_set_state (GTK_WIDGET (button), new_state);
976 gtk_widget_queue_draw (GTK_WIDGET (button));
981 gtk_real_button_released (GtkButton *button)
983 GtkStateType new_state;
985 g_return_if_fail (button != NULL);
986 g_return_if_fail (GTK_IS_BUTTON (button));
988 if (button->button_down)
990 button->button_down = FALSE;
992 if (button->in_button)
993 gtk_button_clicked (button);
995 new_state = (button->in_button ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL);
997 if (GTK_WIDGET_STATE (button) != new_state)
999 gtk_widget_set_state (GTK_WIDGET (button), new_state);
1000 /* We _draw () instead of queue_draw so that if the operation
1001 * blocks, the label doesn't vanish.
1003 gtk_widget_draw (GTK_WIDGET (button), NULL);
1009 gtk_real_button_enter (GtkButton *button)
1011 GtkStateType new_state;
1013 g_return_if_fail (button != NULL);
1014 g_return_if_fail (GTK_IS_BUTTON (button));
1016 new_state = (button->button_down ? GTK_STATE_ACTIVE : GTK_STATE_PRELIGHT);
1018 if (GTK_WIDGET_STATE (button) != new_state)
1020 gtk_widget_set_state (GTK_WIDGET (button), new_state);
1021 gtk_widget_queue_draw (GTK_WIDGET (button));
1026 gtk_real_button_leave (GtkButton *button)
1028 g_return_if_fail (button != NULL);
1029 g_return_if_fail (GTK_IS_BUTTON (button));
1031 if (GTK_WIDGET_STATE (button) != GTK_STATE_NORMAL)
1033 gtk_widget_set_state (GTK_WIDGET (button), GTK_STATE_NORMAL);
1034 gtk_widget_queue_draw (GTK_WIDGET (button));