[Tizen] Provide GetActiveWindow interface 13/267313/9 accepted/tizen/unified/20211228.140402 submit/tizen/20211227.065503
authorShinwoo Kim <cinoo.kim@samsung.com>
Wed, 1 Dec 2021 08:36:19 +0000 (17:36 +0900)
committerShinwoo Kim <cinoo.kim@samsung.com>
Tue, 21 Dec 2021 18:06:59 +0000 (03:06 +0900)
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
atspi/atspi-registry.h
registryd/registry-main.c
registryd/registry.c
registryd/registry.h

index 2bb4d08..e9a47e5 100644 (file)
@@ -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)
 {
index 43150c2..b266c7b 100644 (file)
@@ -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,
index be01d2c..c137182 100644 (file)
@@ -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);
index aa867ca..fa2d3a5 100644 (file)
@@ -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, &registry_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, &registry_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------------------------------------------------------------------------*/
index 19b1a8f..ee82ef5 100644 (file)
@@ -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;
 };