1 /* GAIL - The GNOME Accessibility Implementation Library
2 * Copyright 2001, 2002, 2003 Sun Microsystems Inc.
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.
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.
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.
25 #ifdef GDK_WINDOWING_X11
26 #include <gdk/x11/gdkx.h>
28 #include "gailwidget.h"
29 #include "gailnotebookpage.h"
30 #include "gail-private-macros.h"
32 extern GtkWidget *focus_widget;
34 static void gail_widget_class_init (GailWidgetClass *klass);
35 static void gail_widget_init (GailWidget *accessible);
36 static void gail_widget_connect_widget_destroyed (GtkAccessible *accessible);
37 static void gail_widget_destroyed (GtkWidget *widget,
38 GtkAccessible *accessible);
40 static G_CONST_RETURN gchar* gail_widget_get_description (AtkObject *accessible);
41 static AtkObject* gail_widget_get_parent (AtkObject *accessible);
42 static AtkStateSet* gail_widget_ref_state_set (AtkObject *accessible);
43 static AtkRelationSet* gail_widget_ref_relation_set (AtkObject *accessible);
44 static gint gail_widget_get_index_in_parent (AtkObject *accessible);
46 static void atk_component_interface_init (AtkComponentIface *iface);
48 static guint gail_widget_add_focus_handler
49 (AtkComponent *component,
50 AtkFocusHandler handler);
52 static void gail_widget_get_extents (AtkComponent *component,
57 AtkCoordType coord_type);
59 static void gail_widget_get_size (AtkComponent *component,
63 static AtkLayer gail_widget_get_layer (AtkComponent *component);
65 static gboolean gail_widget_grab_focus (AtkComponent *component);
68 static void gail_widget_remove_focus_handler
69 (AtkComponent *component,
72 static gboolean gail_widget_set_extents (AtkComponent *component,
77 AtkCoordType coord_type);
79 static gboolean gail_widget_set_position (AtkComponent *component,
82 AtkCoordType coord_type);
84 static gboolean gail_widget_set_size (AtkComponent *component,
88 static gint gail_widget_map_gtk (GtkWidget *widget);
89 static void gail_widget_real_notify_gtk (GObject *obj,
91 static void gail_widget_notify_gtk (GObject *obj,
93 static gboolean gail_widget_focus_gtk (GtkWidget *widget,
94 GdkEventFocus *event);
95 static gboolean gail_widget_real_focus_gtk (GtkWidget *widget,
96 GdkEventFocus *event);
97 static void gail_widget_size_allocate_gtk (GtkWidget *widget,
98 GtkAllocation *allocation);
100 static void gail_widget_focus_event (AtkObject *obj,
103 static void gail_widget_real_initialize (AtkObject *obj,
105 static GtkWidget* gail_widget_find_viewport (GtkWidget *widget);
106 static gboolean gail_widget_on_screen (GtkWidget *widget);
107 static gboolean gail_widget_all_parents_visible(GtkWidget *widget);
109 G_DEFINE_TYPE_WITH_CODE (GailWidget, gail_widget, GTK_TYPE_ACCESSIBLE,
110 G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, atk_component_interface_init))
113 gail_widget_class_init (GailWidgetClass *klass)
115 AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
116 GtkAccessibleClass *accessible_class = GTK_ACCESSIBLE_CLASS (klass);
118 klass->notify_gtk = gail_widget_real_notify_gtk;
119 klass->focus_gtk = gail_widget_real_focus_gtk;
121 accessible_class->connect_widget_destroyed = gail_widget_connect_widget_destroyed;
123 class->get_description = gail_widget_get_description;
124 class->get_parent = gail_widget_get_parent;
125 class->ref_relation_set = gail_widget_ref_relation_set;
126 class->ref_state_set = gail_widget_ref_state_set;
127 class->get_index_in_parent = gail_widget_get_index_in_parent;
128 class->initialize = gail_widget_real_initialize;
132 gail_widget_init (GailWidget *accessible)
137 * This function specifies the GtkWidget for which the GailWidget was created
138 * and specifies a handler to be called when the GtkWidget is destroyed.
141 gail_widget_real_initialize (AtkObject *obj,
144 GtkAccessible *accessible;
147 g_return_if_fail (GTK_IS_WIDGET (data));
149 widget = GTK_WIDGET (data);
151 accessible = GTK_ACCESSIBLE (obj);
152 gtk_accessible_set_widget (accessible, widget);
153 gtk_accessible_connect_widget_destroyed (accessible);
154 g_signal_connect_after (widget,
156 G_CALLBACK (gail_widget_focus_gtk),
158 g_signal_connect_after (widget,
160 G_CALLBACK (gail_widget_focus_gtk),
162 g_signal_connect (widget,
164 G_CALLBACK (gail_widget_notify_gtk),
166 g_signal_connect (widget,
168 G_CALLBACK (gail_widget_size_allocate_gtk),
170 atk_component_add_focus_handler (ATK_COMPONENT (accessible),
171 gail_widget_focus_event);
173 * Add signal handlers for GTK signals required to support property changes
175 g_signal_connect (widget,
177 G_CALLBACK (gail_widget_map_gtk),
179 g_signal_connect (widget,
181 G_CALLBACK (gail_widget_map_gtk),
183 g_object_set_data (G_OBJECT (obj), "atk-component-layer",
184 GINT_TO_POINTER (ATK_LAYER_WIDGET));
186 obj->role = ATK_ROLE_UNKNOWN;
190 gail_widget_new (GtkWidget *widget)
193 AtkObject *accessible;
195 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
197 object = g_object_new (GAIL_TYPE_WIDGET, NULL);
199 accessible = ATK_OBJECT (object);
200 atk_object_initialize (accessible, widget);
206 * This function specifies the function to be called when the widget
210 gail_widget_connect_widget_destroyed (GtkAccessible *accessible)
214 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
217 g_signal_connect_after (widget,
219 G_CALLBACK (gail_widget_destroyed),
225 * This function is called when the widget is destroyed.
226 * It sets the widget field in the GtkAccessible structure to NULL
227 * and emits a state-change signal for the state ATK_STATE_DEFUNCT
230 gail_widget_destroyed (GtkWidget *widget,
231 GtkAccessible *accessible)
233 gtk_accessible_set_widget (accessible, NULL);
234 atk_object_notify_state_change (ATK_OBJECT (accessible), ATK_STATE_DEFUNCT,
238 static G_CONST_RETURN gchar*
239 gail_widget_get_description (AtkObject *accessible)
241 if (accessible->description)
242 return accessible->description;
247 /* Get the tooltip from the widget */
248 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
255 return gtk_widget_get_tooltip_text (widget);
260 gail_widget_get_parent (AtkObject *accessible)
264 parent = accessible->accessible_parent;
267 g_return_val_if_fail (ATK_IS_OBJECT (parent), NULL);
270 GtkWidget *widget, *parent_widget;
272 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
278 gail_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
280 parent_widget = gtk_widget_get_parent (widget);
281 if (parent_widget == NULL)
285 * For a widget whose parent is a GtkNoteBook, we return the
286 * accessible object corresponding the GtkNotebookPage containing
287 * the widget as the accessible parent.
289 if (GTK_IS_NOTEBOOK (parent_widget))
293 GtkNotebook *notebook;
296 notebook = GTK_NOTEBOOK (parent_widget);
299 child = gtk_notebook_get_nth_page (notebook, page_num);
304 parent = gtk_widget_get_accessible (parent_widget);
305 parent = atk_object_ref_accessible_child (parent, page_num);
306 g_object_unref (parent);
313 parent = gtk_widget_get_accessible (parent_widget);
319 find_label (GtkWidget *widget)
323 GtkWidget *temp_widget;
325 labels = gtk_widget_list_mnemonic_labels (widget);
333 g_warning ("Widget (%s) has more than one label", G_OBJECT_TYPE_NAME (widget));
338 label = labels->data;
341 g_list_free (labels);
345 * Ignore a label within a button; bug #136602
347 if (label && GTK_IS_BUTTON (widget))
352 if (temp_widget == widget)
357 temp_widget = gtk_widget_get_parent (temp_widget);
363 static AtkRelationSet*
364 gail_widget_ref_relation_set (AtkObject *obj)
367 AtkRelationSet *relation_set;
370 AtkRelation* relation;
372 gail_return_val_if_fail (GAIL_IS_WIDGET (obj), NULL);
374 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
381 relation_set = ATK_OBJECT_CLASS (gail_widget_parent_class)->ref_relation_set (obj);
383 if (GTK_IS_BOX (widget))
385 * Do not report labelled-by for a GtkBox which could be a
390 if (!atk_relation_set_contains (relation_set, ATK_RELATION_LABELLED_BY))
392 label = find_label (widget);
395 if (GTK_IS_BUTTON (widget))
397 * Handle the case where GnomeIconEntry is the mnemonic widget.
398 * The GtkButton which is a grandchild of the GnomeIconEntry
399 * should really be the mnemonic widget. See bug #133967.
402 GtkWidget *temp_widget;
404 temp_widget = gtk_widget_get_parent (widget);
406 if (GTK_IS_ALIGNMENT (temp_widget))
408 temp_widget = gtk_widget_get_parent (temp_widget);
409 if (GTK_IS_BOX (temp_widget))
411 label = find_label (temp_widget);
414 label = find_label (gtk_widget_get_parent (temp_widget));
418 else if (GTK_IS_COMBO_BOX (widget))
420 * Handle the case when GtkFileChooserButton is the mnemonic
421 * widget. The GtkComboBox which is a child of the
422 * GtkFileChooserButton should be the mnemonic widget.
426 GtkWidget *temp_widget;
428 temp_widget = gtk_widget_get_parent (widget);
429 if (GTK_IS_HBOX (temp_widget))
431 label = find_label (temp_widget);
438 array [0] = gtk_widget_get_accessible (label);
440 relation = atk_relation_new (array, 1, ATK_RELATION_LABELLED_BY);
441 atk_relation_set_add (relation_set, relation);
442 g_object_unref (relation);
450 gail_widget_ref_state_set (AtkObject *accessible)
452 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
453 AtkStateSet *state_set;
455 state_set = ATK_OBJECT_CLASS (gail_widget_parent_class)->ref_state_set (accessible);
459 atk_state_set_add_state (state_set, ATK_STATE_DEFUNCT);
463 if (gtk_widget_is_sensitive (widget))
465 atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE);
466 atk_state_set_add_state (state_set, ATK_STATE_ENABLED);
469 if (gtk_widget_get_can_focus (widget))
471 atk_state_set_add_state (state_set, ATK_STATE_FOCUSABLE);
474 * We do not currently generate notifications when an ATK object
475 * corresponding to a GtkWidget changes visibility by being scrolled
476 * on or off the screen. The testcase for this is the main window
477 * of the testgtk application in which a set of buttons in a GtkVBox
478 * is in a scrooled window with a viewport.
480 * To generate the notifications we would need to do the following:
481 * 1) Find the GtkViewPort among the antecendents of the objects
482 * 2) Create an accesible for the GtkViewPort
483 * 3) Connect to the value-changed signal on the viewport
484 * 4) When the signal is received we need to traverse the children
485 * of the viewport and check whether the children are visible or not
486 * visible; we may want to restrict this to the widgets for which
487 * accessible objects have been created.
488 * 5) We probably need to store a variable on_screen in the
489 * GailWidget data structure so we can determine whether the value has
492 if (gtk_widget_get_visible (widget))
494 atk_state_set_add_state (state_set, ATK_STATE_VISIBLE);
495 if (gail_widget_on_screen (widget) && gtk_widget_get_mapped (widget) &&
496 gail_widget_all_parents_visible (widget))
498 atk_state_set_add_state (state_set, ATK_STATE_SHOWING);
502 if (gtk_widget_has_focus (widget) && (widget == focus_widget))
504 AtkObject *focus_obj;
506 focus_obj = g_object_get_data (G_OBJECT (accessible), "gail-focus-object");
507 if (focus_obj == NULL)
508 atk_state_set_add_state (state_set, ATK_STATE_FOCUSED);
510 if (gtk_widget_has_default (widget))
512 atk_state_set_add_state (state_set, ATK_STATE_DEFAULT);
519 gail_widget_get_index_in_parent (AtkObject *accessible)
522 GtkWidget *parent_widget;
527 type = g_type_from_name ("GailCanvasWidget");
528 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
536 if (accessible->accessible_parent)
540 parent = accessible->accessible_parent;
542 if (GAIL_IS_NOTEBOOK_PAGE (parent) ||
543 G_TYPE_CHECK_INSTANCE_TYPE ((parent), type))
548 gboolean found = FALSE;
550 n_children = atk_object_get_n_accessible_children (parent);
551 for (i = 0; i < n_children; i++)
555 child = atk_object_ref_accessible_child (parent, i);
556 if (child == accessible)
559 g_object_unref (child);
566 gail_return_val_if_fail (GTK_IS_WIDGET (widget), -1);
567 parent_widget = gtk_widget_get_parent (widget);
568 if (parent_widget == NULL)
570 gail_return_val_if_fail (GTK_IS_CONTAINER (parent_widget), -1);
572 children = gtk_container_get_children (GTK_CONTAINER (parent_widget));
574 index = g_list_index (children, widget);
575 g_list_free (children);
580 atk_component_interface_init (AtkComponentIface *iface)
583 * Use default implementation for contains and get_position
585 iface->add_focus_handler = gail_widget_add_focus_handler;
586 iface->get_extents = gail_widget_get_extents;
587 iface->get_size = gail_widget_get_size;
588 iface->get_layer = gail_widget_get_layer;
589 iface->grab_focus = gail_widget_grab_focus;
590 iface->remove_focus_handler = gail_widget_remove_focus_handler;
591 iface->set_extents = gail_widget_set_extents;
592 iface->set_position = gail_widget_set_position;
593 iface->set_size = gail_widget_set_size;
597 gail_widget_add_focus_handler (AtkComponent *component,
598 AtkFocusHandler handler)
600 GSignalMatchType match_type;
604 match_type = G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC;
605 signal_id = g_signal_lookup ("focus-event", ATK_TYPE_OBJECT);
607 ret = g_signal_handler_find (component, match_type, signal_id, 0, NULL,
608 (gpointer) handler, NULL);
611 return g_signal_connect_closure_by_id (component,
614 G_CALLBACK (handler), NULL,
615 (GClosureNotify) NULL),
625 gail_widget_get_extents (AtkComponent *component,
630 AtkCoordType coord_type)
632 GtkAllocation allocation;
634 gint x_window, y_window;
635 gint x_toplevel, y_toplevel;
636 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
644 gail_return_if_fail (GTK_IS_WIDGET (widget));
646 gtk_widget_get_allocation (widget, &allocation);
647 *width = allocation.width;
648 *height = allocation.height;
649 if (!gail_widget_on_screen (widget) || (!gtk_widget_is_drawable (widget)))
656 if (gtk_widget_get_parent (widget))
660 window = gtk_widget_get_parent_window (widget);
666 window = gtk_widget_get_window (widget);
668 gdk_window_get_origin (window, &x_window, &y_window);
673 if (coord_type == ATK_XY_WINDOW)
675 window = gdk_window_get_toplevel (gtk_widget_get_window (widget));
676 gdk_window_get_origin (window, &x_toplevel, &y_toplevel);
684 gail_widget_get_size (AtkComponent *component,
688 GtkAllocation allocation;
689 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
697 gail_return_if_fail (GTK_IS_WIDGET (widget));
699 gtk_widget_get_allocation (widget, &allocation);
700 *width = allocation.width;
701 *height = allocation.height;
705 gail_widget_get_layer (AtkComponent *component)
708 layer = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (component), "atk-component-layer"));
710 return (AtkLayer) layer;
714 gail_widget_grab_focus (AtkComponent *component)
716 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
719 gail_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
720 if (gtk_widget_get_can_focus (widget))
722 gtk_widget_grab_focus (widget);
723 toplevel = gtk_widget_get_toplevel (widget);
724 if (gtk_widget_is_toplevel (toplevel))
726 #ifdef GDK_WINDOWING_X11
727 gtk_window_present_with_time (GTK_WINDOW (toplevel),
728 gdk_x11_get_server_time (gtk_widget_get_window (widget)));
730 gtk_window_present (GTK_WINDOW (toplevel));
740 gail_widget_remove_focus_handler (AtkComponent *component,
743 g_signal_handler_disconnect (component, handler_id);
747 gail_widget_set_extents (AtkComponent *component,
752 AtkCoordType coord_type)
754 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
761 gail_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
763 if (gtk_widget_is_toplevel (widget))
765 if (coord_type == ATK_XY_WINDOW)
767 gint x_current, y_current;
768 GdkWindow *window = gtk_widget_get_window (widget);
770 gdk_window_get_origin (window, &x_current, &y_current);
773 if (x_current < 0 || y_current < 0)
777 gtk_window_move (GTK_WINDOW (widget), x_current, y_current);
778 gtk_widget_set_size_request (widget, width, height);
782 else if (coord_type == ATK_XY_SCREEN)
784 gtk_window_move (GTK_WINDOW (widget), x, y);
785 gtk_widget_set_size_request (widget, width, height);
793 gail_widget_set_position (AtkComponent *component,
796 AtkCoordType coord_type)
798 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
805 gail_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
807 if (gtk_widget_is_toplevel (widget))
809 if (coord_type == ATK_XY_WINDOW)
811 gint x_current, y_current;
812 GdkWindow *window = gtk_widget_get_window (widget);
814 gdk_window_get_origin (window, &x_current, &y_current);
817 if (x_current < 0 || y_current < 0)
821 gtk_window_move (GTK_WINDOW (widget), x_current, y_current);
825 else if (coord_type == ATK_XY_SCREEN)
827 gtk_window_move (GTK_WINDOW (widget), x, y);
835 gail_widget_set_size (AtkComponent *component,
839 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
846 gail_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
848 if (gtk_widget_is_toplevel (widget))
850 gtk_widget_set_size_request (widget, width, height);
858 * This function is a signal handler for notify_in_event and focus_out_event
859 * signal which gets emitted on a GtkWidget.
862 gail_widget_focus_gtk (GtkWidget *widget,
863 GdkEventFocus *event)
865 GailWidget *gail_widget;
866 GailWidgetClass *klass;
868 gail_widget = GAIL_WIDGET (gtk_widget_get_accessible (widget));
869 klass = GAIL_WIDGET_GET_CLASS (gail_widget);
870 if (klass->focus_gtk)
871 return klass->focus_gtk (widget, event);
877 * This function is the signal handler defined for focus_in_event and
878 * focus_out_event got GailWidget.
880 * It emits a focus-event signal on the GailWidget.
883 gail_widget_real_focus_gtk (GtkWidget *widget,
884 GdkEventFocus *event)
886 AtkObject* accessible;
890 accessible = gtk_widget_get_accessible (widget);
891 g_signal_emit_by_name (accessible, "focus_event", event->in, &return_val);
896 gail_widget_size_allocate_gtk (GtkWidget *widget,
897 GtkAllocation *allocation)
899 AtkObject* accessible;
902 accessible = gtk_widget_get_accessible (widget);
903 if (ATK_IS_COMPONENT (accessible))
905 rect.x = allocation->x;
906 rect.y = allocation->y;
907 rect.width = allocation->width;
908 rect.height = allocation->height;
909 g_signal_emit_by_name (accessible, "bounds_changed", &rect);
914 * This function is the signal handler defined for map and unmap signals.
917 gail_widget_map_gtk (GtkWidget *widget)
919 AtkObject* accessible;
921 accessible = gtk_widget_get_accessible (widget);
922 atk_object_notify_state_change (accessible, ATK_STATE_SHOWING,
923 gtk_widget_get_mapped (widget));
928 * This function is a signal handler for notify signal which gets emitted
929 * when a property changes value on the GtkWidget associated with the object.
931 * It calls a function for the GailWidget type
934 gail_widget_notify_gtk (GObject *obj,
938 GailWidgetClass *klass;
940 widget = GAIL_WIDGET (gtk_widget_get_accessible (GTK_WIDGET (obj)));
941 klass = GAIL_WIDGET_GET_CLASS (widget);
942 if (klass->notify_gtk)
943 klass->notify_gtk (obj, pspec);
947 * This function is a signal handler for notify signal which gets emitted
948 * when a property changes value on the GtkWidget associated with a GailWidget.
950 * It constructs an AtkPropertyValues structure and emits a "property_changed"
951 * signal which causes the user specified AtkPropertyChangeHandler
955 gail_widget_real_notify_gtk (GObject *obj,
958 GtkWidget* widget = GTK_WIDGET (obj);
959 AtkObject* atk_obj = gtk_widget_get_accessible (widget);
963 if (strcmp (pspec->name, "has-focus") == 0)
965 * We use focus-in-event and focus-out-event signals to catch
966 * focus changes so we ignore this.
969 else if (strcmp (pspec->name, "visible") == 0)
971 state = ATK_STATE_VISIBLE;
972 value = gtk_widget_get_visible (widget);
974 else if (strcmp (pspec->name, "sensitive") == 0)
976 state = ATK_STATE_SENSITIVE;
977 value = gtk_widget_get_sensitive (widget);
982 atk_object_notify_state_change (atk_obj, state, value);
983 if (state == ATK_STATE_SENSITIVE)
984 atk_object_notify_state_change (atk_obj, ATK_STATE_ENABLED, value);
989 gail_widget_focus_event (AtkObject *obj,
992 AtkObject *focus_obj;
994 focus_obj = g_object_get_data (G_OBJECT (obj), "gail-focus-object");
995 if (focus_obj == NULL)
997 atk_object_notify_state_change (focus_obj, ATK_STATE_FOCUSED, focus_in);
1001 gail_widget_find_viewport (GtkWidget *widget)
1004 * Find an antecedent which is a GtkViewPort
1008 parent = gtk_widget_get_parent (widget);
1009 while (parent != NULL)
1011 if (GTK_IS_VIEWPORT (parent))
1013 parent = gtk_widget_get_parent (parent);
1019 * This function checks whether the widget has an antecedent which is
1020 * a GtkViewport and, if so, whether any part of the widget intersects
1021 * the visible rectangle of the GtkViewport.
1023 static gboolean gail_widget_on_screen (GtkWidget *widget)
1025 GtkAllocation allocation;
1026 GtkWidget *viewport;
1027 gboolean return_value;
1029 gtk_widget_get_allocation (widget, &allocation);
1031 viewport = gail_widget_find_viewport (widget);
1034 GtkAllocation viewport_allocation;
1035 GtkAdjustment *adjustment;
1036 GdkRectangle visible_rect;
1038 gtk_widget_get_allocation (viewport, &viewport_allocation);
1040 adjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (viewport));
1041 visible_rect.y = adjustment->value;
1042 adjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (viewport));
1043 visible_rect.x = adjustment->value;
1044 visible_rect.width = viewport_allocation.width;
1045 visible_rect.height = viewport_allocation.height;
1047 if (((allocation.x + allocation.width) < visible_rect.x) ||
1048 ((allocation.y + allocation.height) < visible_rect.y) ||
1049 (allocation.x > (visible_rect.x + visible_rect.width)) ||
1050 (allocation.y > (visible_rect.y + visible_rect.height)))
1051 return_value = FALSE;
1053 return_value = TRUE;
1058 * Check whether the widget has been placed of the screen. The
1059 * widget may be MAPPED as when toolbar items do not fit on the toolbar.
1061 if (allocation.x + allocation.width <= 0 &&
1062 allocation.y + allocation.height <= 0)
1063 return_value = FALSE;
1065 return_value = TRUE;
1068 return return_value;
1072 * gail_widget_all_parents_visible:
1073 * @widget: a #GtkWidget
1075 * Checks if all the predecesors (the parent widget, his parent, etc) are visible
1076 * Used to check properly the SHOWING state.
1078 * Return value: TRUE if all the parent hierarchy is visible, FALSE otherwise
1080 static gboolean gail_widget_all_parents_visible (GtkWidget *widget)
1082 GtkWidget *iter_parent = NULL;
1083 gboolean result = TRUE;
1085 for (iter_parent = gtk_widget_get_parent (widget); iter_parent;
1086 iter_parent = gtk_widget_get_parent (iter_parent))
1088 if (!gtk_widget_get_visible (iter_parent))