From ca3ab5aea45e50202be4547f090d737e72fe6f6b Mon Sep 17 00:00:00 2001 From: Shinwoo Kim Date: Wed, 1 Dec 2021 17:36:19 +0900 Subject: [PATCH] [Tizen] Provide GetActiveWindow interface If there are two AT clients, AT server does not send 'activate' signal for the second AT client. Because AT server send the 'activate' signal when the 'IsEnabled' status was set to be TRUE. AT client is able to search the 'activate' window using the desktop and its children - applications, but some times it is very slow. Probably.. It is caused by 'throttle' feature of EFL application. We need to keep the 'activate' window information for the second client. The at-spi2-registryd will keep the 'activate' window information. The AT client gets the information using atspi_get_activate_window. Change-Id: Ia5f22465b10a46411768866f245aa8309b2cc013 --- atspi/atspi-registry.c | 47 ++++++++++++++++++ atspi/atspi-registry.h | 4 ++ registryd/registry-main.c | 13 +++++ registryd/registry.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++ registryd/registry.h | 14 ++++++ 5 files changed, 202 insertions(+) diff --git a/atspi/atspi-registry.c b/atspi/atspi-registry.c index 2bb4d08..e9a47e5 100644 --- a/atspi/atspi-registry.c +++ b/atspi/atspi-registry.c @@ -98,6 +98,53 @@ atspi_get_desktop_list () return array; } + +//TIZEN_ONLY(20211206) Provide GetActiveWindow +/** + * atspi_get_active_window: + * + * Gets recently activated window. + * NOTE: the Tizen only interface for multiple AT-clients + * + * Returns: (transfer full): a pointer to active window's + * #AtspiAccessible representation. + **/ +AtspiAccessible* +atspi_get_active_window () +{ + DBusMessage *message, *reply; + DBusMessageIter iter; + AtspiAccessible* active_window; + + message = dbus_message_new_method_call (ATSPI_DBUS_NAME_REGISTRY, + ATSPI_DBUS_PATH_ROOT, + ATSPI_DBUS_INTERFACE_SOCKET, + "GetActiveWindow"); + if (!message) + return NULL; + + reply = _atspi_dbus_send_with_reply_and_block (message, NULL); + if (!reply) + return NULL; + + if (strcmp (dbus_message_get_signature (reply), "(so)") != 0) + { + dbus_message_unref (reply); + return NULL; + } + + dbus_message_iter_init (reply, &iter); + active_window = _atspi_dbus_return_accessible_from_iter (&iter); + + dbus_message_unref (reply); + + if (!active_window) + return NULL; + + return g_object_ref (active_window); +} +// + static gboolean notify_keystroke_listener (DeviceListenerEntry *e) { diff --git a/atspi/atspi-registry.h b/atspi/atspi-registry.h index 43150c2..b266c7b 100644 --- a/atspi/atspi-registry.h +++ b/atspi/atspi-registry.h @@ -39,6 +39,10 @@ AtspiAccessible* atspi_get_desktop (gint i); GArray *atspi_get_desktop_list (); +//TIZEN_ONLY(20211206) Provide GetActiveWindow +AtspiAccessible* atspi_get_active_window (); +// + gboolean atspi_register_keystroke_listener (AtspiDeviceListener *listener, GArray *key_set, diff --git a/registryd/registry-main.c b/registryd/registry-main.c index be01d2c..c137182 100644 --- a/registryd/registry-main.c +++ b/registryd/registry-main.c @@ -259,6 +259,19 @@ main (int argc, char **argv) g_main_loop_run (mainloop); + //TIZEN_ONLY(20211206) Provide GetActiveWindow + if (registry->active_window_name) + { + g_free (registry->active_window_name); + registry->active_window_name = NULL; + } + if (registry->active_window_path) + { + g_free (registry->active_window_path); + registry->active_window_path = NULL; + } + // + dbus_connection_close (bus); dbus_connection_unref (bus); g_object_unref (dec); diff --git a/registryd/registry.c b/registryd/registry.c index aa867ca..fa2d3a5 100644 --- a/registryd/registry.c +++ b/registryd/registry.c @@ -303,6 +303,63 @@ handle_disconnection (DBusConnection *bus, DBusMessage *message, void *user_data } } +//TIZEN_ONLY(20211206) Provide GetActiveWindow +static void +handle_activate_window (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + SpiRegistry *reg = SPI_REGISTRY (user_data); + + const char *sender = dbus_message_get_sender (message); + const char *path = dbus_message_get_path (message); + + if (!sender || !path) + return; + + char *detail = NULL; + dbus_int32_t detail1; + DBusMessageIter iter; + dbus_message_iter_init (message, &iter); + dbus_message_iter_get_basic (&iter, &detail); + dbus_message_iter_next (&iter); + dbus_message_iter_get_basic (&iter, &detail1); + + if (detail1 & ACCESSIBLE_WINDOW_ACTIVATE_INFO_KEYBOARD) + return; + + if (reg->active_window_name) + g_free (reg->active_window_name); + if (reg->active_window_path) + g_free (reg->active_window_path); + + reg->active_window_name = g_strdup(sender); + reg->active_window_path = g_strdup(path); +} + +static void +handle_deactivate_window (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + SpiRegistry *reg = SPI_REGISTRY (user_data); + + if (!reg->active_window_name || !reg->active_window_path) + return; + + const char *sender = dbus_message_get_sender (message); + const char *path = dbus_message_get_path (message); + + if (!sender || !path) + return; + + if (!g_strcmp0(reg->active_window_name, sender) && + !g_strcmp0(reg->active_window_path, path)) + { + g_free (reg->active_window_name); + g_free (reg->active_window_path); + reg->active_window_name = NULL; + reg->active_window_path = NULL; + } +} +// + /* * Converts names of the form "active-descendant-changed" to *" ActiveDescendantChanged" @@ -352,6 +409,15 @@ signal_filter (DBusConnection *bus, DBusMessage *message, void *user_data) if (!g_strcmp0(iface, DBUS_INTERFACE_DBUS) && !g_strcmp0(member, "NameOwnerChanged")) handle_disconnection (bus, message, user_data); + //TIZEN_ONLY(20211206) Provide GetActiveWindow + else if (!g_strcmp0(iface, "org.a11y.atspi.Event.Window")) + { + if (!g_strcmp0(member, "Activate")) + handle_activate_window (bus, message, user_data); + else if (!g_strcmp0(member, "Deactivate")) + handle_deactivate_window (bus, message, user_data); + } + // else res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -831,6 +897,27 @@ impl_GetInterfaces (DBusConnection * bus, return reply; } +//TIZEN_ONLY(20211206) Provide GetActiveWindow +static DBusMessage * +impl_GetActiveWindow (DBusConnection * bus, + DBusMessage * message, void *user_data) +{ + SpiRegistry *reg = SPI_REGISTRY (user_data); + DBusMessage *reply; + DBusMessageIter iter; + + reply = dbus_message_new_method_return (message); + dbus_message_iter_init_append (reply, &iter); + + if (!reg->active_window_name || !reg->active_window_path) + append_reference (&iter, SPI_DBUS_NAME_REGISTRY, SPI_DBUS_PATH_NULL); + else + append_reference (&iter, reg->active_window_name, reg->active_window_path); + + return reply; +} +// + static DBusMessage * impl_GetItems (DBusConnection * bus, DBusMessage * message, void *user_data) { @@ -957,6 +1044,24 @@ impl_get_registered_events (DBusConnection *bus, DBusMessage *message, void *use dbus_message_iter_init_append (reply, &iter); dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ss)", &iter_array); + + //TIZEN_ONLY(20211206) Provide GetActiveWindow + //we need this part because EFL sends only registered event + const char *registry_bus_name = SPI_DBUS_NAME_REGISTRY; + const char *window_activate_event = "Window:Activate:"; + const char *window_deactivate_event = "Window:Deactivate:"; + + dbus_message_iter_open_container (&iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, ®istry_bus_name); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &window_activate_event); + dbus_message_iter_close_container (&iter_array, &iter_struct); + + dbus_message_iter_open_container (&iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, ®istry_bus_name); + dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &window_deactivate_event); + dbus_message_iter_close_container (&iter_array, &iter_struct); + // + for (list = registry->events; list; list = list->next) { gchar *str; @@ -1289,6 +1394,10 @@ handle_method_root (DBusConnection *bus, DBusMessage *message, void *user_data) reply = impl_Embed (bus, message, user_data); else if (!strcmp (member, "Unembed")) reply = impl_Unembed (bus, message, user_data); + //TIZEN_ONLY(20211206) Provide GetActiveWindow + else if (!strcmp (member, "GetActiveWindow")) + reply = impl_GetActiveWindow (bus, message, user_data); + // else result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } @@ -1446,6 +1555,13 @@ static DBusObjectPathVTable cache_vtable = static gchar *app_sig_match_name_owner = "type='signal', interface='org.freedesktop.DBus', member='NameOwnerChanged'"; +//TIZEN_ONLY(20211206) Provide GetActivateWindow +static gchar *app_sig_match_window_activate = + "type='signal',interface='org.a11y.atspi.Event.Window',member='Activate'"; +static gchar *app_sig_match_window_deactivate = + "type='signal',interface='org.a11y.atspi.Event.Window',member='Deactivate'"; +// + SpiRegistry * spi_registry_new (DBusConnection *bus) { @@ -1456,6 +1572,13 @@ spi_registry_new (DBusConnection *bus) dbus_bus_add_match (bus, app_sig_match_name_owner, NULL); dbus_connection_add_filter (bus, signal_filter, reg, NULL); + //TIZEN_ONLY(20211206) Provide GetActiveWindow + reg->active_window_name = NULL; + reg->active_window_path = NULL; + dbus_bus_add_match (reg->bus, app_sig_match_window_activate, NULL); + dbus_bus_add_match (reg->bus, app_sig_match_window_deactivate, NULL); + // + dbus_connection_register_object_path (bus, SPI_DBUS_PATH_ROOT, &root_vtable, reg); dbus_connection_register_object_path (bus, SPI_DBUS_PATH_CACHE, &cache_vtable, reg); @@ -1468,5 +1591,6 @@ spi_registry_new (DBusConnection *bus) return reg; } +// /*END------------------------------------------------------------------------*/ diff --git a/registryd/registry.h b/registryd/registry.h index 19b1a8f..ee82ef5 100644 --- a/registryd/registry.h +++ b/registryd/registry.h @@ -50,8 +50,22 @@ struct _SpiRegistry { DBusConnection *bus; GList *events; + + //TIZEN_ONLY(20211206) Provide GetActiveWindow + gchar *active_window_name; + gchar *active_window_path; + // }; +//TIZEN_ONLY(20211206) Provide GetActiveWindow +typedef enum { + ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED = 0, + ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_ENABLED_WITHOUT_WINDOW = 1 << 0, + ACCESSIBLE_WINDOW_ACTIVATE_INFO_DEFAULT_LABEL_DISABLED = 1 << 1, + ACCESSIBLE_WINDOW_ACTIVATE_INFO_KEYBOARD = 1 << 2, +} WindowActivateInfoType; +// + struct _SpiRegistryClass { GObjectClass parent_class; }; -- 2.7.4