+ BonoboObject *app = (BonoboObject *) this_app;
+
+ DBG (1, g_message ("exiting bridge\n"));
+
+ if (!app)
+ {
+ return;
+ }
+ this_app = NULL;
+
+ /*
+ * Check whether we still have windows which have not been deleted.
+ */
+ spi_atk_tidy_windows ();
+ /*
+ * FIXME: this may be incorrect for apps that do their own bonobo
+ * shutdown, until we can explicitly shutdown to get the ordering
+ * right.
+ */
+ if (!bonobo_is_initialized ())
+ {
+ DBG (1, g_warning ("Re-initializing bonobo\n"));
+ g_assert (bonobo_init (0, NULL));
+ g_assert (bonobo_activate ());
+ }
+
+ deregister_application (app);
+
+ DBG (1, g_message ("bridge exit func complete.\n"));
+
+ if (g_getenv ("AT_BRIDGE_SHUTDOWN"))
+ {
+ g_assert (!bonobo_debug_shutdown ());
+ }
+}
+
+void
+gnome_accessibility_module_init (void)
+{
+ atk_bridge_init (NULL, NULL);
+
+ if (g_getenv ("AT_BRIDGE_SHUTDOWN"))
+ {
+ g_print("Atk Accessibility bridge initialized\n");
+ }
+}
+
+void
+gnome_accessibility_module_shutdown (void)
+{
+ BonoboObject *app = (BonoboObject *) this_app;
+ int i;
+ GArray *ids = listener_ids;
+
+ if (!atk_bridge_initialized)
+ {
+ return;
+ }
+ atk_bridge_initialized = FALSE;
+ this_app = NULL;
+
+ if (g_getenv ("AT_BRIDGE_SHUTDOWN"))
+ {
+ g_print("Atk Accessibility bridge shutdown\n");
+ }
+
+ listener_ids = NULL;
+ atk_remove_focus_tracker (atk_bridge_focus_tracker_id);
+
+ for (i = 0; ids && i < ids->len; i++)
+ {
+ atk_remove_global_event_listener (g_array_index (ids, guint, i));
+ }
+
+ atk_remove_key_event_listener (atk_bridge_key_event_listener_id);
+
+ deregister_application (app);
+}
+
+static void
+spi_atk_bridge_focus_tracker (AtkObject *object)
+{
+ SpiAccessible *source;
+ Accessibility_Event e;
+
+ source = spi_accessible_new (object);
+
+ e.type = "focus:";
+ e.source = BONOBO_OBJREF (source);
+ e.detail1 = 0;
+ e.detail2 = 0;
+ spi_init_any_nil (&e.any_data);
+
+ CORBA_exception_init (&ev);
+ Accessibility_Registry_notifyEvent (spi_atk_bridge_get_registry (), &e, &ev);
+ if (BONOBO_EX (&ev))
+ registry_died = TRUE;
+
+ bonobo_object_unref (source);
+
+ CORBA_exception_free (&ev);
+}
+
+static void
+spi_atk_emit_eventv (const GObject *gobject,
+ long detail1,
+ long detail2,
+ CORBA_any *any,
+ const char *format, ...)
+{
+ va_list args;
+ Accessibility_Event e;
+ SpiAccessible *source;
+ AtkObject *aobject;
+#ifdef SPI_BRIDGE_DEBUG
+ CORBA_string s;
+#endif
+
+ va_start (args, format);
+
+ if (ATK_IS_IMPLEMENTOR (gobject))
+ {
+ aobject = atk_implementor_ref_accessible (ATK_IMPLEMENTOR (gobject));
+ source = spi_accessible_new (aobject);
+ g_object_unref (G_OBJECT (aobject));
+ }
+ else if (ATK_IS_OBJECT (gobject))
+ {
+ aobject = ATK_OBJECT (gobject);
+ source = spi_accessible_new (aobject);
+ }
+ else
+ {
+ aobject = NULL;
+ source = NULL;
+ DBG (0, g_warning ("received property-change event from non-AtkImplementor"));
+ }
+
+ if (source)
+ {
+ e.type = g_strdup_vprintf (format, args);
+ e.source = BONOBO_OBJREF (source);
+ e.detail1 = detail1;
+ e.detail2 = detail2;
+ if (any) e.any_data = *any;
+ else spi_init_any_nil (&e.any_data);
+
+#ifdef SPI_BRIDGE_DEBUG
+ s = Accessibility_Accessible__get_name (BONOBO_OBJREF (source), &ev);
+ g_warning ("Emitting event '%s' (%lu, %lu) on %s",
+ e.type, e.detail1, e.detail2, s);
+ CORBA_free (s);
+#endif
+ CORBA_exception_init (&ev);
+ Accessibility_Registry_notifyEvent (spi_atk_bridge_get_registry (),
+ &e, &ev);
+#ifdef SPI_BRIDGE_DEBUG
+ if (ev._major != CORBA_NO_EXCEPTION)
+ g_warning ("error emitting event %s, (%d) %s",
+ e.type,
+ ev._major,
+ CORBA_exception_id(&ev));
+#endif
+ if (BONOBO_EX (&ev)) registry_died = TRUE;
+ Accessibility_Accessible_unref (e.source, &ev);
+
+ CORBA_exception_free (&ev);
+
+ g_free (e.type);
+ }
+
+ va_end (args);
+