[dali_2.3.28] Merge branch 'devel/master'
[platform/core/uifw/dali-adaptor.git] / dali / internal / accessibility / bridge / bridge-impl.cpp
index 644aca4..2fd6c49 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <dali/internal/accessibility/bridge/accessibility-common.h>
 #include <dali/internal/accessibility/bridge/bridge-accessible.h>
 #include <dali/internal/accessibility/bridge/bridge-action.h>
+#include <dali/internal/accessibility/bridge/bridge-application.h>
 #include <dali/internal/accessibility/bridge/bridge-collection.h>
 #include <dali/internal/accessibility/bridge/bridge-component.h>
 #include <dali/internal/accessibility/bridge/bridge-editable-text.h>
-#include <dali/internal/accessibility/bridge/bridge-hypertext.h>
 #include <dali/internal/accessibility/bridge/bridge-hyperlink.h>
+#include <dali/internal/accessibility/bridge/bridge-hypertext.h>
 #include <dali/internal/accessibility/bridge/bridge-object.h>
 #include <dali/internal/accessibility/bridge/bridge-selection.h>
 #include <dali/internal/accessibility/bridge/bridge-socket.h>
+#include <dali/internal/accessibility/bridge/bridge-table-cell.h>
+#include <dali/internal/accessibility/bridge/bridge-table.h>
 #include <dali/internal/accessibility/bridge/bridge-text.h>
 #include <dali/internal/accessibility/bridge/bridge-value.h>
-#include <dali/internal/accessibility/bridge/bridge-application.h>
-#include <dali/internal/accessibility/bridge/dummy-atspi.h>
+#include <dali/internal/accessibility/bridge/dummy/dummy-atspi.h>
 #include <dali/internal/adaptor/common/adaptor-impl.h>
 #include <dali/internal/system/common/environment-variables.h>
 
@@ -49,7 +51,6 @@ using namespace Dali::Accessibility;
 
 namespace // unnamed namespace
 {
-
 const int RETRY_INTERVAL = 1000;
 
 } // unnamed namespace
@@ -70,17 +71,19 @@ class BridgeImpl : public virtual BridgeBase,
                    public BridgeApplication,
                    public BridgeHypertext,
                    public BridgeHyperlink,
