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 const 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 AtkAttributeSet *gail_widget_get_attributes(AtkObject *obj);
106 static GtkWidget* gail_widget_find_viewport (GtkWidget *widget);
107 static gboolean gail_widget_on_screen (GtkWidget *widget);
108 static gboolean gail_widget_all_parents_visible(GtkWidget *widget);
110 G_DEFINE_TYPE_WITH_CODE (GailWidget, gail_widget, GTK_TYPE_ACCESSIBLE,
111 G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, atk_component_interface_init))
114 gail_widget_class_init (GailWidgetClass *klass)
116 AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
117 GtkAccessibleClass *accessible_class = GTK_ACCESSIBLE_CLASS (klass);
119 klass->notify_gtk = gail_widget_real_notify_gtk;
120 klass->focus_gtk = gail_widget_real_focus_gtk;
122 accessible_class->connect_widget_destroyed = gail_widget_connect_widget_destroyed;
124 class->get_description = gail_widget_get_description;
125 class->get_parent = gail_widget_get_parent;
126 class->ref_relation_set = gail_widget_ref_relation_set;
127 class->ref_state_set = gail_widget_ref_state_set;
128 class->get_index_in_parent = gail_widget_get_index_in_parent;
129 class->initialize = gail_widget_real_initialize;
130 class->get_attributes = gail_widget_get_attributes;
134 gail_widget_init (GailWidget *accessible)
139 * This function specifies the GtkWidget for which the GailWidget was created
140 * and specifies a handler to be called when the GtkWidget is destroyed.
143 gail_widget_real_initialize (AtkObject *obj,
146 GtkAccessible *accessible;
149 g_return_if_fail (GTK_IS_WIDGET (data));
151 widget = GTK_WIDGET (data);
153 accessible = GTK_ACCESSIBLE (obj);
154 gtk_accessible_set_widget (accessible, widget);
155 gtk_accessible_connect_widget_destroyed (accessible);
156 g_signal_connect_after (widget,
158 G_CALLBACK (gail_widget_focus_gtk),
160 g_signal_connect_after (widget,
162 G_CALLBACK (gail_widget_focus_gtk),
164 g_signal_connect (widget,
166 G_CALLBACK (gail_widget_notify_gtk),
168 g_signal_connect (widget,
170 G_CALLBACK (gail_widget_size_allocate_gtk),
172 atk_component_add_focus_handler (ATK_COMPONENT (accessible),
173 gail_widget_focus_event);
175 * Add signal handlers for GTK signals required to support property changes
177 g_signal_connect (widget,
179 G_CALLBACK (gail_widget_map_gtk),
181 g_signal_connect (widget,
183 G_CALLBACK (gail_widget_map_gtk),
185 g_object_set_data (G_OBJECT (obj), "atk-component-layer",
186 GINT_TO_POINTER (ATK_LAYER_WIDGET));
188 obj->role = ATK_ROLE_UNKNOWN;
192 gail_widget_new (GtkWidget *widget)
195 AtkObject *accessible;
197 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
199 object = g_object_new (GAIL_TYPE_WIDGET, NULL);
201 accessible = ATK_OBJECT (object);
202 atk_object_initialize (accessible, widget);
208 * This function specifies the function to be called when the widget
212 gail_widget_connect_widget_destroyed (GtkAccessible *accessible)
216 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
219 g_signal_connect_after (widget,
221 G_CALLBACK (gail_widget_destroyed),
227 * This function is called when the widget is destroyed.
228 * It sets the widget field in the GtkAccessible structure to NULL
229 * and emits a state-change signal for the state ATK_STATE_DEFUNCT
232 gail_widget_destroyed (GtkWidget *widget,
233 GtkAccessible *accessible)
235 gtk_accessible_set_widget (accessible, NULL);
236 atk_object_notify_state_change (ATK_OBJECT (accessible), ATK_STATE_DEFUNCT,
241 gail_widget_get_description (AtkObject *accessible)
243 if (accessible->description)
244 return accessible->description;
249 /* Get the tooltip from the widget */
250 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
257 return gtk_widget_get_tooltip_text (widget);
262 gail_widget_get_parent (AtkObject *accessible)
266 parent = accessible->accessible_parent;
269 g_return_val_if_fail (ATK_IS_OBJECT (parent), NULL);
272 GtkWidget *widget, *parent_widget;
274 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
280 gail_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
282 parent_widget = gtk_widget_get_parent (widget);
283 if (parent_widget == NULL)
287 * For a widget whose parent is a GtkNoteBook, we return the
288 * accessible object corresponding the GtkNotebookPage containing
289 * the widget as the accessible parent.
291 if (GTK_IS_NOTEBOOK (parent_widget))
295 GtkNotebook *notebook;
298 notebook = GTK_NOTEBOOK (parent_widget);
301 child = gtk_notebook_get_nth_page (notebook, page_num);
306 parent = gtk_widget_get_accessible (parent_widget);
307 parent = atk_object_ref_accessible_child (parent, page_num);
308 g_object_unref (parent);
315 parent = gtk_widget_get_accessible (parent_widget);
321 find_label (GtkWidget *widget)
325 GtkWidget *temp_widget;
327 labels = gtk_widget_list_mnemonic_labels (widget);
335 g_warning ("Widget (%s) has more than one label", G_OBJECT_TYPE_NAME (widget));
340 label = labels->data;
343 g_list_free (labels);
347 * Ignore a label within a button; bug #136602
349 if (label && GTK_IS_BUTTON (widget))
354 if (temp_widget == widget)
359 temp_widget = gtk_widget_get_parent (temp_widget);
365 static AtkRelationSet*
366 gail_widget_ref_relation_set (AtkObject *obj)
369 AtkRelationSet *relation_set;
372 AtkRelation* relation;
374 gail_return_val_if_fail (GAIL_IS_WIDGET (obj), NULL);
376 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
383 relation_set = ATK_OBJECT_CLASS (gail_widget_parent_class)->ref_relation_set (obj);
385 if (GTK_IS_BOX (widget))
387 * Do not report labelled-by for a GtkBox which could be a
392 if (!atk_relation_set_contains (relation_set, ATK_RELATION_LABELLED_BY))
394 label = find_label (widget);
397 if (GTK_IS_BUTTON (widget))
399 * Handle the case where GnomeIconEntry is the mnemonic widget.
400 * The GtkButton which is a grandchild of the GnomeIconEntry
401 * should really be the mnemonic widget. See bug #133967.
404 GtkWidget *temp_widget;
406 temp_widget = gtk_widget_get_parent (widget);
408 if (GTK_IS_ALIGNMENT (temp_widget))
410 temp_widget = gtk_widget_get_parent (temp_widget);
411 if (GTK_IS_BOX (temp_widget))
413 label = find_label (temp_widget);
416 label = find_label (gtk_widget_get_parent (temp_widget));
420 else if (GTK_IS_COMBO_BOX (widget))
422 * Handle the case when GtkFileChooserButton is the mnemonic
423 * widget. The GtkComboBox which is a child of the
424 * GtkFileChooserButton should be the mnemonic widget.
428 GtkWidget *temp_widget;
430 temp_widget = gtk_widget_get_parent (widget);
431 if (GTK_IS_BOX (temp_widget))
433 label = find_label (temp_widget);
440 array [0] = gtk_widget_get_accessible (label);
442 relation = atk_relation_new (array, 1, ATK_RELATION_LABELLED_BY);
443 atk_relation_set_add (relation_set, relation);
444 g_object_unref (relation);
452 gail_widget_ref_state_set (AtkObject *accessible)
454 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
455 AtkStateSet *state_set;
457 state_set = ATK_OBJECT_CLASS (gail_widget_parent_class)->ref_state_set (accessible);
461 atk_state_set_add_state (state_set, ATK_STATE_DEFUNCT);
465 if (gtk_widget_is_sensitive (widget))
467 atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE);
468 atk_state_set_add_state (state_set, ATK_STATE_ENABLED);
471 if (gtk_widget_get_can_focus (widget))
473 atk_state_set_add_state (state_set, ATK_STATE_FOCUSABLE);
476 * We do not currently generate notifications when an ATK object
477 * corresponding to a GtkWidget changes visibility by being scrolled
478 * on or off the screen. The testcase for this is the main window
479 * of the testgtk application in which a set of buttons in a GtkVBox
480 * is in a scrooled window with a viewport.
482 * To generate the notifications we would need to do the following:
483 * 1) Find the GtkViewPort among the antecendents of the objects
484 * 2) Create an accesible for the GtkViewPort
485 * 3) Connect to the value-changed signal on the viewport
486 * 4) When the signal is received we need to traverse the children
487 * of the viewport and check whether the children are visible or not
488 * visible; we may want to restrict this to the widgets for which
489 * accessible objects have been created.
490 * 5) We probably need to store a variable on_screen in the
491 * GailWidget data structure so we can determine whether the value has
494 if (gtk_widget_get_visible (widget))
496 atk_state_set_add_state (state_set, ATK_STATE_VISIBLE);
497 if (gail_widget_on_screen (widget) && gtk_widget_get_mapped (widget) &&
498 gail_widget_all_parents_visible (widget))
500 atk_state_set_add_state (state_set, ATK_STATE_SHOWING);
504 if (gtk_widget_has_focus (widget) && (widget == focus_widget))
506 AtkObject *focus_obj;
508 focus_obj = g_object_get_data (G_OBJECT (accessible), "gail-focus-object");
509 if (focus_obj == NULL)
510 atk_state_set_add_state (state_set, ATK_STATE_FOCUSED);
512 if (gtk_widget_has_default (widget))
514 atk_state_set_add_state (state_set, ATK_STATE_DEFAULT);
517 if (GTK_IS_ORIENTABLE(widget))
518 switch (gtk_orientable_get_orientation (GTK_ORIENTABLE (widget)))
520 case GTK_ORIENTATION_HORIZONTAL:
521 atk_state_set_add_state (state_set, ATK_STATE_HORIZONTAL);
524 case GTK_ORIENTATION_VERTICAL:
525 atk_state_set_add_state (state_set, ATK_STATE_VERTICAL);
533 gail_widget_get_index_in_parent (AtkObject *accessible)
536 GtkWidget *parent_widget;
541 type = g_type_from_name ("GailCanvasWidget");
542 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
550 if (accessible->accessible_parent)
554 parent = accessible->accessible_parent;
556 if (GAIL_IS_NOTEBOOK_PAGE (parent) ||
557 G_TYPE_CHECK_INSTANCE_TYPE ((parent), type))
562 gboolean found = FALSE;
564 n_children = atk_object_get_n_accessible_children (parent);
565 for (i = 0; i < n_children; i++)
569 child = atk_object_ref_accessible_child (parent, i);
570 if (child == accessible)
573 g_object_unref (child);
580 gail_return_val_if_fail (GTK_IS_WIDGET (widget), -1);
581 parent_widget = gtk_widget_get_parent (widget);
582 if (parent_widget == NULL)
584 gail_return_val_if_fail (GTK_IS_CONTAINER (parent_widget), -1);
586 children = gtk_container_get_children (GTK_CONTAINER (parent_widget));
588 index = g_list_index (children, widget);
589 g_list_free (children);
594 atk_component_interface_init (AtkComponentIface *iface)
597 * Use default implementation for contains and get_position
599 iface->add_focus_handler = gail_widget_add_focus_handler;
600 iface->get_extents = gail_widget_get_extents;
601 iface->get_size = gail_widget_get_size;
602 iface->get_layer = gail_widget_get_layer;
603 iface->grab_focus = gail_widget_grab_focus;
604 iface->remove_focus_handler = gail_widget_remove_focus_handler;
605 iface->set_extents = gail_widget_set_extents;
606 iface->set_position = gail_widget_set_position;
607 iface->set_size = gail_widget_set_size;
611 gail_widget_add_focus_handler (AtkComponent *component,
612 AtkFocusHandler handler)
614 GSignalMatchType match_type;
618 match_type = G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC;
619 signal_id = g_signal_lookup ("focus-event", ATK_TYPE_OBJECT);
621 ret = g_signal_handler_find (component, match_type, signal_id, 0, NULL,
622 (gpointer) handler, NULL);
625 return g_signal_connect_closure_by_id (component,
628 G_CALLBACK (handler), NULL,
629 (GClosureNotify) NULL),
639 gail_widget_get_extents (AtkComponent *component,
644 AtkCoordType coord_type)
646 GtkAllocation allocation;
648 gint x_window, y_window;
649 gint x_toplevel, y_toplevel;
650 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
658 gail_return_if_fail (GTK_IS_WIDGET (widget));
660 gtk_widget_get_allocation (widget, &allocation);
661 *width = allocation.width;
662 *height = allocation.height;
663 if (!gail_widget_on_screen (widget) || (!gtk_widget_is_drawable (widget)))
670 if (gtk_widget_get_parent (widget))
674 window = gtk_widget_get_parent_window (widget);
680 window = gtk_widget_get_window (widget);
682 gdk_window_get_origin (window, &x_window, &y_window);
687 if (coord_type == ATK_XY_WINDOW)
689 window = gdk_window_get_toplevel (gtk_widget_get_window (widget));
690 gdk_window_get_origin (window, &x_toplevel, &y_toplevel);
698 gail_widget_get_size (AtkComponent *component,
702 GtkAllocation allocation;
703 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
711 gail_return_if_fail (GTK_IS_WIDGET (widget));
713 gtk_widget_get_allocation (widget, &allocation);
714 *width = allocation.width;
715 *height = allocation.height;
719 gail_widget_get_layer (AtkComponent *component)
722 layer = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (component), "atk-component-layer"));
724 return (AtkLayer) layer;
728 gail_widget_grab_focus (AtkComponent *component)
730 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
733 gail_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
734 if (gtk_widget_get_can_focus (widget))
736 gtk_widget_grab_focus (widget);
737 toplevel = gtk_widget_get_toplevel (widget);
738 if (gtk_widget_is_toplevel (toplevel))
740 #ifdef GDK_WINDOWING_X11
741 gtk_window_present_with_time (GTK_WINDOW (toplevel),
742 gdk_x11_get_server_time (gtk_widget_get_window (widget)));
744 gtk_window_present (GTK_WINDOW (toplevel));
754 gail_widget_remove_focus_handler (AtkComponent *component,
757 g_signal_handler_disconnect (component, handler_id);
761 gail_widget_set_extents (AtkComponent *component,
766 AtkCoordType coord_type)
768 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
775 gail_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
777 if (gtk_widget_is_toplevel (widget))
779 if (coord_type == ATK_XY_WINDOW)
781 gint x_current, y_current;
782 GdkWindow *window = gtk_widget_get_window (widget);
784 gdk_window_get_origin (window, &x_current, &y_current);
787 if (x_current < 0 || y_current < 0)
791 gtk_window_move (GTK_WINDOW (widget), x_current, y_current);
792 gtk_widget_set_size_request (widget, width, height);
796 else if (coord_type == ATK_XY_SCREEN)
798 gtk_window_move (GTK_WINDOW (widget), x, y);
799 gtk_widget_set_size_request (widget, width, height);
807 gail_widget_set_position (AtkComponent *component,
810 AtkCoordType coord_type)
812 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
819 gail_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
821 if (gtk_widget_is_toplevel (widget))
823 if (coord_type == ATK_XY_WINDOW)
825 gint x_current, y_current;
826 GdkWindow *window = gtk_widget_get_window (widget);
828 gdk_window_get_origin (window, &x_current, &y_current);
831 if (x_current < 0 || y_current < 0)
835 gtk_window_move (GTK_WINDOW (widget), x_current, y_current);
839 else if (coord_type == ATK_XY_SCREEN)
841 gtk_window_move (GTK_WINDOW (widget), x, y);
849 gail_widget_set_size (AtkComponent *component,
853 GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
860 gail_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
862 if (gtk_widget_is_toplevel (widget))
864 gtk_widget_set_size_request (widget, width, height);
872 * This function is a signal handler for notify_in_event and focus_out_event
873 * signal which gets emitted on a GtkWidget.
876 gail_widget_focus_gtk (GtkWidget *widget,
877 GdkEventFocus *event)
879 GailWidget *gail_widget;
880 GailWidgetClass *klass;
882 gail_widget = GAIL_WIDGET (gtk_widget_get_accessible (widget));
883 klass = GAIL_WIDGET_GET_CLASS (gail_widget);
884 if (klass->focus_gtk)
885 return klass->focus_gtk (widget, event);
891 * This function is the signal handler defined for focus_in_event and
892 * focus_out_event got GailWidget.
894 * It emits a focus-event signal on the GailWidget.
897 gail_widget_real_focus_gtk (GtkWidget *widget,
898 GdkEventFocus *event)
900 AtkObject* accessible;
904 accessible = gtk_widget_get_accessible (widget);
905 g_signal_emit_by_name (accessible, "focus_event", event->in, &return_val);
910 gail_widget_size_allocate_gtk (GtkWidget *widget,
911 GtkAllocation *allocation)
913 AtkObject* accessible;
916 accessible = gtk_widget_get_accessible (widget);
917 if (ATK_IS_COMPONENT (accessible))
919 rect.x = allocation->x;
920 rect.y = allocation->y;
921 rect.width = allocation->width;
922 rect.height = allocation->height;
923 g_signal_emit_by_name (accessible, "bounds_changed", &rect);
928 * This function is the signal handler defined for map and unmap signals.
931 gail_widget_map_gtk (GtkWidget *widget)
933 AtkObject* accessible;
935 accessible = gtk_widget_get_accessible (widget);
936 atk_object_notify_state_change (accessible, ATK_STATE_SHOWING,
937 gtk_widget_get_mapped (widget));
942 * This function is a signal handler for notify signal which gets emitted
943 * when a property changes value on the GtkWidget associated with the object.
945 * It calls a function for the GailWidget type
948 gail_widget_notify_gtk (GObject *obj,
952 GailWidgetClass *klass;
954 widget = GAIL_WIDGET (gtk_widget_get_accessible (GTK_WIDGET (obj)));
955 klass = GAIL_WIDGET_GET_CLASS (widget);
956 if (klass->notify_gtk)
957 klass->notify_gtk (obj, pspec);
961 * This function is a signal handler for notify signal which gets emitted
962 * when a property changes value on the GtkWidget associated with a GailWidget.
964 * It constructs an AtkPropertyValues structure and emits a "property_changed"
965 * signal which causes the user specified AtkPropertyChangeHandler
969 gail_widget_real_notify_gtk (GObject *obj,
972 GtkWidget* widget = GTK_WIDGET (obj);
973 AtkObject* atk_obj = gtk_widget_get_accessible (widget);
977 if (strcmp (pspec->name, "has-focus") == 0)
979 * We use focus-in-event and focus-out-event signals to catch
980 * focus changes so we ignore this.
983 else if (strcmp (pspec->name, "visible") == 0)
985 state = ATK_STATE_VISIBLE;
986 value = gtk_widget_get_visible (widget);
988 else if (strcmp (pspec->name, "sensitive") == 0)
990 state = ATK_STATE_SENSITIVE;
991 value = gtk_widget_get_sensitive (widget);
993 else if (strcmp (pspec->name, "orientation") == 0)
995 GtkOrientable *orientable;
997 orientable = GTK_ORIENTABLE (widget);
999 state = ATK_STATE_HORIZONTAL;
1000 value = (gtk_orientable_get_orientation (orientable) == GTK_ORIENTATION_HORIZONTAL);
1005 atk_object_notify_state_change (atk_obj, state, value);
1006 if (state == ATK_STATE_SENSITIVE)
1007 atk_object_notify_state_change (atk_obj, ATK_STATE_ENABLED, value);
1009 if (state == ATK_STATE_HORIZONTAL)
1010 atk_object_notify_state_change (atk_obj, ATK_STATE_VERTICAL, !value);
1014 gail_widget_focus_event (AtkObject *obj,
1017 AtkObject *focus_obj;
1019 focus_obj = g_object_get_data (G_OBJECT (obj), "gail-focus-object");
1020 if (focus_obj == NULL)
1022 atk_object_notify_state_change (focus_obj, ATK_STATE_FOCUSED, focus_in);
1026 gail_widget_find_viewport (GtkWidget *widget)
1029 * Find an antecedent which is a GtkViewPort
1033 parent = gtk_widget_get_parent (widget);
1034 while (parent != NULL)
1036 if (GTK_IS_VIEWPORT (parent))
1038 parent = gtk_widget_get_parent (parent);
1044 * This function checks whether the widget has an antecedent which is
1045 * a GtkViewport and, if so, whether any part of the widget intersects
1046 * the visible rectangle of the GtkViewport.
1048 static gboolean gail_widget_on_screen (GtkWidget *widget)
1050 GtkAllocation allocation;
1051 GtkWidget *viewport;
1052 gboolean return_value;
1054 gtk_widget_get_allocation (widget, &allocation);
1056 viewport = gail_widget_find_viewport (widget);
1059 GtkAllocation viewport_allocation;
1060 GtkAdjustment *adjustment;
1061 GdkRectangle visible_rect;
1063 gtk_widget_get_allocation (viewport, &viewport_allocation);
1065 adjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (viewport));
1066 visible_rect.y = gtk_adjustment_get_value (adjustment);
1067 adjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (viewport));
1068 visible_rect.x = gtk_adjustment_get_value (adjustment);
1069 visible_rect.width = viewport_allocation.width;
1070 visible_rect.height = viewport_allocation.height;
1072 if (((allocation.x + allocation.width) < visible_rect.x) ||
1073 ((allocation.y + allocation.height) < visible_rect.y) ||
1074 (allocation.x > (visible_rect.x + visible_rect.width)) ||
1075 (allocation.y > (visible_rect.y + visible_rect.height)))
1076 return_value = FALSE;
1078 return_value = TRUE;
1083 * Check whether the widget has been placed of the screen. The
1084 * widget may be MAPPED as when toolbar items do not fit on the toolbar.
1086 if (allocation.x + allocation.width <= 0 &&
1087 allocation.y + allocation.height <= 0)
1088 return_value = FALSE;
1090 return_value = TRUE;
1093 return return_value;
1097 * gail_widget_all_parents_visible:
1098 * @widget: a #GtkWidget
1100 * Checks if all the predecesors (the parent widget, his parent, etc) are visible
1101 * Used to check properly the SHOWING state.
1103 * Return value: TRUE if all the parent hierarchy is visible, FALSE otherwise
1105 static gboolean gail_widget_all_parents_visible (GtkWidget *widget)
1107 GtkWidget *iter_parent = NULL;
1108 gboolean result = TRUE;
1110 for (iter_parent = gtk_widget_get_parent (widget); iter_parent;
1111 iter_parent = gtk_widget_get_parent (iter_parent))
1113 if (!gtk_widget_get_visible (iter_parent))
1123 static AtkAttributeSet *gail_widget_get_attributes(AtkObject *obj)
1125 AtkAttributeSet *attributes;
1126 AtkAttribute *toolkit = g_malloc(sizeof(AtkAttribute));
1128 toolkit->name = g_strdup("toolkit");
1129 toolkit->value = g_strdup("gail");
1131 attributes = g_slist_append(NULL, toolkit);