*/
#include "atspi-private.h"
+#include <string.h>
G_DEFINE_TYPE (AtspiAccessible, atspi_accessible, G_TYPE_OBJECT)
object_class->finalize = atspi_accessible_finalize;
}
+
/* TODO: Generate following from spec? */
static const char *role_names [] =
{
atspi_accessible_get_name (AtspiAccessible *obj, GError **error)
{
g_return_val_if_fail (obj != NULL, NULL);
- if (!obj->cached_properties & ATSPI_CACHE_NAME)
+ if (!(obj->cached_properties & ATSPI_CACHE_NAME))
{
- if (!_atspi_dbus_call (obj, atspi_interface_accessible, "GetName", NULL, "=>s", &obj->name))
+ if (!_atspi_dbus_get_property (obj, atspi_interface_accessible, "Name", NULL, "s", &obj->name))
return NULL;
obj->cached_properties |= ATSPI_CACHE_NAME;
}
{
g_return_val_if_fail (obj != NULL, NULL);
- if (!obj->cached_properties & ATSPI_CACHE_DESCRIPTION)
+ if (!(obj->cached_properties & ATSPI_CACHE_DESCRIPTION))
{
if (!_atspi_dbus_call (obj, atspi_interface_accessible, "GetDescription", NULL, "=>s", &obj->description))
return NULL;
return g_strdup (obj->description);
}
+const char *str_parent = "Parent";
+
/**
* atspi_accessible_get_parent:
* @obj: a pointer to the #AtspiAccessible object to query.
{
g_return_val_if_fail (obj != NULL, NULL);
+ if (!(obj->cached_properties & ATSPI_CACHE_PARENT))
+ {
+ DBusMessage *message, *reply;
+ DBusMessageIter iter, iter_variant;
+ message = dbus_message_new_method_call (obj->app->bus_name, obj->path,
+ DBUS_INTERFACE_PROPERTIES, "Get");
+ if (!message)
+ return NULL;
+ dbus_message_append_args (message, DBUS_TYPE_STRING, &atspi_interface_accessible,
+ DBUS_TYPE_STRING, &str_parent,
+ DBUS_TYPE_INVALID);
+ reply = _atspi_dbus_send_with_reply_and_block (message);
+ if (!reply ||
+ (strcmp (dbus_message_get_signature (reply), "v") != 0))
+ return NULL;
+ dbus_message_iter_init (reply, &iter);
+ dbus_message_iter_recurse (&iter, &iter_variant);
+ obj->accessible_parent = _atspi_dbus_return_accessible_from_iter (&iter_variant);
+ dbus_message_unref (reply);
+ obj->cached_properties |= ATSPI_CACHE_PARENT;
+ }
+ if (!obj->accessible_parent)
+ return NULL;
return g_object_ref (obj->accessible_parent);
}
{
g_return_val_if_fail (obj != NULL, ATSPI_ROLE_INVALID);
- if (!obj->cached_properties & ATSPI_CACHE_ROLE)
+ if (!(obj->cached_properties & ATSPI_CACHE_ROLE))
{
dbus_uint32_t role;
+ /* TODO: Make this a property */
if (_atspi_dbus_call (obj, atspi_interface_accessible, "GetRole", NULL, "=>u", &role))
{
obj->cached_properties |= ATSPI_CACHE_ROLE;
AtspiAccessible *
atspi_accessible_get_host_application (AtspiAccessible *obj, GError **error)
{
- while (obj->accessible_parent && atspi_accessible_get_role (obj->accessible_parent, NULL) != ATSPI_ROLE_DESKTOP_FRAME)
- obj = obj->accessible_parent;
- return g_object_ref (obj);
+ AtspiAccessible *parent;
+
+ for (;;)
+ {
+ parent = atspi_accessible_get_parent (obj, NULL);
+ if (!parent || parent == obj ||
+ atspi_accessible_get_role (parent, NULL) == ATSPI_ROLE_DESKTOP_FRAME)
+ return obj;
+ obj = parent;
+ }
}
#if 0 // TODO: interfaces */
AtspiEvent e;
/* TODO: Only fire if object not already marked defunct */
+ memset (&e, 0, sizeof (e));
e.type = "object:state-change:defunct";
e.source = accessible;
e.detail1 = 1;
e.detail2 = 0;
- g_value_unset (&e.any);
_atspi_send_event (&e);
g_free (accessible->path);
struct _AtspiAccessible
{
GObject parent;
- gint ref_count;
AtspiAccessible *accessible_parent;
GList *children;
AtspiApplication *app;
char *path;
- gint role : 8;
- gint interfaces : 24;
+ AtspiRole role;
+ gint interfaces;
char *name;
char *description;
AtspiStateSet *states;
{
AtspiAccessible *child;
- if (!G_VALUE_HOLDS (&event->any, ATSPI_TYPE_ACCESSIBLE) ||
+ if (!G_VALUE_HOLDS (&event->any_data, ATSPI_TYPE_ACCESSIBLE) ||
!event->source->children ||
atspi_state_set_contains (event->source->states, ATSPI_STATE_MANAGES_DESCENDANTS))
return;
- child = g_value_get_object (&event->any);
+ child = g_value_get_object (&event->any_data);
if (!strncmp (event->type, "object:children-changed:add", 27))
{
{
if (event->source->accessible_parent)
g_object_unref (event->source->accessible_parent);
- if (G_VALUE_HOLDS (&event->any, ATSPI_TYPE_ACCESSIBLE))
+ if (G_VALUE_HOLDS (&event->any_data, ATSPI_TYPE_ACCESSIBLE))
{
- event->source->accessible_parent = g_value_dup_object (&event->any);
+ event->source->accessible_parent = g_value_dup_object (&event->any_data);
event->source->cached_properties |= ATSPI_CACHE_PARENT;
}
else
{
if (event->source->name)
g_free (event->source->name);
- if (G_VALUE_HOLDS_STRING (&event->any))
+ if (G_VALUE_HOLDS_STRING (&event->any_data))
{
- event->source->name = g_value_dup_string (&event->any);
+ event->source->name = g_value_dup_string (&event->any_data);
event->source->cached_properties |= ATSPI_CACHE_NAME;
}
else
{
if (event->source->description)
g_free (event->source->description);
- if (G_VALUE_HOLDS_STRING (&event->any))
+ if (G_VALUE_HOLDS_STRING (&event->any_data))
{
- event->source->description = g_value_dup_string (&event->any);
+ event->source->description = g_value_dup_string (&event->any_data);
event->source->cached_properties |= ATSPI_CACHE_DESCRIPTION;
}
else
char *category, *name, *detail;
GList *l;
+ /* Ensure that the value is set to avoid a Python exception */
+ /* TODO: Figure out how to do this without using a private field */
+ if (e->any_data.g_type == 0)
+ g_value_set_int (&e->any_data, 0);
+
if (!convert_event_type_to_dbus (e->type, &category, &name, &detail, NULL))
{
g_warning ("Atspi: Couldn't parse event: %s\n", e->type);
AtspiRect rect;
if (demarshal_rect (&iter_variant, &rect))
{
- g_value_init (&e.any, ATSPI_TYPE_RECT);
- g_value_set_boxed (&e.any, &rect);
+ g_value_init (&e.any_data, ATSPI_TYPE_RECT);
+ g_value_set_boxed (&e.any_data, &rect);
}
else
{
AtspiAccessible *accessible;
accessible = _atspi_dbus_return_accessible_from_iter (&iter_variant);
- g_value_init (&e.any, ATSPI_TYPE_ACCESSIBLE);
- g_value_set_instance (&e.any, accessible);
+ g_value_init (&e.any_data, ATSPI_TYPE_ACCESSIBLE);
+ g_value_set_instance (&e.any_data, accessible);
}
break;
}
case DBUS_TYPE_STRING:
{
dbus_message_iter_get_basic (&iter_variant, &p);
- g_value_set_string (&e.any, p);
+ g_value_set_string (&e.any_data, p);
break;
}
default:
g_free (name);
g_free (detail);
g_object_unref (e.source);
- g_value_unset (&e.any);
+ g_value_unset (&e.any_data);
return DBUS_HANDLER_RESULT_HANDLED;
}
dst->type = g_strdup (src->type);
dst->detail1 = src->detail1;
dst->detail2 = src->detail2;
- g_value_copy (&dst->any, &src->any);
+ g_value_copy (&dst->any_data, &src->any_data);
}
static void
{
g_object_unref (event->source);
g_free (event->type);
- g_value_unset (&event->any);
+ g_value_unset (&event->any_data);
g_free (event);
}
AtspiAccessible *source;
gint detail1;
gint detail2;
- GValue any;
+ GValue any_data;
};
/**
#include "atspi-private.h"
#include "X11/Xlib.h"
#include <stdio.h>
+#include <string.h>
static DBusConnection *bus = NULL;
static GHashTable *apps = NULL;
app = _atspi_application_new (bus_name);
if (!app) return NULL;
app->bus_name = bus_name_dup;
- if (APP_IS_REGISTRY (app))
- {
- app->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
- }
- else
- {
- app->hash = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, g_object_unref);
- }
+ app->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
g_hash_table_insert (app_hash, bus_name_dup, app);
return app;
}
AtspiApplication *app = get_application (app_name);
AtspiAccessible *a;
+ if (!strcmp (path, ATSPI_DBUS_PATH_NULL))
+ return NULL;
+
if (!strcmp (path, "/org/a11y/atspi/accessible/root"))
{
if (!app->root)
a = g_hash_table_lookup (app->hash, path);
if (a)
{
- g_object_ref (a);
- return a;
+ return g_object_ref (a);
}
a = atspi_accessible_new (app, path);
if (!a)
dbus_message_iter_get_basic (&iter_struct, &path);
app = get_application (sender);
a = ref_accessible (sender, path);
+ if (!a)
+ return DBUS_HANDLER_RESULT_HANDLED;
if (a->accessible_parent && g_list_find (a->accessible_parent->children, a))
{
a->accessible_parent->children = g_list_remove (a->accessible_parent->children, a);
{
AtspiEvent e;
+ memset (&e, 0, sizeof (e));
e.type = (add? "object:children-changed:add": "object:children-changed:remove");
e.source = parent;
e.detail1 = g_list_index (parent->children, child);
e.detail2 = 0;
- g_value_unset (&e.any);
_atspi_send_event (&e);
}
/* get accessible */
get_reference_from_iter (&iter_struct, &app_name, &path);
accessible = ref_accessible (app_name, path);
+ if (!accessible)
+ return;
/* Get application: TODO */
dbus_message_iter_next (&iter_struct);
/* TODO: Write this function; allow reentrancy */
reply = dbus_connection_send_with_reply_and_block (_atspi_bus(), message, 1000, &err);
dbus_message_unref (message);
+ if (err.message)
+ g_warning ("Atspi: Got error: %s\n", err.message);
return reply;
}
#include "config.h"
#include "dbind/dbind.h"
+static int dbind_timeout = -1;
+
/*
* FIXME: compare types - to ensure they match &
* do dynamic padding of structures etc.
/*---------------------------------------------------------------------------*/
+typedef struct _SpiReentrantCallClosure
+{
+ GMainLoop *loop;
+ DBusMessage *reply;
+} SpiReentrantCallClosure;
+
static void
-set_reply (DBusPendingCall *pending, void *user_data)
+set_reply (DBusPendingCall * pending, void *user_data)
{
- void **replyptr = (void **)user_data;
+ SpiReentrantCallClosure* closure = (SpiReentrantCallClosure *) user_data;
- *replyptr = dbus_pending_call_steal_reply (pending);
+ closure->reply = dbus_pending_call_steal_reply (pending);
+ g_main_loop_quit (closure->loop);
}
DBusMessage *
-dbind_send_and_allow_reentry (DBusConnection *bus, DBusMessage *message, DBusError *error)
+dbind_send_and_allow_reentry (DBusConnection * bus, DBusMessage * message, DBusError *error)
{
- DBusPendingCall *pending;
- DBusMessage *reply = NULL;
+ DBusPendingCall *pending;
+ SpiReentrantCallClosure closure;
+
+ if (strcmp (dbus_message_get_destination (message),
+ dbus_bus_get_unique_name (bus)) != 0)
+ return dbus_connection_send_with_reply_and_block (bus, message, dbind_timeout, error);
- if (!dbus_connection_send_with_reply (bus, message, &pending, -1))
+ if (!dbus_connection_send_with_reply (bus, message, &pending, dbind_timeout))
+ return NULL;
+ dbus_pending_call_set_notify (pending, set_reply, (void *) &closure, NULL);
+ closure.loop = g_main_loop_new (NULL, FALSE);
+ dbus_connection_setup_with_g_main(bus, NULL);
+
+ if (1)
{
- return NULL;
+ g_main_loop_run (closure.loop);
}
- dbus_pending_call_set_notify (pending, set_reply, (void *)&reply, NULL);
- while (!reply)
+ else
{
- if (!dbus_connection_read_write_dispatch (bus, -1)) return NULL;
+ closure.reply = NULL;
+ while (!closure.reply)
+ {
+ if (!dbus_connection_read_write_dispatch (bus, dbind_timeout))
+ return NULL;
+ }
}
- return reply;
+
+ g_main_loop_unref (closure.loop);
+ return closure.reply;
}
dbus_bool_t
return success;
}
+void
+dbind_set_timeout (int timeout)
+{
+ dbind_timeout = timeout;
+}
+
/*END------------------------------------------------------------------------*/
const char *arg_types,
...);
+void dbind_set_timeout (int timeout);
#endif /* _DBIND_H_ */