X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=atspi%2Fatspi-misc.c;h=7dacde29d5db088fbc6b8b012c22793d67295385;hb=d17bd107e0b8774c280aa8bf7682ec850ed9c439;hp=c52fe9fca674e767e25480b46abb8206f3352030;hpb=e6e8611f117791e42a4eb971fd75840cb654a365;p=platform%2Fupstream%2Fat-spi2-core.git diff --git a/atspi/atspi-misc.c b/atspi/atspi-misc.c index c52fe9f..7dacde2 100644 --- a/atspi/atspi-misc.c +++ b/atspi/atspi-misc.c @@ -110,7 +110,7 @@ _atspi_get_iface_num (const char *iface) GHashTable * _atspi_get_live_refs (void) { - if (!live_refs) + if (!live_refs) { live_refs = g_hash_table_new (g_direct_hash, g_direct_equal); } @@ -124,7 +124,7 @@ _atspi_bus () if (!bus) atspi_init (); if (!bus) - g_error ("AT-SPI: COuldn't connect to accessibility bus. Is at-spi-bus-launcher running?"); + g_error ("AT-SPI: Couldn't connect to accessibility bus. Is at-spi-bus-launcher running?"); return bus; } @@ -136,7 +136,7 @@ static void cleanup () { GHashTable *refs; - GList *l; + gint i; refs = live_refs; live_refs = NULL; @@ -154,14 +154,15 @@ cleanup () if (!desktop) return; - for (l = desktop->children; l;) + + /* TODO: Do we need this code, or should we just dispose the desktop? */ + for (i = desktop->children->len - 1; i >= 0; i--) { - GList *next = l->next; - AtspiAccessible *child = l->data; + AtspiAccessible *child = g_ptr_array_index (desktop->children, i); g_object_run_dispose (G_OBJECT (child->parent.app)); g_object_run_dispose (G_OBJECT (child)); - l = next; } + g_object_run_dispose (G_OBJECT (desktop->parent.app)); g_object_unref (desktop); desktop = NULL; @@ -179,6 +180,7 @@ handle_get_bus_address (DBusPendingCall *pending, void *user_data) DBusMessage *message; const char *address; DBusPendingCall *new_pending; + dbus_bool_t result; if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_METHOD_RETURN) { @@ -197,10 +199,12 @@ handle_get_bus_address (DBusPendingCall *pending, void *user_data) dbus_connection_unref (app->bus); } app->bus = bus; + atspi_dbus_connection_setup_with_g_main(bus, g_main_context_default()); } else { - g_warning ("Unable to open bus connection: %s", error.message); + if (!strcmp (error.name, DBUS_ERROR_FILE_NOT_FOUND)) + g_warning ("AT-SPI: Unable to open bus connection: %s", error.message); dbus_error_free (&error); } } @@ -215,9 +219,11 @@ handle_get_bus_address (DBusPendingCall *pending, void *user_data) "/org/a11y/atspi/cache", atspi_interface_cache, "GetItems"); - dbus_connection_send_with_reply (app->bus, message, &new_pending, 2000); - dbus_pending_call_set_notify (new_pending, handle_get_items, app, NULL); + result = dbus_connection_send_with_reply (app->bus, message, &new_pending, 2000); dbus_message_unref (message); + if (!result || !new_pending) + return; + dbus_pending_call_set_notify (new_pending, handle_get_items, app, NULL); } static AtspiApplication * @@ -227,6 +233,7 @@ get_application (const char *bus_name) char *bus_name_dup; DBusMessage *message; DBusPendingCall *pending = NULL; + dbus_bool_t result; if (!app_hash) { @@ -247,13 +254,18 @@ get_application (const char *bus_name) message = dbus_message_new_method_call (bus_name, atspi_path_root, atspi_interface_application, "GetApplicationBusAddress"); - dbus_connection_send_with_reply (app->bus, message, &pending, 2000); - dbus_pending_call_set_notify (pending, handle_get_bus_address, app, NULL); + result = dbus_connection_send_with_reply (app->bus, message, &pending, 2000); dbus_message_unref (message); + if (!result || !pending) + { + g_hash_table_remove (app_hash, bus_name_dup); + return NULL; + } + dbus_pending_call_set_notify (pending, handle_get_bus_address, app, NULL); return app; } -static AtspiAccessible * +AtspiAccessible * ref_accessible (const char *app_name, const char *path) { AtspiApplication *app; @@ -270,7 +282,7 @@ ref_accessible (const char *app_name, const char *path) { app->root = _atspi_accessible_new (app, atspi_path_root); app->root->accessible_parent = atspi_get_desktop (0); - app->root->accessible_parent->children = g_list_append (app->root->accessible_parent->children, g_object_ref (app->root)); + g_ptr_array_add (app->root->accessible_parent->children, g_object_ref (app->root)); } return g_object_ref (app->root); } @@ -377,17 +389,11 @@ handle_name_owner_changed (DBusConnection *bus, DBusMessage *message, void *user else if (!new[0]) registry_lost = TRUE; } - else + else if (app_hash) { - AtspiAccessible *desktop = atspi_get_desktop (0); - GList *l; - for (l = desktop->children; l; l = l->next) - { - AtspiAccessible *child = l->data; - if (!strcmp (child->parent.app->bus_name, old)) - g_object_run_dispose (G_OBJECT (child->parent.app)); - } - g_object_unref (desktop); + AtspiApplication *app = g_hash_table_lookup (app_hash, old); + if (app && app->bus_name && !strcmp(app->bus_name, name)) + g_object_run_dispose (G_OBJECT (app)); } return DBUS_HANDLER_RESULT_HANDLED; } @@ -422,6 +428,8 @@ add_accessible_from_iter (DBusMessageIter *iter) AtspiAccessible *accessible; const char *name, *description; dbus_uint32_t role; + gboolean children_cached = FALSE; + dbus_int32_t count, index; dbus_message_iter_recurse (iter, &iter_struct); @@ -440,19 +448,40 @@ add_accessible_from_iter (DBusMessageIter *iter) g_object_unref (accessible->accessible_parent); accessible->accessible_parent = ref_accessible (app_name, path); - /* Get children */ - while (accessible->children) + if (dbus_message_iter_get_arg_type (&iter_struct) == 'i') { - g_object_unref (accessible->children->data); - accessible->children = g_list_remove (accessible->children, accessible->children->data); + /* Get index in parent */ + dbus_message_iter_get_basic (&iter_struct, &index); + if (index >= 0 && accessible->accessible_parent) + { + if (index >= accessible->accessible_parent->children->len) + g_ptr_array_set_size (accessible->accessible_parent->children, index + 1); + g_ptr_array_index (accessible->accessible_parent->children, index) = g_object_ref (accessible); + } + + /* get child count */ + dbus_message_iter_next (&iter_struct); + dbus_message_iter_get_basic (&iter_struct, &count); + if (count >= 0) + { + g_ptr_array_set_size (accessible->children, count); + children_cached = TRUE; + } } - dbus_message_iter_recurse (&iter_struct, &iter_array); - while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID) + else if (dbus_message_iter_get_arg_type (&iter_struct) == 'a') { - AtspiAccessible *child; - get_reference_from_iter (&iter_array, &app_name, &path); - child = ref_accessible (app_name, path); - accessible->children = g_list_append (accessible->children, child); + /* It's the old API with a list of children */ + /* TODO: Perhaps remove this code eventually */ + dbus_message_iter_recurse (&iter_struct, &iter_array); + while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID) + { + AtspiAccessible *child; + get_reference_from_iter (&iter_array, &app_name, &path); + child = ref_accessible (app_name, path); + g_ptr_array_remove (accessible->children, child); + g_ptr_array_add (accessible->children, child); + } + children_cached = TRUE; } /* interfaces */ @@ -485,7 +514,8 @@ add_accessible_from_iter (DBusMessageIter *iter) _atspi_accessible_add_cache (accessible, ATSPI_CACHE_NAME | ATSPI_CACHE_ROLE | ATSPI_CACHE_PARENT | ATSPI_CACHE_DESCRIPTION); if (!atspi_state_set_contains (accessible->states, - ATSPI_STATE_MANAGES_DESCENDANTS)) + ATSPI_STATE_MANAGES_DESCENDANTS) && + children_cached) _atspi_accessible_add_cache (accessible, ATSPI_CACHE_CHILDREN); /* This is a bit of a hack since the cache holds a ref, so we don't need @@ -503,9 +533,16 @@ handle_get_items (DBusPendingCall *pending, void *user_data) { const char *sender = dbus_message_get_sender (reply); const char *error = NULL; - dbus_message_get_args (reply, NULL, DBUS_TYPE_STRING, &error, - DBUS_TYPE_INVALID); - g_warning ("AT-SPI: Error in GetItems, sender=%s, error=%s", sender, error); + if (!strcmp (dbus_message_get_error_name (reply), + DBUS_ERROR_SERVICE_UNKNOWN)) + { + } + else + { + dbus_message_get_args (reply, NULL, DBUS_TYPE_STRING, &error, + DBUS_TYPE_INVALID); + g_warning ("AT-SPI: Error in GetItems, sender=%s, error=%s", sender, error); + } dbus_message_unref (reply); dbus_pending_call_unref (pending); return; @@ -572,13 +609,14 @@ ref_accessible_desktop (AtspiApplication *app) get_reference_from_iter (&iter_array, &app_name, &path); add_app_to_desktop (desktop, app_name); } - dbus_message_unref (reply); /* Record the alternate name as an alias for org.a11y.atspi.Registry */ bus_name_dup = g_strdup (dbus_message_get_sender (reply)); if (bus_name_dup) g_hash_table_insert (app_hash, bus_name_dup, app); + dbus_message_unref (reply); + return g_object_ref (desktop); } @@ -636,7 +674,7 @@ _atspi_dbus_return_hyperlink_from_message (DBusMessage *message) DBusMessageIter iter; AtspiHyperlink *retval = NULL; const char *signature; - + if (!message) return NULL; @@ -663,17 +701,19 @@ _atspi_dbus_return_hyperlink_from_iter (DBusMessageIter *iter) return ref_hyperlink (app_name, path); } -const char *cache_signal_type = "((so)(so)(so)a(so)assusau)"; +const char *cache_signal_type = "((so)(so)(so)iiassusau)"; +const char *old_cache_signal_type = "((so)(so)(so)a(so)assusau)"; static DBusHandlerResult handle_add_accessible (DBusConnection *bus, DBusMessage *message, void *user_data) { DBusMessageIter iter; + const char *signature = dbus_message_get_signature (message); - if (strcmp (dbus_message_get_signature (message), cache_signal_type) != 0) + if (strcmp (signature, cache_signal_type) != 0 && + strcmp (signature, old_cache_signal_type) != 0) { - g_warning ("AT-SPI: AddAccessible with unknown signature %s\n", - dbus_message_get_signature (message)); + g_warning ("AT-SPI: AddAccessible with unknown signature %s\n", signature); return DBUS_HANDLER_RESULT_HANDLED; } @@ -849,7 +889,7 @@ spi_display_name (void) * * Connects to the accessibility registry and initializes the SPI. * - * Returns: 0 on success, 1 if already initialized, or an integer error code. + * Returns: 0 on success, 1 if already initialized, or an integer error code. **/ int atspi_init (void) @@ -869,7 +909,8 @@ atspi_init (void) bus = atspi_get_a11y_bus (); if (!bus) return 2; - dbus_bus_register (bus, NULL); + if (!dbus_bus_register (bus, NULL)) + return 2; atspi_dbus_connection_setup_with_g_main(bus, g_main_context_default()); dbus_connection_add_filter (bus, atspi_dbus_filter, NULL, NULL); match = g_strdup_printf ("type='signal',interface='%s',member='AddAccessible'", atspi_interface_cache); @@ -946,7 +987,7 @@ atspi_event_quit (void) /** * atspi_exit: * - * Disconnects from #AtspiRegistry instances and releases + * Disconnects from #AtspiRegistry instances and releases * any floating resources. Call only once at exit. * * Returns: 0 if there were no leaks, otherwise other integer values. @@ -982,7 +1023,6 @@ static GSList *hung_processes; static void remove_hung_process (DBusPendingCall *pending, void *data) { - hung_processes = g_slist_remove (hung_processes, data); g_free (data); dbus_pending_call_unref (pending); @@ -998,6 +1038,7 @@ check_for_hang (DBusMessage *message, DBusError *error, DBusConnection *bus, con DBusMessage *message; gchar *bus_name_dup; DBusPendingCall *pending = NULL; + dbus_bool_t result; for (l = hung_processes; l; l = l->next) if (!strcmp (l->data, bus_name)) return; @@ -1006,9 +1047,9 @@ check_for_hang (DBusMessage *message, DBusError *error, DBusConnection *bus, con "Ping"); if (!message) return; - dbus_connection_send_with_reply (bus, message, &pending, -1); + result = dbus_connection_send_with_reply (bus, message, &pending, -1); dbus_message_unref (message); - if (!pending) + if (!result || !pending) return; bus_name_dup = g_strdup (bus_name); hung_processes = g_slist_append (hung_processes, bus_name_dup); @@ -1105,9 +1146,11 @@ _atspi_dbus_call_partial (gpointer obj, const char *type, ...) { va_list args; - + DBusMessage * result; va_start (args, type); - return _atspi_dbus_call_partial_va (obj, interface, method, error, type, args); + result = _atspi_dbus_call_partial_va (obj, interface, method, error, type, args); + va_end (args); + return result; } @@ -1121,9 +1164,9 @@ _atspi_dbus_call_partial_va (gpointer obj, { AtspiObject *aobj = ATSPI_OBJECT (obj); DBusError err; - DBusMessage *msg = NULL, *reply = NULL; - DBusMessageIter iter; - const char *p; + DBusMessage *msg = NULL, *reply = NULL; + DBusMessageIter iter; + const char *p; dbus_error_init (&err); @@ -1148,11 +1191,13 @@ out: process_deferred_messages (); if (dbus_error_is_set (&err)) { - /* TODO: Set gerror */ + g_set_error_literal(error, ATSPI_ERROR, ATSPI_ERROR_IPC, err.message); dbus_error_free (&err); + if (reply) + dbus_message_unref(reply); + return NULL; } - - if (reply && dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) + else if (reply && dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { const char *err_str = NULL; dbus_message_get_args (reply, NULL, DBUS_TYPE_STRING, &err_str, DBUS_TYPE_INVALID); @@ -1161,7 +1206,6 @@ out: dbus_message_unref (reply); return NULL; } - return reply; } @@ -1221,7 +1265,7 @@ _atspi_dbus_get_property (gpointer obj, const char *interface, const char *name, dbus_message_iter_init (reply, &iter); if (dbus_message_iter_get_arg_type (&iter) != 'v') { - g_warning ("AT-SPI: expected a variant when fetching %s from interface %s; got %s\n", name, interface, dbus_message_get_signature (reply)); + g_warning ("atspi_dbus_get_property: expected a variant when fetching %s from interface %s; got %s\n", name, interface, dbus_message_get_signature (reply)); goto done; } dbus_message_iter_recurse (&iter, &iter_variant); @@ -1359,13 +1403,16 @@ void _atspi_dbus_set_interfaces (AtspiAccessible *accessible, DBusMessageIter *iter) { DBusMessageIter iter_array; + char *iter_sig = dbus_message_iter_get_signature (iter); accessible->interfaces = 0; - if (strcmp (dbus_message_iter_get_signature (iter), "as") != 0) + if (strcmp (iter_sig, "as") != 0) { g_warning ("_atspi_dbus_set_interfaces: Passed iterator with invalid signature %s", dbus_message_iter_get_signature (iter)); + dbus_free (iter_sig); return; } + dbus_free (iter_sig); dbus_message_iter_recurse (iter, &iter_array); while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID) { @@ -1447,7 +1494,7 @@ get_accessibility_bus_address_x11 (void) g_warning ("Could not open X display"); return NULL; } - + AT_SPI_BUS = XInternAtom (bridge_display, "AT_SPI_BUS", False); XGetWindowProperty (bridge_display, XDefaultRootWindow (bridge_display), @@ -1490,12 +1537,12 @@ get_accessibility_bus_address_dbus (void) if (!reply) { - g_warning ("Error retrieving accessibility bus address: %s: %s", + g_warning ("AT-SPI: Error retrieving accessibility bus address: %s: %s", error.name, error.message); dbus_error_free (&error); - return NULL; + goto out; } - + { const char *tmp_address; if (!dbus_message_get_args (reply, @@ -1505,12 +1552,14 @@ get_accessibility_bus_address_dbus (void) DBUS_TYPE_INVALID)) { dbus_message_unref (reply); - return NULL; + goto out; } address = g_strdup (tmp_address); dbus_message_unref (reply); } +out: + dbus_connection_unref (session_bus); return address; } @@ -1535,16 +1584,21 @@ atspi_get_a11y_bus (void) { DBusError error; char *address = NULL; + const char *address_env = NULL; if (a11y_bus && dbus_connection_get_is_connected (a11y_bus)) return a11y_bus; if (a11y_dbus_slot == -1) if (!dbus_connection_allocate_data_slot (&a11y_dbus_slot)) - g_warning ("at-spi: Unable to allocate D-Bus slot"); + g_warning ("AT-SPI: Unable to allocate D-Bus slot"); + address_env = g_getenv ("AT_SPI_BUS_ADDRESS"); + if (address_env != NULL && *address_env != 0) + address = g_strdup (address_env); #ifdef HAVE_X11 - address = get_accessibility_bus_address_x11 (); + if (!address) + address = get_accessibility_bus_address_x11 (); #endif if (!address) address = get_accessibility_bus_address_dbus (); @@ -1557,7 +1611,8 @@ atspi_get_a11y_bus (void) if (!a11y_bus) { - g_warning ("Couldn't connect to accessibility bus: %s", error.message); + if (!g_getenv("SSH_CONNECTION")) + g_warning ("Couldn't connect to accessibility bus: %s", error.message); dbus_error_free (&error); return NULL; } @@ -1573,7 +1628,7 @@ atspi_get_a11y_bus (void) return NULL; } } - + /* Simulate a weak ref on the bus */ dbus_connection_set_data (a11y_bus, a11y_dbus_slot, a11y_bus, a11y_bus_free); @@ -1582,23 +1637,23 @@ atspi_get_a11y_bus (void) /** * atspi_set_timeout: - * @val: The timeout value, in milliseconds, or -1 to disable the timeout. - * @startup_time: The amount of time, in milliseconds, to allow to pass - * before enforcing timeouts on an application. Can be used to prevent - * timeout exceptions if an application is likely to block for an extended - * period of time on initialization. -1 can be passed to disable this - * behavior. + * @val: The timeout value, in milliseconds, or -1 to disable the timeout. + * @startup_time: The amount of time, in milliseconds, to allow to pass + * before enforcing timeouts on an application. Can be used to prevent + * timeout exceptions if an application is likely to block for an extended + * period of time on initialization. -1 can be passed to disable this + * behavior. * - * Set the timeout used for method calls. If this is not set explicitly, - * a default of 0.8 ms is used. - * Note that at-spi2-registryd currently uses a timeout of 3 seconds when - * sending a keyboard event notification. This means that, if an AT makes - * a call in response to the keyboard notification and the application - * being called does not respond before the timeout is reached, - * at-spi2-registryd will time out on the keyboard event notification and - * pass the key onto the application (ie, reply to indicate that the key - * was not consumed), so this may make it undesirable to set a timeout - * larger than 3 seconds. + * Set the timeout used for method calls. If this is not set explicitly, + * a default of 0.8 ms is used. + * Note that at-spi2-registryd currently uses a timeout of 3 seconds when + * sending a keyboard event notification. This means that, if an AT makes + * a call in response to the keyboard notification and the application + * being called does not respond before the timeout is reached, + * at-spi2-registryd will time out on the keyboard event notification and + * pass the key onto the application (ie, reply to indicate that the key + * was not consumed), so this may make it undesirable to set a timeout + * larger than 3 seconds. * * By default, the normal timeout is set to 800 ms, and the application startup * timeout is set to 15 seconds. @@ -1635,6 +1690,17 @@ atspi_set_main_context (GMainContext *cnx) } atspi_main_context = cnx; atspi_dbus_connection_setup_with_g_main (atspi_get_a11y_bus (), cnx); + + if (desktop) + { + gint i; + for (i = desktop->children->len - 1; i >= 0; i--) + { + AtspiAccessible *child = g_ptr_array_index (desktop->children, i); + if (child->parent.app && child->parent.app->bus) + atspi_dbus_connection_setup_with_g_main (child->parent.app->bus, cnx); + } + } } #ifdef DEBUG_REF_COUNTS @@ -1694,13 +1760,15 @@ atspi_role_get_name (AtspiRole role) retval = g_strdup (value->value_nick); } + g_type_class_unref (type_class); + if (retval) return _atspi_name_compat (retval); return NULL; } -void +GHashTable * _atspi_dbus_update_cache_from_dict (AtspiAccessible *accessible, DBusMessageIter *iter) { GHashTable *cache = _atspi_accessible_ref_cache (accessible); @@ -1721,22 +1789,30 @@ _atspi_dbus_update_cache_from_dict (AtspiAccessible *accessible, DBusMessageIter } else if (!strcmp (key, "Attributes")) { + char *iter_sig = dbus_message_iter_get_signature (&iter_variant); 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) + if (strcmp (iter_sig, "a{ss}") != 0) + { + dbus_free (iter_sig); break; + } + dbus_free (iter_sig); 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; + char *iter_sig = dbus_message_iter_get_signature (&iter_variant); val = g_new0 (GValue, 1);; g_value_init (val, ATSPI_TYPE_RECT); - if (strcmp (dbus_message_iter_get_signature (&iter_variant), - "(iiii)") != 0) + if (strcmp (iter_sig, "(iiii)") != 0) + { + dbus_free (iter_sig); break; + } + dbus_free (iter_sig); dbus_message_iter_recurse (&iter_variant, &iter_struct); dbus_message_iter_get_basic (&iter_struct, &d_int); extents.x = d_int; @@ -1752,9 +1828,11 @@ _atspi_dbus_update_cache_from_dict (AtspiAccessible *accessible, DBusMessageIter g_value_set_boxed (val, &extents); } if (val) - g_hash_table_insert (cache, g_strdup (key), val); + g_hash_table_insert (cache, g_strdup (key), val); dbus_message_iter_next (&iter_dict); } + + return cache; } gboolean