[dali_2.3.42] Merge branch 'devel/master'
[platform/core/uifw/dali-adaptor.git] / dali / devel-api / adaptor-framework / accessibility.cpp
index 1139607..fe0b3a5 100644 (file)
@@ -19,7 +19,6 @@
 #include <dali/public-api/actors/actor.h>
 #include <dali/public-api/actors/layer.h>
 #include <dali/public-api/object/base-object.h>
-#include <dali/public-api/object/object-registry.h>
 #include <dali/public-api/object/type-info.h>
 #include <dali/public-api/object/type-registry-helper.h>
 #include <string_view>
@@ -40,6 +39,8 @@
 #include <dali/devel-api/atspi-interfaces/hypertext.h>
 #include <dali/devel-api/atspi-interfaces/selection.h>
 #include <dali/devel-api/atspi-interfaces/socket.h>
+#include <dali/devel-api/atspi-interfaces/table-cell.h>
+#include <dali/devel-api/atspi-interfaces/table.h>
 #include <dali/devel-api/atspi-interfaces/text.h>
 #include <dali/devel-api/atspi-interfaces/value.h>
 #include <dali/internal/adaptor/common/adaptor-impl.h>
@@ -241,6 +242,8 @@ AtspiInterfaces Accessible::DoGetInterfaces() const
   interfaces[AtspiInterface::HYPERTEXT]     = dynamic_cast<const Hypertext*>(this);
   interfaces[AtspiInterface::SELECTION]     = dynamic_cast<const Selection*>(this);
   interfaces[AtspiInterface::SOCKET]        = dynamic_cast<const Socket*>(this);
+  interfaces[AtspiInterface::TABLE]         = dynamic_cast<const Table*>(this);
+  interfaces[AtspiInterface::TABLE_CELL]    = dynamic_cast<const TableCell*>(this);
   interfaces[AtspiInterface::TEXT]          = dynamic_cast<const Text*>(this);
   interfaces[AtspiInterface::VALUE]         = dynamic_cast<const Value*>(this);
 
@@ -302,6 +305,13 @@ void Accessible::SetCurrentlyHighlightedActor(Dali::Actor actor)
   }
 }
 
+bool Accessible::IsHighlighted() const
+{
+  Dali::Actor self = GetInternalActor();
+
+  return self && self == GetCurrentlyHighlightedActor();
+}
+
 Dali::Actor Accessible::GetHighlightActor()
 {
   return IsUp() ? Bridge::GetCurrentBridge()->mData->mHighlightActor : Dali::Actor{};
@@ -338,8 +348,9 @@ namespace
 {
 class AdaptorAccessible : public ActorAccessible
 {
-protected:
-  bool mRoot = false;
+private:
+  std::unique_ptr<TriggerEventInterface> mRenderNotification{nullptr};
+  bool                                   mRoot{false};
 
 public:
   AdaptorAccessible(Dali::Actor actor, bool isRoot)
@@ -405,15 +416,14 @@ public:
       return false;
     }
 
-    auto self = Self();
-    if(self != GetCurrentlyHighlightedActor())
+    if(!IsHighlighted())
     {
       return false;
     }
 
     SetCurrentlyHighlightedActor({});
 
-    auto                             window     = Dali::DevelWindow::Get(self);
+    auto                             window     = Dali::DevelWindow::Get(Self());
     Dali::Internal::Adaptor::Window& windowImpl = Dali::GetImplementation(window);
     windowImpl.EmitAccessibilityHighlightSignal(false);
 
@@ -438,12 +448,17 @@ public:
       state[State::VISIBLE]   = true;
       state[State::ACTIVE]    = visible;
     }
-    else
+    else if(GetParent())
     {
       auto parentState      = GetParent()->GetStates();
       state[State::SHOWING] = parentState[State::SHOWING];
       state[State::VISIBLE] = parentState[State::VISIBLE];
     }
+    else
+    {
+      state[State::SHOWING] = false;
+      state[State::VISIBLE] = false;
+    }
     return state;
   }
 
@@ -474,60 +489,99 @@ public:
   {
     return {};
   }
-}; // AdaptorAccessible
 
