+ SpiDesktop *retval = g_object_new (SPI_DESKTOP_TYPE, NULL);
+
+ return retval;
+}
+
+static void
+abnormal_application_termination (gpointer object, Application *app)
+{
+ g_return_if_fail (SPI_IS_DESKTOP (app->desktop));
+
+ spi_desktop_remove_application (app->desktop, app->ref);
+}
+
+void
+spi_desktop_add_application (SpiDesktop *desktop,
+ const Accessibility_Application application)
+{
+ CORBA_Environment ev;
+ Application *app;
+ Accessibility_Application ref;
+
+ g_return_if_fail (SPI_IS_DESKTOP (desktop));
+
+ spi_desktop_remove_application (desktop, application);
+
+ CORBA_exception_init (&ev);
+
+ ref = bonobo_object_dup_ref (application, &ev);
+
+ if (!BONOBO_EX (&ev))
+ {
+ app = g_new (Application, 1);
+ app->desktop = desktop;
+ app->ref = ref;
+
+ desktop->applications = g_list_append (desktop->applications, app);
+
+ ORBit_small_listen_for_broken (app->ref, G_CALLBACK (abnormal_application_termination), app);
+ }
+
+ CORBA_exception_free (&ev);
+}
+
+void
+spi_desktop_remove_application (SpiDesktop *desktop,
+ const Accessibility_Application app_ref)
+{
+ GList *l;
+ CORBA_Environment ev;
+
+ g_return_if_fail (SPI_IS_DESKTOP (desktop));
+
+ CORBA_exception_init (&ev);
+
+ for (l = desktop->applications; l; l = l->next)
+ {
+ Application *app = (Application *) l->data;
+
+ if (CORBA_Object_is_equivalent (app->ref, app_ref, &ev))
+ {
+ break;
+ }
+ }
+
+ CORBA_exception_free (&ev);
+
+ if (l)
+ {
+ Application *app = (Application *) l->data;
+
+ desktop->applications = g_list_delete_link (desktop->applications, l);
+
+ ORBit_small_unlisten_for_broken (app->ref, G_CALLBACK (abnormal_application_termination));
+ bonobo_object_release_unref (app->ref, NULL);
+ g_free (app);
+ }