-static GHashTable *cache_list;
-
-#define UPDATE_NEW 1
-#define UPDATE_REFRESH 2
-#define UPDATE_REMOVE 3
-
-static int update_pending = 0;
-static gint update_pending_id;
-
-typedef struct
-{
- DBusMessageIter iter;
- DRouteData *droute;
- gboolean removing;
-} CacheIterData;
-
-static void handle_cache_item(char *path, guint action, CacheIterData *d)
-{
- AtkObject *obj;
-
- switch (action)
- {
- case UPDATE_NEW:
- case UPDATE_REFRESH:
- default:
- if (d->removing) return;
- obj = spi_dbus_get_object(path);
-//printf("update %s\n", path);
- append_update(&d->iter, obj, FALSE, d->droute);
- break;
- case UPDATE_REMOVE:
-//printf("remove: %s\n", path);
- if (!d->removing) return;
- dbus_message_iter_append_basic(&d->iter, DBUS_TYPE_OBJECT_PATH, &path);
- break;
- }
- g_hash_table_remove(cache_list, path);
-}
-
-gboolean
-spi_dbus_update_cache(DRouteData *data)
-{
- DBusMessage *message;
- DBusMessageIter iter;
- CacheIterData d;
- static gboolean in_update_cache = FALSE;
-
- if (in_update_cache) return TRUE;
- g_assert(data != NULL);
-
- if (update_pending == 0) return FALSE;
-//printf("Sending cache\n");
- message = dbus_message_new_signal ("/org/freedesktop/atspi/tree", SPI_DBUS_INTERFACE_TREE, "updateTree");
- if (!message) goto done;
- dbus_message_iter_init_append (message, &iter);
- dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ooaoassus)",
- &d.iter);
- d.droute = data;
- d.removing = FALSE;
- in_update_cache = TRUE;
- do
- {
- /* This loop is needed because appending an item may cause new children
- * to be registered and consequently added to the hash, so they, too,
- * will need to be sent with the update */
- update_pending = 0;
- g_hash_table_foreach(cache_list, (GHFunc)handle_cache_item, &d);
- } while (update_pending);
- dbus_message_iter_close_container(&iter, &d.iter);
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "o", &d.iter);
- d.removing = TRUE;
- g_hash_table_foreach(cache_list, (GHFunc)handle_cache_item, &d);
- in_update_cache = FALSE;
- dbus_message_iter_close_container(&iter, &d.iter);
- dbus_connection_send(data->bus, message, NULL);
-done:
- return FALSE;
-}
-
-void spi_dbus_notify_change(AtkObject *obj, gboolean new, DRouteData *data)
-{
- guint action = (new? UPDATE_NEW: UPDATE_REFRESH);
- char *path = spi_dbus_get_path(obj);
-
- if (!cache_list)
- {
- cache_list = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
- if (!cache_list)
- {
- g_free(path);
- return;
- }
- }
- if (g_hash_table_lookup(cache_list, path))
- {
- g_free(path);
- return;
- }
-//printf("change: %s\n", path);
- g_hash_table_insert(cache_list, path, (gpointer)action);
- if (update_pending != 2 && data)
- {
- update_pending_id = g_idle_add((GSourceFunc)spi_dbus_update_cache, data);
- update_pending = 2;
- }
- else if (!update_pending) update_pending = 1;
-}
-
-void spi_dbus_notify_remove(AtkObject *obj, DRouteData *data)
-{
- guint action = UPDATE_REMOVE;
- guint cur_action;
- gchar *path = spi_dbus_get_path(obj);
-
-//printf("notify remove: %s\n", path);
- if (!cache_list)
- {
- g_free(path);
- return;
- }
- cur_action = (guint)g_hash_table_lookup(cache_list, path);
- if (cur_action == UPDATE_NEW)
- {
- /* No one knew that this object ever existed, so just remove it */
-//printf("Removing object from send queue\n");
- g_hash_table_remove(cache_list, path);
- g_free(path);
- }
- else
- {
- g_hash_table_insert(cache_list, path, (gpointer)action);
- if (update_pending != 2 && data)
- {
- update_pending_id = g_idle_add((GSourceFunc)spi_dbus_update_cache, data);
- update_pending = 2;
- }
- else if (!update_pending) update_pending = 1;
- }
-}
-
-gboolean spi_dbus_object_is_known(AtkObject *obj)
-{
- guint cur_action;
- char *path = spi_dbus_get_path(obj);
- if (!path) return FALSE;
- cur_action = (guint)g_hash_table_lookup(cache_list, path);
- g_free(path);
- return (cur_action != UPDATE_NEW);
-}