From: Mark Doffman Date: Tue, 5 Jan 2010 09:47:34 +0000 (-0800) Subject: Integrate leasing scheme in-to atk-bridge. X-Git-Tag: AT_SPI2_ATK_2_12_0~446 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git;a=commitdiff_plain;h=5713a8e46559b6de9fbf5fc3e073d0d482d8c7e1 Integrate leasing scheme in-to atk-bridge. This involved: Separating the 'cache' and registration of accessible objects. This is because the leased objects need to be available over D-Bus but are not cached. Separating the cache updating from the 'events'. This is because we should still recieve updates on leased accessibles, but they are not cached. --- diff --git a/Makefile.am b/Makefile.am index 305d97d..31982fe 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1 +1 @@ -SUBDIRS=droute dbind common atk-adaptor tests +SUBDIRS=droute common atk-adaptor diff --git a/atk-adaptor/Makefile.am b/atk-adaptor/Makefile.am index fea7091..140ede4 100644 --- a/atk-adaptor/Makefile.am +++ b/atk-adaptor/Makefile.am @@ -22,17 +22,20 @@ libatk_bridge_la_LIBADD = $(DBUS_GLIB_LIBS) \ $(ATK_LIBS) \ $(X_LIBS) \ $(top_builddir)/droute/libdroute.la \ - $(top_builddir)/dbind/libdbind.la \ $(top_builddir)/common/libspicommon.la \ $(top_builddir)/atk-adaptor/adaptors/libatk-bridge-adaptors.la libatk_bridge_la_SOURCES = \ accessible-leasing.c \ accessible-leasing.h \ + accessible-cache.c \ + accessible-cache.h \ accessible-register.c \ accessible-register.h \ bridge.c \ bridge.h \ + object.c \ + object.h \ event.c \ event.h diff --git a/atk-adaptor/accessible-cache.c b/atk-adaptor/accessible-cache.c new file mode 100644 index 0000000..4f87b18 --- /dev/null +++ b/atk-adaptor/accessible-cache.c @@ -0,0 +1,389 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2009, 2010 Codethink Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +#include "accessible-cache.h" +#include "accessible-register.h" +#include "bridge.h" + +SpiCache *spi_global_cache = NULL; + +static gboolean +child_added_listener (GSignalInvocationHint * signal_hint, + guint n_param_values, + const GValue * param_values, gpointer data); + +static void +toplevel_added_listener (AtkObject * accessible, + guint index, AtkObject * child); + +static void +remove_object (gpointer data, GObject * gobj); + +static void +add_object (SpiCache * cache, GObject * gobj); + +static void +add_subtree (SpiCache *cache, AtkObject * accessible); + +/*---------------------------------------------------------------------------*/ + +static void +spi_cache_finalize (GObject * object); + +static void +spi_cache_dispose (GObject * object); + +/*---------------------------------------------------------------------------*/ + +enum +{ + OBJECT_ADDED, + OBJECT_REMOVED, + LAST_SIGNAL +}; +static guint cache_signals[LAST_SIGNAL] = { 0 }; + +/*---------------------------------------------------------------------------*/ + +G_DEFINE_TYPE (SpiCache, spi_cache, G_TYPE_OBJECT) + +static void spi_cache_class_init (SpiCacheClass * klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + + spi_cache_parent_class = g_type_class_ref (G_TYPE_OBJECT); + + object_class->finalize = spi_cache_finalize; + object_class->dispose = spi_cache_dispose; + + cache_signals [OBJECT_ADDED] = \ + g_signal_new ("object-added", + SPI_CACHE_TYPE, + G_SIGNAL_ACTION, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + G_TYPE_OBJECT); + + cache_signals [OBJECT_REMOVED] = \ + g_signal_new ("object-removed", + SPI_CACHE_TYPE, + G_SIGNAL_ACTION, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + G_TYPE_OBJECT); +} + +static void +spi_cache_init (SpiCache * cache) +{ + cache->objects = g_hash_table_new (g_direct_hash, g_direct_equal); + +#ifdef SPI_ATK_DEBUG + if (g_thread_supported ()) + g_message ("AT-SPI: Threads enabled"); + + g_debug ("AT-SPI: Initial Atk tree regisration"); +#endif + + g_signal_connect (spi_global_register, + "object-deregistered", + (GCallback) remove_object, cache); + + add_subtree (cache, spi_global_app_data->root); + + 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", + (GCallback) toplevel_added_listener, NULL); +} + +static void +spi_cache_finalize (GObject * object) +{ + SpiCache *cache = SPI_CACHE (object); + + g_free (cache->objects); + + G_OBJECT_CLASS (spi_cache_parent_class)->finalize (object); +} + +static void +spi_cache_dispose (GObject * object) +{ + SpiCache *cache = SPI_CACHE (object); + + G_OBJECT_CLASS (spi_cache_parent_class)->dispose (object); +} + +/*---------------------------------------------------------------------------*/ + +static void +remove_object (gpointer data, GObject * gobj) +{ + SpiCache *cache = SPI_CACHE (data); + + if (spi_cache_in (cache, gobj)) + { + g_signal_emit (cache, cache_signals [OBJECT_REMOVED], 0, gobj); + g_hash_table_remove (cache->objects, gobj); + } +} + +static void +add_object (SpiCache * cache, GObject * gobj) +{ + g_return_if_fail (G_IS_OBJECT (gobj)); + + g_hash_table_insert (cache->objects, gobj, NULL); + + g_signal_emit (cache, cache_signals [OBJECT_ADDED], 0, gobj); +} + +/*---------------------------------------------------------------------------*/ + +static GStaticRecMutex cache_mutex = G_STATIC_REC_MUTEX_INIT; +static GStaticMutex recursion_check_guard = G_STATIC_MUTEX_INIT; + +static gboolean recursion_check = FALSE; + +static gboolean +recursion_check_and_set () +{ + gboolean ret; + g_static_mutex_lock (&recursion_check_guard); + ret = recursion_check; + recursion_check = TRUE; + g_static_mutex_unlock (&recursion_check_guard); + return ret; +} + +static void +recursion_check_unset () +{ + g_static_mutex_lock (&recursion_check_guard); + recursion_check = FALSE; + g_static_mutex_unlock (&recursion_check_guard); +} + +/*---------------------------------------------------------------------------*/ + +static void +append_children (AtkObject * accessible, GQueue * traversal) +{ + AtkObject *current; + guint i; + gint count = atk_object_get_n_accessible_children (accessible); + + if (count < 0) + count = 0; + for (i = 0; i < count; i++) + { + current = atk_object_ref_accessible_child (accessible, i); + if (current) + { + g_queue_push_tail (traversal, current); + } + } +} + +/* + * Adds a subtree of accessible objects + * to the cache at the accessible object provided. + * + * The leaf nodes do not have their children + * registered. A node is considered a leaf + * if it has the state "manages-descendants" + * or if it has already been registered. + */ +static void +add_subtree (SpiCache *cache, AtkObject * accessible) +{ + 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)) + { + AtkStateSet *set; + + current = g_queue_pop_head (traversal); + set = atk_object_ref_state_set (current); + + if (!atk_state_set_contains_state (set, ATK_STATE_TRANSIENT)) + { + g_queue_push_tail (to_add, current); + if (!spi_cache_in (cache, G_OBJECT (current)) && + !atk_state_set_contains_state (set, ATK_STATE_MANAGES_DESCENDANTS)) + { +#ifdef SPI_ATK_DEBUG + g_debug ("REG - %s - %d - %s", atk_object_get_name (current), + atk_object_get_role (current), + atk_dbus_object_to_path (current)); +#endif + append_children (current, traversal); + } + } + + g_object_unref (set); + } + + while (!g_queue_is_empty (to_add)) + { + current = g_queue_pop_head (to_add); + add_object (cache, G_OBJECT(current)); + g_object_unref (G_OBJECT (current)); + } + + g_queue_free (traversal); + g_queue_free (to_add); +} + +/*---------------------------------------------------------------------------*/ + +static gboolean +child_added_listener (GSignalInvocationHint * signal_hint, + guint n_param_values, + const GValue * param_values, gpointer data) +{ + SpiCache *cache = spi_global_cache; + + AtkObject *accessible; + AtkObject *child; + + const gchar *detail = NULL; + + g_static_rec_mutex_lock (&cache_mutex); + + /* + * Ensure that only accessibles already in the cache + * have their signals processed. + */ + accessible = ATK_OBJECT (g_value_get_object (¶m_values[0])); + g_return_val_if_fail (ATK_IS_OBJECT (accessible), TRUE); + + if (spi_cache_in (cache, G_OBJECT(accessible))) + { +#ifdef SPI_ATK_DEBUG + if (recursion_check_and_set ()) + g_warning ("AT-SPI: Recursive use of cache module"); + + g_debug ("AT-SPI: Tree update listener"); +#endif + if (signal_hint->detail) + detail = g_quark_to_string (signal_hint->detail); + + if (!strcmp (detail, "add")) + { + gpointer child; + int index = g_value_get_uint (param_values + 1); + child = g_value_get_pointer (param_values + 2); + + if (!ATK_IS_OBJECT (child)) + { + child = atk_object_ref_accessible_child (accessible, index); + } + add_subtree (cache, child); + } +#ifdef SPI_ATK_DEBUG + recursion_check_unset (); +#endif + } + + g_static_rec_mutex_unlock (&cache_mutex); + + return TRUE; +} + +/*---------------------------------------------------------------------------*/ + +static void +toplevel_added_listener (AtkObject * accessible, + guint index, AtkObject * child) +{ + SpiCache *cache = spi_global_cache; + + g_static_rec_mutex_lock (&cache_mutex); + + g_return_if_fail (ATK_IS_OBJECT (accessible)); + + if (spi_cache_in (cache, G_OBJECT(accessible))) + { +#ifdef SPI_ATK_DEBUG + if (recursion_check_and_set ()) + g_warning ("AT-SPI: Recursive use of registration module"); + + g_debug ("AT-SPI: Toplevel added listener"); +#endif + if (!ATK_IS_OBJECT (child)) + { + child = atk_object_ref_accessible_child (accessible, index); + } + add_subtree (cache, child); +#ifdef SPI_ATK_DEBUG + recursion_check_unset (); +#endif + } + + g_static_rec_mutex_unlock (&cache_mutex); +} + +/*---------------------------------------------------------------------------*/ + +void +spi_cache_foreach (SpiCache * cache, GHFunc func, gpointer data) +{ + g_hash_table_foreach (cache->objects, func, data); +} + +gboolean +spi_cache_in (SpiCache * cache, GObject * object) +{ + if (g_hash_table_lookup_extended (cache->objects, + object, + NULL, + NULL)) + return TRUE; + else + return FALSE; +} + +/*END------------------------------------------------------------------------*/ diff --git a/atk-adaptor/accessible-cache.h b/atk-adaptor/accessible-cache.h new file mode 100644 index 0000000..8d75b5d --- /dev/null +++ b/atk-adaptor/accessible-cache.h @@ -0,0 +1,63 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2010 Codethink Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef ACCESSIBLE_CACHE_H +#define ACCESSIBLE_CACHE_H + +#include +#include + +typedef struct _SpiCache SpiCache; +typedef struct _SpiCacheClass SpiCacheClass; + +G_BEGIN_DECLS + +#define SPI_CACHE_TYPE (spi_cache_get_type ()) +#define SPI_CACHE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SPI_CACHE_TYPE, SpiCache)) +#define SPI_CACHE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), SPI_CACHE_TYPE, SpiCacheClass)) +#define SPI_IS_CACHE(o) (G_TYPE_CHECK__INSTANCE_TYPE ((o), SPI_CACHE_TYPE)) +#define SPI_IS_CACHE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SPI_CACHE_TYPE)) + +struct _SpiCache +{ + GObject parent; + + GHashTable * objects; +}; + +struct _SpiCacheClass +{ + GObjectClass parent_class; +}; + +GType spi_cache_get_type (void); + +extern SpiCache *spi_global_cache; + +void +spi_cache_foreach (SpiCache * cache, GHFunc func, gpointer data); + +gboolean +spi_cache_in (SpiCache * cache, GObject * object); + +G_END_DECLS +#endif /* ACCESSIBLE_CACHE_H */ diff --git a/atk-adaptor/accessible-leasing.c b/atk-adaptor/accessible-leasing.c index 0bfd496..28d4099 100644 --- a/atk-adaptor/accessible-leasing.c +++ b/atk-adaptor/accessible-leasing.c @@ -24,10 +24,12 @@ #include #include -#include +#include "accessible-leasing.h" /*---------------------------------------------------------------------------*/ +SpiLeasing *spi_global_leasing; + typedef struct _ExpiryElement { guint expiry_s; diff --git a/atk-adaptor/accessible-leasing.h b/atk-adaptor/accessible-leasing.h index 50f1f3c..af01a78 100644 --- a/atk-adaptor/accessible-leasing.h +++ b/atk-adaptor/accessible-leasing.h @@ -21,8 +21,8 @@ * Boston, MA 02111-1307, USA. */ -#ifndef ACCESSIBLE_LEASING -#define ACCESSIBLE_LEASING +#ifndef ACCESSIBLE_LEASING_H +#define ACCESSIBLE_LEASING_H #include #include @@ -53,7 +53,9 @@ struct _SpiLeasingClass GType spi_leasing_get_type (void); +extern SpiLeasing *spi_global_leasing; + GObject *spi_leasing_take (SpiLeasing * leasing, GObject * object); G_END_DECLS -#endif /* ACCESSIBLE_LEASING */ +#endif /* ACCESSIBLE_LEASING_H */ diff --git a/atk-adaptor/accessible-register.c b/atk-adaptor/accessible-register.c index f0963af..ac93dee 100644 --- a/atk-adaptor/accessible-register.c +++ b/atk-adaptor/accessible-register.c @@ -3,7 +3,7 @@ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) * * Copyright 2008 Novell, Inc. - * Copyright 2008, 2009 Codethink Ltd. + * Copyright 2008, 2009, 2010 Codethink Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -26,7 +26,6 @@ #include #include "bridge.h" -#include "tree-adaptor.h" #include "accessible-register.h" /* @@ -46,74 +45,95 @@ * object destruction. When an object is destroyed it must be 'deregistered' * To do this lookup we keep a dbus-id attribute on each AtkObject. * - * In addition to accessing the objects remotely we must be able to update - * the client side cache. This is done using the 'update' signal of the - * org.freedesktop.atspi.Tree interface. The update signal should send out - * all of the cacheable data for an Accessible object. - * */ -/* - * FIXME - * - * This code seems very brittle. - * I would prefer changes to be made to - * gail and the ATK interface so that all Accessible - * objects are registered with an exporting module. - * - * This is the same system as Qt has with the QAccessibleBridge - * and QAccessibleBridgePlugin. It entails some rather - * large structural changes to ATK though: - * - * Removing infinite spaces (Child access no longer references child). - * Removing lazy creation of accessible objects. - */ - -#define SPI_ATK_OBJECT_PATH_PREFIX "/org/freedesktop/atspi/accessible" -#define SPI_ATK_OBJECT_PATH_DESKTOP "/desktop" +#define SPI_ATK_PATH_PREFIX_LENGTH 22 +#define SPI_ATK_OBJECT_PATH_PREFIX "/org/at_spi/accessible" +#define SPI_ATK_OBJECT_PATH_DESKTOP SPI_ATK_OBJECT_PATH_PREFIX "/desktop" -#define SPI_ATK_PATH_PREFIX_LENGTH 33 #define SPI_ATK_OBJECT_REFERENCE_TEMPLATE SPI_ATK_OBJECT_PATH_PREFIX "/%d" +#define SPI_DBUS_ID "spi-dbus-id" + +SpiRegister *spi_global_register = NULL; + +enum +{ + OBJECT_REGISTERED, + OBJECT_DEREGISTERED, + LAST_SIGNAL +}; +static guint register_signals[LAST_SIGNAL] = { 0 }; -static GHashTable *ref2ptr = NULL; /* Used for converting a D-Bus path (Reference) to the object pointer */ -static GHashTable *objects_with_subrefs = NULL; -static GHashTable *leased_refs = NULL; -static int leased_refs_count; +/*---------------------------------------------------------------------------*/ -static guint reference_counter = 0; +static void +spi_register_finalize (GObject * object); -static GStaticRecMutex registration_mutex = G_STATIC_REC_MUTEX_INIT; +static void +spi_register_dispose (GObject * object); /*---------------------------------------------------------------------------*/ -static GStaticMutex recursion_check_guard = G_STATIC_MUTEX_INIT; -static gboolean recursion_check = FALSE; -static int last_gc_time; +G_DEFINE_TYPE (SpiRegister, spi_register, G_TYPE_OBJECT) -static void deregister_sub_accessible (gpointer key, gpointer obj_data, - gpointer iter); +static void spi_register_class_init (SpiRegisterClass * klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; -static void deregister_sub_hyperlink (gpointer key, gpointer obj_data, - gpointer iter); + spi_register_parent_class = g_type_class_ref (G_TYPE_OBJECT); + + object_class->finalize = spi_register_finalize; + object_class->dispose = spi_register_dispose; + + register_signals [OBJECT_REGISTERED] = + g_signal_new ("object-registered", + SPI_REGISTER_TYPE, + G_SIGNAL_ACTION, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + G_TYPE_OBJECT); + + register_signals [OBJECT_DEREGISTERED] = + g_signal_new ("object-deregistered", + SPI_REGISTER_TYPE, + G_SIGNAL_ACTION, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + G_TYPE_OBJECT); +} -static gboolean -recursion_check_and_set () +static void +spi_register_init (SpiRegister * reg) { - gboolean ret; - g_static_mutex_lock (&recursion_check_guard); - ret = recursion_check; - recursion_check = TRUE; - g_static_mutex_unlock (&recursion_check_guard); - return ret; + reg->ref2ptr = g_hash_table_new (g_direct_hash, g_direct_equal); + reg->reference_counter = 0; } static void -recursion_check_unset () +spi_register_finalize (GObject * object) { - g_static_mutex_lock (&recursion_check_guard); - recursion_check = FALSE; - g_static_mutex_unlock (&recursion_check_guard); + SpiRegister *reg = SPI_REGISTER (object); + + g_free (reg->ref2ptr); + + G_OBJECT_CLASS (spi_register_parent_class)->finalize (object); +} + +static void +spi_register_dispose (GObject * object) +{ + SpiRegister *reg = SPI_REGISTER (object); + + G_OBJECT_CLASS (spi_register_parent_class)->dispose (object); } /*---------------------------------------------------------------------------*/ @@ -123,44 +143,35 @@ recursion_check_unset () * * This function provides an integer reference for a new * AtkObject. + * + * TODO: Make this reference a little more unique, this is shoddy. */ static guint -assign_reference (void) +assign_reference (SpiRegister * reg) { - reference_counter++; + reg->reference_counter++; /* Reference of 0 not allowed as used as direct key in hash table */ - if (reference_counter == 0) - reference_counter++; - /* TODO: If we've wrapped, ensure that two objects don't have the same ref */ - return reference_counter; + if (reg->reference_counter == 0) + reg->reference_counter++; + return reg->reference_counter; } +/*---------------------------------------------------------------------------*/ + /* * Returns the reference of the object, or 0 if it is not registered. */ static guint -gobject_to_ref (GObject * gobj) -{ - return GPOINTER_TO_INT (g_object_get_data (gobj, "dbus-id")); -} - -static guint -object_to_ref (AtkObject * accessible) +object_to_ref (GObject * gobj) { - return gobject_to_ref (G_OBJECT (accessible)); -} - -static guint -hyperlink_to_ref (AtkHyperlink * link) -{ - return gobject_to_ref (G_OBJECT (link)); + return GPOINTER_TO_INT (g_object_get_data (gobj, SPI_DBUS_ID)); } /* * Converts the Accessible object reference to its D-Bus object path */ -gchar * -atk_dbus_ref_to_path (guint ref) +static gchar * +ref_to_path (guint ref) { return g_strdup_printf (SPI_ATK_OBJECT_REFERENCE_TEMPLATE, ref); } @@ -176,305 +187,44 @@ atk_dbus_ref_to_path (guint ref) static void deregister_object (gpointer data, GObject * gobj) { + SpiRegister *reg = SPI_REGISTER (data); guint ref; - GHashTable *subrefs_atk; - GHashTable *subrefs_hyperlink; - g_return_if_fail (ATK_IS_OBJECT (gobj) || ATK_IS_HYPERLINK (gobj)); - - subrefs_atk = (GHashTable *) g_object_get_data (gobj, "dbus-subrefs-atk"); - subrefs_hyperlink = - (GHashTable *) g_object_get_data (gobj, "dbus-subrefs-hyperlink"); - - if (subrefs_atk) - { - g_hash_table_foreach (subrefs_atk, deregister_sub_accessible, data); - g_hash_table_unref (subrefs_atk); - } - - if (subrefs_hyperlink) - { - g_hash_table_foreach (subrefs_hyperlink, deregister_sub_hyperlink, - data); - g_hash_table_unref (subrefs_hyperlink); - } - - if (subrefs_atk || subrefs_hyperlink) - g_hash_table_remove (objects_with_subrefs, gobj); - - if (ATK_IS_OBJECT (gobj)) - { - ref = object_to_ref (ATK_OBJECT (gobj)); - if (ref != 0) - { - spi_emit_cache_removal (ref, atk_adaptor_app_data->bus); - g_hash_table_remove (ref2ptr, GINT_TO_POINTER (ref)); - } - } -} - -static void -deregister_sub_accessible (gpointer key, gpointer obj_data, gpointer iter) -{ - GObject *obj = G_OBJECT (obj_data); - deregister_object (NULL, obj); - g_hash_table_remove (leased_refs, obj); - g_object_unref (obj); -} - -static void -deregister_sub_hyperlink (gpointer key, gpointer obj_data, gpointer iter) -{ - guint ref; - GObject *ghyperlink = G_OBJECT (obj_data); - g_return_if_fail (ATK_IS_HYPERLINK (ghyperlink)); - - ref = gobject_to_ref (ghyperlink); + ref = object_to_ref (gobj); if (ref != 0) { - g_hash_table_remove (ref2ptr, GINT_TO_POINTER (ref)); + g_signal_emit (reg, + register_signals [OBJECT_DEREGISTERED], + 0, + gobj); + g_hash_table_remove (reg->ref2ptr, GINT_TO_POINTER (ref)); } - g_object_unref (ghyperlink); } static void -register_gobject (GObject * gobj, GObject * container) +register_object (SpiRegister * reg, GObject * gobj) { guint ref; g_return_if_fail (G_IS_OBJECT (gobj)); - ref = assign_reference (); - - g_hash_table_insert (ref2ptr, GINT_TO_POINTER (ref), gobj); - g_object_set_data (G_OBJECT (gobj), "dbus-id", GINT_TO_POINTER (ref)); - g_object_weak_ref (G_OBJECT (gobj), deregister_object, NULL); - - if (container) - { - GHashTable *subrefs = - (GHashTable *) g_object_get_data (G_OBJECT (container), - "dbus-subrefs-atk"); - if (!subrefs) - { - subrefs = g_hash_table_new (g_direct_hash, g_direct_equal); - g_object_set_data (G_OBJECT (container), "dbus-subrefs-atk", - subrefs); - } - g_hash_table_insert (subrefs, GINT_TO_POINTER (ref), gobj); - g_hash_table_insert (objects_with_subrefs, gobj, subrefs); - } - - if (ATK_IS_HYPERLINK (gobj)) - g_object_ref (gobj); - else if (ATK_IS_OBJECT (gobj)) - { - AtkObject *accessible = ATK_OBJECT (gobj); - AtkStateSet *state = atk_object_ref_state_set (accessible); - if (atk_state_set_contains_state (state, ATK_STATE_TRANSIENT)) - { - g_object_ref (gobj); - /* We should only get here as the result of a query other than GetTree */ - spi_emit_cache_update (accessible, atk_adaptor_app_data->bus); - } - g_object_unref (state); - } -} - -/* - * Called to register an AtkObject with AT-SPI and expose it over D-Bus. - */ -static void -register_accessible (AtkObject * accessible, AtkObject * container) -{ - g_return_if_fail (ATK_IS_OBJECT (accessible)); - - register_gobject (G_OBJECT (accessible), G_OBJECT (container)); -} - -static void -register_hyperlink (AtkHyperlink * hyperlink, AtkObject * container) -{ - guint ref; - g_return_if_fail (ATK_IS_HYPERLINK (hyperlink)); - g_return_if_fail (container); - - ref = assign_reference (); + ref = assign_reference (reg); - g_hash_table_insert (ref2ptr, GINT_TO_POINTER (ref), hyperlink); - g_object_set_data (G_OBJECT (hyperlink), "dbus-id", GINT_TO_POINTER (ref)); - g_object_ref (G_OBJECT (hyperlink)); + g_hash_table_insert (reg->ref2ptr, GINT_TO_POINTER (ref), gobj); + g_object_set_data (G_OBJECT (gobj), SPI_DBUS_ID, GINT_TO_POINTER (ref)); + g_object_weak_ref (G_OBJECT (gobj), deregister_object, reg); - GHashTable *subrefs = - (GHashTable *) g_object_get_data (G_OBJECT (container), - "dbus-subrefs-hyperlink"); - if (!subrefs) - { - subrefs = g_hash_table_new (g_direct_hash, g_direct_equal); - g_object_set_data (G_OBJECT (container), "dbus-subrefs-hyperlink", - GINT_TO_POINTER (ref)); - } - g_hash_table_insert (subrefs, GINT_TO_POINTER (ref), hyperlink); -} - -/*---------------------------------------------------------------------------*/ - -#ifdef SPI_ATK_DEBUG -/* - * This function checks that the ref-count of an accessible - * is greater than 1. - * - * There is not currently any remote reference counting - * in AT-SPI D-Bus so objects that are remotely owned are not - * allowed. - * - * TODO Add debug wrapper - */ -static gboolean -non_owned_accessible (AtkObject * accessible) -{ - if ((G_OBJECT (accessible))->ref_count <= 1) - { - g_warning ("AT-SPI: Child referenced that is not owned by its parent"); - return TRUE; - } - else - { - return FALSE; - } -} -#endif /* SPI_ATK_DEBUG */ - -/*---------------------------------------------------------------------------*/ - -/* TRUE if we should not keep this object / tell the AT about it - * Currently true if TRANSIENT and not SHOWING - */ -static gboolean -object_is_moot (AtkObject * accessible) -{ - AtkStateSet *state; - gboolean result = FALSE; - - /* This is dangerous, refing the state set - * seems to do wierd things to the tree & cause recursion - * by modifying the tree alot. - */ - state = atk_object_ref_state_set (accessible); - if (atk_state_set_contains_state (state, ATK_STATE_TRANSIENT) && - !atk_state_set_contains_state (state, ATK_STATE_SHOWING)) - { - result = TRUE; - } - g_object_unref (state); - - return result; -} - -static void -append_children (AtkObject * accessible, GQueue * traversal) -{ - AtkObject *current; - guint i; - gint count = atk_object_get_n_accessible_children (accessible); - - if (count < 0) - count = 0; - for (i = 0; i < count; i++) - { - current = atk_object_ref_accessible_child (accessible, i); - if (current) - { -#ifdef SPI_ATK_DEBUG - non_owned_accessible (current); -#endif - g_queue_push_tail (traversal, current); - } - } -} - -/* - * Registers a subtree of accessible objects - * rooted at the accessible object provided. - * - * The leaf nodes do not have their children - * registered. A node is considered a leaf - * if it has the state "manages-descendants" - * or if it has already been registered. - */ -void -register_subtree (AtkObject * accessible) -{ - AtkObject *current; - GQueue *traversal; - GQueue *emit_update; - - g_return_if_fail (ATK_IS_OBJECT (accessible)); - - traversal = g_queue_new (); - emit_update = g_queue_new (); - - g_object_ref (accessible); - g_queue_push_tail (traversal, accessible); - - while (!g_queue_is_empty (traversal)) - { - current = g_queue_pop_head (traversal); - g_queue_push_tail (emit_update, current); - if (!object_to_ref (current)) - { - register_accessible (current, NULL); -#ifdef SPI_ATK_DEBUG - g_debug ("REG - %s - %d - %s", atk_object_get_name (current), - atk_object_get_role (current), - atk_dbus_object_to_path (current)); -#endif - append_children (current, traversal); - } - } - - while (!g_queue_is_empty (emit_update)) - { - current = g_queue_pop_head (emit_update); - spi_emit_cache_update (current, atk_adaptor_app_data->bus); - g_object_unref (G_OBJECT (current)); - } - - g_queue_free (traversal); - g_queue_free (emit_update); -} - -/*---------------------------------------------------------------------------*/ - -/* - * Called when an already registered object is updated in such a - * way that client side cache needs to be updated. - */ -static void -update_accessible (AtkObject * accessible) -{ - guint ref = 0; - g_return_if_fail (ATK_IS_OBJECT (accessible)); - - ref = object_to_ref (accessible); - if (ref) - { - spi_emit_cache_update (accessible, atk_adaptor_app_data->bus); - } + g_signal_emit (reg, register_signals [OBJECT_REGISTERED], 0, gobj); } /*---------------------------------------------------------------------------*/ -void -atk_dbus_foreach_registered (GHFunc func, gpointer data) -{ - g_hash_table_foreach (ref2ptr, func, data); -} - /* - * Used to lookup an AtkObject from its D-Bus path. + * Used to lookup an GObject from its D-Bus path. + * + * If the D-Bus path is not found this function returns NULL. */ GObject * -atk_dbus_path_to_gobject (const char *path) +spi_register_path_to_object (SpiRegister * reg, const char *path) { guint index; void *data; @@ -494,447 +244,58 @@ atk_dbus_path_to_gobject (const char *path) path++; index = atoi (path); - data = g_hash_table_lookup (ref2ptr, GINT_TO_POINTER (index)); + data = g_hash_table_lookup (reg->ref2ptr, GINT_TO_POINTER (index)); if (data) - { - GObject *gobj = G_OBJECT (data); - g_object_set_data (gobj, "last-ref-time", (gpointer) time (NULL)); - return gobj; - } + return G_OBJECT(data); else return NULL; } -AtkObject * -atk_dbus_path_to_object (const char *path) +GObject * +spi_global_register_path_to_object (const char * path) { - return ATK_OBJECT (atk_dbus_path_to_gobject (path)); + return spi_register_path_to_object (spi_global_register, path); } /* - * TODO WARNING HACK This function is dangerous. - * It should only be called before sending an event on an - * object that has not already been registered. + * Used to lookup a D-Bus path from the GObject. + * + * If the objects is not already registered, + * this function will register it. */ gchar * -atk_dbus_object_attempt_registration (AtkObject * accessible) +spi_register_object_to_path (SpiRegister * reg, GObject * gobj) { guint ref; - ref = object_to_ref (accessible); + ref = object_to_ref (gobj); if (!ref) { - /* See if the object is attached to the main tree */ - AtkObject *current, *prev = NULL; - guint cref = 0; - - /* This should iterate until it hits a NULL or registered parent */ - prev = accessible; - current = atk_object_get_parent (accessible); - if (current) - cref = object_to_ref (current); - while (current && !cref) - { - prev = current; - current = atk_object_get_parent (current); - if (current) - cref = object_to_ref (current); - } - - /* A registered parent, with non-registered child, has been found */ - if (current) - { - register_subtree (prev); - } - - /* The object SHOULD be registered now. If it isn't - I give up */ - ref = object_to_ref (accessible); - if (ref) - { - return atk_dbus_ref_to_path (ref); - } - else - { -#ifdef SPI_ATK_DEBUG - g_debug - ("AT-SPI: Could not register a non-attached accessible object"); -#endif - return NULL; - } - } - else - { - return atk_dbus_ref_to_path (ref); - } -} - - -/* - * Used to lookup a D-Bus path from the AtkObject. - */ -static gchar * -atk_dbus_gobject_to_path_internal (GObject * gobj, gboolean do_register, - GObject * container) -{ - guint ref; - - ref = gobject_to_ref (gobj); - if (!ref && do_register) - { - register_gobject (gobj, container); - ref = gobject_to_ref (gobj); + register_object (reg, gobj); + ref = object_to_ref (gobj); } if (!ref) return NULL; else - return atk_dbus_ref_to_path (ref); -} - -gchar * -atk_dbus_object_to_path (AtkObject * accessible, gboolean do_register) -{ - AtkObject *container = (accessible - && do_register ? atk_object_get_parent (accessible) - : NULL); - return atk_dbus_gobject_to_path_internal (G_OBJECT (accessible), - do_register, - G_OBJECT (container)); -} - -gchar * -atk_dbus_sub_object_to_path (GObject * gobj, GObject * container) -{ - return atk_dbus_gobject_to_path_internal (gobj, TRUE, container); -} - -gchar * -atk_dbus_hyperlink_to_path (AtkHyperlink * hyperlink, AtkObject * container) -{ - guint ref; - - ref = gobject_to_ref (G_OBJECT (hyperlink)); - if (!ref && container) - { - register_hyperlink (hyperlink, container); - ref = hyperlink_to_ref (hyperlink); - } - - if (!ref) - return NULL; - else - return atk_dbus_ref_to_path (ref); -} - -gchar * -atk_dbus_desktop_object_path () -{ - return g_strdup (SPI_ATK_OBJECT_PATH_PREFIX SPI_ATK_OBJECT_PATH_DESKTOP); -} - -/*---------------------------------------------------------------------------*/ - -typedef gboolean (*TreeUpdateAction) (GSignalInvocationHint * signal_hint, - guint n_param_values, - const GValue * param_values, - gpointer data, AtkObject * accessible); - -/* - * Events are not evaluated for non-registered accessibles. - * - * When a property change is made on a registered accessible - * the client side cache should be updated. - * - * When a parent is changed the subtree is de-registered - * if the parent is not attached to the root accessible. - */ -/* TODO Turn this function into a macro? */ -static gboolean -tree_update_wrapper (GSignalInvocationHint * signal_hint, - guint n_param_values, - const GValue * param_values, - gpointer data, TreeUpdateAction action) -{ - AtkObject *accessible; - - g_static_rec_mutex_lock (®istration_mutex); - - /* Ensure that only registered accessibles - * have their signals processed. - */ - accessible = ATK_OBJECT (g_value_get_object (¶m_values[0])); - g_return_val_if_fail (ATK_IS_OBJECT (accessible), TRUE); - - if (object_to_ref (accessible)) - { -#ifdef SPI_ATK_DEBUG - if (recursion_check_and_set ()) - g_warning ("AT-SPI: Recursive use of registration module"); - - g_debug ("AT-SPI: Tree update listener"); -#endif - action (signal_hint, n_param_values, param_values, data, accessible); - - 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; + return ref_to_path (ref); } -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) +guint +spi_register_object_to_ref (GObject * gobj) { - 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; - - values = (AtkPropertyValues *) g_value_get_pointer (¶m_values[1]); - pname = values[0].property_name; - if (strcmp (pname, "accessible-name") == 0 || - strcmp (pname, "accessible-description") == 0 || - strcmp (pname, "accessible-parent") == 0 || - strcmp (pname, "accessible-role") == 0) - { - update_accessible (accessible); - } - /* Parent value us updated by child-add signal of parent object */ - return TRUE; -} - -static gboolean -tree_update_property_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_property_action); - return TRUE; -} - -static gboolean -tree_update_children_action (GSignalInvocationHint * signal_hint, - guint n_param_values, - const GValue * param_values, - gpointer data, AtkObject * accessible) -{ - const gchar *detail = NULL; - AtkObject *child; - - if (signal_hint->detail) - detail = g_quark_to_string (signal_hint->detail); - - if (!strcmp (detail, "add")) - { - gpointer child; - int index = g_value_get_uint (param_values + 1); - child = g_value_get_pointer (param_values + 2); - - if (!ATK_IS_OBJECT (child)) - { - child = atk_object_ref_accessible_child (accessible, index); -#ifdef SPI_ATK_DEBUG - non_owned_accessible (child); -#endif - } - register_subtree (child); - update_accessible (accessible); - } - else if (!strcmp (detail, "remove")) - { - update_accessible (accessible); - } - return TRUE; + return object_to_ref (gobj); } - -static gboolean -tree_update_children_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_children_action); - return TRUE; -} - -/*---------------------------------------------------------------------------*/ - -static void -spi_atk_register_toplevel_added (AtkObject * accessible, - guint index, AtkObject * child) -{ - g_static_rec_mutex_lock (®istration_mutex); - - g_return_if_fail (ATK_IS_OBJECT (accessible)); - - if (object_to_ref (accessible)) - { -#ifdef SPI_ATK_DEBUG - if (recursion_check_and_set ()) - g_warning ("AT-SPI: Recursive use of registration module"); - - g_debug ("AT-SPI: Toplevel added listener"); -#endif - if (!ATK_IS_OBJECT (child)) - { - child = atk_object_ref_accessible_child (accessible, index); -#ifdef SPI_ATK_DEBUG - non_owned_accessible (child); -#endif - } - register_subtree (child); - update_accessible (accessible); - - recursion_check_unset (); - } - - g_static_rec_mutex_unlock (®istration_mutex); -} - -static void -spi_atk_register_toplevel_removed (AtkObject * accessible, - guint index, AtkObject * child) -{ - g_static_rec_mutex_lock (®istration_mutex); - - g_return_if_fail (ATK_IS_OBJECT (accessible)); - - if (object_to_ref (accessible)) - { -#ifdef SPI_ATK_DEBUG - if (recursion_check_and_set ()) - g_warning ("AT-SPI: Recursive use of registration module"); - - g_debug ("AT-SPI: Toplevel removed listener"); -#endif - update_accessible (accessible); - recursion_check_unset (); - } - - g_static_rec_mutex_unlock (®istration_mutex); -} - + /* - * Initializes required global data. The update and removal lists - * and the reference lookup tables. - * - * Initializes all of the required D-Bus interfaces. + * Gets the path that indicates the accessible desktop object. + * This object is logically located on the registry daemon and not + * within any particular application. */ -void -atk_dbus_initialize (AtkObject * root) +gchar * +spi_register_desktop_object_path () { - if (!ref2ptr) - ref2ptr = g_hash_table_new (g_direct_hash, g_direct_equal); - - if (!objects_with_subrefs) - objects_with_subrefs = g_hash_table_new (g_direct_hash, g_direct_equal); - - if (!leased_refs) - leased_refs = g_hash_table_new (g_direct_hash, g_direct_equal); - -#ifdef SPI_ATK_DEBUG - if (g_thread_supported ()) - g_message ("AT-SPI: Threads enabled"); - - g_debug ("AT-SPI: Initial Atk tree regisration"); -#endif - - register_subtree (root); - - atk_add_global_event_listener (tree_update_property_listener, - "Gtk:AtkObject:property-change"); - atk_add_global_event_listener (tree_update_children_listener, - "Gtk:AtkObject:children-changed"); - atk_add_global_event_listener (tree_update_state_listener, - "Gtk:AtkObject:state-change"); - - g_signal_connect (root, - "children-changed::add", - (GCallback) spi_atk_register_toplevel_added, NULL); - g_signal_connect (root, - "children-changed::remove", - (GCallback) spi_atk_register_toplevel_removed, NULL); + return g_strdup (SPI_ATK_OBJECT_PATH_PREFIX SPI_ATK_OBJECT_PATH_DESKTOP); } /*END------------------------------------------------------------------------*/ diff --git a/atk-adaptor/accessible-register.h b/atk-adaptor/accessible-register.h index fe1912d..dda103b 100644 --- a/atk-adaptor/accessible-register.h +++ b/atk-adaptor/accessible-register.h @@ -21,31 +21,57 @@ * Boston, MA 02111-1307, USA. */ -#ifndef ACCESSIBLE_REGISTER -#define ACCESSIBLE_REGISTER +#ifndef ACCESSIBLE_REGISTER_H +#define ACCESSIBLE_REGISTER_H -#include #include +#include -void atk_dbus_foreach_registered (GHFunc func, gpointer data); +typedef struct _SpiRegister SpiRegister; +typedef struct _SpiRegisterClass SpiRegisterClass; -/*---------------------------------------------------------------------------*/ +G_BEGIN_DECLS + +#define SPI_REGISTER_TYPE (spi_register_get_type ()) +#define SPI_REGISTER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SPI_REGISTER_TYPE, SpiRegister)) +#define SPI_REGISTER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), SPI_REGISTER_TYPE, SpiRegisterClass)) +#define SPI_IS_REGISTER(o) (G_TYPE_CHECK__INSTANCE_TYPE ((o), SPI_REGISTER_TYPE)) +#define SPI_IS_REGISTER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SPI_REGISTER_TYPE)) + +struct _SpiRegister +{ + GObject parent; + + GHashTable * ref2ptr; + guint reference_counter; +}; -GObject *atk_dbus_path_to_gobject (const char *path); +struct _SpiRegisterClass +{ + GObjectClass parent_class; +}; -AtkObject *atk_dbus_path_to_object (const char *path); +GType spi_register_get_type (void); -gchar *atk_dbus_object_attempt_registration (AtkObject * accessible); +extern SpiRegister *spi_global_register; -gchar *atk_dbus_object_to_path (AtkObject * accessible, gboolean do_register); +/*---------------------------------------------------------------------------*/ + +GObject * +spi_register_path_to_object (SpiRegister * reg, const char *path); -gchar *atk_dbus_sub_object_to_path (GObject * accessible, - GObject * container); +GObject * +spi_global_register_path_to_object (const char * path); -gchar *atk_dbus_hyperlink_to_path (AtkHyperlink * hyperlink, - AtkObject * container); +gchar * +spi_register_object_to_path (SpiRegister * reg, GObject * gobj); -gchar *atk_dbus_desktop_object_path (); +guint +spi_register_object_to_ref (GObject * gobj); + +gchar * +spi_register_desktop_object_path (); + +/*---------------------------------------------------------------------------*/ -gchar *atk_dbus_ref_to_path (guint ref); -#endif /* ACCESSIBLE_REGISTER */ +#endif /* ACCESSIBLE_REGISTER_H */ diff --git a/atk-adaptor/adaptors/Makefile.am b/atk-adaptor/adaptors/Makefile.am index d130c80..e3f5cf9 100644 --- a/atk-adaptor/adaptors/Makefile.am +++ b/atk-adaptor/adaptors/Makefile.am @@ -14,11 +14,10 @@ libatk_bridge_adaptors_la_LIBADD =\ libatk_bridge_adaptors_la_SOURCES =\ accessible-adaptor.c \ - accessible-marshaller.c \ - accessible-marshaller.h \ action-adaptor.c \ adaptors.h \ application-adaptor.c \ + cache-adaptor.c \ collection-adaptor.c \ component-adaptor.c \ document-adaptor.c \ @@ -29,6 +28,4 @@ libatk_bridge_adaptors_la_SOURCES =\ selection-adaptor.c \ table-adaptor.c \ text-adaptor.c \ - tree-adaptor.c \ - tree-adaptor.h \ value-adaptor.c diff --git a/atk-adaptor/adaptors/accessible-adaptor.c b/atk-adaptor/adaptors/accessible-adaptor.c index 434223e..6359fa7 100644 --- a/atk-adaptor/adaptors/accessible-adaptor.c +++ b/atk-adaptor/adaptors/accessible-adaptor.c @@ -27,8 +27,7 @@ #include "common/spi-dbus.h" #include "common/spi-stateset.h" -#include "accessible-marshaller.h" -#include "accessible-register.h" +#include "object.h" static dbus_bool_t impl_get_Name (DBusMessageIter * iter, void *user_data) @@ -81,8 +80,8 @@ impl_get_Parent (DBusMessageIter * iter, void *user_data) g_return_val_if_fail (ATK_IS_OBJECT (user_data), FALSE); - return spi_dbus_return_v_object (iter, - atk_object_get_parent (object), FALSE); + spi_object_append_v_reference (iter, atk_object_get_parent (object)); + return TRUE; } static dbus_bool_t @@ -115,7 +114,7 @@ impl_GetChildAtIndex (DBusConnection * bus, return droute_invalid_arguments_error (message); } child = atk_object_ref_accessible_child (object, i); - return spi_dbus_return_object (message, child, TRUE, TRUE); + return spi_object_return_reference (message, child); } static DBusMessage * @@ -136,18 +135,12 @@ impl_GetChildren (DBusConnection * bus, goto oom; dbus_message_iter_init_append (reply, &iter); if (!dbus_message_iter_open_container - (&iter, DBUS_TYPE_ARRAY, "o", &iter_array)) + (&iter, DBUS_TYPE_ARRAY, "(so)", &iter_array)) goto oom; for (i = 0; i < count; i++) { AtkObject *child = atk_object_ref_accessible_child (object, i); - char *path = atk_dbus_object_to_path (child, FALSE); - if (path) - { - dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_OBJECT_PATH, - &path); - g_free (path); - } + spi_object_append_reference (&iter_array, child); if (child) g_object_unref (child); } @@ -169,13 +162,10 @@ impl_GetIndexInParent (DBusConnection * bus, g_return_val_if_fail (ATK_IS_OBJECT (user_data), droute_not_yet_handled_error (message)); + rv = atk_object_get_index_in_parent (object); reply = dbus_message_new_method_return (message); - if (reply) - { - dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv, - DBUS_TYPE_INVALID); - } + dbus_message_append_args (reply, DBUS_TYPE_UINT32, &rv, DBUS_TYPE_INVALID); return reply; } @@ -278,13 +268,7 @@ impl_GetRelationSet (DBusConnection * bus, char *path; if (!obj) continue; - path = atk_dbus_object_to_path (obj, FALSE); - if (!path) - { - g_warning ("Unknown object in relation type %d\n", type); - continue; - } - spi_dbus_append_name_and_path_inner (&iter_targets, NULL, path); + spi_object_append_reference (&iter_targets, obj); } dbus_message_iter_close_container (&iter_struct, &iter_targets); dbus_message_iter_close_container (&iter_array, &iter_struct); @@ -295,133 +279,6 @@ oom: return reply; } -static gboolean -spi_init_role_lookup_table (Accessibility_Role * role_table) -{ - int i; - /* if it's not in the list below, dunno what it is */ - for (i = 0; i < ATK_ROLE_LAST_DEFINED; ++i) - { - role_table[i] = Accessibility_ROLE_UNKNOWN; - } - - role_table[ATK_ROLE_INVALID] = Accessibility_ROLE_INVALID; - role_table[ATK_ROLE_ACCEL_LABEL] = Accessibility_ROLE_ACCELERATOR_LABEL; - role_table[ATK_ROLE_ALERT] = Accessibility_ROLE_ALERT; - role_table[ATK_ROLE_ANIMATION] = Accessibility_ROLE_ANIMATION; - role_table[ATK_ROLE_ARROW] = Accessibility_ROLE_ARROW; - role_table[ATK_ROLE_CALENDAR] = Accessibility_ROLE_CALENDAR; - role_table[ATK_ROLE_CANVAS] = Accessibility_ROLE_CANVAS; - role_table[ATK_ROLE_CHECK_BOX] = Accessibility_ROLE_CHECK_BOX; - role_table[ATK_ROLE_CHECK_MENU_ITEM] = Accessibility_ROLE_CHECK_MENU_ITEM; - role_table[ATK_ROLE_COLOR_CHOOSER] = Accessibility_ROLE_COLOR_CHOOSER; - role_table[ATK_ROLE_COLUMN_HEADER] = Accessibility_ROLE_COLUMN_HEADER; - role_table[ATK_ROLE_COMBO_BOX] = Accessibility_ROLE_COMBO_BOX; - role_table[ATK_ROLE_DATE_EDITOR] = Accessibility_ROLE_DATE_EDITOR; - role_table[ATK_ROLE_DESKTOP_ICON] = Accessibility_ROLE_DESKTOP_ICON; - role_table[ATK_ROLE_DESKTOP_FRAME] = Accessibility_ROLE_DESKTOP_FRAME; - role_table[ATK_ROLE_DIAL] = Accessibility_ROLE_DIAL; - role_table[ATK_ROLE_DIALOG] = Accessibility_ROLE_DIALOG; - role_table[ATK_ROLE_DIRECTORY_PANE] = Accessibility_ROLE_DIRECTORY_PANE; - role_table[ATK_ROLE_DRAWING_AREA] = Accessibility_ROLE_DRAWING_AREA; - role_table[ATK_ROLE_FILE_CHOOSER] = Accessibility_ROLE_FILE_CHOOSER; - role_table[ATK_ROLE_FILLER] = Accessibility_ROLE_FILLER; - role_table[ATK_ROLE_FONT_CHOOSER] = Accessibility_ROLE_FONT_CHOOSER; - role_table[ATK_ROLE_FRAME] = Accessibility_ROLE_FRAME; - role_table[ATK_ROLE_GLASS_PANE] = Accessibility_ROLE_GLASS_PANE; - role_table[ATK_ROLE_HTML_CONTAINER] = Accessibility_ROLE_HTML_CONTAINER; - role_table[ATK_ROLE_ICON] = Accessibility_ROLE_ICON; - role_table[ATK_ROLE_IMAGE] = Accessibility_ROLE_IMAGE; - role_table[ATK_ROLE_INTERNAL_FRAME] = Accessibility_ROLE_INTERNAL_FRAME; - role_table[ATK_ROLE_LABEL] = Accessibility_ROLE_LABEL; - role_table[ATK_ROLE_LAYERED_PANE] = Accessibility_ROLE_LAYERED_PANE; - role_table[ATK_ROLE_LIST] = Accessibility_ROLE_LIST; - role_table[ATK_ROLE_LIST_ITEM] = Accessibility_ROLE_LIST_ITEM; - role_table[ATK_ROLE_MENU] = Accessibility_ROLE_MENU; - role_table[ATK_ROLE_MENU_BAR] = Accessibility_ROLE_MENU_BAR; - role_table[ATK_ROLE_MENU_ITEM] = Accessibility_ROLE_MENU_ITEM; - role_table[ATK_ROLE_OPTION_PANE] = Accessibility_ROLE_OPTION_PANE; - role_table[ATK_ROLE_PAGE_TAB] = Accessibility_ROLE_PAGE_TAB; - role_table[ATK_ROLE_PAGE_TAB_LIST] = Accessibility_ROLE_PAGE_TAB_LIST; - role_table[ATK_ROLE_PANEL] = Accessibility_ROLE_PANEL; - role_table[ATK_ROLE_PASSWORD_TEXT] = Accessibility_ROLE_PASSWORD_TEXT; - role_table[ATK_ROLE_POPUP_MENU] = Accessibility_ROLE_POPUP_MENU; - role_table[ATK_ROLE_PROGRESS_BAR] = Accessibility_ROLE_PROGRESS_BAR; - role_table[ATK_ROLE_PUSH_BUTTON] = Accessibility_ROLE_PUSH_BUTTON; - role_table[ATK_ROLE_RADIO_BUTTON] = Accessibility_ROLE_RADIO_BUTTON; - role_table[ATK_ROLE_RADIO_MENU_ITEM] = Accessibility_ROLE_RADIO_MENU_ITEM; - role_table[ATK_ROLE_ROOT_PANE] = Accessibility_ROLE_ROOT_PANE; - role_table[ATK_ROLE_ROW_HEADER] = Accessibility_ROLE_ROW_HEADER; - role_table[ATK_ROLE_SCROLL_BAR] = Accessibility_ROLE_SCROLL_BAR; - role_table[ATK_ROLE_SCROLL_PANE] = Accessibility_ROLE_SCROLL_PANE; - role_table[ATK_ROLE_SEPARATOR] = Accessibility_ROLE_SEPARATOR; - role_table[ATK_ROLE_SLIDER] = Accessibility_ROLE_SLIDER; - role_table[ATK_ROLE_SPIN_BUTTON] = Accessibility_ROLE_SPIN_BUTTON; - role_table[ATK_ROLE_SPLIT_PANE] = Accessibility_ROLE_SPLIT_PANE; - role_table[ATK_ROLE_STATUSBAR] = Accessibility_ROLE_STATUS_BAR; - role_table[ATK_ROLE_TABLE] = Accessibility_ROLE_TABLE; - role_table[ATK_ROLE_TABLE_CELL] = Accessibility_ROLE_TABLE_CELL; - role_table[ATK_ROLE_TABLE_COLUMN_HEADER] = - Accessibility_ROLE_TABLE_COLUMN_HEADER; - role_table[ATK_ROLE_TABLE_ROW_HEADER] = Accessibility_ROLE_TABLE_ROW_HEADER; - role_table[ATK_ROLE_TEAR_OFF_MENU_ITEM] = - Accessibility_ROLE_TEAROFF_MENU_ITEM; - role_table[ATK_ROLE_TERMINAL] = Accessibility_ROLE_TERMINAL; - role_table[ATK_ROLE_TEXT] = Accessibility_ROLE_TEXT; - role_table[ATK_ROLE_TOGGLE_BUTTON] = Accessibility_ROLE_TOGGLE_BUTTON; - role_table[ATK_ROLE_TOOL_BAR] = Accessibility_ROLE_TOOL_BAR; - role_table[ATK_ROLE_TOOL_TIP] = Accessibility_ROLE_TOOL_TIP; - role_table[ATK_ROLE_TREE] = Accessibility_ROLE_TREE; - role_table[ATK_ROLE_TREE_TABLE] = Accessibility_ROLE_TREE_TABLE; - role_table[ATK_ROLE_UNKNOWN] = Accessibility_ROLE_UNKNOWN; - role_table[ATK_ROLE_VIEWPORT] = Accessibility_ROLE_VIEWPORT; - role_table[ATK_ROLE_WINDOW] = Accessibility_ROLE_WINDOW; - role_table[ATK_ROLE_HEADER] = Accessibility_ROLE_HEADER; - role_table[ATK_ROLE_FOOTER] = Accessibility_ROLE_FOOTER; - role_table[ATK_ROLE_PARAGRAPH] = Accessibility_ROLE_PARAGRAPH; - role_table[ATK_ROLE_RULER] = Accessibility_ROLE_RULER; - role_table[ATK_ROLE_APPLICATION] = Accessibility_ROLE_APPLICATION; - role_table[ATK_ROLE_AUTOCOMPLETE] = Accessibility_ROLE_AUTOCOMPLETE; - role_table[ATK_ROLE_EDITBAR] = Accessibility_ROLE_EDITBAR; - role_table[ATK_ROLE_EMBEDDED] = Accessibility_ROLE_EMBEDDED; - role_table[ATK_ROLE_ENTRY] = Accessibility_ROLE_ENTRY; - role_table[ATK_ROLE_CHART] = Accessibility_ROLE_CHART; - role_table[ATK_ROLE_CAPTION] = Accessibility_ROLE_CAPTION; - role_table[ATK_ROLE_DOCUMENT_FRAME] = Accessibility_ROLE_DOCUMENT_FRAME; - role_table[ATK_ROLE_HEADING] = Accessibility_ROLE_HEADING; - role_table[ATK_ROLE_PAGE] = Accessibility_ROLE_PAGE; - role_table[ATK_ROLE_SECTION] = Accessibility_ROLE_SECTION; - role_table[ATK_ROLE_FORM] = Accessibility_ROLE_FORM; - role_table[ATK_ROLE_REDUNDANT_OBJECT] = Accessibility_ROLE_REDUNDANT_OBJECT; - role_table[ATK_ROLE_LINK] = Accessibility_ROLE_LINK; - role_table[ATK_ROLE_INPUT_METHOD_WINDOW] = - Accessibility_ROLE_INPUT_METHOD_WINDOW; - return TRUE; -} - -Accessibility_Role -spi_accessible_role_from_atk_role (AtkRole role) -{ - static gboolean is_initialized = FALSE; - static Accessibility_Role spi_role_table[ATK_ROLE_LAST_DEFINED]; - Accessibility_Role spi_role; - - if (!is_initialized) - { - is_initialized = spi_init_role_lookup_table (spi_role_table); - } - - if (role >= 0 && role < ATK_ROLE_LAST_DEFINED) - { - spi_role = spi_role_table[role]; - } - else - { - spi_role = Accessibility_ROLE_EXTENDED; - } - return spi_role; -} - static DBusMessage * impl_GetRole (DBusConnection * bus, DBusMessage * message, void *user_data) { @@ -534,9 +391,8 @@ impl_GetAttributes (DBusConnection * bus, DBusMessage * message, void *user_data) { AtkObject *object = (AtkObject *) user_data; - DBusMessage *reply = NULL; - AtkAttributeSet *attributes; + DBusMessage *reply = NULL; DBusMessageIter iter; g_return_val_if_fail (ATK_IS_OBJECT (user_data), @@ -546,10 +402,9 @@ impl_GetAttributes (DBusConnection * bus, reply = dbus_message_new_method_return (message); dbus_message_iter_init_append (reply, &iter); - spi_atk_append_attribute_set (&iter, attributes); + spi_object_append_attribute_set (&iter, attributes); - if (attributes) - atk_attribute_set_free (attributes); + atk_attribute_set_free (attributes); return reply; } @@ -559,7 +414,7 @@ impl_GetApplication (DBusConnection * bus, DBusMessage * message, void *user_data) { AtkObject *root = atk_get_root (); - return spi_dbus_return_object (message, root, FALSE, FALSE); + return spi_object_return_reference (message, root); } static DBusMessage * @@ -580,7 +435,7 @@ impl_GetInterfaces (DBusConnection * bus, dbus_message_iter_init_append (reply, &iter); dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &iter_array); - append_atk_object_interfaces (object, &iter_array); + spi_object_append_interfaces (&iter_array, object); dbus_message_iter_close_container (&iter, &iter_array); } return reply; diff --git a/atk-adaptor/adaptors/accessible-marshaller.c b/atk-adaptor/adaptors/accessible-marshaller.c deleted file mode 100644 index f087171..0000000 --- a/atk-adaptor/adaptors/accessible-marshaller.c +++ /dev/null @@ -1,445 +0,0 @@ -/* - * AT-SPI - Assistive Technology Service Provider Interface - * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) - * - * Copyright 2008 Novell, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include - -#include "common/spi-dbus.h" -#include "common/spi-stateset.h" - -#include "accessible-register.h" -#include "accessible-marshaller.h" -#include "bridge.h" - -#include "adaptors.h" - -/*---------------------------------------------------------------------------*/ - -void -spi_dbus_append_name_and_path_inner (DBusMessageIter * iter, - const char *bus_name, const char *path) -{ - DBusMessageIter iter_struct; - - if (!bus_name) - bus_name = ""; - if (!path) - path = SPI_DBUS_PATH_NULL; - - dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL, - &iter_struct); - dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &bus_name); - dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path); - dbus_message_iter_close_container (iter, &iter_struct); -} - -extern gchar *atspi_dbus_name; - -void -spi_dbus_append_name_and_path (DBusMessage * message, DBusMessageIter * iter, - AtkObject * obj, gboolean do_register, - gboolean unref) -{ - gchar *path; - DBusMessageIter iter_struct; - - path = atk_dbus_object_to_path (obj, do_register); - - spi_dbus_append_name_and_path_inner (iter, atspi_dbus_name, path); - - g_free (path); - if (obj && unref) - g_object_unref (obj); -} - -/* - * Marshals the D-Bus path of an AtkObject into a D-Bus message. - * - * Unrefs the AtkObject if unref is true. - */ -DBusMessage * -spi_dbus_return_object (DBusMessage * message, AtkObject * obj, - gboolean do_register, gboolean unref) -{ - DBusMessage *reply; - reply = dbus_message_new_method_return (message); - if (reply) - { - DBusMessageIter iter; - dbus_message_iter_init_append (reply, &iter); - spi_dbus_append_name_and_path (message, &iter, obj, do_register, unref); - } - - return reply; -} - -DBusMessage * -spi_dbus_return_hyperlink (DBusMessage * message, AtkHyperlink * link, - AtkObject * container, gboolean unref) -{ - return spi_dbus_return_sub_object (message, G_OBJECT (link), - G_OBJECT (container), unref); -} - -DBusMessage * -spi_dbus_return_sub_object (DBusMessage * message, GObject * sub, - GObject * container, gboolean unref) -{ - DBusMessage *reply; - gchar *path; - - path = atk_dbus_sub_object_to_path (sub, container); - - if (sub && unref) - g_object_unref (sub); - - if (!path) - path = g_strdup (SPI_DBUS_PATH_NULL); - - reply = dbus_message_new_method_return (message); - if (reply) - { - dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID); - } - - g_free (path); - - return reply; -} - -/*---------------------------------------------------------------------------*/ - -/* - * Marshals a variant containing the D-Bus path of an AtkObject into a D-Bus - * message. - * - * Unrefs the object if unref is true. - */ -dbus_bool_t -spi_dbus_return_v_object (DBusMessageIter * iter, AtkObject * obj, int unref) -{ - DBusMessageIter iter_variant; - char *path; - - path = atk_dbus_object_to_path (obj, FALSE); - - if (!path) - path = g_strdup (SPI_DBUS_PATH_NULL); - - if (unref) - g_object_unref (obj); - - dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "(so)", - &iter_variant); - spi_dbus_append_name_and_path_inner (&iter_variant, NULL, path); - dbus_message_iter_close_container (iter, &iter_variant); - return TRUE; -} - -/*---------------------------------------------------------------------------*/ - -void -append_atk_object_interfaces (AtkObject * object, DBusMessageIter * iter) -{ - const gchar *itf; - - itf = SPI_DBUS_INTERFACE_ACCESSIBLE; - dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); - - if (ATK_IS_ACTION (object)) - { - itf = SPI_DBUS_INTERFACE_ACTION; - dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); - } - - if (ATK_IS_COMPONENT (object)) - { - itf = SPI_DBUS_INTERFACE_COMPONENT; - dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); - } - - if (ATK_IS_EDITABLE_TEXT (object)) - { - itf = SPI_DBUS_INTERFACE_EDITABLE_TEXT; - dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); - } - - if (ATK_IS_TEXT (object)) - { - itf = SPI_DBUS_INTERFACE_TEXT; - dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); - } - - if (ATK_IS_HYPERTEXT (object)) - { - itf = SPI_DBUS_INTERFACE_HYPERTEXT; - dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); - } - - if (ATK_IS_IMAGE (object)) - { - itf = SPI_DBUS_INTERFACE_IMAGE; - dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); - } - - if (ATK_IS_SELECTION (object)) - { - itf = SPI_DBUS_INTERFACE_SELECTION; - dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); - } - - if (ATK_IS_TABLE (object)) - { - itf = SPI_DBUS_INTERFACE_TABLE; - dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); - } - - if (ATK_IS_VALUE (object)) - { - itf = SPI_DBUS_INTERFACE_VALUE; - dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); - } - - if (ATK_IS_STREAMABLE_CONTENT (object)) - { - itf = "org.freedesktop.atspi.StreamableContent"; - dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); - } - - if (ATK_IS_DOCUMENT (object)) - { - itf = "org.freedesktop.atspi.Collection"; - dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); - itf = SPI_DBUS_INTERFACE_DOCUMENT; - dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); - } - - if (ATK_IS_HYPERLINK_IMPL (object)) - { - itf = SPI_DBUS_INTERFACE_HYPERLINK; - dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); - } -} - -/*---------------------------------------------------------------------------*/ - -/* - * Marshals the given AtkObject into the provided D-Bus iterator. - * - * The object is marshalled including all its client side cache data. - * The format of the structure is (o(so)a(so)assusau). - * This is used in the updateTree signal and the GetTree method - * of the org.freedesktop.atspi.Tree interface. - * - * To marshal an object its parent, and all its children must already - * be registered with D-Bus and have been given a D-Bus object path. - */ -void -spi_atk_append_accessible (AtkObject * obj, gpointer data) -{ - DBusMessageIter iter_struct, iter_sub_array; - dbus_uint32_t states[2]; - int count; - AtkStateSet *set; - DBusMessageIter *iter_array = (DBusMessageIter *) data; - - const char *name, *desc; - dbus_uint32_t role; - - set = atk_object_ref_state_set (obj); - { - AtkObject *parent; - gchar *path; - gchar *bus_parent = NULL, *path_parent; - - /* Marshall object path */ - path = atk_dbus_object_to_path (obj, FALSE); - - role = spi_accessible_role_from_atk_role (atk_object_get_role (obj)); - - /* Marshall parent */ - parent = atk_object_get_parent (obj); - if (parent == NULL) - { - /* TODO: Support getting parent of an AtkPlug */ -#ifdef __ATK_PLUG_H__ - if (ATK_IS_PLUG (obj)) - { - char *id = g_object_get_data (G_OBJECT (obj), "dbus-plug-parent"); - if (id) - bus_parent = g_strdup (id); - if (bus_parent && (path_parent = g_utf8_strchr (bus_parent + 1, -1, ':'))) - { - *(path_parent++) = '\0'; - /* path_parent is going to be freed, so dup it */ - path_parent = g_strdup (path_parent); - } - } - else if (role != Accessibility_ROLE_APPLICATION) -#else - if (role != Accessibility_ROLE_APPLICATION) -#endif - path_parent = g_strdup (SPI_DBUS_PATH_NULL); - else - path_parent = atk_dbus_desktop_object_path (); - } - else - { - path_parent = atk_dbus_object_to_path (parent, FALSE); - if (!path_parent) - { - /* This should only happen if a widget is re-parented to - * an AtkObject that has not been registered and is then - * updated. Ideally objects would be de-registered when - * they are removed from a registered tree object, but - * this would invalidate a huge amount of cache when - * re-parenting. - */ -#if SPI_ATK_DEBUG - g_warning - ("AT-SPI: Registered accessible marshalled when parent not registered"); -#endif - path_parent = atk_dbus_desktop_object_path (); - } - } - - dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL, - &iter_struct); - dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, - &path); - spi_dbus_append_name_and_path_inner (&iter_struct, bus_parent, - path_parent); - g_free (path_parent); - g_free (bus_parent); - - /* Marshall children */ - dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "(so)", - &iter_sub_array); - if (!atk_state_set_contains_state (set, ATK_STATE_MANAGES_DESCENDANTS)) - { - gint childcount, i; - - childcount = atk_object_get_n_accessible_children (obj); - for (i = 0; i < childcount; i++) - { - AtkObject *child; - gchar *child_path; - - child = atk_object_ref_accessible_child (obj, i); - child_path = atk_dbus_object_to_path (child, FALSE); - if (child_path) - { - spi_dbus_append_name_and_path_inner (&iter_sub_array, NULL, - child_path); - g_free (child_path); - } - g_object_unref (G_OBJECT (child)); - } - } -#ifdef __ATK_PLUG_H__ - if (ATK_IS_SOCKET (obj) && atk_socket_is_occupied (ATK_SOCKET (obj))) - { - AtkSocket *socket = ATK_SOCKET (obj); - gchar *child_name, *child_path; - child_name = g_strdup (socket->embedded_plug_id); - child_path = g_utf8_strchr (child_name + 1, -1, ':'); - if (child_path) - { - *(child_path++) = '\0'; - spi_dbus_append_name_and_path_inner (&iter_sub_array, child_name, - child_path); - } - g_free (child_name); - } -#endif - - dbus_message_iter_close_container (&iter_struct, &iter_sub_array); - - /* Marshall interfaces */ - dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s", - &iter_sub_array); - append_atk_object_interfaces (obj, &iter_sub_array); - dbus_message_iter_close_container (&iter_struct, &iter_sub_array); - - /* Marshall name */ - name = atk_object_get_name (obj); - if (!name) - name = ""; - dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name); - - /* Marshall role */ - dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &role); - - /* Marshall description */ - desc = atk_object_get_description (obj); - if (!desc) - desc = ""; - dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &desc); - - g_free (path); - - /* Marshall state set */ - spi_atk_state_set_to_dbus_array (set, states); - dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "u", - &iter_sub_array); - for (count = 0; count < 2; count++) - { - dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_UINT32, - &states[count]); - } - dbus_message_iter_close_container (&iter_struct, &iter_sub_array); - } - dbus_message_iter_close_container (iter_array, &iter_struct); - g_object_unref (set); -} - -void -spi_atk_append_attribute_set (DBusMessageIter * iter, AtkAttributeSet * attr) -{ - DBusMessageIter dictIter; - - dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "{ss}", &dictIter); - spi_atk_append_attribute_set_inner (&dictIter, attr); - dbus_message_iter_close_container (iter, &dictIter); -} - -void -spi_atk_append_attribute_set_inner (DBusMessageIter * iter, - AtkAttributeSet * attr) -{ - DBusMessageIter dictEntryIter; - - while (attr) - { - AtkAttribute *attribute = (AtkAttribute *) attr->data; - dbus_message_iter_open_container (iter, DBUS_TYPE_DICT_ENTRY, NULL, - &dictEntryIter); - dbus_message_iter_append_basic (&dictEntryIter, DBUS_TYPE_STRING, - &attribute->name); - dbus_message_iter_append_basic (&dictEntryIter, DBUS_TYPE_STRING, - &attribute->value); - dbus_message_iter_close_container (iter, &dictEntryIter); - attr = g_slist_next (attr); - } -} - -/*END------------------------------------------------------------------------*/ diff --git a/atk-adaptor/adaptors/accessible-marshaller.h b/atk-adaptor/adaptors/accessible-marshaller.h deleted file mode 100644 index 4d0a131..0000000 --- a/atk-adaptor/adaptors/accessible-marshaller.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * AT-SPI - Assistive Technology Service Provider Interface - * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) - * - * Copyright 2008 Novell, Inc. - * Copyright 2008, 2009 Codethink Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef ACCESSIBLE_MARSHALLER -#define ACCESSIBLE_MARSHALLER - -#include -#include - -void -spi_dbus_append_name_and_path_inner (DBusMessageIter * iter, - const char *bus_name, const char *path); - -void -spi_dbus_append_name_and_path (DBusMessage * message, DBusMessageIter * iter, - AtkObject * obj, gboolean do_register, - gboolean unref); - -DBusMessage *spi_dbus_return_object (DBusMessage * message, AtkObject * obj, - gboolean do_register, gboolean unref); - -DBusMessage *spi_dbus_return_hyperlink (DBusMessage * message, - AtkHyperlink * link, - AtkObject * container, - gboolean unref); - -DBusMessage *spi_dbus_return_sub_object (DBusMessage * message, GObject * sub, - GObject * container, gboolean unref); - -dbus_bool_t -spi_dbus_return_v_object (DBusMessageIter * iter, AtkObject * obj, int unref); - -void spi_atk_append_accessible (AtkObject * obj, gpointer iter); - -void -spi_atk_append_attribute_set (DBusMessageIter * iter, AtkAttributeSet * attr); - -void -spi_atk_append_attribute_set_inner (DBusMessageIter * iter, - AtkAttributeSet * attr); - -void -append_atk_object_interfaces (AtkObject * object, DBusMessageIter * iter); -#endif /* ACCESSIBLE_MARSHALLER */ diff --git a/atk-adaptor/adaptors/adaptors.h b/atk-adaptor/adaptors/adaptors.h index 7f8bdd9..ccc07ab 100644 --- a/atk-adaptor/adaptors/adaptors.h +++ b/atk-adaptor/adaptors/adaptors.h @@ -43,6 +43,6 @@ void spi_initialize_selection (DRoutePath * path); void spi_initialize_table (DRoutePath * path); void spi_initialize_text (DRoutePath * path); void spi_initialize_value (DRoutePath * path); -void spi_initialize_tree (DRoutePath * path); +void spi_initialize_cache (DRoutePath * path); #endif /* ADAPTORS_H */ diff --git a/atk-adaptor/adaptors/cache-adaptor.c b/atk-adaptor/adaptors/cache-adaptor.c new file mode 100644 index 0000000..45eb41b --- /dev/null +++ b/atk-adaptor/adaptors/cache-adaptor.c @@ -0,0 +1,301 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2008 Novell, Inc. + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * Copyright 2008, 2009 Codethink Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +#include +#include + +#include "common/spi-dbus.h" +#include "accessible-cache.h" +#include "bridge.h" +#include "object.h" + +/* TODO - This should possibly be a common define */ +#define SPI_OBJECT_PREFIX "/org/at_spi" +#define SPI_CACHE_OBJECT_SUFFIX "/cache" +#define SPI_CACHE_OBJECT_PATH SPI_OBJECT_PREFIX SPI_CACHE_OBJECT_SUFFIX + +#define SPI_OBJECT_REFERENCE_SIGNATURE "(" \ + DBUS_TYPE_STRING_AS_STRING \ + DBUS_TYPE_OBJECT_PATH_AS_STRING \ + ")" + +#define SPI_CACHE_ITEM_SIGNATURE "(" \ + DBUS_TYPE_OBJECT_PATH_AS_STRING \ + SPI_OBJECT_REFERENCE_SIGNATURE \ + SPI_OBJECT_REFERENCE_SIGNATURE \ + DBUS_TYPE_ARRAY_AS_STRING \ + SPI_OBJECT_REFERENCE_SIGNATURE \ + DBUS_TYPE_ARRAY_AS_STRING \ + DBUS_TYPE_STRING_AS_STRING \ + DBUS_TYPE_STRING_AS_STRING \ + DBUS_TYPE_UINT32_AS_STRING \ + DBUS_TYPE_STRING_AS_STRING \ + DBUS_TYPE_ARRAY_AS_STRING \ + DBUS_TYPE_UINT32_AS_STRING \ + ")" + +/*---------------------------------------------------------------------------*/ + +/* + * Marshals the given AtkObject into the provided D-Bus iterator. + * + * The object is marshalled including all its client side cache data. + * The format of the structure is (o(so)a(so)assusau). + */ +static void +append_cache_item (AtkObject * obj, gpointer data) +{ + DBusMessageIter iter_struct, iter_sub_array; + dbus_uint32_t states[2]; + int count; + AtkStateSet *set; + DBusMessageIter *iter_array = (DBusMessageIter *) data; + + const char *name, *desc; + dbus_uint32_t role; + + set = atk_object_ref_state_set (obj); + { + AtkObject *application, *parent; + + dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL, + &iter_struct); + + /* Marshall object path */ + spi_object_append_reference (&iter_struct, obj); + + role = spi_accessible_role_from_atk_role (atk_object_get_role (obj)); + + /* Marshall application */ + application = spi_global_app_data->root; + spi_object_append_reference (&iter_struct, application); + + /* Marshall parent */ + parent = atk_object_get_parent (obj); + if (parent == NULL) + { + /* TODO: Support getting parent of an AtkPlug */ +#ifdef __ATK_PLUG_H__ + if (role != Accessibility_ROLE_APPLICATION && !ATK_IS_PLUG (obj)) +#else + if (role != Accessibility_ROLE_APPLICATION) +#endif + spi_object_append_null_reference (&iter_struct); + else + spi_object_append_desktop_reference (&iter_struct); + } + else + { + spi_object_append_reference (&iter_struct, parent); + } + + /* Marshall children */ + dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "(so)", + &iter_sub_array); + if (!atk_state_set_contains_state (set, ATK_STATE_MANAGES_DESCENDANTS)) + { + gint childcount, i; + + childcount = atk_object_get_n_accessible_children (obj); + for (i = 0; i < childcount; i++) + { + AtkObject *child; + gchar *child_path; + + child = atk_object_ref_accessible_child (obj, i); + spi_object_append_reference (&iter_sub_array, child); + g_object_unref (G_OBJECT (child)); + } + } +#ifdef __ATK_PLUG_H__ + if (ATK_IS_SOCKET (obj) && atk_socket_is_occupied (ATK_SOCKET (obj))) + { + AtkSocket *socket = ATK_SOCKET (obj); + gchar *child_name, *child_path; + child_name = g_strdup (socket->embedded_plug_id); + child_path = g_utf8_strchr (child_name + 1, -1, ':'); + if (child_path) + { + DBusMessageIter iter_socket; + *(child_path++) = '\0'; + dbus_message_iter_open_container (&iter_sub_array, DBUS_TYPE_STRUCT, NULL, + &iter_socket); + dbus_message_iter_append_basic (&iter_socket, DBUS_TYPE_STRING, &name); + dbus_message_iter_append_basic (&iter_socket, DBUS_TYPE_OBJECT_PATH, &path); + dbus_message_iter_close_container (&iter_sub_array, &iter_socket); + } + g_free (child_name); + } +#endif + + dbus_message_iter_close_container (&iter_struct, &iter_sub_array); + + /* Marshall interfaces */ + dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "s", + &iter_sub_array); + spi_object_append_interfaces (&iter_sub_array, obj); + dbus_message_iter_close_container (&iter_struct, &iter_sub_array); + + /* Marshall name */ + name = atk_object_get_name (obj); + if (!name) + name = ""; + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name); + + /* Marshall role */ + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_UINT32, &role); + + /* Marshall description */ + desc = atk_object_get_description (obj); + if (!desc) + desc = ""; + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &desc); + + /* Marshall state set */ + spi_atk_state_set_to_dbus_array (set, states); + dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "u", + &iter_sub_array); + for (count = 0; count < 2; count++) + { + dbus_message_iter_append_basic (&iter_sub_array, DBUS_TYPE_UINT32, + &states[count]); + } + dbus_message_iter_close_container (&iter_struct, &iter_sub_array); + } + dbus_message_iter_close_container (iter_array, &iter_struct); + g_object_unref (set); +} + +/*---------------------------------------------------------------------------*/ + +/* For use as a GHFunc */ +static void +append_accessible_hf (gpointer key, gpointer obj_data, gpointer data) +{ + /* Make sure it isn't a hyperlink */ + if (ATK_IS_OBJECT (obj_data)) + append_cache_item (ATK_OBJECT (obj_data), data); +} + +/*---------------------------------------------------------------------------*/ + +static void +emit_cache_remove (SpiCache *cache, GObject * obj) +{ + DBusMessage *message; + + if ((message = dbus_message_new_signal (SPI_CACHE_OBJECT_PATH, + SPI_DBUS_INTERFACE_CACHE, + "RemoveAccessible"))) + { + DBusMessageIter iter; + gchar *path; + + dbus_message_iter_init_append (message, &iter); + + spi_object_append_reference (&iter, ATK_OBJECT (obj)); + + dbus_connection_send (spi_global_app_data->bus, message, NULL); + + dbus_message_unref (message); + } +} + +static void +emit_cache_add (SpiCache *cache, GObject * obj) +{ + AtkObject *accessible = ATK_OBJECT (obj); + DBusMessage *message; + + if ((message = dbus_message_new_signal (SPI_CACHE_OBJECT_PATH, + SPI_DBUS_INTERFACE_CACHE, + "AddAccessible"))) + { + DBusMessageIter iter; + + dbus_message_iter_init_append (message, &iter); + append_cache_item (accessible, &iter); + + dbus_connection_send (spi_global_app_data->bus, message, NULL); + + dbus_message_unref (message); + } +} + + +/*---------------------------------------------------------------------------*/ + +static DBusMessage * +impl_GetRoot (DBusConnection * bus, DBusMessage * message, void *user_data) +{ + return spi_object_return_reference (message, + g_object_ref (G_OBJECT (spi_global_app_data->root))); +} + +/*---------------------------------------------------------------------------*/ + +static DBusMessage * +impl_GetItems (DBusConnection * bus, DBusMessage * message, void *user_data) +{ + DBusMessage *reply; + DBusMessageIter iter, iter_array; + + reply = dbus_message_new_method_return (message); + + dbus_message_iter_init_append (reply, &iter); + dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, + SPI_CACHE_ITEM_SIGNATURE, &iter_array); + spi_cache_foreach (spi_global_cache, append_accessible_hf, &iter_array); + dbus_message_iter_close_container (&iter, &iter_array); + return reply; +} + +/*---------------------------------------------------------------------------*/ + +static DRouteMethod methods[] = { + {impl_GetRoot, "GetRoot"}, + {impl_GetItems, "GetItems"}, + {NULL, NULL} +}; + +void +spi_initialize_cache (DRoutePath * path) +{ + droute_path_add_interface (path, SPI_DBUS_INTERFACE_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); +}; + +/*END------------------------------------------------------------------------*/ diff --git a/atk-adaptor/adaptors/collection-adaptor.c b/atk-adaptor/adaptors/collection-adaptor.c index e920545..1702ee7 100644 --- a/atk-adaptor/adaptors/collection-adaptor.c +++ b/atk-adaptor/adaptors/collection-adaptor.c @@ -27,13 +27,13 @@ #include #include -#include "accessible-register.h" -#include "accessible-marshaller.h" - #include "common/bitarray.h" #include "common/spi-dbus.h" #include "common/spi-stateset.h" +#include "accessible-register.h" +#include "object.h" + typedef struct _MatchRulePrivate MatchRulePrivate; struct _MatchRulePrivate { @@ -762,8 +762,7 @@ return_and_free_list (DBusMessage * message, GList * ls) goto oom; for (item = ls; item; item = g_list_next (item)) { - spi_dbus_append_name_and_path (message, &iter_array, - ATK_OBJECT (item->data), TRUE, FALSE); + spi_object_append_reference (&iter_array, ATK_OBJECT (item->data)); } if (!dbus_message_iter_close_container (&iter, &iter_array)) goto oom; @@ -871,7 +870,7 @@ GetMatchesInOrder (DBusMessage * message, ls = g_list_append (ls, current_object); - obj = atk_dbus_path_to_object (dbus_message_get_path (message)); + obj = ATK_OBJECT(spi_register_path_to_object (spi_global_register, dbus_message_get_path (message))); kount = inorder (obj, mrp, ls, 0, count, current_object, TRUE, NULL, traverse); @@ -903,7 +902,7 @@ GetMatchesInBackOrder (DBusMessage * message, ls = g_list_append (ls, current_object); - collection = atk_dbus_path_to_object (dbus_message_get_path (message)); + collection = ATK_OBJECT(spi_register_path_to_object (spi_global_register, dbus_message_get_path (message))); kount = sort_order_rev_canonical (mrp, ls, 0, count, current_object, FALSE, collection); @@ -933,13 +932,13 @@ GetMatchesTo (DBusMessage * message, if (recurse) { - obj = atk_object_get_parent (current_object); + obj = ATK_OBJECT (atk_object_get_parent (current_object)); kount = query_exec (mrp, sortby, ls, 0, count, obj, 0, TRUE, current_object, TRUE, traverse); } else { - obj = atk_dbus_path_to_object (dbus_message_get_path (message)); + obj = ATK_OBJECT (spi_register_path_to_object (spi_global_register, dbus_message_get_path (message))); kount = query_exec (mrp, sortby, ls, 0, count, obj, 0, TRUE, current_object, TRUE, traverse); @@ -978,7 +977,7 @@ impl_GetMatchesFrom (DBusConnection * bus, DBusMessage * message, dbus_message_iter_init (message, &iter); dbus_message_iter_get_basic (&iter, ¤t_object_path); - current_object = atk_dbus_path_to_object (current_object_path); + current_object = ATK_OBJECT (spi_register_path_to_object (spi_global_register, current_object_path)); if (!current_object) { // TODO: object-not-found error @@ -1042,7 +1041,7 @@ impl_GetMatchesTo (DBusConnection * bus, DBusMessage * message, dbus_message_iter_init (message, &iter); dbus_message_iter_get_basic (&iter, ¤t_object_path); - current_object = atk_dbus_path_to_object (current_object_path); + current_object = ATK_OBJECT (spi_register_path_to_object (spi_global_register, current_object_path)); if (!current_object) { // TODO: object-not-found error @@ -1086,7 +1085,7 @@ impl_GetMatchesTo (DBusConnection * bus, DBusMessage * message, static DBusMessage * impl_GetMatches (DBusConnection * bus, DBusMessage * message, void *user_data) { - AtkObject *obj = atk_dbus_path_to_object (dbus_message_get_path (message)); + AtkObject *obj = ATK_OBJECT (spi_register_path_to_object (spi_global_register, dbus_message_get_path (message))); DBusMessageIter iter; MatchRulePrivate rule; dbus_uint32_t sortby; diff --git a/atk-adaptor/adaptors/component-adaptor.c b/atk-adaptor/adaptors/component-adaptor.c index 40f8360..a3810de 100644 --- a/atk-adaptor/adaptors/component-adaptor.c +++ b/atk-adaptor/adaptors/component-adaptor.c @@ -25,8 +25,8 @@ #include #include -#include "accessible-marshaller.h" #include "common/spi-dbus.h" +#include "object.h" static DBusMessage * impl_contains (DBusConnection * bus, DBusMessage * message, void *user_data) @@ -82,7 +82,7 @@ impl_GetAccessibleAtPoint (DBusConnection * bus, DBusMessage * message, child = atk_component_ref_accessible_at_point (component, x, y, (AtkCoordType) coord_type); - return spi_dbus_return_object (message, child, TRUE, TRUE); + return spi_object_return_reference (message, child); } static DBusMessage * diff --git a/atk-adaptor/adaptors/document-adaptor.c b/atk-adaptor/adaptors/document-adaptor.c index de83a0d..dc3f628 100644 --- a/atk-adaptor/adaptors/document-adaptor.c +++ b/atk-adaptor/adaptors/document-adaptor.c @@ -26,8 +26,7 @@ #include #include "common/spi-dbus.h" - -#include "accessible-marshaller.h" +#include "object.h" static DBusMessage * impl_GetLocale (DBusConnection * bus, DBusMessage * message, void *user_data) diff --git a/atk-adaptor/adaptors/hyperlink-adaptor.c b/atk-adaptor/adaptors/hyperlink-adaptor.c index 75521ed..732ab2b 100644 --- a/atk-adaptor/adaptors/hyperlink-adaptor.c +++ b/atk-adaptor/adaptors/hyperlink-adaptor.c @@ -25,8 +25,8 @@ #include #include -#include "accessible-marshaller.h" #include "common/spi-dbus.h" +#include "object.h" static AtkHyperlink * get_hyperlink (void *user_data) @@ -80,8 +80,7 @@ impl_GetObject (DBusConnection * bus, DBusMessage * message, void *user_data) return droute_invalid_arguments_error (message); } atk_object = atk_hyperlink_get_object (link, i); - return spi_dbus_return_sub_object (message, G_OBJECT (atk_object), - G_OBJECT (link), FALSE); + return spi_object_return_reference (message, atk_object); } static DBusMessage * diff --git a/atk-adaptor/adaptors/hypertext-adaptor.c b/atk-adaptor/adaptors/hypertext-adaptor.c index 082dde3..0bb4060 100644 --- a/atk-adaptor/adaptors/hypertext-adaptor.c +++ b/atk-adaptor/adaptors/hypertext-adaptor.c @@ -26,7 +26,7 @@ #include #include "common/spi-dbus.h" -#include "accessible-marshaller.h" +#include "object.h" static DBusMessage * impl_GetNLinks (DBusConnection * bus, DBusMessage * message, void *user_data) @@ -64,8 +64,7 @@ impl_GetLink (DBusConnection * bus, DBusMessage * message, void *user_data) return droute_invalid_arguments_error (message); } link = atk_hypertext_get_link (hypertext, linkIndex); - return spi_dbus_return_hyperlink (message, link, ATK_OBJECT (hypertext), - TRUE); + return spi_object_return_reference (message, ATK_OBJECT (hypertext)); } static DBusMessage * diff --git a/atk-adaptor/adaptors/image-adaptor.c b/atk-adaptor/adaptors/image-adaptor.c index 1ed7b24..c2e00b0 100644 --- a/atk-adaptor/adaptors/image-adaptor.c +++ b/atk-adaptor/adaptors/image-adaptor.c @@ -26,6 +26,7 @@ #include #include "common/spi-dbus.h" +#include "object.h" static dbus_bool_t impl_get_ImageDescription (DBusMessageIter * iter, void *user_data) diff --git a/atk-adaptor/adaptors/selection-adaptor.c b/atk-adaptor/adaptors/selection-adaptor.c index 4516b52..02e28f2 100644 --- a/atk-adaptor/adaptors/selection-adaptor.c +++ b/atk-adaptor/adaptors/selection-adaptor.c @@ -26,7 +26,7 @@ #include #include "common/spi-dbus.h" -#include "accessible-marshaller.h" +#include "object.h" static dbus_bool_t impl_get_NSelectedChildren (DBusMessageIter * iter, void *user_data) @@ -66,7 +66,7 @@ impl_GetSelectedChild (DBusConnection * bus, DBusMessage * message, return droute_invalid_arguments_error (message); } atk_object = atk_selection_ref_selection (selection, selectedChildIndex); - return spi_dbus_return_object (message, atk_object, TRUE, TRUE); + return spi_object_return_reference (message, atk_object); } static DBusMessage * diff --git a/atk-adaptor/adaptors/table-adaptor.c b/atk-adaptor/adaptors/table-adaptor.c index 212004a..b61caa2 100644 --- a/atk-adaptor/adaptors/table-adaptor.c +++ b/atk-adaptor/adaptors/table-adaptor.c @@ -25,8 +25,8 @@ #include #include -#include "accessible-marshaller.h" #include "common/spi-dbus.h" +#include "object.h" static dbus_bool_t impl_get_NRows (DBusMessageIter * iter, void *user_data) @@ -49,8 +49,8 @@ impl_get_Caption (DBusMessageIter * iter, void *user_data) { AtkTable *table = (AtkTable *) user_data; g_return_val_if_fail (ATK_IS_TABLE (user_data), FALSE); - return spi_dbus_return_v_object (iter, atk_table_get_caption (table), - FALSE); + spi_object_append_v_reference (iter, atk_table_get_caption (table)); + return TRUE; } static dbus_bool_t @@ -58,8 +58,8 @@ impl_get_Summary (DBusMessageIter * iter, void *user_data) { AtkTable *table = (AtkTable *) user_data; g_return_val_if_fail (ATK_IS_TABLE (user_data), FALSE); - return spi_dbus_return_v_object (iter, atk_table_get_summary (table), - FALSE); + spi_object_append_v_reference (iter, atk_table_get_summary (table)); + return TRUE; } static dbus_bool_t @@ -107,7 +107,7 @@ impl_GetAccessibleAt (DBusConnection * bus, DBusMessage * message, return droute_invalid_arguments_error (message); } obj = atk_table_ref_at (table, row, column); - return spi_dbus_return_object (message, obj, TRUE, TRUE); + return spi_object_return_reference (message, obj); } static DBusMessage * @@ -331,7 +331,7 @@ impl_GetRowHeader (DBusConnection * bus, DBusMessage * message, } obj = atk_table_get_row_header (table, row); obj = atk_table_get_row_header (table, row); - return spi_dbus_return_object (message, obj, TRUE, FALSE); + return spi_object_return_reference (message, obj); } static DBusMessage * @@ -353,7 +353,7 @@ impl_GetColumnHeader (DBusConnection * bus, DBusMessage * message, } obj = atk_table_get_column_header (table, column); obj = atk_table_get_column_header (table, column); - return spi_dbus_return_object (message, obj, TRUE, FALSE); + return spi_object_return_reference (message, obj); } static DBusMessage * diff --git a/atk-adaptor/adaptors/text-adaptor.c b/atk-adaptor/adaptors/text-adaptor.c index a15f9c7..dc20a80 100644 --- a/atk-adaptor/adaptors/text-adaptor.c +++ b/atk-adaptor/adaptors/text-adaptor.c @@ -28,8 +28,7 @@ #include #include "common/spi-dbus.h" - -#include "accessible-marshaller.h" +#include "object.h" static dbus_bool_t impl_get_CharacterCount (DBusMessageIter * iter, void *user_data) @@ -735,7 +734,7 @@ impl_GetAttributeRun (DBusConnection * bus, DBusMessage * message, dbus_int32_t startOffset, endOffset; gint intstart_offset = 0, intend_offset = 0; DBusMessage *reply; - AtkAttributeSet *attributes, *default_attributes = NULL; + AtkAttributeSet *attributes = NULL; AtkAttribute *attr = NULL; DBusMessageIter iter, iterArray; @@ -753,20 +752,18 @@ impl_GetAttributeRun (DBusConnection * bus, DBusMessage * message, atk_text_get_run_attributes (text, offset, &intstart_offset, &intend_offset); + if (includeDefaults) + { + attributes = g_slist_concat (attributes, + atk_text_get_default_attributes (text)); + } + reply = dbus_message_new_method_return (message); if (!reply) return NULL; dbus_message_iter_init_append (reply, &iter); - dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{ss}", - &iterArray); - spi_atk_append_attribute_set_inner (&iterArray, attributes); - if (includeDefaults) - { - default_attributes = atk_text_get_default_attributes (text); - spi_atk_append_attribute_set_inner (&iterArray, default_attributes); - } - dbus_message_iter_close_container (&iter, &iterArray); + spi_object_append_attribute_set (&iter, attributes); startOffset = intstart_offset; endOffset = intend_offset; @@ -774,8 +771,6 @@ impl_GetAttributeRun (DBusConnection * bus, DBusMessage * message, dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &endOffset); atk_attribute_set_free (attributes); - if (default_attributes) - atk_attribute_set_free (default_attributes); return reply; } diff --git a/atk-adaptor/adaptors/tree-adaptor.c b/atk-adaptor/adaptors/tree-adaptor.c deleted file mode 100644 index 89a065f..0000000 --- a/atk-adaptor/adaptors/tree-adaptor.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * AT-SPI - Assistive Technology Service Provider Interface - * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) - * - * Copyright 2008 Novell, Inc. - * Copyright 2001, 2002 Sun Microsystems Inc., - * Copyright 2001, 2002 Ximian, Inc. - * Copyright 2008, 2009 Codethink Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include - -#include -#include - -#include "bridge.h" -#include "accessible-register.h" -#include "accessible-marshaller.h" -#include "common/spi-dbus.h" - -/*---------------------------------------------------------------------------*/ - -/* For use as a GHFunc */ -static void -append_accessible_hf (gpointer key, gpointer obj_data, gpointer data) -{ - /* Make sure it isn't a hyperlink */ - if (ATK_IS_OBJECT (obj_data)) - spi_atk_append_accessible (ATK_OBJECT (obj_data), data); -} - -/*---------------------------------------------------------------------------*/ - -void -spi_emit_cache_removal (guint ref, DBusConnection * bus) -{ - DBusMessage *message; - - if ((message = dbus_message_new_signal ("/org/freedesktop/atspi/tree", - SPI_DBUS_INTERFACE_TREE, - "RemoveAccessible"))) - { - DBusMessageIter iter; - gchar *path; - - dbus_message_iter_init_append (message, &iter); - - path = atk_dbus_ref_to_path (ref); - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &path); - - dbus_connection_send (bus, message, NULL); - - dbus_message_unref (message); - } -} - -void -spi_emit_cache_update (AtkObject * accessible, DBusConnection * bus) -{ - DBusMessage *message; - - if ((message = dbus_message_new_signal ("/org/freedesktop/atspi/tree", - SPI_DBUS_INTERFACE_TREE, - "UpdateAccessible"))) - { - DBusMessageIter iter; - - dbus_message_iter_init_append (message, &iter); - spi_atk_append_accessible (accessible, &iter); - - dbus_connection_send (bus, message, NULL); - - dbus_message_unref (message); - } -} - - -/*---------------------------------------------------------------------------*/ - -static DBusMessage * -impl_GetRoot (DBusConnection * bus, DBusMessage * message, void *user_data) -{ - AtkObject *root = atk_get_root (); - char *path; - DBusMessage *reply; - gchar *errmsg; - - if (!root) - { - reply = dbus_message_new_error (message, - DBUS_ERROR_FAILED, - "No root accessible available"); - } - path = atk_dbus_object_to_path (root, FALSE); - if (!path) - { - reply = dbus_message_new_error (message, - DBUS_ERROR_FAILED, - "No root accessible available"); - } - reply = dbus_message_new_method_return (message); - dbus_message_append_args (reply, DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID); - g_free (path); - return reply; -} - -/*---------------------------------------------------------------------------*/ - -static DBusMessage * -impl_GetTree (DBusConnection * bus, DBusMessage * message, void *user_data) -{ - DBusMessage *reply; - DBusMessageIter iter, iter_array; - - reply = dbus_message_new_method_return (message); - - dbus_message_iter_init_append (reply, &iter); - dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, - "(o(so)a(so)assusau)", &iter_array); - atk_dbus_foreach_registered (append_accessible_hf, &iter_array); - dbus_message_iter_close_container (&iter, &iter_array); - return reply; -} - -/*---------------------------------------------------------------------------*/ - -static DRouteMethod methods[] = { - {impl_GetRoot, "GetRoot"}, - {impl_GetTree, "GetTree"}, - {NULL, NULL} -}; - -void -spi_initialize_tree (DRoutePath * path) -{ - droute_path_add_interface (path, SPI_DBUS_INTERFACE_TREE, methods, NULL); -}; - -/*END------------------------------------------------------------------------*/ diff --git a/atk-adaptor/bridge.c b/atk-adaptor/bridge.c index 00ead5c..b283506 100644 --- a/atk-adaptor/bridge.c +++ b/atk-adaptor/bridge.c @@ -31,15 +31,19 @@ #include #include #include +#include #include #include #include "bridge.h" #include "event.h" -#include "accessible-register.h" #include "adaptors.h" +#include "accessible-register.h" +#include "accessible-leasing.h" +#include "accessible-cache.h" + #include "common/spi-dbus.h" /* @@ -51,7 +55,7 @@ /*---------------------------------------------------------------------------*/ -SpiAppData *atk_adaptor_app_data = NULL; +SpiBridge *spi_global_app_data = NULL; static const AtkMisc *atk_misc = NULL; @@ -151,7 +155,7 @@ spi_atk_bridge_get_bus (void) else { if (!dbus_bus_register (bus, &error)) - g_error ("AT-SPI: Couldn't register with bus: %s\n"); + g_error ("AT-SPI: Couldn't register with bus: %s\n", error.message); } } @@ -161,7 +165,7 @@ spi_atk_bridge_get_bus (void) /*---------------------------------------------------------------------------*/ static void -register_application (SpiAppData * app) +register_application (SpiBridge * app) { DBusMessage *message; DBusMessageIter iter; @@ -192,7 +196,7 @@ register_application (SpiAppData * app) /*---------------------------------------------------------------------------*/ static void -deregister_application (SpiAppData * app) +deregister_application (SpiBridge * app) { DBusMessage *message; DBusMessageIter iter; @@ -221,17 +225,17 @@ deregister_application (SpiAppData * app) static void exit_func (void) { - if (!atk_adaptor_app_data) + if (!spi_global_app_data) { return; } spi_atk_tidy_windows (); spi_atk_deregister_event_listeners (); - deregister_application (atk_adaptor_app_data); + deregister_application (spi_global_app_data); - g_free (atk_adaptor_app_data); - atk_adaptor_app_data = NULL; + g_free (spi_global_app_data); + spi_global_app_data = NULL; /* Not currently creating an XDisplay */ #if 0 @@ -249,7 +253,7 @@ static AtkSocketClass *socket_class; static gchar * get_plug_id (AtkPlug * plug) { - const char *uname = dbus_bus_get_unique_name (atk_adaptor_app_data->bus); + const char *uname = dbus_bus_get_unique_name (spi_global_app_data->bus); gchar *path; GString *str = g_string_new (NULL); @@ -352,24 +356,24 @@ adaptor_init (gint * argc, gchar ** argv[]) g_warning ("AT-SPI Option parsing failed: %s\n", err->message); /* Allocate global data and do ATK initializations */ - atk_adaptor_app_data = g_new0 (SpiAppData, 1); + spi_global_app_data = g_new0 (SpiBridge, 1); atk_misc = atk_misc_get_instance (); - atk_adaptor_app_data->root = root; + spi_global_app_data->root = root; /* Set up D-Bus connection and register bus name */ dbus_error_init (&error); - atk_adaptor_app_data->bus = spi_atk_bridge_get_bus (); - if (!atk_adaptor_app_data->bus) + spi_global_app_data->bus = spi_atk_bridge_get_bus (); + if (!spi_global_app_data->bus) { - g_free (atk_adaptor_app_data); - atk_adaptor_app_data = NULL; + g_free (spi_global_app_data); + spi_global_app_data = NULL; return 0; } if (atspi_dbus_name != NULL) { if (dbus_bus_request_name - (atk_adaptor_app_data->bus, atspi_dbus_name, 0, &error)) + (spi_global_app_data->bus, atspi_dbus_name, 0, &error)) { g_print ("AT-SPI Recieved D-Bus name - %s\n", atspi_dbus_name); } @@ -381,7 +385,7 @@ adaptor_init (gint * argc, gchar ** argv[]) } } - dbus_connection_setup_with_g_main (atk_adaptor_app_data->bus, + dbus_connection_setup_with_g_main (spi_global_app_data->bus, g_main_context_default ()); /* Get D-Bus introspection directory */ @@ -390,21 +394,29 @@ adaptor_init (gint * argc, gchar ** argv[]) introspection_directory = ATSPI_INTROSPECTION_PATH; /* Register droute for routing AT-SPI messages */ - atk_adaptor_app_data->droute = - droute_new (atk_adaptor_app_data->bus, introspection_directory); + spi_global_app_data->droute = + droute_new (spi_global_app_data->bus, introspection_directory); - treepath = droute_add_one (atk_adaptor_app_data->droute, - "/org/freedesktop/atspi/tree", NULL); + treepath = droute_add_one (spi_global_app_data->droute, + "/org/at_spi/cache", NULL); - accpath = droute_add_many (atk_adaptor_app_data->droute, - "/org/freedesktop/atspi/accessible", + accpath = droute_add_many (spi_global_app_data->droute, + "/org/at_spi/accessible", NULL, (DRouteGetDatumFunction) - atk_dbus_path_to_gobject); + spi_global_register_path_to_object); - /* Register all interfaces with droute and set up application accessible db */ - spi_initialize_tree (treepath); + /* + * Create the leasing, register and cache objects. + * The order is important here, the cache depends on the + * register object. + */ + spi_global_register = g_object_new (SPI_REGISTER_TYPE, NULL); + spi_global_leasing = g_object_new (SPI_LEASING_TYPE, NULL); + spi_global_cache = g_object_new (SPI_CACHE_TYPE, NULL); + /* Register all interfaces with droute and set up application accessible db */ + spi_initialize_cache (treepath); spi_initialize_accessible (accpath); spi_initialize_application (accpath); spi_initialize_action (accpath); @@ -420,9 +432,6 @@ adaptor_init (gint * argc, gchar ** argv[]) spi_initialize_text (accpath); spi_initialize_value (accpath); - /* Initialize the AtkObject registration */ - atk_dbus_initialize (atk_adaptor_app_data->root); - /* Register methods to send D-Bus signals on certain ATK events */ spi_atk_register_event_listeners (); @@ -433,7 +442,7 @@ adaptor_init (gint * argc, gchar ** argv[]) /* Register this app by sending a signal out to AT-SPI registry daemon */ if (!atspi_no_register) - register_application (atk_adaptor_app_data); + register_application (spi_global_app_data); g_atexit (exit_func); diff --git a/atk-adaptor/bridge.h b/atk-adaptor/bridge.h index 44315f1..2a95fcd 100644 --- a/atk-adaptor/bridge.h +++ b/atk-adaptor/bridge.h @@ -4,7 +4,7 @@ * * Copyright 2001, 2002, 2003 Sun Microsystems Inc., * Copyright 2001, 2002, 2003 Ximian, Inc. - * Copyright 2008, 2009 Codethink Ltd. + * Copyright 2008, 2009, 2010 Codethink Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -28,15 +28,29 @@ #include #include -typedef struct _SpiAppData SpiAppData; -struct _SpiAppData +typedef struct _SpiBridge SpiBridge; +typedef struct _SpiBridgeClass SpiBridgeClass; + +G_BEGIN_DECLS + +struct _SpiBridge { + GObject parent; + AtkObject *root; DBusConnection *bus; - DRouteContext *droute; + DRouteContext *droute; + +/* + SpiRegister *reg; + SpiCache *cache; + SpiLeasing *leasing; +*/ }; -extern SpiAppData *atk_adaptor_app_data; +extern SpiBridge *spi_global_app_data; + +G_END_DECLS #endif /* BRIDGE_H */ diff --git a/atk-adaptor/event.c b/atk-adaptor/event.c index 687fc79..e97046b 100644 --- a/atk-adaptor/event.c +++ b/atk-adaptor/event.c @@ -73,6 +73,14 @@ send_and_allow_reentry (DBusConnection * bus, DBusMessage * message) return reply; } +/*---------------------------------------------------------------------------*/ + +/* + * Functionality related to sending device events from the application. + * + * This is used for forwarding key events on to the registry daemon. + */ + static gboolean Accessibility_DeviceEventController_NotifyListenersSync (const Accessibility_DeviceEvent @@ -92,7 +100,7 @@ Accessibility_DeviceEventController_NotifyListenersSync (const if (spi_dbus_marshal_deviceEvent (message, key_event)) { DBusMessage *reply = - send_and_allow_reentry (atk_adaptor_app_data->bus, message); + send_and_allow_reentry (spi_global_app_data->bus, message); if (reply) { DBusError error; @@ -169,22 +177,10 @@ spi_atk_bridge_key_listener (AtkKeyEventStruct * event, gpointer data) return result; } - /*---------------------------------------------------------------------------*/ -/* - * Emits an AT-SPI event. - * AT-SPI events names are split into three parts: - * class:major:minor - * This is mapped onto D-Bus events as: - * D-Bus Interface:Signal Name:Detail argument - * - * Marshals a basic type into the 'any_data' attribute of - * the AT-SPI event. - */ - static gchar * -DBusSignalName (const gchar * s) +convert_signal_name (const gchar * s) { gchar *ret = g_strdup (s); gchar *t; @@ -200,103 +196,122 @@ DBusSignalName (const gchar * s) return ret; } +static const void * +replace_null (const gint type, + const void *val) +{ + switch (type) + { + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + if (!val) + return ""; + else + return val; + default: + return val; + } +} + static void -emit (AtkObject * accessible, - const char *klass, - const char *major, - const char *minor, - dbus_int32_t detail1, - dbus_int32_t detail2, const char *type, const void *val) +append_basic (DBusMessageIter *iter, + const char *type, + const void *val) { - gchar *path; - gchar *cname; + DBusMessageIter sub; - /* TODO this is a hack, used becuase child-added events are not guaranteed. - * On recieving an event from a non-registered object we check if it can be safely - * registered before sending the event. - */ - path = atk_dbus_object_attempt_registration (accessible); + dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, type, &sub); - /* Tough decision here - * We won't send events from accessible - * objects that have not yet been added to the accessible tree. - */ - if (path == NULL) - { -#ifdef SPI_ATK_DEBUG - g_debug ("AT-SPI: Event recieved from non-registered object"); -#endif - return; - } + val = replace_null ((int) *type, val); + dbus_message_iter_append_basic(&sub, (int) *type, &val); - cname = DBusSignalName (major); - spi_dbus_emit_signal (atk_adaptor_app_data->bus, path, klass, cname, minor, - detail1, detail2, type, val); - g_free (cname); - g_free (path); + dbus_message_iter_close_container(iter, &sub); } -/*---------------------------------------------------------------------------*/ - -/* - * Emits an AT-SPI event, marshalling a BoundingBox structure into the - * 'any_data' variant of the event. - */ static void -emit_rect (AtkObject * accessible, - const char *klass, - const char *major, const char *minor, AtkRectangle * rect) +append_rect (DBusMessageIter *iter, + const char *type, + const void *val) { - DBusMessage *sig; - DBusMessageIter iter, variant, sub; - gchar *path, *cname; - dbus_int32_t dummy = 0; + DBusMessageIter variant, sub; + const AtkRectangle *rect = (const AtkRectangle *) val; - path = atk_dbus_object_to_path (accessible, FALSE); + dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, type, &variant); - /* Tough decision here - * We won't send events from accessible - * objects that have not yet been added to the accessible tree. - */ - if (path == NULL) - return; + dbus_message_iter_open_container (&variant, DBUS_TYPE_STRUCT, NULL, &sub); + + dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->x)); + dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->y)); + dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->width)); + dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->height)); - if (!klass) - klass = ""; - if (!major) - major = ""; - if (!minor) - minor = ""; + dbus_message_iter_close_container (&variant, &sub); + + dbus_message_iter_close_container(iter, &variant); +} + +static void +append_object (DBusMessageIter *iter, + const char *type, + const void *val) +{ + spi_object_append_v_reference (iter, ATK_OBJECT (val)); +} + +/* + * Emits an AT-SPI event. + * AT-SPI events names are split into three parts: + * class:major:minor + * This is mapped onto D-Bus events as: + * D-Bus Interface:Signal Name:Detail argument + * + * Marshals a basic type into the 'any_data' attribute of + * the AT-SPI event. + */ +static void +emit_event (AtkObject *obj, + const char *klass, + const char *major, + const char *minor, + dbus_int32_t detail1, + dbus_int32_t detail2, + const char *type, + const void *val, + void (*append_variant) (DBusMessageIter *, const char *, const void *)) +{ + DBusConnection *bus = spi_global_app_data->bus; + const char *path = spi_register_object_to_path (spi_global_register, + G_OBJECT (obj)); + + gchar *cname, *t; + DBusMessage *sig; + DBusMessageIter iter; + + if (!klass) klass = ""; + if (!major) major = ""; + if (!minor) minor = ""; + if (!type) type = "u"; /* * This is very annoying, but as '-' isn't a legal signal * name in D-Bus (Why not??!?) The names need converting * on this side, and again on the client side. */ - cname = DBusSignalName (major); - - sig = dbus_message_new_signal (path, klass, cname); - g_free (path); - g_free (cname); - - dbus_message_iter_init_append (sig, &iter); - dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &minor); - dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &dummy); - dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &dummy); - - dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "(iiii)", - &variant); - dbus_message_iter_open_container (&variant, DBUS_TYPE_STRUCT, NULL, &sub); - dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->x)); - dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->y)); - dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->width)); - dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &(rect->height)); - dbus_message_iter_close_container (&variant, &sub); - dbus_message_iter_close_container (&iter, &variant); - - dbus_connection_send (atk_adaptor_app_data->bus, sig, NULL); - - dbus_message_unref (sig); + cname = g_strdup(major); + while ((t = strchr(cname, '-')) != NULL) *t = '_'; + sig = dbus_message_new_signal(path, klass, cname); + g_free(cname); + + dbus_message_iter_init_append(sig, &iter); + + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &minor); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &detail1); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &detail2); + + append_variant (&iter, type, val); + + dbus_connection_send(bus, sig, NULL); + dbus_message_unref(sig); } /*---------------------------------------------------------------------------*/ @@ -308,8 +323,8 @@ emit_rect (AtkObject * accessible, static void focus_tracker (AtkObject * accessible) { - emit (accessible, ITF_EVENT_FOCUS, "focus", "", 0, 0, - DBUS_TYPE_INT32_AS_STRING, 0); + emit_event (accessible, ITF_EVENT_FOCUS, "focus", "", 0, 0, + DBUS_TYPE_INT32_AS_STRING, 0, append_basic); } /*---------------------------------------------------------------------------*/ @@ -335,75 +350,85 @@ property_event_listener (GSignalInvocationHint * signal_hint, const gchar *pname = NULL; AtkObject *otemp; - const gchar *stemp; + const gchar *s1, s2; gint i; accessible = g_value_get_object (¶m_values[0]); values = (AtkPropertyValues *) g_value_get_pointer (¶m_values[1]); pname = values[0].property_name; - if (strcmp (pname, "accessible-name") == 0 || - strcmp (pname, "accessible-description") == 0 || - strcmp (pname, "accessible-role") == 0 || - strcmp (pname, "accessible-parent") == 0) - { - return TRUE; - } /* TODO Could improve this control statement by matching * on only the end of the signal names, */ + if (strcmp (pname, "accessible-name") == 0) + { + s1 = atk_object_get_name (accessible); + if (s1 != NULL) + emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, + DBUS_TYPE_STRING_AS_STRING, s1, append_basic); + } + if (strcmp (pname, "accessible-description") == 0) + { + s1 = atk_object_get_description (accessible); + if (s1 != NULL) + emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, + DBUS_TYPE_STRING_AS_STRING, s1, append_basic); + } + if (strcmp (pname, "accessible-parent") == 0) + { + otemp = atk_object_get_parent (accessible); + if (otemp != NULL) + emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, + "(so)", otemp, append_object); + } if (strcmp (pname, "accessible-table-summary") == 0) { otemp = atk_table_get_summary (ATK_TABLE (accessible)); - stemp = atk_dbus_object_to_path (otemp, FALSE); - if (stemp != NULL) - emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, - DBUS_TYPE_OBJECT_PATH_AS_STRING, stemp); + if (otemp != NULL) + emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, + "(so)", otemp, append_object); } else if (strcmp (pname, "accessible-table-column-header") == 0) { i = g_value_get_int (&(values->new_value)); otemp = atk_table_get_column_header (ATK_TABLE (accessible), i); - stemp = atk_dbus_object_to_path (otemp, FALSE); - if (stemp != NULL) - emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, - DBUS_TYPE_OBJECT_PATH_AS_STRING, stemp); + if (otemp != NULL) + emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, + "(so)", otemp, append_object); } else if (strcmp (pname, "accessible-table-row-header") == 0) { i = g_value_get_int (&(values->new_value)); otemp = atk_table_get_row_header (ATK_TABLE (accessible), i); - stemp = atk_dbus_object_to_path (otemp, FALSE); - if (stemp != NULL) - emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, - DBUS_TYPE_OBJECT_PATH_AS_STRING, stemp); + if (otemp != NULL) + emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, + "(so)", otemp, append_object); } else if (strcmp (pname, "accessible-table-row-description") == 0) { i = g_value_get_int (&(values->new_value)); - stemp = atk_table_get_row_description (ATK_TABLE (accessible), i); - emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, - DBUS_TYPE_STRING_AS_STRING, stemp); + s1 = atk_table_get_row_description (ATK_TABLE (accessible), i); + emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, + DBUS_TYPE_STRING_AS_STRING, s1, append_basic); } else if (strcmp (pname, "accessible-table-column-description") == 0) { i = g_value_get_int (&(values->new_value)); - stemp = atk_table_get_column_description (ATK_TABLE (accessible), i); - emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, - DBUS_TYPE_STRING_AS_STRING, stemp); + s1 = atk_table_get_column_description (ATK_TABLE (accessible), i); + emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, + DBUS_TYPE_STRING_AS_STRING, s1, append_basic); } else if (strcmp (pname, "accessible-table-caption-object") == 0) { otemp = atk_table_get_caption (ATK_TABLE (accessible)); - stemp = atk_object_get_name (otemp); - emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, - DBUS_TYPE_STRING_AS_STRING, stemp); + emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, + "(so)", otemp, append_object); } else { - emit (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, - DBUS_TYPE_INT32_AS_STRING, 0); + emit_event (accessible, ITF_EVENT_OBJECT, PCHANGE, pname, 0, 0, + DBUS_TYPE_INT32_AS_STRING, 0, append_basic); } return TRUE; } @@ -433,8 +458,8 @@ state_event_listener (GSignalInvocationHint * signal_hint, * This is because without reference counting defunct objects should be removed. */ detail1 = (g_value_get_boolean (¶m_values[2])) ? 1 : 0; - emit (accessible, ITF_EVENT_OBJECT, STATE_CHANGED, pname, detail1, 0, - DBUS_TYPE_INT32_AS_STRING, 0); + emit_event (accessible, ITF_EVENT_OBJECT, STATE_CHANGED, pname, detail1, 0, + DBUS_TYPE_INT32_AS_STRING, 0, append_basic); g_free (pname); return TRUE; } @@ -466,8 +491,8 @@ window_event_listener (GSignalInvocationHint * signal_hint, accessible = ATK_OBJECT (g_value_get_object (¶m_values[0])); s = atk_object_get_name (accessible); - emit (accessible, ITF_EVENT_WINDOW, name, "", 0, 0, - DBUS_TYPE_STRING_AS_STRING, s); + emit_event (accessible, ITF_EVENT_WINDOW, name, "", 0, 0, + DBUS_TYPE_STRING_AS_STRING, s, append_basic); return TRUE; } @@ -496,8 +521,8 @@ document_event_listener (GSignalInvocationHint * signal_hint, accessible = ATK_OBJECT (g_value_get_object (¶m_values[0])); s = atk_object_get_name (accessible); - emit (accessible, ITF_EVENT_DOCUMENT, name, "", 0, 0, - DBUS_TYPE_STRING_AS_STRING, s); + emit_event (accessible, ITF_EVENT_DOCUMENT, name, "", 0, 0, + DBUS_TYPE_STRING_AS_STRING, s, append_basic); return TRUE; } @@ -524,9 +549,12 @@ bounds_event_listener (GSignalInvocationHint * signal_hint, accessible = ATK_OBJECT (g_value_get_object (¶m_values[0])); if (G_VALUE_HOLDS_BOXED (param_values + 1)) + { atk_rect = g_value_get_boxed (param_values + 1); - emit_rect (accessible, ITF_EVENT_OBJECT, name, "", atk_rect); + emit_event (accessible, ITF_EVENT_OBJECT, name, "", 0, 0, + "(iiii)", atk_rect, append_rect); + } return TRUE; } @@ -558,15 +586,9 @@ active_descendant_event_listener (GSignalInvocationHint * signal_hint, minor = g_quark_to_string (signal_hint->detail); detail1 = atk_object_get_index_in_parent (child); - s = atk_dbus_object_to_path (child, FALSE); - if (s == NULL) - { - g_free (s); - return TRUE; - } - emit (accessible, ITF_EVENT_OBJECT, name, "", detail1, 0, - DBUS_TYPE_OBJECT_PATH_AS_STRING, s); + emit_event (accessible, ITF_EVENT_OBJECT, name, "", detail1, 0, + "(so)", child, append_object); g_free (s); return TRUE; } @@ -597,8 +619,8 @@ link_selected_event_listener (GSignalInvocationHint * signal_hint, if (G_VALUE_TYPE (¶m_values[1]) == G_TYPE_INT) detail1 = g_value_get_int (¶m_values[1]); - emit (accessible, ITF_EVENT_OBJECT, name, minor, detail1, 0, - DBUS_TYPE_INT32_AS_STRING, 0); + emit_event (accessible, ITF_EVENT_OBJECT, name, minor, detail1, 0, + DBUS_TYPE_INT32_AS_STRING, 0, append_basic); return TRUE; } @@ -635,8 +657,8 @@ text_changed_event_listener (GSignalInvocationHint * signal_hint, selected = atk_text_get_text (ATK_TEXT (accessible), detail1, detail1 + detail2); - emit (accessible, ITF_EVENT_OBJECT, name, minor, detail1, detail2, - DBUS_TYPE_STRING_AS_STRING, selected); + emit_event (accessible, ITF_EVENT_OBJECT, name, minor, detail1, detail2, + DBUS_TYPE_STRING_AS_STRING, selected, append_basic); return TRUE; } @@ -670,8 +692,8 @@ text_selection_changed_event_listener (GSignalInvocationHint * signal_hint, if (G_VALUE_TYPE (¶m_values[2]) == G_TYPE_INT) detail2 = g_value_get_int (¶m_values[2]); - emit (accessible, ITF_EVENT_OBJECT, name, minor, detail1, detail2, - DBUS_TYPE_STRING_AS_STRING, ""); + emit_event (accessible, ITF_EVENT_OBJECT, name, minor, detail1, detail2, + DBUS_TYPE_STRING_AS_STRING, "", append_basic); return TRUE; } @@ -708,8 +730,8 @@ generic_event_listener (GSignalInvocationHint * signal_hint, if (n_param_values > 2 && G_VALUE_TYPE (¶m_values[2]) == G_TYPE_INT) detail2 = g_value_get_int (¶m_values[2]); - emit (accessible, ITF_EVENT_OBJECT, name, "", detail1, detail2, - DBUS_TYPE_INT32_AS_STRING, 0); + emit_event (accessible, ITF_EVENT_OBJECT, name, "", detail1, detail2, + DBUS_TYPE_INT32_AS_STRING, 0, append_basic); return TRUE; } @@ -861,13 +883,13 @@ spi_atk_tidy_windows (void) name = atk_object_get_name (child); if (atk_state_set_contains_state (stateset, ATK_STATE_ACTIVE)) { - emit (child, ITF_EVENT_WINDOW, "deactivate", NULL, 0, 0, - DBUS_TYPE_STRING_AS_STRING, name); + emit_event (child, ITF_EVENT_WINDOW, "deactivate", NULL, 0, 0, + DBUS_TYPE_STRING_AS_STRING, name, append_basic); } g_object_unref (stateset); - emit (child, ITF_EVENT_WINDOW, "destroy", NULL, 0, 0, - DBUS_TYPE_STRING_AS_STRING, name); + emit_event (child, ITF_EVENT_WINDOW, "destroy", NULL, 0, 0, + DBUS_TYPE_STRING_AS_STRING, name, append_basic); g_object_unref (child); } } diff --git a/atk-adaptor/object.c b/atk-adaptor/object.c new file mode 100644 index 0000000..856e991 --- /dev/null +++ b/atk-adaptor/object.c @@ -0,0 +1,404 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2008 Novell, Inc. + * Copyright 2008, 2009, 2010 Codethink Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * This module contains utility functions for exporting AT-SPI + * objects based upon an ATK object. + * + * It incudes functions for marshalling object references + * and supported interfaces to a D-Bus message. + */ + +#include +#include +#include + +#include "accessible-register.h" +#include "accessible-cache.h" +#include "accessible-leasing.h" + +#include "bridge.h" + +/*---------------------------------------------------------------------------*/ + +/* + * This is the all important function that decides whether an object should + * be leased or not. + * + * The choice of algorithm for this is somewhat vuage. We want ideally to lease + * all atk objects that are not owned by their parent. + * + * The 'cache' object attempts to cache all objects that are owned by their + * parent by traversing the tree of accessibles, ignoring the children of + * manages-descendants and transient objects. + * + * This function will simply look for all the accessibles that the cache object + * has not found and assume that they need to be leased. + */ +static void +maybe_lease (AtkObject *obj) +{ + if (!spi_cache_in (spi_global_cache, G_OBJECT (obj))) + { + spi_leasing_take (spi_global_leasing, G_OBJECT (obj)); + } +} + +/*---------------------------------------------------------------------------*/ + +/* + * It is assumed that all of these functions are returning an accessible + * object to the client side. + * + * All of them will lease the AtkObject if it is deemed neccessary. + */ + +void +spi_object_append_reference (DBusMessageIter * iter, AtkObject * obj) +{ + DBusMessageIter iter_struct; + const gchar *name; + gchar *path; + + maybe_lease (obj); + + name = dbus_bus_get_unique_name (spi_global_app_data->bus); + path = spi_register_object_to_path (spi_global_register, G_OBJECT (obj)); + + if (!path) + path = g_strdup (SPI_DBUS_PATH_NULL); + + dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL, + &iter_struct); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path); + dbus_message_iter_close_container (iter, &iter_struct); + + g_free (path); +} + +void +spi_object_append_v_reference (DBusMessageIter * iter, AtkObject * obj) +{ + DBusMessageIter iter_variant; + + dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, "(so)", + &iter_variant); + spi_object_append_reference (&iter_variant, obj); + dbus_message_iter_close_container (iter, &iter_variant); +} + +void +spi_object_append_desktop_reference (DBusMessageIter * iter) +{ + DBusMessageIter iter_struct; + const char *name = SPI_DBUS_NAME_REGISTRY; + const char *path = SPI_DBUS_PATH_DESKTOP; + + dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL, + &iter_struct); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path); + dbus_message_iter_close_container (iter, &iter_struct); +} + +void +spi_object_append_null_reference (DBusMessageIter * iter) +{ + DBusMessageIter iter_struct; + const char *name; + const char *path = "/org/at_spi/null"; + + name = dbus_bus_get_unique_name (spi_global_app_data->bus); + + dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, NULL, + &iter_struct); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &name); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_OBJECT_PATH, &path); + dbus_message_iter_close_container (iter, &iter_struct); +} + +DBusMessage * +spi_object_return_reference (DBusMessage * msg, AtkObject * obj) +{ + DBusMessage *reply; + + reply = dbus_message_new_method_return (msg); + if (reply) + { + DBusMessageIter iter; + dbus_message_iter_init_append (reply, &iter); + spi_object_append_reference (&iter, obj); + } + g_object_unref (G_OBJECT (obj)); + + return reply; +} + +/*---------------------------------------------------------------------------*/ + +void +spi_object_append_interfaces (DBusMessageIter * iter, AtkObject * obj) +{ + const gchar *itf; + + itf = SPI_DBUS_INTERFACE_ACCESSIBLE; + dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); + + if (ATK_IS_ACTION (obj)) + { + itf = SPI_DBUS_INTERFACE_ACTION; + dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); + } + + if (ATK_IS_COMPONENT (obj)) + { + itf = SPI_DBUS_INTERFACE_COMPONENT; + dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); + } + + if (ATK_IS_EDITABLE_TEXT (obj)) + { + itf = SPI_DBUS_INTERFACE_EDITABLE_TEXT; + dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); + } + + if (ATK_IS_TEXT (obj)) + { + itf = SPI_DBUS_INTERFACE_TEXT; + dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); + } + + if (ATK_IS_HYPERTEXT (obj)) + { + itf = SPI_DBUS_INTERFACE_HYPERTEXT; + dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); + } + + if (ATK_IS_IMAGE (obj)) + { + itf = SPI_DBUS_INTERFACE_IMAGE; + dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); + } + + if (ATK_IS_SELECTION (obj)) + { + itf = SPI_DBUS_INTERFACE_SELECTION; + dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); + } + + if (ATK_IS_TABLE (obj)) + { + itf = SPI_DBUS_INTERFACE_TABLE; + dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); + } + + if (ATK_IS_VALUE (obj)) + { + itf = SPI_DBUS_INTERFACE_VALUE; + dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); + } + + if (ATK_IS_STREAMABLE_CONTENT (obj)) + { + itf = "org.freedesktop.atspi.StreamableContent"; + dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); + } + + if (ATK_IS_DOCUMENT (obj)) + { + itf = "org.freedesktop.atspi.Collection"; + dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); + itf = SPI_DBUS_INTERFACE_DOCUMENT; + dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); + } + + if (ATK_IS_HYPERLINK_IMPL (obj)) + { + itf = SPI_DBUS_INTERFACE_HYPERLINK; + dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &itf); + } +} + +/*---------------------------------------------------------------------------*/ + +void +spi_object_append_attribute_set (DBusMessageIter * iter, AtkAttributeSet * attr) +{ + DBusMessageIter dictIter; + + dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "{ss}", &dictIter); + while (attr) + { + DBusMessageIter dictEntryIter; + AtkAttribute *attribute = (AtkAttribute *) attr->data; + const char *key = attribute->name; + const char *value = attribute->value; + + if (key == NULL) + key = ""; + if (value == NULL) + value = ""; + + dbus_message_iter_open_container (&dictIter, DBUS_TYPE_DICT_ENTRY, NULL, + &dictEntryIter); + dbus_message_iter_append_basic (&dictEntryIter, DBUS_TYPE_STRING, + &key); + dbus_message_iter_append_basic (&dictEntryIter, DBUS_TYPE_STRING, + &value); + dbus_message_iter_close_container (&dictIter, &dictEntryIter); + attr = g_slist_next (attr); + } + dbus_message_iter_close_container (iter, &dictIter); +} + +/*---------------------------------------------------------------------------*/ + +static gboolean +init_role_lookup_table (Accessibility_Role * role_table) +{ + int i; + /* if it's not in the list below, dunno what it is */ + for (i = 0; i < ATK_ROLE_LAST_DEFINED; ++i) + { + role_table[i] = Accessibility_ROLE_UNKNOWN; + } + + role_table[ATK_ROLE_INVALID] = Accessibility_ROLE_INVALID; + role_table[ATK_ROLE_ACCEL_LABEL] = Accessibility_ROLE_ACCELERATOR_LABEL; + role_table[ATK_ROLE_ALERT] = Accessibility_ROLE_ALERT; + role_table[ATK_ROLE_ANIMATION] = Accessibility_ROLE_ANIMATION; + role_table[ATK_ROLE_ARROW] = Accessibility_ROLE_ARROW; + role_table[ATK_ROLE_CALENDAR] = Accessibility_ROLE_CALENDAR; + role_table[ATK_ROLE_CANVAS] = Accessibility_ROLE_CANVAS; + role_table[ATK_ROLE_CHECK_BOX] = Accessibility_ROLE_CHECK_BOX; + role_table[ATK_ROLE_CHECK_MENU_ITEM] = Accessibility_ROLE_CHECK_MENU_ITEM; + role_table[ATK_ROLE_COLOR_CHOOSER] = Accessibility_ROLE_COLOR_CHOOSER; + role_table[ATK_ROLE_COLUMN_HEADER] = Accessibility_ROLE_COLUMN_HEADER; + role_table[ATK_ROLE_COMBO_BOX] = Accessibility_ROLE_COMBO_BOX; + role_table[ATK_ROLE_DATE_EDITOR] = Accessibility_ROLE_DATE_EDITOR; + role_table[ATK_ROLE_DESKTOP_ICON] = Accessibility_ROLE_DESKTOP_ICON; + role_table[ATK_ROLE_DESKTOP_FRAME] = Accessibility_ROLE_DESKTOP_FRAME; + role_table[ATK_ROLE_DIAL] = Accessibility_ROLE_DIAL; + role_table[ATK_ROLE_DIALOG] = Accessibility_ROLE_DIALOG; + role_table[ATK_ROLE_DIRECTORY_PANE] = Accessibility_ROLE_DIRECTORY_PANE; + role_table[ATK_ROLE_DRAWING_AREA] = Accessibility_ROLE_DRAWING_AREA; + role_table[ATK_ROLE_FILE_CHOOSER] = Accessibility_ROLE_FILE_CHOOSER; + role_table[ATK_ROLE_FILLER] = Accessibility_ROLE_FILLER; + role_table[ATK_ROLE_FONT_CHOOSER] = Accessibility_ROLE_FONT_CHOOSER; + role_table[ATK_ROLE_FRAME] = Accessibility_ROLE_FRAME; + role_table[ATK_ROLE_GLASS_PANE] = Accessibility_ROLE_GLASS_PANE; + role_table[ATK_ROLE_HTML_CONTAINER] = Accessibility_ROLE_HTML_CONTAINER; + role_table[ATK_ROLE_ICON] = Accessibility_ROLE_ICON; + role_table[ATK_ROLE_IMAGE] = Accessibility_ROLE_IMAGE; + role_table[ATK_ROLE_INTERNAL_FRAME] = Accessibility_ROLE_INTERNAL_FRAME; + role_table[ATK_ROLE_LABEL] = Accessibility_ROLE_LABEL; + role_table[ATK_ROLE_LAYERED_PANE] = Accessibility_ROLE_LAYERED_PANE; + role_table[ATK_ROLE_LIST] = Accessibility_ROLE_LIST; + role_table[ATK_ROLE_LIST_ITEM] = Accessibility_ROLE_LIST_ITEM; + role_table[ATK_ROLE_MENU] = Accessibility_ROLE_MENU; + role_table[ATK_ROLE_MENU_BAR] = Accessibility_ROLE_MENU_BAR; + role_table[ATK_ROLE_MENU_ITEM] = Accessibility_ROLE_MENU_ITEM; + role_table[ATK_ROLE_OPTION_PANE] = Accessibility_ROLE_OPTION_PANE; + role_table[ATK_ROLE_PAGE_TAB] = Accessibility_ROLE_PAGE_TAB; + role_table[ATK_ROLE_PAGE_TAB_LIST] = Accessibility_ROLE_PAGE_TAB_LIST; + role_table[ATK_ROLE_PANEL] = Accessibility_ROLE_PANEL; + role_table[ATK_ROLE_PASSWORD_TEXT] = Accessibility_ROLE_PASSWORD_TEXT; + role_table[ATK_ROLE_POPUP_MENU] = Accessibility_ROLE_POPUP_MENU; + role_table[ATK_ROLE_PROGRESS_BAR] = Accessibility_ROLE_PROGRESS_BAR; + role_table[ATK_ROLE_PUSH_BUTTON] = Accessibility_ROLE_PUSH_BUTTON; + role_table[ATK_ROLE_RADIO_BUTTON] = Accessibility_ROLE_RADIO_BUTTON; + role_table[ATK_ROLE_RADIO_MENU_ITEM] = Accessibility_ROLE_RADIO_MENU_ITEM; + role_table[ATK_ROLE_ROOT_PANE] = Accessibility_ROLE_ROOT_PANE; + role_table[ATK_ROLE_ROW_HEADER] = Accessibility_ROLE_ROW_HEADER; + role_table[ATK_ROLE_SCROLL_BAR] = Accessibility_ROLE_SCROLL_BAR; + role_table[ATK_ROLE_SCROLL_PANE] = Accessibility_ROLE_SCROLL_PANE; + role_table[ATK_ROLE_SEPARATOR] = Accessibility_ROLE_SEPARATOR; + role_table[ATK_ROLE_SLIDER] = Accessibility_ROLE_SLIDER; + role_table[ATK_ROLE_SPIN_BUTTON] = Accessibility_ROLE_SPIN_BUTTON; + role_table[ATK_ROLE_SPLIT_PANE] = Accessibility_ROLE_SPLIT_PANE; + role_table[ATK_ROLE_STATUSBAR] = Accessibility_ROLE_STATUS_BAR; + role_table[ATK_ROLE_TABLE] = Accessibility_ROLE_TABLE; + role_table[ATK_ROLE_TABLE_CELL] = Accessibility_ROLE_TABLE_CELL; + role_table[ATK_ROLE_TABLE_COLUMN_HEADER] = + Accessibility_ROLE_TABLE_COLUMN_HEADER; + role_table[ATK_ROLE_TABLE_ROW_HEADER] = Accessibility_ROLE_TABLE_ROW_HEADER; + role_table[ATK_ROLE_TEAR_OFF_MENU_ITEM] = + Accessibility_ROLE_TEAROFF_MENU_ITEM; + role_table[ATK_ROLE_TERMINAL] = Accessibility_ROLE_TERMINAL; + role_table[ATK_ROLE_TEXT] = Accessibility_ROLE_TEXT; + role_table[ATK_ROLE_TOGGLE_BUTTON] = Accessibility_ROLE_TOGGLE_BUTTON; + role_table[ATK_ROLE_TOOL_BAR] = Accessibility_ROLE_TOOL_BAR; + role_table[ATK_ROLE_TOOL_TIP] = Accessibility_ROLE_TOOL_TIP; + role_table[ATK_ROLE_TREE] = Accessibility_ROLE_TREE; + role_table[ATK_ROLE_TREE_TABLE] = Accessibility_ROLE_TREE_TABLE; + role_table[ATK_ROLE_UNKNOWN] = Accessibility_ROLE_UNKNOWN; + role_table[ATK_ROLE_VIEWPORT] = Accessibility_ROLE_VIEWPORT; + role_table[ATK_ROLE_WINDOW] = Accessibility_ROLE_WINDOW; + role_table[ATK_ROLE_HEADER] = Accessibility_ROLE_HEADER; + role_table[ATK_ROLE_FOOTER] = Accessibility_ROLE_FOOTER; + role_table[ATK_ROLE_PARAGRAPH] = Accessibility_ROLE_PARAGRAPH; + role_table[ATK_ROLE_RULER] = Accessibility_ROLE_RULER; + role_table[ATK_ROLE_APPLICATION] = Accessibility_ROLE_APPLICATION; + role_table[ATK_ROLE_AUTOCOMPLETE] = Accessibility_ROLE_AUTOCOMPLETE; + role_table[ATK_ROLE_EDITBAR] = Accessibility_ROLE_EDITBAR; + role_table[ATK_ROLE_EMBEDDED] = Accessibility_ROLE_EMBEDDED; + role_table[ATK_ROLE_ENTRY] = Accessibility_ROLE_ENTRY; + role_table[ATK_ROLE_CHART] = Accessibility_ROLE_CHART; + role_table[ATK_ROLE_CAPTION] = Accessibility_ROLE_CAPTION; + role_table[ATK_ROLE_DOCUMENT_FRAME] = Accessibility_ROLE_DOCUMENT_FRAME; + role_table[ATK_ROLE_HEADING] = Accessibility_ROLE_HEADING; + role_table[ATK_ROLE_PAGE] = Accessibility_ROLE_PAGE; + role_table[ATK_ROLE_SECTION] = Accessibility_ROLE_SECTION; + role_table[ATK_ROLE_FORM] = Accessibility_ROLE_FORM; + role_table[ATK_ROLE_REDUNDANT_OBJECT] = Accessibility_ROLE_REDUNDANT_OBJECT; + role_table[ATK_ROLE_LINK] = Accessibility_ROLE_LINK; + role_table[ATK_ROLE_INPUT_METHOD_WINDOW] = + Accessibility_ROLE_INPUT_METHOD_WINDOW; + return TRUE; +} + +Accessibility_Role +spi_accessible_role_from_atk_role (AtkRole role) +{ + static gboolean is_initialized = FALSE; + static Accessibility_Role spi_role_table[ATK_ROLE_LAST_DEFINED]; + Accessibility_Role spi_role; + + if (!is_initialized) + { + is_initialized = init_role_lookup_table (spi_role_table); + } + + if (role >= 0 && role < ATK_ROLE_LAST_DEFINED) + { + spi_role = spi_role_table[role]; + } + else + { + spi_role = Accessibility_ROLE_EXTENDED; + } + return spi_role; +} + +/*END------------------------------------------------------------------------*/ diff --git a/atk-adaptor/adaptors/tree-adaptor.h b/atk-adaptor/object.h similarity index 54% rename from atk-adaptor/adaptors/tree-adaptor.h rename to atk-adaptor/object.h index 2406448..fb30b04 100644 --- a/atk-adaptor/adaptors/tree-adaptor.h +++ b/atk-adaptor/object.h @@ -2,9 +2,8 @@ * AT-SPI - Assistive Technology Service Provider Interface * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) * - * Copyright 2001, 2002 Sun Microsystems Inc., - * Copyright 2001, 2002 Ximian, Inc. - * Copyright 2008, 2009 Codethink Ltd. + * Copyright 2008 Novell, Inc. + * Copyright 2008, 2009, 2010 Codethink Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -22,14 +21,34 @@ * Boston, MA 02111-1307, USA. */ -#ifndef TREE_ADAPTOR_H -#define TREE_ADAPTOR_H +#ifndef ACCESSIBLE_OBJECT_H +#define ACCESSIBLE_OBJECT_H #include #include -void spi_emit_cache_update (AtkObject * accessible, DBusConnection * bus); +void +spi_object_append_reference (DBusMessageIter * iter, AtkObject * obj); -void spi_emit_cache_removal (guint ref, DBusConnection * bus); +void +spi_object_append_v_reference (DBusMessageIter * iter, AtkObject * obj); -#endif /* TREE_ADAPTOR_H */ +void +spi_object_append_desktop_reference (DBusMessageIter * iter); + +void +spi_object_append_null_reference (DBusMessageIter * iter); + +DBusMessage * +spi_object_return_reference (DBusMessage * msg, AtkObject * obj); + +void +spi_object_append_interfaces (DBusMessageIter * iter, AtkObject * obj); + +void +spi_object_append_attribute_set (DBusMessageIter * iter, AtkAttributeSet * attr); + +Accessibility_Role +spi_accessible_role_from_atk_role (AtkRole role); + +#endif /* ACCESSIBLE_OBJECT_H */ diff --git a/common/spi-dbus.c b/common/spi-dbus.c index f859156..b24a8ee 100644 --- a/common/spi-dbus.c +++ b/common/spi-dbus.c @@ -172,6 +172,43 @@ provide_defaults(const gint type, } } +/* + * Appends all the standard parameters to an AT-SPI event. + */ +void +spi_dbus_signal_new (const char *path, + const char *klass, + const char *major, + const char *minor, + dbus_int32_t detail1, + dbus_int32_t detail2) +{ + DBusMessage *sig; + DBusMessageIter iter, sub; + gchar *cname, *t; + + if (!klass) klass = ""; + if (!major) major = ""; + if (!minor) minor = ""; + + /* + * This is very annoying, but as '-' isn't a legal signal + * name in D-Bus (Why not??!?) The names need converting + * on this side, and again on the client side. + */ + cname = g_strdup(major); + while ((t = strchr(cname, '-')) != NULL) *t = '_'; + + sig = dbus_message_new_signal(path, klass, cname); + g_free(cname); + + dbus_message_iter_init_append(sig, &iter); + + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &minor); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &detail1); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &detail2); +} + void spi_dbus_emit_signal(DBusConnection *bus, const char *path, const char *klass, @@ -222,6 +259,7 @@ spi_dbus_emit_signal(DBusConnection *bus, const char *path, dbus_message_unref(sig); } + /* dbus_bool_t spi_dbus_get_simple_property (DBusConnection *bus, const char *dest, const char *path, const char *interface, const char *prop, int *type, void *ptr, DBusError *error) { diff --git a/common/spi-dbus.h b/common/spi-dbus.h index b6e1283..f82e24c 100644 --- a/common/spi-dbus.h +++ b/common/spi-dbus.h @@ -44,7 +44,7 @@ extern int _dbg; #define SPI_DBUS_INTERFACE_DEC "org.freedesktop.atspi.DeviceEventController" #define SPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER "org.freedesktop.atspi.DeviceEventListener" -#define SPI_DBUS_INTERFACE_TREE "org.freedesktop.atspi.Tree" +#define SPI_DBUS_INTERFACE_CACHE "org.freedesktop.atspi.Cache" #define SPI_DBUS_INTERFACE_ACCESSIBLE "org.freedesktop.atspi.Accessible" #define SPI_DBUS_INTERFACE_ACTION "org.freedesktop.atspi.Action" #define SPI_DBUS_INTERFACE_APPLICATION "org.freedesktop.atspi.Application" diff --git a/common/spi-stateset.c b/common/spi-stateset.c index ff0a53d..2c148f0 100644 --- a/common/spi-stateset.c +++ b/common/spi-stateset.c @@ -154,7 +154,7 @@ spi_atk_state_from_spi_state (Accessibility_StateType state) } AtkStateSet * -spi_state_set_cache_from_sequence (const GArray *seq) +spi_state_set_cache_from_sequence (GArray *seq) { int i; AtkStateSet *set; diff --git a/common/spi-stateset.h b/common/spi-stateset.h index b82466d..f097c92 100644 --- a/common/spi-stateset.h +++ b/common/spi-stateset.h @@ -30,7 +30,7 @@ G_BEGIN_DECLS /* private - internal API to abstract away atk API */ -AtkStateSet *spi_state_set_cache_from_sequence(const GArray *seq); +AtkStateSet *spi_state_set_cache_from_sequence(GArray *seq); AtkState spi_atk_state_from_spi_state (Accessibility_StateType state); void spi_atk_state_to_dbus_array (AtkObject * object, dbus_uint32_t * array); void spi_atk_state_set_to_dbus_array (AtkStateSet *set, dbus_uint32_t * array); diff --git a/configure.ac b/configure.ac index aadf7f5..f16ff7f 100644 --- a/configure.ac +++ b/configure.ac @@ -98,26 +98,23 @@ fi AC_SUBST(EXTRA_SOCKET_LIBS) dnl find sizes & alignments -orig_CPPFLAGS=$CPPFLAGS -CPPFLAGS="$CPPFLAGS $DBUS_CFLAGS" -DBIND_CHECK_ALIGNOF(char) -DBIND_CHECK_ALIGNOF(dbus_bool_t) -DBIND_CHECK_ALIGNOF(dbus_int16_t) -DBIND_CHECK_ALIGNOF(dbus_int32_t) -DBIND_CHECK_ALIGNOF(dbus_int64_t) -DBIND_CHECK_ALIGNOF(double) -DBIND_CHECK_ALIGNOF(dbind_pointer) -DBIND_CHECK_ALIGNOF(dbind_struct) -CPPFLAGS=$orig_CPPFLAGS +#orig_CPPFLAGS=$CPPFLAGS +#CPPFLAGS="$CPPFLAGS $DBUS_CFLAGS" +#DBIND_CHECK_ALIGNOF(char) +#DBIND_CHECK_ALIGNOF(dbus_bool_t) +#DBIND_CHECK_ALIGNOF(dbus_int16_t) +#DBIND_CHECK_ALIGNOF(dbus_int32_t) +#DBIND_CHECK_ALIGNOF(dbus_int64_t) +#DBIND_CHECK_ALIGNOF(double) +#DBIND_CHECK_ALIGNOF(dbind_pointer) +#DBIND_CHECK_ALIGNOF(dbind_struct) +#CPPFLAGS=$orig_CPPFLAGS AC_CONFIG_FILES([Makefile droute/Makefile - dbind/Makefile - dbind/dbind-config.h common/Makefile atk-adaptor/Makefile atk-adaptor/adaptors/Makefile - tests/Makefile ]) AC_OUTPUT diff --git a/droute/droute.c b/droute/droute.c index 55020a7..5ab1478 100644 --- a/droute/droute.c +++ b/droute/droute.c @@ -525,6 +525,8 @@ handle_message (DBusConnection *bus, DBusMessage *message, void *user_data) const gint type = dbus_message_get_type (message); const gchar *pathstr = dbus_message_get_path (message); + _DROUTE_DEBUG ("DRoute (handle message): %s|%s of type %d on %s\n", member, iface, type, pathstr); + /* Check for basic reasons not to handle */ if (type != DBUS_MESSAGE_TYPE_METHOD_CALL || member == NULL ||