1 /* GAIL - The GNOME Accessibility Implementation Library
2 * Copyright 2001 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.
27 #include "gailfactory.h"
29 #define GNOME_ACCESSIBILITY_ENV "GNOME_ACCESSIBILITY"
31 static gboolean gail_focus_watcher (GSignalInvocationHint *ihint,
33 const GValue *param_values,
35 static gboolean gail_select_watcher (GSignalInvocationHint *ihint,
37 const GValue *param_values,
39 static gboolean gail_deselect_watcher (GSignalInvocationHint *ihint,
41 const GValue *param_values,
43 static gboolean gail_switch_page_watcher(GSignalInvocationHint *ihint,
45 const GValue *param_values,
47 static AtkObject* gail_get_accessible_for_widget (GtkWidget *widget,
49 static void gail_finish_select (GtkWidget *widget);
50 static void gail_map_cb (GtkWidget *widget);
51 static void gail_map_submenu_cb (GtkWidget *widget);
52 static gint gail_focus_idle_handler (gpointer data);
53 static void gail_focus_notify (GtkWidget *widget);
54 static void gail_focus_notify_when_idle (GtkWidget *widget);
56 static void gail_focus_tracker_init (void);
57 static void gail_focus_object_destroyed (gpointer data);
58 static void gail_focus_tracker (AtkObject *object);
59 static void gail_set_focus_widget (GtkWidget *focus_widget,
61 static void gail_set_focus_object (AtkObject *focus_obj,
64 GtkWidget* focus_widget = NULL;
65 static GtkWidget* next_focus_widget = NULL;
66 static gboolean was_deselect = FALSE;
67 static GtkWidget* subsequent_focus_widget = NULL;
68 static GtkWidget* focus_before_menu = NULL;
69 static guint focus_notify_handler = 0;
70 static guint focus_tracker_id = 0;
71 static GQuark quark_focus_object = 0;
73 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_WIDGET, gail_widget, gail_widget_new)
74 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_CONTAINER, gail_container, gail_container_new)
75 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_BUTTON, gail_button, gail_button_new)
76 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_ITEM, gail_item, gail_item_new)
77 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_MENU_ITEM, gail_menu_item, gail_menu_item_new)
78 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_TOGGLE_BUTTON, gail_toggle_button, gail_toggle_button_new)
79 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_IMAGE, gail_image, gail_image_new)
80 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_TEXT_VIEW, gail_text_view, gail_text_view_new)
81 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_COMBO, gail_combo, gail_combo_new)
82 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_COMBO_BOX, gail_combo_box, gail_combo_box_new)
83 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_ENTRY, gail_entry, gail_entry_new)
84 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_MENU_SHELL, gail_menu_shell, gail_menu_shell_new)
85 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_MENU, gail_menu, gail_menu_new)
86 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_WINDOW, gail_window, gail_window_new)
87 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_RANGE, gail_range, gail_range_new)
88 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_SCALE, gail_scale, gail_scale_new)
89 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_CLIST, gail_clist, gail_clist_new)
90 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_LABEL, gail_label, gail_label_new)
91 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_STATUSBAR, gail_statusbar, gail_statusbar_new)
92 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_NOTEBOOK, gail_notebook, gail_notebook_new)
93 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_CALENDAR, gail_calendar, gail_calendar_new)
94 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_PROGRESS_BAR, gail_progress_bar, gail_progress_bar_new)
95 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_SPIN_BUTTON, gail_spin_button, gail_spin_button_new)
96 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_TREE_VIEW, gail_tree_view, gail_tree_view_new)
97 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_FRAME, gail_frame, gail_frame_new)
98 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_RADIO_BUTTON, gail_radio_button, gail_radio_button_new)
99 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_ARROW, gail_arrow, gail_arrow_new)
100 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_PIXMAP, gail_pixmap, gail_pixmap_new)
101 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_SEPARATOR, gail_separator, gail_separator_new)
102 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_BOX, gail_box, gail_box_new)
103 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_SCROLLED_WINDOW, gail_scrolled_window, gail_scrolled_window_new)
104 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_LIST, gail_list, gail_list_new)
105 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_PANED, gail_paned, gail_paned_new)
106 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_SCROLLBAR, gail_scrollbar, gail_scrollbar_new)
107 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_OPTION_MENU, gail_option_menu, gail_option_menu_new)
108 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_CHECK_MENU_ITEM, gail_check_menu_item, gail_check_menu_item_new)
109 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_RADIO_MENU_ITEM, gail_radio_menu_item, gail_radio_menu_item_new)
110 GAIL_ACCESSIBLE_FACTORY (GAIL_TYPE_EXPANDER, gail_expander, gail_expander_new)
113 gail_get_accessible_for_widget (GtkWidget *widget,
116 AtkObject *obj = NULL;
119 gnome_canvas = g_type_from_name ("GnomeCanvas");
125 if (GTK_IS_ENTRY (widget))
127 GtkWidget *other_widget = widget->parent;
128 if (GTK_IS_COMBO (other_widget))
130 gail_set_focus_widget (other_widget, widget);
131 widget = other_widget;
134 else if (GTK_IS_NOTEBOOK (widget))
136 GtkNotebook *notebook;
139 notebook = GTK_NOTEBOOK (widget);
141 * Report the currently focused tab rather than the currently selected tab
143 if (notebook->focus_tab)
145 page_num = g_list_index (notebook->children, notebook->focus_tab->data);
149 obj = gtk_widget_get_accessible (widget);
150 obj = atk_object_ref_accessible_child (obj, page_num);
151 g_object_unref (obj);
154 else if (GTK_CHECK_TYPE ((widget), gnome_canvas))
156 GObject *focused_item;
157 GValue value = {0, };
159 g_value_init (&value, G_TYPE_OBJECT);
160 g_object_get_property (G_OBJECT (widget), "focused_item", &value);
161 focused_item = g_value_get_object (&value);
167 obj = atk_gobject_accessible_for_object (G_OBJECT (focused_item));
168 tmp = g_object_get_qdata (G_OBJECT (obj), quark_focus_object);
173 else if (GTK_IS_TOGGLE_BUTTON (widget))
175 GtkWidget *other_widget = widget->parent;
176 if (GTK_IS_COMBO_BOX (other_widget))
178 gail_set_focus_widget (other_widget, widget);
179 widget = other_widget;
184 AtkObject *focus_object;
186 obj = gtk_widget_get_accessible (widget);
187 focus_object = g_object_get_qdata (G_OBJECT (obj), quark_focus_object);
189 * We check whether the object for this focus_object has been deleted.
190 * This can happen when navigating to an empty directory in nautilus.
193 if (ATK_IS_GOBJECT_ACCESSIBLE (focus_object))
195 if (!atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (focus_object)))
206 gail_focus_watcher (GSignalInvocationHint *ihint,
207 guint n_param_values,
208 const GValue *param_values,
215 object = g_value_get_object (param_values + 0);
216 g_return_val_if_fail (GTK_IS_WIDGET(object), FALSE);
218 event = g_value_get_boxed (param_values + 1);
219 widget = GTK_WIDGET (object);
221 if (event->type == GDK_FOCUS_CHANGE)
223 if (event->focus_change.in)
225 if (GTK_IS_WINDOW (widget))
229 window = GTK_WINDOW (widget);
230 if (window->focus_widget)
233 * If we already have a potential focus widget set this
234 * windows's focus widget to focus_before_menu so that
235 * it will be reported when menu item is unset.
237 if (next_focus_widget)
239 if (GTK_IS_MENU_ITEM (next_focus_widget) &&
242 void *vp_focus_before_menu = &focus_before_menu;
243 focus_before_menu = window->focus_widget;
244 g_object_add_weak_pointer (G_OBJECT (focus_before_menu), vp_focus_before_menu);
249 widget = window->focus_widget;
251 else if (window->type == GTK_WINDOW_POPUP)
253 if (GTK_IS_BIN (widget))
255 GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
257 if (GTK_IS_WIDGET (child) && GTK_WIDGET_HAS_GRAB (child))
259 if (GTK_IS_MENU_SHELL (child))
261 if (GTK_MENU_SHELL (child)->active_menu_item)
264 * We have a menu which has a menu item selected
265 * so we do not report focus on the menu.
273 else /* popup window has no children; this edge case occurs in some custom code (OOo for instance) */
278 else /* Widget is a non-popup toplevel with no focus children;
279 don't emit for this case either, as it's useless */
287 if (next_focus_widget)
291 toplevel = gtk_widget_get_toplevel (next_focus_widget);
292 if (toplevel == widget)
293 next_focus_widget = NULL;
301 if (event->type == GDK_MOTION_NOTIFY && GTK_WIDGET_HAS_FOCUS (widget))
303 if (widget == focus_widget)
314 * If the focus widget is a GtkSocket without a plug
315 * then ignore the focus notification as the embedded
316 * plug will report a focus notification.
318 if (GTK_IS_SOCKET (widget) &&
319 GTK_SOCKET (widget)->plug_widget == NULL)
322 * The widget may not yet be visible on the screen so we wait until it is.
324 gail_focus_notify_when_idle (widget);
329 gail_select_watcher (GSignalInvocationHint *ihint,
330 guint n_param_values,
331 const GValue *param_values,
337 object = g_value_get_object (param_values + 0);
338 g_return_val_if_fail (GTK_IS_WIDGET(object), FALSE);
340 widget = GTK_WIDGET (object);
342 if (!GTK_WIDGET_MAPPED (widget))
344 g_signal_connect (widget, "map",
345 G_CALLBACK (gail_map_cb),
349 gail_finish_select (widget);
355 gail_finish_select (GtkWidget *widget)
357 if (GTK_IS_MENU_ITEM (widget))
359 GtkMenuItem* menu_item;
361 menu_item = GTK_MENU_ITEM (widget);
362 if (menu_item->submenu &&
363 !GTK_WIDGET_MAPPED (menu_item->submenu))
366 * If the submenu is not visble, wait until it is before
367 * reporting focus on the menu item.
371 handler_id = g_signal_handler_find (menu_item->submenu,
373 g_signal_lookup ("map",
377 (gpointer) gail_map_submenu_cb,
380 g_signal_connect (menu_item->submenu, "map",
381 G_CALLBACK (gail_map_submenu_cb),
387 * If we are waiting to report focus on a menubar or a menu item
388 * because of a previous deselect, cancel it.
391 focus_notify_handler &&
393 (GTK_IS_MENU_BAR (next_focus_widget) ||
394 GTK_IS_MENU_ITEM (next_focus_widget)))
396 void *vp_next_focus_widget = &next_focus_widget;
397 g_source_remove (focus_notify_handler);
398 g_object_remove_weak_pointer (G_OBJECT (next_focus_widget), vp_next_focus_widget);
399 next_focus_widget = NULL;
400 focus_notify_handler = 0;
401 was_deselect = FALSE;
405 * If previously focused widget is not a GtkMenuItem or a GtkMenu,
406 * keep track of it so we can return to it after menubar is deactivated
409 !GTK_IS_MENU_ITEM (focus_widget) &&
410 !GTK_IS_MENU (focus_widget))
412 void *vp_focus_before_menu = &focus_before_menu;
413 focus_before_menu = focus_widget;
414 g_object_add_weak_pointer (G_OBJECT (focus_before_menu), vp_focus_before_menu);
417 gail_focus_notify_when_idle (widget);
423 gail_map_cb (GtkWidget *widget)
425 gail_finish_select (widget);
429 gail_map_submenu_cb (GtkWidget *widget)
431 if (GTK_IS_MENU (widget))
433 if (GTK_MENU (widget)->parent_menu_item)
434 gail_finish_select (GTK_MENU (widget)->parent_menu_item);
440 gail_deselect_watcher (GSignalInvocationHint *ihint,
441 guint n_param_values,
442 const GValue *param_values,
447 GtkWidget *menu_shell;
449 object = g_value_get_object (param_values + 0);
450 g_return_val_if_fail (GTK_IS_WIDGET(object), FALSE);
452 widget = GTK_WIDGET (object);
454 if (!GTK_IS_MENU_ITEM (widget))
457 if (subsequent_focus_widget == widget)
458 subsequent_focus_widget = NULL;
460 menu_shell = gtk_widget_get_parent (widget);
461 if (GTK_IS_MENU_SHELL (menu_shell))
463 GtkWidget *parent_menu_shell;
465 parent_menu_shell = GTK_MENU_SHELL (menu_shell)->parent_menu_shell;
466 if (parent_menu_shell)
468 GtkWidget *active_menu_item;
470 active_menu_item = GTK_MENU_SHELL (parent_menu_shell)->active_menu_item;
471 if (active_menu_item)
473 gail_focus_notify_when_idle (active_menu_item);
478 if (!GTK_IS_MENU_BAR (menu_shell))
480 gail_focus_notify_when_idle (menu_shell);
489 gail_switch_page_watcher (GSignalInvocationHint *ihint,
490 guint n_param_values,
491 const GValue *param_values,
496 GtkNotebook *notebook;
498 object = g_value_get_object (param_values + 0);
499 g_return_val_if_fail (GTK_IS_WIDGET(object), FALSE);
501 widget = GTK_WIDGET (object);
503 if (!GTK_IS_NOTEBOOK (widget))
506 notebook = GTK_NOTEBOOK (widget);
507 if (!notebook->focus_tab)
510 gail_focus_notify_when_idle (widget);
515 gail_focus_idle_handler (gpointer data)
517 focus_notify_handler = 0;
519 * The widget which was to receive focus may have been removed
521 if (!next_focus_widget)
523 if (next_focus_widget != data)
528 void *vp_next_focus_widget = &next_focus_widget;
529 g_object_remove_weak_pointer (G_OBJECT (next_focus_widget), vp_next_focus_widget);
530 next_focus_widget = NULL;
533 gail_focus_notify (data);
539 gail_focus_notify (GtkWidget *widget)
544 if (widget != focus_widget)
548 void *vp_focus_widget = &focus_widget;
549 g_object_remove_weak_pointer (G_OBJECT (focus_widget), vp_focus_widget);
551 focus_widget = widget;
554 void *vp_focus_widget = &focus_widget;
555 g_object_add_weak_pointer (G_OBJECT (focus_widget), vp_focus_widget);
557 * The UI may not have been updated yet; e.g. in gtkhtml2
558 * html_view_layout() is called in a idle handler
560 if (focus_widget == focus_before_menu)
562 void *vp_focus_before_menu = &focus_before_menu;
563 g_object_remove_weak_pointer (G_OBJECT (focus_before_menu), vp_focus_before_menu);
564 focus_before_menu = NULL;
567 gail_focus_notify_when_idle (focus_widget);
572 atk_obj = gail_get_accessible_for_widget (focus_widget, &transient);
576 * Do not report focus on redundant object
579 (atk_object_get_role(atk_obj) != ATK_ROLE_REDUNDANT_OBJECT))
580 atk_focus_tracker_notify (atk_obj);
581 if (atk_obj && transient)
582 g_object_unref (atk_obj);
583 if (subsequent_focus_widget)
585 GtkWidget *tmp_widget = subsequent_focus_widget;
586 subsequent_focus_widget = NULL;
587 gail_focus_notify_when_idle (tmp_widget);
593 gail_focus_notify_when_idle (GtkWidget *widget)
595 if (focus_notify_handler)
600 * Ignore focus request when menu item is going to be focused.
603 if (GTK_IS_MENU_ITEM (next_focus_widget) && !GTK_IS_MENU_ITEM (widget))
606 if (next_focus_widget)
608 if (GTK_IS_MENU_ITEM (next_focus_widget) && GTK_IS_MENU_ITEM (widget))
610 if (gtk_menu_item_get_submenu (GTK_MENU_ITEM (next_focus_widget)) == gtk_widget_get_parent (widget))
612 if (subsequent_focus_widget)
613 g_assert_not_reached ();
614 subsequent_focus_widget = widget;
619 g_source_remove (focus_notify_handler);
620 if (next_focus_widget)
622 void *vp_next_focus_widget = &next_focus_widget;
623 g_object_remove_weak_pointer (G_OBJECT (next_focus_widget), vp_next_focus_widget);
624 next_focus_widget = NULL;
629 * Ignore if focus is being set to NULL and we are waiting to set focus
636 void *vp_next_focus_widget = &next_focus_widget;
637 next_focus_widget = widget;
638 g_object_add_weak_pointer (G_OBJECT (next_focus_widget), vp_next_focus_widget);
643 * We are about to report focus as NULL so remove the weak pointer
644 * for the widget we were waiting to report focus on.
646 if (next_focus_widget)
648 void *vp_next_focus_widget = &next_focus_widget;
649 g_object_remove_weak_pointer (G_OBJECT (next_focus_widget), vp_next_focus_widget);
650 next_focus_widget = NULL;
654 focus_notify_handler = gdk_threads_add_idle (gail_focus_idle_handler, widget);
658 gail_deactivate_watcher (GSignalInvocationHint *ihint,
659 guint n_param_values,
660 const GValue *param_values,
666 GtkWidget *focus = NULL;
668 object = g_value_get_object (param_values + 0);
669 g_return_val_if_fail (GTK_IS_WIDGET(object), FALSE);
670 widget = GTK_WIDGET (object);
672 g_return_val_if_fail (GTK_IS_MENU_SHELL(widget), TRUE);
673 shell = GTK_MENU_SHELL(widget);
674 if (!shell->parent_menu_shell)
675 focus = focus_before_menu;
678 * If we are waiting to report focus on a menubar or a menu item
679 * because of a previous deselect, cancel it.
682 focus_notify_handler &&
684 (GTK_IS_MENU_BAR (next_focus_widget) ||
685 GTK_IS_MENU_ITEM (next_focus_widget)))
687 void *vp_next_focus_widget = &next_focus_widget;
688 g_source_remove (focus_notify_handler);
689 g_object_remove_weak_pointer (G_OBJECT (next_focus_widget), vp_next_focus_widget);
690 next_focus_widget = NULL;
691 focus_notify_handler = 0;
692 was_deselect = FALSE;
694 gail_focus_notify_when_idle (focus);
700 gail_focus_tracker_init (void)
702 static gboolean emission_hooks_added = FALSE;
704 if (!emission_hooks_added)
707 * We cannot be sure that the classes exist so we make sure that they do.
709 gtk_type_class (GTK_TYPE_WIDGET);
710 gtk_type_class (GTK_TYPE_ITEM);
711 gtk_type_class (GTK_TYPE_MENU_SHELL);
712 gtk_type_class (GTK_TYPE_NOTEBOOK);
715 * We listen for event_after signal and then check that the
716 * event was a focus in event so we get called after the event.
718 g_signal_add_emission_hook (
719 g_signal_lookup ("event-after", GTK_TYPE_WIDGET), 0,
720 gail_focus_watcher, NULL, (GDestroyNotify) NULL);
722 * A "select" signal is emitted when arrow key is used to
723 * move to a list item in the popup window of a GtkCombo or
724 * a menu item in a menu.
726 g_signal_add_emission_hook (
727 g_signal_lookup ("select", GTK_TYPE_ITEM), 0,
728 gail_select_watcher, NULL, (GDestroyNotify) NULL);
731 * A "deselect" signal is emitted when arrow key is used to
732 * move from a menu item in a menu to the parent menu.
734 g_signal_add_emission_hook (
735 g_signal_lookup ("deselect", GTK_TYPE_ITEM), 0,
736 gail_deselect_watcher, NULL, (GDestroyNotify) NULL);
739 * We listen for deactivate signals on menushells to determine
740 * when the "focus" has left the menus.
742 g_signal_add_emission_hook (
743 g_signal_lookup ("deactivate", GTK_TYPE_MENU_SHELL), 0,
744 gail_deactivate_watcher, NULL, (GDestroyNotify) NULL);
747 * We listen for "switch-page" signal on a GtkNotebook to notify
748 * when page has changed because of clicking on a notebook tab.
750 g_signal_add_emission_hook (
751 g_signal_lookup ("switch-page", GTK_TYPE_NOTEBOOK), 0,
752 gail_switch_page_watcher, NULL, (GDestroyNotify) NULL);
753 emission_hooks_added = TRUE;
758 gail_focus_object_destroyed (gpointer data)
762 obj = G_OBJECT (data);
763 g_object_set_qdata (obj, quark_focus_object, NULL);
764 g_object_unref (obj);
768 gail_focus_tracker (AtkObject *focus_object)
771 * Do not report focus on redundant object
774 (atk_object_get_role(focus_object) != ATK_ROLE_REDUNDANT_OBJECT))
776 AtkObject *old_focus_object;
778 if (!GTK_IS_ACCESSIBLE (focus_object))
782 parent = focus_object;
785 parent = atk_object_get_parent (parent);
788 if (GTK_IS_ACCESSIBLE (parent))
794 gail_set_focus_object (focus_object, parent);
799 old_focus_object = g_object_get_qdata (G_OBJECT (focus_object), quark_focus_object);
800 if (old_focus_object)
802 g_object_weak_unref (G_OBJECT (old_focus_object),
803 (GWeakNotify) gail_focus_object_destroyed,
805 g_object_set_qdata (G_OBJECT (focus_object), quark_focus_object, NULL);
806 g_object_unref (G_OBJECT (focus_object));
813 gail_set_focus_widget (GtkWidget *focus_widget,
816 AtkObject *focus_obj;
819 focus_obj = gtk_widget_get_accessible (focus_widget);
820 obj = gtk_widget_get_accessible (widget);
821 gail_set_focus_object (focus_obj, obj);
825 gail_set_focus_object (AtkObject *focus_obj,
828 AtkObject *old_focus_obj;
830 old_focus_obj = g_object_get_qdata (G_OBJECT (obj), quark_focus_object);
831 if (old_focus_obj != obj)
834 g_object_weak_unref (G_OBJECT (old_focus_obj),
835 (GWeakNotify) gail_focus_object_destroyed,
839 * We call g_object_ref as if obj is destroyed
840 * while the weak reference exists then destroying the
841 * focus_obj would cause gail_focus_object_destroyed to be
842 * called when obj is not a valid GObject.
846 g_object_weak_ref (G_OBJECT (focus_obj),
847 (GWeakNotify) gail_focus_object_destroyed,
849 g_object_set_qdata (G_OBJECT (obj), quark_focus_object, focus_obj);
854 * These exported symbols are hooked by gnome-program
855 * to provide automatic module initialization and shutdown.
857 extern void gnome_accessibility_module_init (void);
858 extern void gnome_accessibility_module_shutdown (void);
860 static int gail_initialized = FALSE;
863 gail_accessibility_module_init (void)
865 const char *env_a_t_support;
866 gboolean a_t_support = FALSE;
868 if (gail_initialized)
872 gail_initialized = TRUE;
873 quark_focus_object = g_quark_from_static_string ("gail-focus-object");
875 env_a_t_support = g_getenv (GNOME_ACCESSIBILITY_ENV);
878 a_t_support = atoi (env_a_t_support);
880 fprintf (stderr, "GTK Accessibility Module initialized\n");
882 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_WIDGET, gail_widget);
883 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_CONTAINER, gail_container);
884 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_BUTTON, gail_button);
885 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_ITEM, gail_item);
886 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_MENU_ITEM, gail_menu_item);
887 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_TOGGLE_BUTTON, gail_toggle_button);
888 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_IMAGE, gail_image);
889 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_TEXT_VIEW, gail_text_view);
890 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_COMBO, gail_combo);
891 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_COMBO_BOX, gail_combo_box);
892 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_ENTRY, gail_entry);
893 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_MENU_BAR, gail_menu_shell);
894 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_MENU, gail_menu);
895 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_WINDOW, gail_window);
896 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_RANGE, gail_range);
897 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_SCALE, gail_scale);
898 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_CLIST, gail_clist);
899 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_LABEL, gail_label);
900 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_STATUSBAR, gail_statusbar);
901 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_NOTEBOOK, gail_notebook);
902 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_CALENDAR, gail_calendar);
903 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_PROGRESS_BAR, gail_progress_bar);
904 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_SPIN_BUTTON, gail_spin_button);
905 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_TREE_VIEW, gail_tree_view);
906 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_FRAME, gail_frame);
907 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_CELL_RENDERER_TEXT, gail_text_cell);
908 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_CELL_RENDERER_TOGGLE, gail_boolean_cell);
909 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_CELL_RENDERER_PIXBUF, gail_image_cell);
910 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_CELL_RENDERER, gail_renderer_cell);
911 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_RADIO_BUTTON, gail_radio_button);
912 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_ARROW, gail_arrow);
913 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_PIXMAP, gail_pixmap);
914 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_SEPARATOR, gail_separator);
915 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_BOX, gail_box);
916 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_SCROLLED_WINDOW, gail_scrolled_window);
917 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_LIST, gail_list);
918 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_PANED, gail_paned);
919 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_SCROLLBAR, gail_scrollbar);
920 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_OPTION_MENU, gail_option_menu);
921 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_CHECK_MENU_ITEM, gail_check_menu_item);
922 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_RADIO_MENU_ITEM, gail_radio_menu_item);
923 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_EXPANDER, gail_expander);
925 /* LIBGNOMECANVAS SUPPORT */
926 GAIL_WIDGET_SET_FACTORY (GTK_TYPE_OBJECT, gail_object);
928 atk_focus_tracker_init (gail_focus_tracker_init);
929 focus_tracker_id = atk_add_focus_tracker (gail_focus_tracker);
931 /* Initialize the GailUtility class */
932 g_type_class_unref (g_type_class_ref (GAIL_TYPE_UTIL));
933 g_type_class_unref (g_type_class_ref (GAIL_TYPE_MISC));
937 * gnome_accessibility_module_init:
940 * This method is invoked by name from libgnome's
941 * gnome-program.c to activate accessibility support.
944 gnome_accessibility_module_init (void)
946 gail_accessibility_module_init ();
950 * gnome_accessibility_module_shutdown:
953 * This method is invoked by name from libgnome's
954 * gnome-program.c to de-activate accessibility support.
957 gnome_accessibility_module_shutdown (void)
959 if (!gail_initialized)
963 gail_initialized = FALSE;
964 atk_remove_focus_tracker (focus_tracker_id);
966 fprintf (stderr, "GTK Accessibility Module shutdown\n");
968 /* FIXME: de-register the factory types so we can unload ? */
972 gtk_module_init (gint *argc, char** argv[])
974 gail_accessibility_module_init ();