X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=cspi%2Fspi-main.c;h=0cbb6bda2c8749d2828532c4ddc7357d39361eb2;hb=b6a9e880c09f13a391a2a23b0dd685a518fe61a1;hp=4b0dd93a77694852b273c404079d701b9bf1835b;hpb=7aa7c6c299666bc09207ff218672c4f09b44738c;p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git diff --git a/cspi/spi-main.c b/cspi/spi-main.c index 4b0dd93..0cbb6bd 100644 --- a/cspi/spi-main.c +++ b/cspi/spi-main.c @@ -93,15 +93,16 @@ static const char *interfaces[] = SPI_DBUS_INTERFACE_ACCESSIBLE, SPI_DBUS_INTERFACE_ACTION, SPI_DBUS_INTERFACE_APPLICATION, + SPI_DBUS_INTERFACE_COLLECTION, SPI_DBUS_INTERFACE_COMPONENT, SPI_DBUS_INTERFACE_DOCUMENT, SPI_DBUS_INTERFACE_EDITABLE_TEXT, SPI_DBUS_INTERFACE_HYPERLINK, SPI_DBUS_INTERFACE_HYPERTEXT, SPI_DBUS_INTERFACE_IMAGE, - "org.freedesktop.atspi.LoginHelper", + "org.a11y.atspi.LoginHelper", SPI_DBUS_INTERFACE_SELECTION, - "org.freedesktop.atspi.Selector", + "org.a11y.atspi.Selector", SPI_DBUS_INTERFACE_TABLE, SPI_DBUS_INTERFACE_TEXT, SPI_DBUS_INTERFACE_VALUE, @@ -218,6 +219,10 @@ cspi_object_unref_internal (Accessible *accessible, gboolean defunct) { g_free (accessible->v.path); } + if (accessible->states) + spi_state_set_cache_unref (accessible->states); + g_free (accessible->description); + g_free (accessible->name); g_free(accessible); } } @@ -253,7 +258,7 @@ ref_accessible (CSpiApplication *app, const char *path) int id; guint *id_val; - if (sscanf (path, "/org/freedesktop/atspi/accessible/%d", &id) != 1) + if (sscanf (path, "/org/a11y/atspi/accessible/%d", &id) != 1) { return NULL; } @@ -288,7 +293,7 @@ cspi_get_application (const char *bus_name) if (!app_hash) { app_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_hash_table_unref); - if (!app_hash) return; + if (!app_hash) return NULL; } app = g_hash_table_lookup (app_hash, bus_name); if (app) return app; @@ -296,7 +301,11 @@ cspi_get_application (const char *bus_name) if (!bus_name_dup) return NULL; // TODO: change below to something that will send state-change:defunct notification if necessary */ app = g_new (CSpiApplication, 1); - if (!app) return NULL; + if (!app) + { + g_free (bus_name_dup); + return NULL; + } app->bus_name = bus_name_dup; if (APP_IS_REGISTRY (app)) { @@ -319,14 +328,64 @@ typedef struct char *name; dbus_uint32_t role; char *description; + GArray *state_bitflags; } CACHE_ADDITION; +static void +handle_addition (CSpiApplication*app, CACHE_ADDITION *ca) +{ + gint i; + GList *new_list; + + Accessible *a = ref_accessible (app, ca->path); + /* Note: children don't hold refs for their parents or vice versa */ + a->parent = ref_accessible (app, ca->parent); + if (a->parent) cspi_object_unref (a->parent); + if (a->children) + { + g_list_free (a->children); + a->children = NULL; + } + for (i = 0; i < ca->children->len; i++) + { + const char *child_path = g_array_index (ca->children, const char *, i); + Accessible *child = ref_accessible (app, child_path); + new_list = g_list_append (a->children, child); + if (new_list) a->children = new_list; + cspi_object_unref (child); + } + a->interfaces = 0; + for (i = 0; i < ca->interfaces->len; i++) + { + const char *iface = g_array_index (ca->interfaces, const char *, i); + if (!strcmp (iface, "org.freedesktop.DBus.Introspectable")) continue; + gint n = get_iface_num (iface); + if (n == -1) + { + g_warning ("Unknown interface %s", iface); + } + else a->interfaces |= (1 << n); + g_free (iface); + } + if (a->name) g_free (a->name); + a->name = ca->name; + a->role = ca->role; + if (a->description) g_free (a->description); + a->description = ca->description; + a->states = spi_state_set_cache_new (ca->state_bitflags); + g_array_free (ca->interfaces, TRUE); + g_array_free (ca->children, TRUE); + /* spi_state_set_cache_new frees state_bitflags */ + /* This is a bit of a hack since ref_accessible sets ref_count to 2 + * for a new object, one of the refs being for the cache */ + cspi_object_unref (a); +} + /* Update the cache with added/modified objects and free the array */ static void handle_additions (CSpiApplication*app, GArray *additions) { - gint i, j; - GList *l, *new_list; + gint i; if (!additions) { @@ -335,69 +394,33 @@ handle_additions (CSpiApplication*app, GArray *additions) for (i = 0; i < additions->len; i++) { CACHE_ADDITION *ca = &g_array_index (additions, CACHE_ADDITION, i); - Accessible *a = ref_accessible (app, ca->path); - /* Note: children don't hold refs for their parents or vice versa */ - a->parent = ref_accessible (app, ca->parent); - if (a->parent) cspi_object_unref (a->parent); - if (a->children) - { - g_list_free (a->children); - a->children = NULL; - } - for (j = 0; j < ca->children->len; j++) - { - const char *child_path = g_array_index (ca->children, const char *, j); - Accessible *child = ref_accessible (app, child_path); - new_list = g_list_append (a->children, child); - if (new_list) a->children = new_list; - cspi_object_unref (child); - } - a->interfaces = 0; - for (j = 0; j < ca->interfaces->len; j++) - { - const char *iface = g_array_index (ca->interfaces, const char *, j); - if (!strcmp (iface, "org.freedesktop.DBus.Introspectable")) continue; - gint n = get_iface_num (iface); - if (n == -1) - { - g_warning ("Unknown interface %s", iface); - } - else a->interfaces |= (1 << n); - g_free (iface); - } - if (a->name) g_free (a->name); - a->name = ca->name; - a->role = ca->role; - if (a->description) g_free (a->description); - a->description = ca->description; - g_array_free (ca->interfaces, TRUE); - g_array_free (ca->children, TRUE); - /* This is a bit of a hack since ref_accessible sets ref_count to 2 - * for a new object, one of the refs being for the cache */ - cspi_object_unref (a); + handle_addition (app, ca); } - g_array_free (additions, TRUE); } -static void -handle_removals (CSpiApplication *app, GArray *removals) +static DBusHandlerResult +cspi_dbus_handle_remove_accessible (DBusConnection *bus, DBusMessage *message, void *user_data) { - gint j; + const char *sender = dbus_message_get_sender (message); + CSpiApplication *app = cspi_get_application (sender); + const char *path; + Accessible *a; - if (!removals) return; - for (j = 0; j < removals->len; j++) + if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID)) { - const char *path = g_array_index (removals, const char *, j); - Accessible *a = ref_accessible (app, path); - if (a->parent && g_list_find (a->parent->children, a)) - { - a->parent->children = g_list_remove (a->parent->children, a); - /* Note: children don't hold refs for their parents or vice versa */ - } - g_hash_table_remove (app->hash, &a->v.id); - cspi_object_unref_internal (a, TRUE); /* unref our own ref */ + g_warning ("Received RemoveAccessible with invalid arguments"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + a = ref_accessible (app, path); + if (a->parent && g_list_find (a->parent->children, a)) + { + a->parent->children = g_list_remove (a->parent->children, a); + // TODO: Send children-changed:remove event + /* Note: children don't hold refs for their parents or vice versa */ } - g_array_free (removals, TRUE); + g_hash_table_remove (app->hash, &a->v.id); + cspi_object_unref_internal (a, TRUE); /* unref our own ref */ + return DBUS_HANDLER_RESULT_HANDLED; } static gboolean @@ -407,7 +430,7 @@ add_app_to_desktop (Accessible *a, const char *bus_name) char *root_path; dbus_error_init (&error); - if (dbind_connection_method_call (bus, bus_name, "/org/freedesktop/atspi/tree", spi_interface_tree, "getRoot", &error, "=>o", &root_path)) + if (dbind_method_call_reentrant (bus, bus_name, "/org/a11y/atspi/tree", spi_interface_tree, "getRoot", &error, "=>o", &root_path)) { Accessible *obj = cspi_ref_accessible (bus_name, root_path); if (obj) @@ -499,7 +522,7 @@ ref_accessible_desktop (CSpiApplication *app) desktop->ref_count = 2; /* one for the caller, one for the hash */ desktop->name = g_strdup (""); dbus_error_init (&error); - if (!dbind_connection_method_call (bus, spi_bus_registry, spi_path_registry, spi_interface_registry, "getApplications", &error, "=>as", &apps)) + if (!dbind_method_call_reentrant (bus, spi_bus_registry, spi_path_registry, spi_interface_registry, "getApplications", &error, "=>as", &apps)) { g_error ("Couldn't get application list: %s", error.message); } @@ -514,7 +537,7 @@ ref_accessible_desktop (CSpiApplication *app) CSpiApplication *app = cspi_get_application (app_name); additions = NULL; dbus_error_init (&error); - dbind_connection_method_call (bus, app_name, "/org/freedesktop/atspi/tree", spi_interface_tree, "getTree", &error, "=>a(ooaoassus)", &additions); + dbind_method_call_reentrant (bus, app_name, "/org/a11y/atspi/tree", spi_interface_tree, "getTree", &error, "=>a(ooaoassusau)", &additions); if (error.message) { g_warning ("getTree (%s): %s", app_name, error.message); @@ -544,35 +567,28 @@ cspi_ref_related_accessible (Accessible *obj, const char *path) return ref_accessible (obj->app, path); } -typedef struct -{ - GArray *additions; - GArray *removals; -} CacheSignalData; - -static const char *cacheSignalType = "a(ooaoassus)ao"; +static const char *cacheSignalType = "(ooaoassusau)"; static DBusHandlerResult -cspi_dbus_handle_update_tree (DBusConnection *bus, DBusMessage *message, void *user_data) +cspi_dbus_handle_update_accessible (DBusConnection *bus, DBusMessage *message, void *user_data) { DBusMessageIter iter; - CacheSignalData cd; - void *p = &cd; + CACHE_ADDITION ca; + void *p = &ca; const char *sender = dbus_message_get_sender (message); CSpiApplication *app = cspi_get_application (sender); const char *type = cacheSignalType; if (!app) { - g_warning ("UpdateTree from unknown app. Should we add it?", sender); - return; + g_warning ("UpdateAccessible from unknown app. Should we add it?", sender); + return DBUS_HANDLER_RESULT_HANDLED; } dbus_message_iter_init (message, &iter); // TODO: Check signature dbind_any_demarshal (&iter, &type, &p); /* additions */ - dbind_any_demarshal (&iter, &type, &p); /* removals */ - handle_additions (app, cd.additions); - handle_removals (app, cd.removals); + handle_addition (app, &ca); + return DBUS_HANDLER_RESULT_HANDLED; } static DBusHandlerResult @@ -625,7 +641,7 @@ cspi_dbus_filter (DBusConnection *bus, DBusMessage *message, void *data) char *bus_name; if (type == DBUS_MESSAGE_TYPE_SIGNAL && - !strcmp (interface, SPI_DBUS_INTERFACE_ACCESSIBLE)) + !strncmp (interface, "org.a11y.atspi.Event.", 28)) { return cspi_dbus_handle_event (bus, message, data); } @@ -633,21 +649,36 @@ cspi_dbus_filter (DBusConnection *bus, DBusMessage *message, void *data) { return cspi_dbus_handle_deviceEvent (bus, message, data); } - if (dbus_message_is_signal (message, spi_interface_tree, "updateTree")) + if (dbus_message_is_signal (message, spi_interface_tree, "updateAccessible")) + { + return cspi_dbus_handle_update_accessible (bus, message, data); + } + if (dbus_message_is_signal (message, spi_interface_tree, "removeAccessible")) { - return cspi_dbus_handle_update_tree (bus, message, data); + return cspi_dbus_handle_remove_accessible (bus, message, data); } - if (dbus_message_is_signal (message, spi_interface_tree, "registerApplication")) + if (dbus_message_is_method_call (message, spi_interface_registry, "registerApplication")) { return cspi_dbus_handle_register_application (bus, message, data); } - if (dbus_message_is_signal (message, spi_interface_registry, "deregisterApplication")) + if (dbus_message_is_method_call (message, spi_interface_registry, "deregisterApplication")) { return cspi_dbus_handle_deregister_application (bus, message, data); } return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } +static const char *signal_interfaces[] = +{ + "org.a11y.atspi.Event.Object", + "org.a11y.atspi.Event.Window", + "org.a11y.atspi.Event.Mouse", + "org.a11y.atspi.Event.Terminal", + "org.a11y.atspi.Event.Document", + "org.a11y.atspi.Event.Focus", + NULL +}; + /** * SPI_init: * @@ -660,6 +691,7 @@ SPI_init (void) { DBusError error; char *match; + int i; if (SPI_inited) { @@ -683,13 +715,23 @@ SPI_init (void) dbus_bus_register (bus, &error); dbus_connection_setup_with_g_main(bus, g_main_context_default()); dbus_connection_add_filter (bus, cspi_dbus_filter, NULL, NULL); - match = g_strdup_printf ("type='signal',interface='%s',member='updateTree'", spi_interface_tree); + match = g_strdup_printf ("type='signal',interface='%s',member='updateAccessible'", spi_interface_tree); dbus_error_init (&error); dbus_bus_add_match (bus, match, &error); g_free (match); - match = g_strdup_printf ("type='signal',interface='%s'", spi_interface_tree); + match = g_strdup_printf ("type='signal',interface='%s',member='removeAccessible'", spi_interface_tree); + dbus_error_init (&error); dbus_bus_add_match (bus, match, &error); g_free (match); + match = g_strdup_printf ("type='method_call',interface='%s'", spi_interface_registry); + dbus_bus_add_match (bus, match, &error); + g_free (match); + for (i = 0; signal_interfaces[i]; i++) + { + match = g_strdup_printf ("type='signal',interface='%s'", signal_interfaces[i]); + dbus_bus_add_match (bus, match, &error); + g_free (match); + } return 0; } @@ -999,7 +1041,7 @@ get_path (Accessible *obj) { return g_strdup_printf (SPI_DBUS_PATH_REGISTRY); } - return g_strdup_printf ("/org/freedesktop/atspi/accessible/%d", obj->v.id); + return g_strdup_printf ("/org/a11y/atspi/accessible/%d", obj->v.id); } dbus_bool_t @@ -1013,7 +1055,7 @@ cspi_dbus_call (Accessible *obj, const char *interface, const char *method, DBus if (!error) error = &err; dbus_error_init (error); va_start (args, type); - retval = dbind_connection_method_call_va (SPI_bus(), obj->app->bus_name, path, interface, method, error, type, args); + retval = dbind_method_call_reentrant_va (SPI_bus(), obj->app->bus_name, path, interface, method, error, type, args); va_end (args); g_free (path); if (dbus_error_is_set (error))