-                   public BridgeSocket
+                   public BridgeSocket,
+                   public BridgeTable,
+                   public BridgeTableCell
 {
-  DBus::DBusClient                                              mAccessibilityStatusClient;
-  DBus::DBusClient                                              mRegistryClient;
-  DBus::DBusClient                                              mDirectReadingClient;
-  bool                                                          mIsScreenReaderEnabled = false;
-  bool                                                          mIsEnabled             = false;
-  std::unordered_map<int32_t, std::function<void(std::string)>> mDirectReadingCallbacks;
+  DBus::DBusClient                                              mAccessibilityStatusClient{};
+  DBus::DBusClient                                              mRegistryClient{};
+  DBus::DBusClient                                              mDirectReadingClient{};
+  bool                                                          mIsScreenReaderEnabled{false};
+  bool                                                          mIsEnabled{false};
+  std::unordered_map<int32_t, std::function<void(std::string)>> mDirectReadingCallbacks{};
   Dali::Actor                                                   mHighlightedActor;
-  std::function<void(Dali::Actor)>                              mHighlightClearAction;
-  Dali::CallbackBase*                                           mIdleCallback          = NULL;
+  std::function<void(Dali::Actor)>                              mHighlightClearAction{nullptr};
+  Dali::CallbackBase*                                           mIdleCallback{};
   Dali::Timer                                                   mInitializeTimer;
   Dali::Timer                                                   mReadIsEnabledTimer;
   Dali::Timer                                                   mReadScreenReaderEnabledTimer;
@@ -88,48 +91,46 @@ class BridgeImpl : public virtual BridgeBase,
   std::string                                                   mPreferredBusName;
 
 public:
-  BridgeImpl()
-  {
-  }
+  BridgeImpl() = default;
 
   /**
-   * @copydoc Dali::Accessibility::Bridge::Emit()
+   * @copydoc Dali::Accessibility::Bridge::EmitKeyEvent()
    */
-  Consumed Emit(KeyEventType type, unsigned int keyCode, const std::string& keyName, unsigned int timeStamp, bool isText) override
+  bool EmitKeyEvent(Dali::KeyEvent keyEvent, std::function<void(Dali::KeyEvent, bool)> callback) override
   {
+    using ArgumentTypes = std::tuple<uint32_t, int32_t, int32_t, int32_t, int32_t, std::string, bool>;
+
+    static const char* methodName = "NotifyListenersSync";
+
     if(!IsUp())
     {
-      return Consumed::NO;
+      return false;
     }
 
-    unsigned int keyType = 0;
+    uint32_t keyType   = (keyEvent.GetState() == Dali::KeyEvent::DOWN ? 0U : 1U);
+    auto     timeStamp = static_cast<std::int32_t>(keyEvent.GetTime());
+    bool     isText    = !keyEvent.GetKeyString().empty();
 
-    switch(type)
-    {
-      case KeyEventType::KEY_PRESSED:
-      {
-        keyType = 0;
-        break;
-      }
-      case KeyEventType::KEY_RELEASED:
+    ArgumentTypes arguments(keyType, 0, keyEvent.GetKeyCode(), 0, timeStamp, keyEvent.GetKeyName(), isText);
+
+    auto functor = [keyEvent = std::move(keyEvent), callback = std::move(callback)](DBus::ValueOrError<bool> reply) {
+      bool consumed = false;
+
+      if(!reply)
       {
-        keyType = 1;
-        break;
+        DALI_LOG_ERROR("%s call failed: %s", methodName, reply.getError().message.c_str());
       }
-      default:
+      else
       {
-        return Consumed::NO;
+        consumed = std::get<0>(reply.getValues());
       }
-    }
 
-    auto methodObject = mRegistryClient.method<bool(std::tuple<uint32_t, int32_t, int32_t, int32_t, int32_t, std::string, bool>)>("NotifyListenersSync");
-    auto result       = methodObject.call(std::tuple<uint32_t, int32_t, int32_t, int32_t, int32_t, std::string, bool>{keyType, 0, static_cast<int32_t>(keyCode), 0, static_cast<int32_t>(timeStamp), keyName, isText ? 1 : 0});
-    if(!result)
-    {
-      LOG() << result.getError().message;
-      return Consumed::NO;
-    }
-    return std::get<0>(result) ? Consumed::YES : Consumed::NO;
+      callback(std::move(keyEvent), consumed);
+    };
+
+    mRegistryClient.method<bool(ArgumentTypes)>(methodName).asyncCall(std::move(functor), arguments);
+
+    return true;
   }
 
   /**
@@ -148,7 +149,7 @@ public:
         LOG() << "Direct reading command failed (" << msg.getError().message << ")\n";
       }
     },
-                                                                                        true);
+                                                                                         true);
   }
 
   /**
@@ -167,7 +168,7 @@ public:
         LOG() << "Direct reading command failed (" << msg.getError().message << ")\n";
       }
     },
-                                                                                        false);
+                                                                                         false);
   }
 
   /**
@@ -186,7 +187,7 @@ public:
         LOG() << "Direct reading command failed (" << msg.getError().message << ")\n";
       }
     },
-                                                                                        alsoNonDiscardable);
+                                                                                         alsoNonDiscardable);
   }
 
   /**
@@ -209,8 +210,8 @@ public:
         mDirectReadingCallbacks.emplace(std::get<2>(msg), callback);
       }
     },
-                                                                                                                           text,
-                                                                                                                           discardable);
+                                                                                                                            text,
+                                                                                                                            discardable);
   }
 
   /**
@@ -235,8 +236,8 @@ public:
     mHighlightedActor     = {};
     mHighlightClearAction = {};
     BridgeAccessible::ForceDown();
-    mRegistryClient       = {};
-    mDirectReadingClient  = {};
+    mRegistryClient      = {};
+    mDirectReadingClient = {};
     mDirectReadingCallbacks.clear();
     mApplication.mChildren.clear();
     ClearTimer();
@@ -289,9 +290,9 @@ public:
     {
       Dali::Adaptor::Get().RemoveIdle(mIdleCallback);
     }
-    mAccessibilityStatusClient        = {};
-    mDbusServer                       = {};
-    mConnectionPtr                    = {};
+    mAccessibilityStatusClient = {};
+    mDbusServer                = {};
+    mConnectionPtr             = {};
   }
 
   bool ForceUpTimerCallback()
@@ -337,6 +338,8 @@ public:
     BridgeHypertext::RegisterInterfaces();
     BridgeHyperlink::RegisterInterfaces();
     BridgeSocket::RegisterInterfaces();
+    BridgeTable::RegisterInterfaces();
+    BridgeTableCell::RegisterInterfaces();
 
     RegisterOnBridge(&mApplication);
 
@@ -365,6 +368,21 @@ public:
   }
 
   /**
+   * @brief Sends a signal to dbus that the window is created.
+   *
+   * @param[in] window The window to be created
+   * @see BridgeObject::Emit()
+   */
+  void EmitCreated(Dali::Window window)
+  {
+    auto windowAccessible = mApplication.GetWindowAccessible(window);
+    if(windowAccessible)
+    {
+      windowAccessible->Emit(WindowEvent::CREATE, 0);
+    }
+  }
+
+  /**
    * @brief Sends a signal to dbus that the window is shown.
    *
    * @param[in] window The window to be shown
@@ -425,6 +443,63 @@ public:
   }
 
   /**
+   * @brief Sends a signal to dbus that the window is minimized.
+   *
+   * @param[in] window The window to be minimized
+   * @see BridgeObject::Emit()
+   */
+  void EmitMinimize(Dali::Window window)
+  {
+    auto windowAccessible = mApplication.GetWindowAccessible(window);
+    if(windowAccessible)
+    {
+      windowAccessible->Emit(WindowEvent::MINIMIZE, 0);
+    }
+  }
+
+  /**
+   * @brief Sends a signal to dbus that the window is restored.
+   *
+   * @param[in] window The window to be restored
+   * @param[in] detail Restored window state
+   * @see BridgeObject::Emit()
+   */
+  void EmitRestore(Dali::Window window, Dali::Accessibility::WindowRestoreType detail)
+  {
+    auto windowAccessible = mApplication.GetWindowAccessible(window);
+    if(windowAccessible)
+    {
+      windowAccessible->Emit(WindowEvent::RESTORE, static_cast<unsigned int>(detail));
+    }
+  }
+
+  /**
+   * @brief Sends a signal to dbus that the window is maximized.
+   *
+   * @param[in] window The window to be maximized
+   * @see BridgeObject::Emit()
+   */
+  void EmitMaximize(Dali::Window window)
+  {
+    auto windowAccessible = mApplication.GetWindowAccessible(window);
+    if(windowAccessible)
+    {
+      windowAccessible->Emit(WindowEvent::MAXIMIZE, 0);
+    }
+  }
+
+  /**
+   * @copydoc Dali::Accessibility::Bridge::WindowCreated()
+   */
+  void WindowCreated(Dali::Window window) override
+  {
+    if(IsUp())
+    {
+      EmitCreated(window);
+    }
+  }
+
+  /**
    * @copydoc Dali::Accessibility::Bridge::WindowShown()
    */
   void WindowShown(Dali::Window window) override
@@ -469,6 +544,39 @@ public:
   }
 
   /**
+   * @copydoc Dali::Accessibility::Bridge::WindowMinimized()
+   */
+  void WindowMinimized(Dali::Window window) override
+  {
+    if(IsUp())
+    {
+      EmitMinimize(window);
+    }
+  }
+
+  /**
+   * @copydoc Dali::Accessibility::Bridge::WindowRestored()
+   */
+  void WindowRestored(Dali::Window window, WindowRestoreType detail) override
+  {
+    if(IsUp())
+    {
+      EmitRestore(window, detail);
+    }
+  }
+
+  /**
+   * @copydoc Dali::Accessibility::Bridge::WindowMaximized()
+   */
+  void WindowMaximized(Dali::Window window) override
+  {
+    if(IsUp())
+    {
+      EmitMaximize(window);
+    }
+  }
+
+  /**
    * @copydoc Dali::Accessibility::Bridge::SuppressScreenReader()
    */
   void SuppressScreenReader(bool suppress) override
