From f9a2201ea0fc9f703a3d20efaf99f18b4b2b2652 Mon Sep 17 00:00:00 2001 From: Mike Gorse Date: Fri, 20 Sep 2013 12:05:05 -0500 Subject: [PATCH] Cache interfaces and extents sent from events Events may now send a list of properties to avoid the need to call out to get information that could be delivered up-front with the event. This will improve performance slightly and is particularly useful in cases where the AT-SPI client may need to respond to non-AT-SPI queries from other processes, creating the possibility of a deadlock. This change is sufficient to allow gnome-shell's focus caret tracker to process state-changed:focused events without needing to make D-Bus method calls. https://bugzilla.gnome.org/show_bug.cgi?id=708387 --- atspi/Makefile.am | 1 + atspi/atspi-accessible-private.h | 40 ++++++++++++++++++++++++++++++++++ atspi/atspi-accessible.c | 7 +++++- atspi/atspi-accessible.h | 3 +++ atspi/atspi-component.c | 6 ++++++ atspi/atspi-event-listener.c | 46 +++++++++++++++++++++++++++++++++++++++- atspi/atspi-misc.c | 5 +++++ 7 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 atspi/atspi-accessible-private.h diff --git a/atspi/Makefile.am b/atspi/Makefile.am index 2cb21da..bd5b279 100644 --- a/atspi/Makefile.am +++ b/atspi/Makefile.am @@ -54,6 +54,7 @@ libatspi_la_SOURCES = \ atspi.h \ atspi-accessible.c \ atspi-accessible.h \ + atspi-accessible-private.h \ atspi-action.c \ atspi-action.h \ atspi-application.c \ diff --git a/atspi/atspi-accessible-private.h b/atspi/atspi-accessible-private.h new file mode 100644 index 0000000..3e8499b --- /dev/null +++ b/atspi/atspi-accessible-private.h @@ -0,0 +1,40 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2002 Ximian, Inc. + * 2002 Sun Microsystems Inc. + * Copyright 2010, 2011 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. + */ + +#ifndef _ATSPI_ACCESSIBLE_PRIVATE_H_ +#define _ATSPI_ACCESSIBLE_PRIVATE_H_ + +G_BEGIN_DECLS + +#include "atspi-accessible.h" + +struct _AtspiAccessiblePrivate +{ + AtspiRect extents; +}; + +G_END_DECLS + +#endif /* _ATSPI_ACCESSIBLE_H_ */ diff --git a/atspi/atspi-accessible.c b/atspi/atspi-accessible.c index 95ac311..dfd60db 100644 --- a/atspi/atspi-accessible.c +++ b/atspi/atspi-accessible.c @@ -23,6 +23,7 @@ */ #include "atspi-private.h" +#include "atspi-accessible-private.h" #include static gboolean enable_caching = FALSE; @@ -84,6 +85,7 @@ atspi_value_interface_init (AtspiValue *value) } G_DEFINE_TYPE_WITH_CODE (AtspiAccessible, atspi_accessible, ATSPI_TYPE_OBJECT, + G_ADD_PRIVATE (AtspiAccessible) G_IMPLEMENT_INTERFACE (ATSPI_TYPE_ACTION, atspi_action_interface_init) G_IMPLEMENT_INTERFACE (ATSPI_TYPE_COLLECTION, atspi_collection_interface_init) G_IMPLEMENT_INTERFACE (ATSPI_TYPE_COMPONENT, atspi_component_interface_init) @@ -108,6 +110,8 @@ atspi_accessible_init (AtspiAccessible *accessible) g_hash_table_insert (_atspi_get_live_refs (), accessible, NULL); g_print("at-spi: init: %d objects\n", accessible_count); #endif + + accessible->priv = atspi_accessible_get_instance_private (accessible); } static void @@ -1667,7 +1671,8 @@ _atspi_accessible_test_cache (AtspiAccessible *accessible, AtspiCache flag) AtspiCache result = accessible->cached_properties & mask & flag; if (accessible->states && atspi_state_set_contains (accessible->states, ATSPI_STATE_TRANSIENT)) return FALSE; - return (result != 0 && (atspi_main_loop || enable_caching) && + return (result != 0 && (atspi_main_loop || enable_caching || + flag == ATSPI_CACHE_INTERFACES) && !atspi_no_cache); } diff --git a/atspi/atspi-accessible.h b/atspi/atspi-accessible.h index 0358950..32439ec 100644 --- a/atspi/atspi-accessible.h +++ b/atspi/atspi-accessible.h @@ -43,6 +43,8 @@ G_BEGIN_DECLS #define ATSPI_IS_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ATSPI_TYPE_ACCESSIBLE)) #define ATSPI_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ATSPI_TYPE_ACCESSIBLE, AtspiAccessibleClass)) +typedef struct _AtspiAccessiblePrivate AtspiAccessiblePrivate; + struct _AtspiAccessible { AtspiObject parent; @@ -55,6 +57,7 @@ struct _AtspiAccessible AtspiStateSet *states; GHashTable *attributes; guint cached_properties; + AtspiAccessiblePrivate *priv; }; typedef struct _AtspiAccessibleClass AtspiAccessibleClass; diff --git a/atspi/atspi-component.c b/atspi/atspi-component.c index 24d74d4..9f695da 100644 --- a/atspi/atspi-component.c +++ b/atspi/atspi-component.c @@ -28,6 +28,7 @@ */ #include "atspi-private.h" +#include "atspi-accessible-private.h" void atspi_rect_free (AtspiRect *rect) @@ -136,10 +137,15 @@ atspi_component_get_extents (AtspiComponent *obj, { dbus_uint32_t d_ctype = ctype; AtspiRect bbox; + AtspiAccessible *accessible; bbox.x = bbox.y = bbox.width = bbox.height = -1; g_return_val_if_fail (obj != NULL, atspi_rect_copy (&bbox)); + accessible = ATSPI_ACCESSIBLE (obj); + if (accessible->priv->extents.width > 0) + return atspi_rect_copy (&accessible->priv->extents); + _atspi_dbus_call (obj, atspi_interface_component, "GetExtents", error, "u=>(iiii)", d_ctype, &bbox); return atspi_rect_copy (&bbox); } diff --git a/atspi/atspi-event-listener.c b/atspi/atspi-event-listener.c index 1291d11..64ecfaa 100644 --- a/atspi/atspi-event-listener.c +++ b/atspi/atspi-event-listener.c @@ -23,6 +23,7 @@ */ #include "atspi-private.h" +#include "atspi-accessible-private.h" #include #include @@ -872,7 +873,8 @@ _atspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data) dbus_int32_t detail1, detail2; char *p; - if (strcmp (signature, "siiv(so)") != 0) + if (strcmp (signature, "siiv(so)") != 0 && + strcmp (signature, "siiva{sv}") != 0) { g_warning ("Got invalid signature %s for signal %s from interface %s\n", signature, member, category); return DBUS_HANDLER_RESULT_HANDLED; @@ -958,6 +960,47 @@ _atspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data) break; } + dbus_message_iter_next (&iter); + if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY) + { + /* new form -- parse properties sent with event */ + DBusMessageIter iter_dict, iter_dict_entry, iter_struct; + dbus_message_iter_recurse (&iter, &iter_dict); + while (dbus_message_iter_get_arg_type (&iter_dict) != DBUS_TYPE_INVALID) + { + const char *key; + dbus_message_iter_recurse (&iter_dict, &iter_dict_entry); + dbus_message_iter_get_basic (&iter_dict_entry, &key); + dbus_message_iter_next (&iter_dict_entry); + dbus_message_iter_recurse (&iter_dict_entry, &iter_variant); + if (!strcmp (key, "interfaces")) + { + _atspi_dbus_set_interfaces (e.source, &iter_variant); + } + else if (!strcmp (key, "extents")) + { + dbus_int32_t val; + if (strcmp (dbus_message_iter_get_signature (&iter_variant), + "(iiii)") != 0) + break; + dbus_message_iter_recurse (&iter_variant, &iter_struct); + dbus_message_iter_get_basic (&iter_struct, &val); + e.source->priv->extents.x = val; + dbus_message_iter_next (&iter_struct); + dbus_message_iter_get_basic (&iter_struct, &val); + e.source->priv->extents.y = val; + dbus_message_iter_next (&iter_struct); + dbus_message_iter_get_basic (&iter_struct, &val); + e.source->priv->extents.width = val; + dbus_message_iter_next (&iter_struct); + dbus_message_iter_get_basic (&iter_struct, &val); + e.source->priv->extents.height = val; + dbus_message_iter_next (&iter_struct); + } + dbus_message_iter_next (&iter_dict); + } + } + if (!strncmp (e.type, "object:children-changed", 23)) { cache_process_children_changed (&e); @@ -978,6 +1021,7 @@ _atspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data) _atspi_send_event (&e); + memset (&e.source->priv->extents, 0, sizeof (AtspiRect)); g_free (converted_type); g_free (name); g_free (detail); diff --git a/atspi/atspi-misc.c b/atspi/atspi-misc.c index 11c4d0f..d91f6e9 100644 --- a/atspi/atspi-misc.c +++ b/atspi/atspi-misc.c @@ -1404,6 +1404,11 @@ _atspi_dbus_set_interfaces (AtspiAccessible *accessible, DBusMessageIter *iter) DBusMessageIter iter_array; accessible->interfaces = 0; + if (strcmp (dbus_message_iter_get_signature (iter), "as") != 0) + { + g_warning ("_atspi_dbus_set_interfaces: Passed iterator with invalid signature %s", dbus_message_iter_get_signature (iter)); + return; + } dbus_message_iter_recurse (iter, &iter_array); while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID) { -- 1.8.1.4