[at-spi2-core] Allow caching of data sent with events and requesting such data
- From: Mike Gorse <mgorse src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [at-spi2-core] Allow caching of data sent with events and requesting such data
- Date: Mon, 3 Feb 2014 23:50:11 +0000 (UTC)
commit 6395af932862454ed292d3623c18c59218ecbe7e
Author: Mike Gorse <mgorse suse com>
Date: Sat Feb 1 17:39:34 2014 -0600
Allow caching of data sent with events and requesting such data
Add atspi_event_listener_register_full, to request that particular data
be sent with an event, and cache the data for the duration of the event
callback.
This also extends the D-Bus protocol, adding an a{sv} to an event to send
this data along, but we will still read events without this array added for
backwards compatibility (and compatibilllity with QT-AT-SPI, which does not
send this data for now).
https://bugzilla.gnome.org/show_bug.cgi?id=708695
atspi/Makefile.am | 1 +
atspi/atspi-accessible.c | 66 ++++++++++++++++++++++++----
atspi/atspi-accessible.h | 3 +
atspi/atspi-component.c | 12 +++++
atspi/atspi-event-listener.c | 98 ++++++++++++++++++++++++++++++++++++-----
atspi/atspi-event-listener.h | 14 ++++++
atspi/atspi-matchrule.c | 6 +--
atspi/atspi-misc-private.h | 11 ++++-
atspi/atspi-misc.c | 97 +++++++++++++++++++++++++++++++++++++++++
atspi/atspi-private.h | 1 +
registryd/registry.c | 47 ++++++++++++++++----
11 files changed, 321 insertions(+), 35 deletions(-)
---
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.c b/atspi/atspi-accessible.c
index b06a36c..bc0ad4d 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 <string.h>
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
@@ -592,6 +596,13 @@ atspi_accessible_get_attributes (AtspiAccessible *obj, GError **error)
g_return_val_if_fail (obj != NULL, NULL);
+ if (obj->priv->cache)
+ {
+ GValue *val = g_hash_table_lookup (obj->priv->cache, "Attributes");
+ if (val)
+ return g_value_dup_boxed (val);
+ }
+
if (!_atspi_accessible_test_cache (obj, ATSPI_CACHE_ATTRIBUTES))
{
message = _atspi_dbus_call_partial (obj, atspi_interface_accessible,
@@ -632,15 +643,16 @@ atspi_accessible_get_attributes_as_array (AtspiAccessible *obj, GError **error)
g_return_val_if_fail (obj != NULL, NULL);
- if (_atspi_accessible_get_cache_mask (obj) & ATSPI_CACHE_ATTRIBUTES)
+ if (obj->priv->cache)
{
- GArray *array = g_array_new (TRUE, TRUE, sizeof (gchar *));
- GHashTable *attributes = atspi_accessible_get_attributes (obj, error);
- if (!attributes)
- return NULL;
- g_hash_table_foreach (attributes, add_to_attribute_array, &array);
- g_hash_table_unref (attributes);
- return array;
+ GValue *val = g_hash_table_lookup (obj->priv->cache, "Attributes");
+ if (val)
+ {
+ GArray *array = g_array_new (TRUE, TRUE, sizeof (gchar *));
+ GHashTable *attributes = g_value_get_boxed (val);
+ g_hash_table_foreach (attributes, add_to_attribute_array, &array);
+ return array;
+ }
}
message = _atspi_dbus_call_partial (obj, atspi_interface_accessible, "GetAttributes", error, "");
@@ -1671,7 +1683,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);
}
@@ -1714,3 +1727,38 @@ atspi_accessible_get_object_locale (AtspiAccessible *accessible, GError **error)
}
return locale;
}
+
+void
+free_value (gpointer data)
+{
+ GValue *value = data;
+
+ g_value_unset (value);
+ g_free (value);
+}
+
+GHashTable *
+_atspi_accessible_ref_cache (AtspiAccessible *accessible)
+{
+ AtspiAccessiblePrivate *priv = accessible->priv;
+
+ priv->cache_ref_count++;
+ if (priv->cache)
+ return g_hash_table_ref (priv->cache);
+ priv->cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+ free_value);
+ return priv->cache;
+}
+
+void
+_atspi_accessible_unref_cache (AtspiAccessible *accessible)
+{
+ AtspiAccessiblePrivate *priv = accessible->priv;
+
+ if (priv->cache)
+ {
+ g_hash_table_unref (priv->cache);
+ if (--priv->cache_ref_count == 0)
+ priv->cache = NULL;
+ }
+}
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 9cdd896..31761cf 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,21 @@ 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->cache && ctype == ATSPI_COORD_TYPE_SCREEN)
+ {
+ GValue *val = g_hash_table_lookup (accessible->priv->cache, "Component.ScreenExtents");
+ if (val)
+ {
+ return g_value_dup_boxed (val);
+ }
+ }
+
_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 a7a2336..3e6e73a 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 <string.h>
#include <ctype.h>
@@ -35,6 +36,7 @@ typedef struct
char *category;
char *name;
char *detail;
+ GArray *properties;
} EventListenerEntry;
G_DEFINE_TYPE (AtspiEventListener, atspi_event_listener, G_TYPE_OBJECT)
@@ -513,22 +515,49 @@ atspi_event_listener_register (AtspiEventListener *listener,
event_type, error);
}
+/**
+ * atspi_event_listener_register_full:
+ * @listener: The #AtspiEventListener to register against an event type.
+ * @event_type: a character string indicating the type of events for which
+ * notification is requested. See #atspi_event_listener_register
+ * for a description of the format and legal event types.
+* @properties: (element-type gchar*) (transfer none) (allow-none): a list of
+ * properties that should be sent along with the event. The
+ * properties are valued for the duration of the event callback.k
+ * TODO: Document.
+ *
+ * Adds an in-process callback function to an existing #AtspiEventListener.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+gboolean
+atspi_event_listener_register_full (AtspiEventListener *listener,
+ const gchar *event_type,
+ GArray *properties,
+ GError **error)
+{
+ /* TODO: Keep track of which events have been registered, so that we
+ * deregister all of them when the event listener is destroyed */
+
+ return atspi_event_listener_register_from_callback_full (listener->callback,
+ listener->user_data,
+ listener->cb_destroyed,
+ event_type,
+ properties,
+ error);
+}
+
static gboolean
notify_event_registered (EventListenerEntry *e)
{
- DBusMessage *message, *reply;
- message = dbus_message_new_method_call (atspi_bus_registry,
- atspi_path_registry,
- atspi_interface_registry,
- "RegisterEvent");
- if (!message)
- return FALSE;
- dbus_message_append_args (message, DBUS_TYPE_STRING, &e->event_type, DBUS_TYPE_INVALID);
- reply = _atspi_dbus_send_with_reply_and_block (message, NULL);
+ dbind_method_call_reentrant (_atspi_bus (), atspi_bus_registry,
+ atspi_path_registry,
+ atspi_interface_registry,
+ "RegisterEvent",
+ NULL, "sas", e->event_type,
+ e->properties);
- if (reply)
- dbus_message_unref (reply);
return TRUE;
}
@@ -554,6 +583,38 @@ atspi_event_listener_register_from_callback (AtspiEventListenerCB callback,
const gchar *event_type,
GError **error)
{
+ return atspi_event_listener_register_from_callback_full (callback,
+ user_data,
+ callback_destroyed,
+ event_type, NULL,
+ error);
+}
+
+static GArray *
+copy_event_properties (GArray *src)
+{
+ gint i;
+
+ GArray *dst = g_array_new (FALSE, FALSE, sizeof (char *));
+
+ if (!src)
+ return dst;
+ for (i = 0; i < src->len; i++)
+ {
+ gchar *dup = g_strdup (g_array_index (src, char *, i));
+ g_array_append_val (dst, dup);
+ }
+ return dst;
+}
+
+gboolean
+atspi_event_listener_register_from_callback_full (AtspiEventListenerCB callback,
+ void *user_data,
+ GDestroyNotify callback_destroyed,
+ const gchar *event_type,
+ GArray *properties,
+ GError **error)
+{
EventListenerEntry *e;
DBusError d_error;
GPtrArray *matchrule_array;
@@ -582,6 +643,7 @@ atspi_event_listener_register_from_callback (AtspiEventListenerCB callback,
g_free (e);
return FALSE;
}
+ e->properties = copy_event_properties (properties);
event_listeners = g_list_prepend (event_listeners, e);
for (i = 0; i < matchrule_array->len; i++)
{
@@ -871,8 +933,10 @@ _atspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data)
AtspiEvent e;
dbus_int32_t detail1, detail2;
char *p;
+ GHashTable *cache = NULL;
- 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 +1022,13 @@ _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 */
+ _atspi_dbus_update_cache_from_dict (e.source, &iter);
+ }
+
if (!strncmp (e.type, "object:children-changed", 23))
{
cache_process_children_changed (&e);
@@ -978,6 +1049,9 @@ _atspi_dbus_handle_event (DBusConnection *bus, DBusMessage *message, void *data)
_atspi_send_event (&e);
+ if (cache)
+ _atspi_accessible_unref_cache (e.source);
+
g_free (converted_type);
g_free (name);
g_free (detail);
diff --git a/atspi/atspi-event-listener.h b/atspi/atspi-event-listener.h
index 12d3c58..ee52fac 100644
--- a/atspi/atspi-event-listener.h
+++ b/atspi/atspi-event-listener.h
@@ -93,6 +93,12 @@ atspi_event_listener_register (AtspiEventListener *listener,
GError **error);
gboolean
+atspi_event_listener_register_full (AtspiEventListener *listener,
+ const gchar *event_type,
+ GArray *properties,
+ GError **error);
+
+gboolean
atspi_event_listener_register_from_callback (AtspiEventListenerCB callback,
void *user_data,
GDestroyNotify callback_destroyed,
@@ -100,6 +106,14 @@ atspi_event_listener_register_from_callback (AtspiEventListenerCB callback,
GError **error);
gboolean
+atspi_event_listener_register_from_callback_full (AtspiEventListenerCB callback,
+ void *user_data,
+ GDestroyNotify callback_destroyed,
+ const gchar *event_type,
+ GArray *properties,
+ GError **error);
+
+gboolean
atspi_event_listener_register_no_data (AtspiEventListenerSimpleCB callback,
GDestroyNotify callback_destroyed,
const gchar *event_type,
diff --git a/atspi/atspi-matchrule.c b/atspi/atspi-matchrule.c
index 1a17cf3..8abeb13 100644
--- a/atspi/atspi-matchrule.c
+++ b/atspi/atspi-matchrule.c
@@ -122,9 +122,6 @@ atspi_match_rule_new (AtspiStateSet *states,
AtspiMatchRule *rule = g_object_new (ATSPI_TYPE_MATCH_RULE, NULL);
int i;
- if (!rule)
- return NULL;
-
if (states)
rule->states = g_object_ref (states);
rule->statematchtype = statematchtype;
@@ -219,7 +216,8 @@ _atspi_match_rule_marshal (AtspiMatchRule *rule, DBusMessageIter *iter)
if (!dbus_message_iter_open_container (&iter_struct, DBUS_TYPE_ARRAY, "{ss}",
&iter_dict))
return FALSE;
- g_hash_table_foreach (rule->attributes, append_entry, &iter_dict);
+ if (rule->attributes)
+ g_hash_table_foreach (rule->attributes, append_entry, &iter_dict);
dbus_message_iter_close_container (&iter_struct, &iter_dict);
dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_INT32, &d_attributematchtype);
diff --git a/atspi/atspi-misc-private.h b/atspi/atspi-misc-private.h
index ec6cef1..4e2df7b 100644
--- a/atspi/atspi-misc-private.h
+++ b/atspi/atspi-misc-private.h
@@ -147,7 +147,8 @@ GQuark _atspi_error_quark (void);
typedef enum
{
ATSPI_ERROR_APPLICATION_GONE,
- ATSPI_ERROR_IPC
+ ATSPI_ERROR_IPC,
+ ATSPI_ERROR_SYNC_NOT_ALLOWED,
} AtspiError;
extern GMainLoop *atspi_main_loop;
@@ -156,6 +157,14 @@ extern gboolean atspi_no_cache;
GHashTable *_atspi_get_live_refs ();
gchar *_atspi_name_compat (gchar *in);
+
+void _atspi_dbus_update_cache_from_dict (AtspiAccessible *accessible, DBusMessageIter *iter);
+
+gboolean _atspi_get_allow_sync ();
+
+gboolean _atspi_set_allow_sync (gboolean val);
+
+void _atspi_set_error_no_sync (GError **error);
G_END_DECLS
#endif /* _ATSPI_MISC_PRIVATE_H_ */
diff --git a/atspi/atspi-misc.c b/atspi/atspi-misc.c
index 2da473c..28de86f 100644
--- a/atspi/atspi-misc.c
+++ b/atspi/atspi-misc.c
@@ -42,6 +42,7 @@ static DBusConnection *bus = NULL;
static GHashTable *live_refs = NULL;
static gint method_call_timeout = 800;
static gint app_startup_time = 15000;
+static gboolean allow_sync = TRUE;
GMainLoop *atspi_main_loop;
GMainContext *atspi_main_context;
@@ -1071,6 +1072,12 @@ _atspi_dbus_call (gpointer obj, const char *interface, const char *method, GErro
if (!check_app (aobj->app, error))
return FALSE;
+ if (!allow_sync)
+ {
+ _atspi_set_error_no_sync (error);
+ return FALSE;
+ }
+
va_start (args, type);
dbus_error_init (&err);
set_timeout (aobj->app);
@@ -1172,6 +1179,12 @@ _atspi_dbus_get_property (gpointer obj, const char *interface, const char *name,
if (!check_app (aobj->app, error))
return FALSE;
+ if (!allow_sync)
+ {
+ _atspi_set_error_no_sync (error);
+ return FALSE;
+ }
+
message = dbus_message_new_method_call (aobj->app->bus_name,
aobj->path,
"org.freedesktop.DBus.Properties",
@@ -1346,6 +1359,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)
{
@@ -1679,3 +1697,82 @@ atspi_role_get_name (AtspiRole role)
return NULL;
}
+
+void
+_atspi_dbus_update_cache_from_dict (AtspiAccessible *accessible, DBusMessageIter *iter)
+{
+ GHashTable *cache = _atspi_accessible_ref_cache (accessible);
+ DBusMessageIter iter_dict, iter_dict_entry, iter_struct, iter_variant;
+
+ dbus_message_iter_recurse (iter, &iter_dict);
+ while (dbus_message_iter_get_arg_type (&iter_dict) != DBUS_TYPE_INVALID)
+ {
+ const char *key;
+ GValue *val = NULL;
+ 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 (accessible, &iter_variant);
+ }
+ else if (!strcmp (key, "Attributes"))
+ {
+ val = g_new0 (GValue, 1);;
+ g_value_init (val, G_TYPE_HASH_TABLE);
+ if (strcmp (dbus_message_iter_get_signature (&iter_variant),
+ "a{ss}") != 0)
+ break;
+ g_value_take_boxed (val, _atspi_dbus_hash_from_iter (&iter_variant));
+ }
+ else if (!strcmp (key, "Component.ScreenExtents"))
+ {
+ dbus_int32_t d_int;
+ AtspiRect extents;
+ val = g_new0 (GValue, 1);;
+ g_value_init (val, ATSPI_TYPE_RECT);
+ 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, &d_int);
+ extents.x = d_int;
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &d_int);
+ extents.y = d_int;
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &d_int);
+ extents.width = d_int;
+ dbus_message_iter_next (&iter_struct);
+ dbus_message_iter_get_basic (&iter_struct, &d_int);
+ extents.height = d_int;
+ g_value_set_boxed (val, &extents);
+ }
+ if (val)
+ g_hash_table_insert (cache, g_strdup (key), val);
+ dbus_message_iter_next (&iter_dict);
+ }
+}
+
+gboolean
+_atspi_get_allow_sync ()
+{
+ return allow_sync;
+}
+
+gboolean
+_atspi_set_allow_sync (gboolean val)
+{
+ gboolean ret = allow_sync;
+
+ allow_sync = val;
+ return ret;
+}
+
+void
+_atspi_set_error_no_sync (GError **error)
+{
+ g_set_error_literal (error, ATSPI_ERROR, ATSPI_ERROR_SYNC_NOT_ALLOWED,
+ _("Attempted synchronous call where prohibited"));
+}
diff --git a/atspi/atspi-private.h b/atspi/atspi-private.h
index b3f5682..2cf5693 100644
--- a/atspi/atspi-private.h
+++ b/atspi/atspi-private.h
@@ -34,6 +34,7 @@
#include "glib/gi18n.h"
#include "atspi.h"
+#include "atspi-accessible-private.h"
G_BEGIN_DECLS
void _atspi_reregister_device_listeners ();
diff --git a/registryd/registry.c b/registryd/registry.c
index 8448bb2..6f37a96 100644
--- a/registryd/registry.c
+++ b/registryd/registry.c
@@ -35,6 +35,7 @@ struct event_data
{
gchar *bus_name;
gchar **data;
+ GSList *properties;
};
static void
@@ -244,6 +245,7 @@ remove_events (SpiRegistry *registry, const char *bus_name, const char *event)
{
g_strfreev (evdata->data);
g_free (evdata->bus_name);
+ g_slist_free_full (evdata->properties, g_free);
g_free (evdata);
registry->events = g_list_remove (registry->events, evdata);
}
@@ -832,19 +834,34 @@ impl_register_event (DBusConnection *bus, DBusMessage *message, void *user_data)
gchar **data;
DBusMessage *signal;
const char *sender = dbus_message_get_sender (message);
+ DBusMessageIter iter, iter_array;
+ const char *signature = dbus_message_get_signature (message);
- if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &orig_name,
- DBUS_TYPE_INVALID))
+ if (strcmp (signature, "sas") != 0)
+ {
+ g_warning ("got RegisterEvent with invalid signature '%s'", signature);
return NULL;
+ }
+ dbus_message_iter_init (message, &iter);
+ dbus_message_iter_get_basic (&iter, &orig_name);
+ dbus_message_iter_next (&iter);
+ dbus_message_iter_recurse (&iter, &iter_array);
name = ensure_proper_format (orig_name);
- evdata = (event_data *) g_malloc (sizeof (*evdata));
- if (!evdata)
- return NULL;
+ evdata = g_new0 (event_data, 1);
data = g_strsplit (name, ":", 3);
evdata->bus_name = g_strdup (sender);
evdata->data = data;
+
+ while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
+ {
+ const char *property;
+ dbus_message_iter_get_basic (&iter_array, &property);
+ evdata->properties = g_slist_append (evdata->properties,
+ g_strdup (property));
+ dbus_message_iter_next (&iter_array);
+ }
registry->events = g_list_append (registry->events, evdata);
if (needs_mouse_poll (evdata->data))
@@ -855,10 +872,22 @@ impl_register_event (DBusConnection *bus, DBusMessage *message, void *user_data)
signal = dbus_message_new_signal (SPI_DBUS_PATH_REGISTRY,
SPI_DBUS_INTERFACE_REGISTRY,
"EventListenerRegistered");
- dbus_message_append_args (signal, DBUS_TYPE_STRING, &sender,
- DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID);
- dbus_connection_send (bus, signal, NULL);
- dbus_message_unref (signal);
+ if (signal)
+ {
+ GSList *ls = evdata->properties;
+ dbus_message_iter_init_append (signal, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &sender);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &name);
+ dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &iter_array);
+ while (ls)
+ {
+ dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &ls->data);
+ ls = g_slist_next (ls);
+ }
+ dbus_message_iter_close_container (&iter, &iter_array);
+ dbus_connection_send (bus, signal, NULL);
+ dbus_message_unref (signal);
+ }
g_free (name);
return dbus_message_new_method_return (message);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]