-using AdaptorAccessiblesType = std::unordered_map<const Dali::RefObject*, std::unique_ptr<AdaptorAccessible> >;
+  void SetListenPostRender(bool enabled) override
+  {
+    if(!mRoot)
+    {
+      return;
+    }
 
-// Save RefObject from an Actor in Accessible::Get()
-AdaptorAccessiblesType& GetAdaptorAccessibles()
-{
-  static AdaptorAccessiblesType gAdaptorAccessibles;
-  return gAdaptorAccessibles;
-}
+    auto                             window     = Dali::DevelWindow::Get(Self());
+    Dali::Internal::Adaptor::Window& windowImpl = Dali::GetImplementation(window);
+
+    if(!mRenderNotification)
+    {
+      mRenderNotification = std::unique_ptr<TriggerEventInterface>(
+        TriggerEventFactory::CreateTriggerEvent(MakeCallback(this, &AdaptorAccessible::OnPostRender),
+                                                TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER));
+    }
+
+    if(enabled)
+    {
+      windowImpl.SetRenderNotification(mRenderNotification.get());
+    }
+    else
+    {
+      windowImpl.SetRenderNotification(nullptr);
+    }
+  }
+
+  void OnPostRender()
+  {
+    Accessibility::Bridge::GetCurrentBridge()->EmitPostRender(shared_from_this());
+  }
+}; // AdaptorAccessible
+
+using ConvertingResult = std::pair<std::shared_ptr<Accessible>, bool>;
 
-std::function<Accessible*(Dali::Actor)> convertingFunctor = [](Dali::Actor) -> Accessible* {
-  return nullptr;
+std::function<ConvertingResult(Dali::Actor)> convertingFunctor = [](Dali::Actor) -> ConvertingResult {
+  return {nullptr, true};
 };
 
-ObjectRegistry objectRegistry;
 } // namespace
 
-void Accessible::SetObjectRegistry(ObjectRegistry registry)
-{
-  objectRegistry = registry;
-  objectRegistry.ObjectDestroyedSignal().Connect([](const Dali::RefObject* obj) {
-    GetAdaptorAccessibles().erase(obj);
-  });
-}
-
-void Accessible::RegisterExternalAccessibleGetter(std::function<Accessible*(Dali::Actor)> functor)
+void Accessible::RegisterExternalAccessibleGetter(std::function<ConvertingResult(Dali::Actor)> functor)
 {
   convertingFunctor = functor;
 }
 
-Accessible* Accessible::Get(Dali::Actor actor)
+std::shared_ptr<Accessible> Accessible::GetOwningPtr(Dali::Actor actor)
 {
   if(!actor)
   {
     return nullptr;
   }
 
-  auto accessible = convertingFunctor(actor);
-  if(!accessible)
+  auto bridge = Bridge::GetCurrentBridge();
+
+  // Try finding exsiting accessible object.
+  auto accessible = bridge->GetAccessible(actor);
+  if(accessible)
   {
-    auto pair = GetAdaptorAccessibles().emplace(&actor.GetBaseObject(), nullptr);
-    if(pair.second)
+    return accessible;
+  }
+
+  // No acessible object created, let's create one.
+  auto result                = convertingFunctor(actor);
+  accessible                 = result.first;
+  const bool creationEnabled = result.second;
+  if(!accessible && creationEnabled)
+  {
+    bool                     isRoot = false;
+    Dali::Integration::Scene scene  = Dali::Integration::Scene::Get(actor);
+    if(scene)
     {
-      bool                     isRoot = false;
-      Dali::Integration::Scene scene  = Dali::Integration::Scene::Get(actor);
-      if(scene)
-      {
-        isRoot = (actor == scene.GetRootLayer());
-      }
-      pair.first->second.reset(new AdaptorAccessible(actor, isRoot));
+      isRoot = (actor == scene.GetRootLayer());
+    }
+    accessible = std::make_shared<AdaptorAccessible>(actor, isRoot);
+  }
+
+  if(accessible)
+  {
+    uint32_t actorId = actor.GetProperty<int>(Dali::Actor::Property::ID);
+    bridge->AddAccessible(actorId, accessible);
+    if(auto actorAccesible = std::dynamic_pointer_cast<ActorAccessible>(accessible))
+    {
+      actorAccesible->StartObservingDestruction();
     }
-    accessible = pair.first->second.get();
   }
 
   return accessible;
 }
+
+Accessible* Accessible::Get(Dali::Actor actor)
+{
+  auto accessible = Accessible::GetOwningPtr(actor);
+  return accessible ? accessible.get() : nullptr;
+}
\ No newline at end of file