+ recursion_check_unset ();
+ }
+
+ g_static_rec_mutex_unlock (®istration_mutex);
+
+ return TRUE;
+}
+
+static gboolean
+maybe_expire_lease (gpointer key, gpointer obj_data, gpointer iter)
+{
+ time_t secs = time (NULL) - (time_t)obj_data;
+
+ if (secs < 30)
+ return FALSE;
+ deregister_sub_accessible (key, obj_data, iter);
+ return TRUE;
+}
+
+static void
+expire_old_leases_in (gpointer key, gpointer obj_data, gpointer iter)
+{
+ g_hash_table_foreach_remove ((GHashTable *)obj_data, maybe_expire_lease, NULL);
+}
+
+static void
+expire_old_leases ()
+{
+ g_hash_table_foreach (objects_with_subrefs, expire_old_leases_in, NULL);
+}
+
+static gboolean
+tree_update_state_action (GSignalInvocationHint *signal_hint,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer data,
+ AtkObject *accessible)
+{
+ const gchar *name;
+ gboolean state;
+
+ if (n_param_values < 3)
+ {
+ g_warning ("at-spi: Not enough params in state-changed signal");
+ return TRUE;
+ }
+
+ name = g_value_get_string (param_values + 1);
+ state = g_value_get_boolean (param_values + 2);
+ if (!strcmp (name, "visible"))
+ {
+ AtkStateSet *set = atk_object_ref_state_set (accessible);
+ if (atk_state_set_contains_state (set, ATK_STATE_TRANSIENT))
+ {
+ if (state == 0)
+ {
+ g_hash_table_insert (leased_refs, accessible, (gpointer) time (NULL));
+ leased_refs_count++;
+ /* todo: Set to a high number: 5 for dbg. */
+ if (leased_refs_count > 5)
+ expire_old_leases ();
+ }
+ else
+ {
+ g_hash_table_remove (leased_refs, accessible);
+ leased_refs_count--;
+ }
+ }
+ g_object_unref (set);
+ }
+
+ update_accessible (accessible);
+ return TRUE;
+}
+
+static gboolean
+tree_update_state_listener (GSignalInvocationHint *signal_hint,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer data)
+{
+ tree_update_wrapper (signal_hint, n_param_values, param_values, data, tree_update_state_action);
+ return TRUE;
+}
+
+static gboolean
+tree_update_property_action (GSignalInvocationHint *signal_hint,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer data,
+ AtkObject *accessible)
+{
+ AtkPropertyValues *values;
+ const gchar *pname = NULL;