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 "gtknotebookpageaccessible.h"
31 extern GtkWidget *focus_widget;
33 static void gail_widget_class_init (GailWidgetClass *klass);
34 static void gail_widget_init (GailWidget *accessible);
35 static void gail_widget_connect_widget_destroyed (GtkAccessible *accessible);
36 static void gail_widget_destroyed (GtkWidget *widget,
37 GtkAccessible *accessible);
39 static const gchar* gail_widget_get_description (AtkObject *accessible);
40 static AtkObject* gail_widget_get_parent (AtkObject *accessible);
41 static AtkStateSet* gail_widget_ref_state_set (AtkObject *accessible);
42 static AtkRelationSet* gail_widget_ref_relation_set (AtkObject *accessible);
43 static gint gail_widget_get_index_in_parent (AtkObject *accessible);
45 static void atk_component_interface_init (AtkComponentIface *iface);
47 static guint gail_widget_add_focus_handler
48 (AtkComponent *component,
49 AtkFocusHandler handler);
51 static void gail_widget_get_extents (AtkComponent *component,
56 AtkCoordType coord_type);
58 static void gail_widget_get_size (AtkComponent *component,
62 static AtkLayer gail_widget_get_layer (AtkComponent *component);
64 static gboolean gail_widget_grab_focus (AtkComponent *component);
67 static void gail_widget_remove_focus_handler
68 (AtkComponent *component,
71 static gboolean gail_widget_set_extents (AtkComponent *component,
76 AtkCoordType coord_type);
78 static gboolean gail_widget_set_position (AtkComponent *component,
81 AtkCoordType coord_type);
83 static gboolean gail_widget_set_size (AtkComponent *component,
87 static gint gail_widget_map_gtk (GtkWidget *widget);
88 static void gail_widget_real_notify_gtk (GObject *obj,
90 static void gail_widget_notify_gtk (GObject *obj,
92 static gboolean gail_widget_focus_gtk (GtkWidget *widget,
93 GdkEventFocus *event);
94 static gboolean gail_widget_real_focus_gtk (GtkWidget *widget,
95 GdkEventFocus *event);
96 static void gail_widget_size_allocate_gtk (GtkWidget *widget,
97 GtkAllocation *allocation);
99 static void gail_widget_focus_event (AtkObject *obj,
102 static void gail_widget_real_initialize (AtkObject *obj,
104 static AtkAttributeSet *gail_widget_get_attributes(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;
129 class->get_attributes = gail_widget_get_attributes;
133 gail_widget_init (GailWidget *accessible)
138 * This function specifies the GtkWidget for which the GailWidget was created
139 * and specifies a handler to be called when the GtkWidget is destroyed.
142 gail_widget_real_initialize (AtkObject *obj,
145 GtkAccessible *accessible;
148 g_return_if_fail (GTK_IS_WIDGET (data));
150 widget = GTK_WIDGET (data);
152 accessible = GTK_ACCESSIBLE (obj);
153 gtk_accessible_set_widget (accessible, widget);
154 gtk_accessible_connect_widget_destroyed (accessible);
155 g_signal_connect_after (widget,
157 G_CALLBACK (gail_widget_focus_gtk),
159 g_signal_connect_after (widget,
161 G_CALLBACK (gail_widget_focus_gtk),
163 g_signal_connect (widget,
165 G_CALLBACK (gail_widget_notify_gtk),
167 g_signal_connect (widget,
169 G_CALLBACK (gail_widget_size_allocate_gtk),
171 atk_component_add_focus_handler (ATK_COMPONENT (accessible),
172 gail_widget_focus_event);
174 * Add signal handlers for GTK signals required to support property changes
176 g_signal_connect (widget,
178 G_CALLBACK (gail_widget_map_gtk),
180 g_signal_connect (widget,
182 G_CALLBACK (gail_widget_map_gtk),
184 g_object_set_data (G_OBJECT (obj), "atk-component-layer",
185 GINT_TO_POINTER (ATK_LAYER_WIDGET));
187 obj->role = ATK_ROLE_UNKNOWN;
191 * This function specifies the function to be called when the widget
195 gail_widget_connect_widget_destroyed (GtkAccessible *accessible)
199 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
202 g_signal_connect_after (widget,
204 G_CALLBACK (gail_widget_destroyed),
210 * This function is called when the widget is destroyed.
211 * It sets the widget field in the GtkAccessible structure to NULL
212 * and emits a state-change signal for the state ATK_STATE_DEFUNCT
215 gail_widget_destroyed (GtkWidget *widget,
216 GtkAccessible *accessible)
218 gtk_accessible_set_widget (accessible, NULL);
219 atk_object_notify_state_change (ATK_OBJECT (accessible), ATK_STATE_DEFUNCT,
224 gail_widget_get_description (AtkObject *accessible)
226 if (accessible->description)
227 return accessible->description;
232 /* Get the tooltip from the widget */
233 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
240 return gtk_widget_get_tooltip_text (widget);
245 gail_widget_get_parent (AtkObject *accessible)
249 parent = accessible->accessible_parent;
252 g_return_val_if_fail (ATK_IS_OBJECT (parent), NULL);
255 GtkWidget *widget, *parent_widget;
257 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
261 parent_widget = gtk_widget_get_parent (widget);
262 if (parent_widget == NULL)
266 * For a widget whose parent is a GtkNoteBook, we return the
267 * accessible object corresponding the GtkNotebookPage containing
268 * the widget as the accessible parent.
270 if (GTK_IS_NOTEBOOK (parent_widget))
274 GtkNotebook *notebook;
277 notebook = GTK_NOTEBOOK (parent_widget);
280 child = gtk_notebook_get_nth_page (notebook, page_num);
285 parent = gtk_widget_get_accessible (parent_widget);
286 parent = atk_object_ref_accessible_child (parent, page_num);
287 g_object_unref (parent);
294 parent = gtk_widget_get_accessible (parent_widget);
300 find_label (GtkWidget *widget)
304 GtkWidget *temp_widget;
306 labels = gtk_widget_list_mnemonic_labels (widget);
314 g_warning ("Widget (%s) has more than one label", G_OBJECT_TYPE_NAME (widget));
319 label = labels->data;
322 g_list_free (labels);
326 * Ignore a label within a button; bug #136602
328 if (label && GTK_IS_BUTTON (widget))
333 if (temp_widget == widget)
338 temp_widget = gtk_widget_get_parent (temp_widget);
344 static AtkRelationSet*
345 gail_widget_ref_relation_set (AtkObject *obj)
348 AtkRelationSet *relation_set;
351 AtkRelation* relation;
353 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
357 relation_set = ATK_OBJECT_CLASS (gail_widget_parent_class)->ref_relation_set (obj);
359 if (GTK_IS_BOX (widget))
361 * Do not report labelled-by for a GtkBox which could be a
366 if (!atk_relation_set_contains (relation_set, ATK_RELATION_LABELLED_BY))
368 label = find_label (widget);
371 if (GTK_IS_BUTTON (widget))
373 * Handle the case where GnomeIconEntry is the mnemonic widget.
374 * The GtkButton which is a grandchild of the GnomeIconEntry
375 * should really be the mnemonic widget. See bug #133967.
378 GtkWidget *temp_widget;
380 temp_widget = gtk_widget_get_parent (widget);
382 if (GTK_IS_ALIGNMENT (temp_widget))
384 temp_widget = gtk_widget_get_parent (temp_widget);
385 if (GTK_IS_BOX (temp_widget))
387 label = find_label (temp_widget);
390 label = find_label (gtk_widget_get_parent (temp_widget));
394 else if (GTK_IS_COMBO_BOX (widget))
396 * Handle the case when GtkFileChooserButton is the mnemonic
397 * widget. The GtkComboBox which is a child of the
398 * GtkFileChooserButton should be the mnemonic widget.
402 GtkWidget *temp_widget;
404 temp_widget = gtk_widget_get_parent (widget);
405 if (GTK_IS_BOX (temp_widget))
407 label = find_label (temp_widget);
414 array [0] = gtk_widget_get_accessible (label);
416 relation = atk_relation_new (array, 1, ATK_RELATION_LABELLED_BY);
417 atk_relation_set_add (relation_set, relation);
418 g_object_unref (relation);
426 gail_widget_ref_state_set (AtkObject *accessible)
428 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
429 AtkStateSet *state_set;
431 state_set = ATK_OBJECT_CLASS (gail_widget_parent_class)->ref_state_set (accessible);
435 atk_state_set_add_state (state_set, ATK_STATE_DEFUNCT);
439 if (gtk_widget_is_sensitive (widget))
441 atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE);
442 atk_state_set_add_state (state_set, ATK_STATE_ENABLED);
445 if (gtk_widget_get_can_focus (widget))
447 atk_state_set_add_state (state_set, ATK_STATE_FOCUSABLE);
450 * We do not currently generate notifications when an ATK object
451 * corresponding to a GtkWidget changes visibility by being scrolled
452 * on or off the screen. The testcase for this is the main window
453 * of the testgtk application in which a set of buttons in a GtkVBox
454 * is in a scrooled window with a viewport.
456 * To generate the notifications we would need to do the following:
457 * 1) Find the GtkViewPort among the antecendents of the objects
458 * 2) Create an accesible for the GtkViewPort
459 * 3) Connect to the value-changed signal on the viewport
460 * 4) When the signal is received we need to traverse the children
461 * of the viewport and check whether the children are visible or not
462 * visible; we may want to restrict this to the widgets for which
463 * accessible objects have been created.
464 * 5) We probably need to store a variable on_screen in the
465 * GailWidget data structure so we can determine whether the value has
468 if (gtk_widget_get_visible (widget))
470 atk_state_set_add_state (state_set, ATK_STATE_VISIBLE);
471 if (gail_widget_on_screen (widget) && gtk_widget_get_mapped (widget) &&
472 gail_widget_all_parents_visible (widget))
474 atk_state_set_add_state (state_set, ATK_STATE_SHOWING);
478 if (gtk_widget_has_focus (widget) && (widget == focus_widget))
480 AtkObject *focus_obj;
482 focus_obj = g_object_get_data (G_OBJECT (accessible), "gail-focus-object");
483 if (focus_obj == NULL)
484 atk_state_set_add_state (state_set, ATK_STATE_FOCUSED);
486 if (gtk_widget_has_default (widget))
488 atk_state_set_add_state (state_set, ATK_STATE_DEFAULT);
491 if (GTK_IS_ORIENTABLE(widget))
492 switch (gtk_orientable_get_orientation (GTK_ORIENTABLE (widget)))
494 case GTK_ORIENTATION_HORIZONTAL:
495 atk_state_set_add_state (state_set, ATK_STATE_HORIZONTAL);
498 case GTK_ORIENTATION_VERTICAL:
499 atk_state_set_add_state (state_set, ATK_STATE_VERTICAL);
507 gail_widget_get_index_in_parent (AtkObject *accessible)
510 GtkWidget *parent_widget;
514 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
522 if (accessible->accessible_parent)
526 parent = accessible->accessible_parent;
528 if (GTK_IS_NOTEBOOK_PAGE_ACCESSIBLE (parent))
533 gboolean found = FALSE;
535 n_children = atk_object_get_n_accessible_children (parent);
536 for (i = 0; i < n_children; i++)
540 child = atk_object_ref_accessible_child (parent, i);
541 if (child == accessible)
544 g_object_unref (child);
551 if (!GTK_IS_WIDGET (widget))
553 parent_widget = gtk_widget_get_parent (widget);
554 if (!GTK_IS_CONTAINER (parent_widget))
557 children = gtk_container_get_children (GTK_CONTAINER (parent_widget));
559 index = g_list_index (children, widget);
560 g_list_free (children);
565 atk_component_interface_init (AtkComponentIface *iface)
568 * Use default implementation for contains and get_position
570 iface->add_focus_handler = gail_widget_add_focus_handler;
571 iface->get_extents = gail_widget_get_extents;
572 iface->get_size = gail_widget_get_size;
573 iface->get_layer = gail_widget_get_layer;
574 iface->grab_focus = gail_widget_grab_focus;
575 iface->remove_focus_handler = gail_widget_remove_focus_handler;
576 iface->set_extents = gail_widget_set_extents;
577 iface->set_position = gail_widget_set_position;
578 iface->set_size = gail_widget_set_size;
582 gail_widget_add_focus_handler (AtkComponent *component,
583 AtkFocusHandler handler)
585 GSignalMatchType match_type;
589 match_type = G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC;
590 signal_id = g_signal_lookup ("focus-event", ATK_TYPE_OBJECT);
592 ret = g_signal_handler_find (component, match_type, signal_id, 0, NULL,
593 (gpointer) handler, NULL);
596 return g_signal_connect_closure_by_id (component,
599 G_CALLBACK (handler), NULL,
600 (GClosureNotify) NULL),
610 gail_widget_get_extents (AtkComponent *component,
615 AtkCoordType coord_type)
617 GtkAllocation allocation;
619 gint x_window, y_window;
620 gint x_toplevel, y_toplevel;
621 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
626 gtk_widget_get_allocation (widget, &allocation);
627 *width = allocation.width;
628 *height = allocation.height;
629 if (!gail_widget_on_screen (widget) || (!gtk_widget_is_drawable (widget)))
636 if (gtk_widget_get_parent (widget))
640 window = gtk_widget_get_parent_window (widget);
646 window = gtk_widget_get_window (widget);
648 gdk_window_get_origin (window, &x_window, &y_window);
653 if (coord_type == ATK_XY_WINDOW)
655 window = gdk_window_get_toplevel (gtk_widget_get_window (widget));
656 gdk_window_get_origin (window, &x_toplevel, &y_toplevel);
664 gail_widget_get_size (AtkComponent *component,
668 GtkAllocation allocation;
669 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
674 gtk_widget_get_allocation (widget, &allocation);
675 *width = allocation.width;
676 *height = allocation.height;
680 gail_widget_get_layer (AtkComponent *component)
683 layer = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (component), "atk-component-layer"));
685 return (AtkLayer) layer;
689 gail_widget_grab_focus (AtkComponent *component)
691 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
697 if (gtk_widget_get_can_focus (widget))
699 gtk_widget_grab_focus (widget);
700 toplevel = gtk_widget_get_toplevel (widget);
701 if (gtk_widget_is_toplevel (toplevel))
703 #ifdef GDK_WINDOWING_X11
704 gtk_window_present_with_time (GTK_WINDOW (toplevel),
705 gdk_x11_get_server_time (gtk_widget_get_window (widget)));
707 gtk_window_present (GTK_WINDOW (toplevel));
717 gail_widget_remove_focus_handler (AtkComponent *component,
720 g_signal_handler_disconnect (component, handler_id);
724 gail_widget_set_extents (AtkComponent *component,
729 AtkCoordType coord_type)
731 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
736 if (gtk_widget_is_toplevel (widget))
738 if (coord_type == ATK_XY_WINDOW)
740 gint x_current, y_current;
741 GdkWindow *window = gtk_widget_get_window (widget);
743 gdk_window_get_origin (window, &x_current, &y_current);
746 if (x_current < 0 || y_current < 0)
750 gtk_window_move (GTK_WINDOW (widget), x_current, y_current);
751 gtk_widget_set_size_request (widget, width, height);
755 else if (coord_type == ATK_XY_SCREEN)
757 gtk_window_move (GTK_WINDOW (widget), x, y);
758 gtk_widget_set_size_request (widget, width, height);
766 gail_widget_set_position (AtkComponent *component,
769 AtkCoordType coord_type)
771 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
776 if (gtk_widget_is_toplevel (widget))
778 if (coord_type == ATK_XY_WINDOW)
780 gint x_current, y_current;
781 GdkWindow *window = gtk_widget_get_window (widget);
783 gdk_window_get_origin (window, &x_current, &y_current);
786 if (x_current < 0 || y_current < 0)
790 gtk_window_move (GTK_WINDOW (widget), x_current, y_current);
794 else if (coord_type == ATK_XY_SCREEN)
796 gtk_window_move (GTK_WINDOW (widget), x, y);
804 gail_widget_set_size (AtkComponent *component,
808 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
813 if (gtk_widget_is_toplevel (widget))
815 gtk_widget_set_size_request (widget, width, height);
823 * This function is a signal handler for notify_in_event and focus_out_event
824 * signal which gets emitted on a GtkWidget.
827 gail_widget_focus_gtk (GtkWidget *widget,
828 GdkEventFocus *event)
830 GailWidget *gail_widget;
831 GailWidgetClass *klass;
833 gail_widget = GAIL_WIDGET (gtk_widget_get_accessible (widget));
834 klass = GAIL_WIDGET_GET_CLASS (gail_widget);
835 if (klass->focus_gtk)
836 return klass->focus_gtk (widget, event);
842 * This function is the signal handler defined for focus_in_event and
843 * focus_out_event got GailWidget.
845 * It emits a focus-event signal on the GailWidget.
848 gail_widget_real_focus_gtk (GtkWidget *widget,
849 GdkEventFocus *event)
851 AtkObject* accessible;
855 accessible = gtk_widget_get_accessible (widget);
856 g_signal_emit_by_name (accessible, "focus_event", event->in, &return_val);
861 gail_widget_size_allocate_gtk (GtkWidget *widget,
862 GtkAllocation *allocation)
864 AtkObject* accessible;
867 accessible = gtk_widget_get_accessible (widget);
868 if (ATK_IS_COMPONENT (accessible))
870 rect.x = allocation->x;
871 rect.y = allocation->y;
872 rect.width = allocation->width;
873 rect.height = allocation->height;
874 g_signal_emit_by_name (accessible, "bounds_changed", &rect);
879 * This function is the signal handler defined for map and unmap signals.
882 gail_widget_map_gtk (GtkWidget *widget)
884 AtkObject* accessible;
886 accessible = gtk_widget_get_accessible (widget);
887 atk_object_notify_state_change (accessible, ATK_STATE_SHOWING,
888 gtk_widget_get_mapped (widget));
893 * This function is a signal handler for notify signal which gets emitted
894 * when a property changes value on the GtkWidget associated with the object.
896 * It calls a function for the GailWidget type
899 gail_widget_notify_gtk (GObject *obj,
903 GailWidgetClass *klass;
905 widget = GAIL_WIDGET (gtk_widget_get_accessible (GTK_WIDGET (obj)));
906 klass = GAIL_WIDGET_GET_CLASS (widget);
907 if (klass->notify_gtk)
908 klass->notify_gtk (obj, pspec);
912 * This function is a signal handler for notify signal which gets emitted
913 * when a property changes value on the GtkWidget associated with a GailWidget.
915 * It constructs an AtkPropertyValues structure and emits a "property_changed"
916 * signal which causes the user specified AtkPropertyChangeHandler
920 gail_widget_real_notify_gtk (GObject *obj,
923 GtkWidget* widget = GTK_WIDGET (obj);
924 AtkObject* atk_obj = gtk_widget_get_accessible (widget);
928 if (strcmp (pspec->name, "has-focus") == 0)
930 * We use focus-in-event and focus-out-event signals to catch
931 * focus changes so we ignore this.
934 else if (strcmp (pspec->name, "visible") == 0)
936 state = ATK_STATE_VISIBLE;
937 value = gtk_widget_get_visible (widget);
939 else if (strcmp (pspec->name, "sensitive") == 0)
941 state = ATK_STATE_SENSITIVE;
942 value = gtk_widget_get_sensitive (widget);
944 else if (strcmp (pspec->name, "orientation") == 0)
946 GtkOrientable *orientable;
948 orientable = GTK_ORIENTABLE (widget);
950 state = ATK_STATE_HORIZONTAL;
951 value = (gtk_orientable_get_orientation (orientable) == GTK_ORIENTATION_HORIZONTAL);
956 atk_object_notify_state_change (atk_obj, state, value);
957 if (state == ATK_STATE_SENSITIVE)
958 atk_object_notify_state_change (atk_obj, ATK_STATE_ENABLED, value);
960 if (state == ATK_STATE_HORIZONTAL)
961 atk_object_notify_state_change (atk_obj, ATK_STATE_VERTICAL, !value);
965 gail_widget_focus_event (AtkObject *obj,
968 AtkObject *focus_obj;
970 focus_obj = g_object_get_data (G_OBJECT (obj), "gail-focus-object");
971 if (focus_obj == NULL)
973 atk_object_notify_state_change (focus_obj, ATK_STATE_FOCUSED, focus_in);
977 gail_widget_find_viewport (GtkWidget *widget)
980 * Find an antecedent which is a GtkViewPort
984 parent = gtk_widget_get_parent (widget);
985 while (parent != NULL)
987 if (GTK_IS_VIEWPORT (parent))
989 parent = gtk_widget_get_parent (parent);
995 * This function checks whether the widget has an antecedent which is
996 * a GtkViewport and, if so, whether any part of the widget intersects
997 * the visible rectangle of the GtkViewport.
999 static gboolean gail_widget_on_screen (GtkWidget *widget)
1001 GtkAllocation allocation;
1002 GtkWidget *viewport;
1003 gboolean return_value;
1005 gtk_widget_get_allocation (widget, &allocation);
1007 viewport = gail_widget_find_viewport (widget);
1010 GtkAllocation viewport_allocation;
1011 GtkAdjustment *adjustment;
1012 GdkRectangle visible_rect;
1014 gtk_widget_get_allocation (viewport, &viewport_allocation);
1016 adjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (viewport));
1017 visible_rect.y = gtk_adjustment_get_value (adjustment);
1018 adjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (viewport));
1019 visible_rect.x = gtk_adjustment_get_value (adjustment);
1020 visible_rect.width = viewport_allocation.width;
1021 visible_rect.height = viewport_allocation.height;
1023 if (((allocation.x + allocation.width) < visible_rect.x) ||
1024 ((allocation.y + allocation.height) < visible_rect.y) ||
1025 (allocation.x > (visible_rect.x + visible_rect.width)) ||
1026 (allocation.y > (visible_rect.y + visible_rect.height)))
1027 return_value = FALSE;
1029 return_value = TRUE;
1034 * Check whether the widget has been placed of the screen. The
1035 * widget may be MAPPED as when toolbar items do not fit on the toolbar.
1037 if (allocation.x + allocation.width <= 0 &&
1038 allocation.y + allocation.height <= 0)
1039 return_value = FALSE;
1041 return_value = TRUE;
1044 return return_value;
1048 * gail_widget_all_parents_visible:
1049 * @widget: a #GtkWidget
1051 * Checks if all the predecesors (the parent widget, his parent, etc) are visible
1052 * Used to check properly the SHOWING state.
1054 * Return value: TRUE if all the parent hierarchy is visible, FALSE otherwise
1056 static gboolean gail_widget_all_parents_visible (GtkWidget *widget)
1058 GtkWidget *iter_parent = NULL;
1059 gboolean result = TRUE;
1061 for (iter_parent = gtk_widget_get_parent (widget); iter_parent;
1062 iter_parent = gtk_widget_get_parent (iter_parent))
1064 if (!gtk_widget_get_visible (iter_parent))
1074 static AtkAttributeSet *gail_widget_get_attributes(AtkObject *obj)
1076 AtkAttributeSet *attributes;
1077 AtkAttribute *toolkit = g_malloc(sizeof(AtkAttribute));
1079 toolkit->name = g_strdup("toolkit");
1080 toolkit->value = g_strdup("gail");
1082 attributes = g_slist_append(NULL, toolkit);