@@ -545,7 +653,7 @@ public:
   void ReadScreenReaderEnabledProperty()
   {
     // can be true because of SuppressScreenReader before init
-    if (!mAccessibilityStatusClient)
+    if(!mAccessibilityStatusClient)
     {
       return;
     }
@@ -579,7 +687,7 @@ public:
 
   void EmitScreenReaderEnabledSignal()
   {
-    if (mIsScreenReaderEnabled)
+    if(mIsScreenReaderEnabled)
     {
       mScreenReaderEnabledSignal.Emit();
     }
@@ -611,7 +719,7 @@ public:
   {
     mAccessibilityStatusClient = DBus::DBusClient{A11yDbusName, A11yDbusPath, A11yDbusStatusInterface, DBus::ConnectionType::SESSION};
 
-    if (!mAccessibilityStatusClient)
+    if(!mAccessibilityStatusClient)
     {
       DALI_LOG_ERROR("Accessibility Status DbusClient is not ready\n");
       return false;
@@ -622,7 +730,7 @@ public:
 
   bool InitializeTimerCallback()
   {
-    if ( InitializeAccessibilityStatusClient() )
+    if(InitializeAccessibilityStatusClient())
     {
       ReadAndListenProperties();
       return false;
@@ -632,7 +740,7 @@ public:
 
   bool OnIdleSignal()
   {
-    if ( InitializeAccessibilityStatusClient() )
+    if(InitializeAccessibilityStatusClient())
     {
       ReadAndListenProperties();
       mIdleCallback = NULL;
@@ -655,20 +763,24 @@ public:
    */
   void Initialize() override
   {
-    if ( InitializeAccessibilityStatusClient() )
+    if(InitializeAccessibilityStatusClient())
     {
       ReadAndListenProperties();
       return;
     }
 
     // Initialize failed. Try it again on Idle
-    if( Dali::Adaptor::IsAvailable() )
+    if(Dali::Adaptor::IsAvailable())
     {
       Dali::Adaptor& adaptor = Dali::Adaptor::Get();
-      if( NULL == mIdleCallback )
+      if(NULL == mIdleCallback)
       {
-        mIdleCallback = MakeCallback( this, &BridgeImpl::OnIdleSignal );
-        adaptor.AddIdle( mIdleCallback, true );
+        mIdleCallback = MakeCallback(this, &BridgeImpl::OnIdleSignal);
+        if(DALI_UNLIKELY(!adaptor.AddIdle(mIdleCallback, true)))
+        {
+          DALI_LOG_ERROR("Fail to add idle callback for bridge initialize. Call it synchronously.\n");
+          OnIdleSignal();
+        }
       }
     }
   }
@@ -707,19 +819,19 @@ public:
   {
     auto client = CreateSocketClient(socket);
 
-    client.method<void(std::string)>("Embedded").call(ATSPI_PREFIX_PATH + plug.GetPath());
+    client.method<void(std::string)>("Embedded").asyncCall([](DBus::ValueOrError<void>) {}, ATSPI_PREFIX_PATH + plug.GetPath());
   }
 
   void UnembedSocket(const Address& plug, const Address& socket) override
   {
     auto client = CreateSocketClient(socket);
 
-    client.method<void(Address)>("Unembed").call(plug);
+    client.method<void(Address)>("Unembed").asyncCall([](DBus::ValueOrError<void>) {}, plug);
   }
 
   void SetSocketOffset(ProxyAccessible* socket, std::int32_t x, std::int32_t y) override
   {
-    AddFilteredEvent(FilteredEvents::SET_OFFSET, socket, 1.0f, [=]() {
+    AddCoalescableMessage(CoalescableMessages::SET_OFFSET, socket, 1.0f, [=]() {
       auto client = CreateSocketClient(socket->GetAddress());
 
       client.method<void(std::int32_t, std::int32_t)>("SetOffset").asyncCall([](DBus::ValueOrError<void>) {}, x, y);
@@ -781,7 +893,6 @@ private:
 
 namespace // unnamed namespace
 {
-
 bool INITIALIZED_BRIDGE = false;
 
 /**