X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=cspi%2Fspi-main.c;h=26687522d6d6fc322837dc7f9ce7ad9ca1c808f4;hb=38b14df983445e90257e6c5bfae8baf18f31da51;hp=1bf7753854c0bf4cab9883a19ee153277b96d223;hpb=dbf73f62ecd7647b628314761b44ed64adb7f9d9;p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git diff --git a/cspi/spi-main.c b/cspi/spi-main.c index 1bf7753..2668752 100644 --- a/cspi/spi-main.c +++ b/cspi/spi-main.c @@ -293,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; @@ -327,12 +327,61 @@ typedef struct 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) { @@ -341,71 +390,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; - 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); + 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 @@ -415,7 +426,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/freedesktop/atspi/tree", spi_interface_tree, "getRoot", &error, "=>o", &root_path)) { Accessible *obj = cspi_ref_accessible (bus_name, root_path); if (obj) @@ -507,7 +518,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); } @@ -522,7 +533,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(ooaoassusau)", &additions); + dbind_method_call_reentrant (bus, app_name, "/org/freedesktop/atspi/tree", spi_interface_tree, "getTree", &error, "=>a(ooaoassusau)", &additions); if (error.message) { g_warning ("getTree (%s): %s", app_name, error.message); @@ -552,35 +563,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(ooaoassusau)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 @@ -641,9 +645,13 @@ 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_tree (bus, message, data); + return cspi_dbus_handle_update_accessible (bus, message, data); + } + if (dbus_message_is_signal (message, spi_interface_tree, "removeAccessible")) + { + return cspi_dbus_handle_remove_accessible (bus, message, data); } if (dbus_message_is_method_call (message, spi_interface_registry, "registerApplication")) { @@ -703,7 +711,11 @@ 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',member='removeAccessible'", spi_interface_tree); dbus_error_init (&error); dbus_bus_add_match (bus, match, &error); g_free (match); @@ -1039,7 +1051,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))