[at-spi2-atk] Move cache updates to an idle



commit 75ff193c80938e04514e9f4a482baa81227be1a2
Author: Mike Gorse <mgorse novell com>
Date:   Tue May 18 18:44:48 2010 -0400

    Move cache updates to an idle
    
    When receiving a children-changed signal, we add a whole subtree to the
    cache, but not all of the objects have necessarily been initialized yet,
    so we may, eg, indicate in the cache that an object's role is UNKNOWN
    (see BNC#600024).
    This also fixes a crash when starting Firefox 3.6 with at-spi2.

 atk-adaptor/accessible-cache.c |   48 +++++++++++++++++++++++++++++----------
 atk-adaptor/accessible-cache.h |    2 +
 2 files changed, 37 insertions(+), 13 deletions(-)
---
diff --git a/atk-adaptor/accessible-cache.c b/atk-adaptor/accessible-cache.c
index 813d03f..da116ec 100644
--- a/atk-adaptor/accessible-cache.c
+++ b/atk-adaptor/accessible-cache.c
@@ -46,6 +46,9 @@ add_object (SpiCache * cache, GObject * gobj);
 static void
 add_subtree (SpiCache *cache, AtkObject * accessible);
 
+static gboolean
+add_pending_items (gpointer data);
+
 /*---------------------------------------------------------------------------*/
 
 static void
@@ -106,6 +109,7 @@ static void
 spi_cache_init (SpiCache * cache)
 {
   cache->objects = g_hash_table_new (g_direct_hash, g_direct_equal);
+  cache->add_traversal = g_queue_new ();
 
 #ifdef SPI_ATK_DEBUG
   if (g_thread_supported ())
@@ -133,6 +137,9 @@ spi_cache_finalize (GObject * object)
 {
   SpiCache *cache = SPI_CACHE (object);
 
+  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_OBJECT_CLASS (spi_cache_parent_class)->finalize (object);
@@ -240,23 +247,27 @@ append_children (AtkObject * accessible, GQueue * traversal)
 static void
 add_subtree (SpiCache *cache, AtkObject * accessible)
 {
+  g_return_if_fail (ATK_IS_OBJECT (accessible));
+
+  g_object_ref (accessible);
+  g_queue_push_tail (cache->add_traversal, accessible);
+  add_pending_items (cache);
+}
+
+static gboolean
+add_pending_items (gpointer data)
+{
+  SpiCache *cache = SPI_CACHE (data);
   AtkObject *current;
-  GQueue *traversal;
   GQueue *to_add;
 
-  g_return_if_fail (ATK_IS_OBJECT (accessible));
-
-  traversal = g_queue_new ();
   to_add = g_queue_new ();
 
-  g_object_ref (accessible);
-  g_queue_push_tail (traversal, accessible);
-
-  while (!g_queue_is_empty (traversal))
+  while (!g_queue_is_empty (cache->add_traversal))
     {
       AtkStateSet *set;
       
-      current = g_queue_pop_head (traversal);
+      current = g_queue_pop_head (cache->add_traversal);
       set = atk_object_ref_state_set (current);
 
       if (!atk_state_set_contains_state (set, ATK_STATE_TRANSIENT))
@@ -265,7 +276,7 @@ add_subtree (SpiCache *cache, AtkObject * accessible)
           if (!spi_cache_in (cache, G_OBJECT (current)) &&
               !atk_state_set_contains_state  (set, ATK_STATE_MANAGES_DESCENDANTS))
             {
-              append_children (current, traversal);
+              append_children (current, cache->add_traversal);
             }
         }
 
@@ -279,8 +290,9 @@ add_subtree (SpiCache *cache, AtkObject * accessible)
       g_object_unref (G_OBJECT (current));
     }
 
-  g_queue_free (traversal);
   g_queue_free (to_add);
+  cache->add_pending_idle = 0;
+  return FALSE;
 }
 
 /*---------------------------------------------------------------------------*/
@@ -327,7 +339,11 @@ child_added_listener (GSignalInvocationHint * signal_hint,
            {
              child = atk_object_ref_accessible_child (accessible, index);
            }
-          add_subtree (cache, child);
+          g_object_ref (child);
+          g_queue_push_tail (cache->add_traversal, child);
+
+          if (cache->add_pending_idle == 0)
+            cache->add_pending_idle = g_idle_add (add_pending_items, cache);
         }
 #ifdef SPI_ATK_DEBUG
       recursion_check_unset ();
@@ -363,7 +379,13 @@ toplevel_added_listener (AtkObject * accessible,
         {
           child = atk_object_ref_accessible_child (accessible, index);
         }
-      add_subtree (cache, child);
+      else
+        g_object_ref (child);
+
+      g_queue_push_tail (cache->add_traversal, child);
+
+      if (cache->add_pending_idle == 0)
+        cache->add_pending_idle = g_idle_add (add_pending_items, cache);
 #ifdef SPI_ATK_DEBUG
       recursion_check_unset ();
 #endif
diff --git a/atk-adaptor/accessible-cache.h b/atk-adaptor/accessible-cache.h
index 8d75b5d..1089c6f 100644
--- a/atk-adaptor/accessible-cache.h
+++ b/atk-adaptor/accessible-cache.h
@@ -42,6 +42,8 @@ struct _SpiCache
   GObject parent;
 
   GHashTable * objects;
+  GQueue *add_traversal;
+  gint add_pending_idle;
 };
 
 struct _SpiCacheClass



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]