add_subtree (cache, spi_global_app_data->root);
- atk_add_global_event_listener (child_added_listener,
- "Gtk:AtkObject:children-changed");
+ cache->child_added_listener = atk_add_global_event_listener (child_added_listener,
+ "Gtk:AtkObject:children-changed");
g_signal_connect (G_OBJECT (spi_global_app_data->root),
"children-changed::add",
while (!g_queue_is_empty (cache->add_traversal))
g_object_unref (G_OBJECT (g_queue_pop_head (cache->add_traversal)));
g_queue_free (cache->add_traversal);
- g_free (cache->objects);
+ g_hash_table_unref (cache->objects);
+
+ g_signal_handlers_disconnect_by_func (spi_global_register,
+ (GCallback) remove_object, cache);
+
+ g_signal_handlers_disconnect_by_func (G_OBJECT (spi_global_app_data->root),
+ (GCallback) toplevel_added_listener, NULL);
+
+ atk_remove_global_event_listener (cache->child_added_listener);
G_OBJECT_CLASS (spi_cache_parent_class)->finalize (object);
}
GHashTable * objects;
GQueue *add_traversal;
gint add_pending_idle;
+
+ guint child_added_listener;
};
struct _SpiCacheClass
{
SpiLeasing *leasing = SPI_LEASING (object);
- g_free (leasing->expiry_queue);
+ if (leasing->expiry_func_id)
+ g_source_remove (leasing->expiry_func_id);
+ g_queue_free (leasing->expiry_queue);
G_OBJECT_CLASS (spi_leasing_parent_class)->finalize (object);
}
reg->reference_counter = 0;
}
+static void
+deregister_object (gpointer data, GObject * gobj)
+{
+ SpiRegister *reg = SPI_REGISTER (data);
+
+ spi_register_deregister_object (reg, gobj, FALSE);
+}
+
+static void
+spi_register_remove_weak_ref (gpointer key, gpointer val, gpointer reg)
+{
+ g_object_weak_unref (val, deregister_object, reg);
+}
+
static void
spi_register_finalize (GObject * object)
{
SpiRegister *reg = SPI_REGISTER (object);
- g_free (reg->ref2ptr);
+ g_hash_table_foreach (reg->ref2ptr, spi_register_remove_weak_ref, reg);
+ g_hash_table_unref (reg->ref2ptr);
G_OBJECT_CLASS (spi_register_parent_class)->finalize (object);
}
* Removes the AtkObject from the reference lookup tables, meaning
* it is no longer exposed over D-Bus.
*/
-static void
-deregister_object (gpointer data, GObject * gobj)
-{
- SpiRegister *reg = SPI_REGISTER (data);
-
- spi_register_deregister_object (reg, gobj);
-}
-
void
-spi_register_deregister_object (SpiRegister *reg, GObject *gobj)
+spi_register_deregister_object (SpiRegister *reg, GObject *gobj, gboolean unref)
{
guint ref;
register_signals [OBJECT_DEREGISTERED],
0,
gobj);
+ if (unref)
+ g_object_weak_unref (gobj, deregister_object, reg);
g_hash_table_remove (reg->ref2ptr, GINT_TO_POINTER (ref));
#ifdef SPI_ATK_DEBUG
spi_register_root_object_path ();
void
-spi_register_deregister_object (SpiRegister *reg, GObject *gobj);
+spi_register_deregister_object (SpiRegister *reg, GObject *gobj, gboolean unref);
/*---------------------------------------------------------------------------*/
{
droute_path_add_interface (path, ATSPI_DBUS_INTERFACE_CACHE, spi_org_a11y_atspi_Cache, methods, NULL);
- g_signal_connect (spi_global_cache,
- "object-added",
- (GCallback) emit_cache_add,
- NULL);
-
- g_signal_connect (spi_global_cache,
- "object-removed",
- (GCallback) emit_cache_remove,
- NULL);
+ g_signal_connect (spi_global_cache, "object-added",
+ (GCallback) emit_cache_add, NULL);
+
+ g_signal_connect (spi_global_cache, "object-removed",
+ (GCallback) emit_cache_remove, NULL);
};
/*END------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
+static DBusHandlerResult
+signal_filter (DBusConnection *bus, DBusMessage *message, void *user_data);
+
SpiBridge *spi_global_app_data = NULL;
/*static Display *bridge_display = NULL;*/
/*---------------------------------------------------------------------------*/
-static void
-exit_func (void)
-{
- if (!spi_global_app_data)
- {
- return;
- }
-
- spi_atk_tidy_windows ();
- spi_atk_deregister_event_listeners ();
- deregister_application (spi_global_app_data);
-
- g_free (spi_global_app_data);
- spi_global_app_data = NULL;
-
- /* Not currently creating an XDisplay */
-#if 0
- if (bridge_display)
- XCloseDisplay (bridge_display);
-#endif
-}
-
/*---------------------------------------------------------------------------*/
static AtkPlugClass *plug_class;
droute_intercept_dbus (con);
droute_context_register (spi_global_app_data->droute, con);
- new_list = g_list_append (spi_global_app_data->direct_connections, con);
- if (new_list)
- spi_global_app_data->direct_connections = new_list;
+ spi_global_app_data->direct_connections = g_list_append (spi_global_app_data->direct_connections, con);
}
static int
void
gnome_accessibility_module_shutdown (void)
{
+ GList *l;
+
+ if (!spi_global_app_data)
+ return;
+
+ spi_atk_tidy_windows ();
spi_atk_deregister_event_listeners ();
- exit_func ();
+
+ deregister_application (spi_global_app_data);
+
+ if (spi_global_app_data->bus)
+ {
+ dbus_connection_remove_filter (spi_global_app_data->bus, signal_filter, NULL);
+ droute_context_unregister (spi_global_app_data->droute, spi_global_app_data->bus);
+ dbus_connection_unref (spi_global_app_data->bus);
+ }
+
+ for (l = spi_global_app_data->direct_connections; l; l = l->next)
+ {
+ droute_context_unregister (spi_global_app_data->droute, l->data);
+ droute_unintercept_dbus (l->data);
+ dbus_connection_unref (l);
+ }
+ g_list_free (spi_global_app_data->direct_connections);
+
+ for (l = clients; l; l = l->next)
+ g_free (l->data);
+ g_list_free (clients);
+ clients = NULL;
+
+ g_object_unref (spi_global_cache);
+ g_object_unref (spi_global_leasing);
+ g_object_unref (spi_global_register);
+
+ if (spi_global_app_data->main_context)
+ g_main_context_unref (spi_global_app_data->main_context);
+
+ droute_free (spi_global_app_data->droute);
+
+ g_free (spi_global_app_data);
+ spi_global_app_data = NULL;
+
+ /* Not currently creating an XDisplay */
+#if 0
+ if (bridge_display)
+ XCloseDisplay (bridge_display);
+#endif
}
static gchar *name_match_tmpl =
DBUS_TYPE_INT32_AS_STRING, 0, append_basic);
if (!g_strcmp0 (pname, "defunct"))
- spi_register_deregister_object (spi_global_register, G_OBJECT (accessible));
+ spi_register_deregister_object (spi_global_register, G_OBJECT (accessible),
+ TRUE);
return TRUE;
}
atk_bridge_focus_tracker_id = 0;
}
- for (i = 0; ids && i < ids->len; i++)
+ if (ids)
{
- atk_remove_global_event_listener (g_array_index (ids, guint, i));
+ for (i = 0; i < ids->len; i++)
+ {
+ atk_remove_global_event_listener (g_array_index (ids, guint, i));
+ }
+ g_array_free (ids, TRUE);
}
- g_array_free (ids, TRUE);
if (atk_bridge_key_event_listener_id)
{
&droute_vtable, path);
}
+void
+droute_path_unregister (DRoutePath *path, DBusConnection *bus)
+{
+ dbus_connection_unregister_object_path (bus, path->path);
+}
+
void
droute_context_register (DRouteContext *cnx, DBusConnection *bus)
{
bus);
}
+void
+droute_context_unregister (DRouteContext *cnx, DBusConnection *bus)
+{
+ g_ptr_array_foreach (cnx->registered_paths, (GFunc) droute_path_unregister,
+ bus);
+}
+
+void
+droute_context_deregister (DRouteContext *cnx, DBusConnection *bus)
+{
+ g_ptr_array_foreach (cnx->registered_paths, (GFunc) droute_path_unregister,
+ bus);
+}
+
void
droute_intercept_dbus (DBusConnection *bus)
{
dbus_connection_register_object_path (bus, DBUS_PATH_DBUS,
&droute_vtable, NULL);
}
+
+void
+droute_unintercept_dbus (DBusConnection *bus)
+{
+ dbus_connection_unregister_object_path (bus, DBUS_PATH_DBUS);
+}
+
/*END------------------------------------------------------------------------*/
void
droute_path_register (DRoutePath *path, DBusConnection *bus);
+void
+droute_path_unregister (DRoutePath *path, DBusConnection *bus);
+
void
droute_context_register (DRouteContext *cnx, DBusConnection *bus);
+void
+droute_context_unregister (DRouteContext *cnx, DBusConnection *bus);
+
void
droute_intercept_dbus (DBusConnection *connection);
+
+void
+droute_unintercept_dbus (DBusConnection *connection);
#endif /* _DROUTE_H */