Merge "Make ModelNode / Light don't work A11y + Clean code lines" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / devel-api / controls / control-accessible.cpp
index 719657d..8788ade 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 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.
@@ -25,6 +25,7 @@
 
 #include <dali/devel-api/actors/actor-devel.h>
 #include <dali/devel-api/adaptor-framework/window-devel.h>
+#include <dali/public-api/object/type-info.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/asset-manager/asset-manager.h>
@@ -69,33 +70,6 @@ static Dali::Actor CreateHighlightIndicatorActor()
 ControlAccessible::ControlAccessible(Dali::Actor self)
 : ActorAccessible(self)
 {
-  auto control = Toolkit::Control::DownCast(self);
-
-  Internal::Control&       internalControl = Toolkit::Internal::GetImplementation(control);
-  Internal::Control::Impl& controlImpl     = Internal::Control::Impl::Get(internalControl);
-
-  self.PropertySetSignal().Connect(&controlImpl, [this, &controlImpl](Dali::Handle& handle, Dali::Property::Index index, Dali::Property::Value value) {
-    if(this->Self() != Dali::Accessibility::Accessible::GetCurrentlyHighlightedActor())
-    {
-      return;
-    }
-
-    if(index == DevelControl::Property::ACCESSIBILITY_NAME || (index == GetNamePropertyIndex() && controlImpl.mAccessibilityName.empty()))
-    {
-      if(controlImpl.mAccessibilityGetNameSignal.Empty())
-      {
-        Emit(Dali::Accessibility::ObjectPropertyChangeEvent::NAME);
-      }
-    }
-
-    if(index == DevelControl::Property::ACCESSIBILITY_DESCRIPTION || (index == GetDescriptionPropertyIndex() && controlImpl.mAccessibilityDescription.empty()))
-    {
-      if(controlImpl.mAccessibilityGetDescriptionSignal.Empty())
-      {
-        Emit(Dali::Accessibility::ObjectPropertyChangeEvent::DESCRIPTION);
-      }
-    }
-  });
 }
 
 std::string ControlAccessible::GetName() const
@@ -195,7 +169,6 @@ bool ControlAccessible::IsShowing()
     return true;
   }
 
-  auto childExtent = child->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
   while(parent)
   {
     auto control = Dali::Toolkit::Control::DownCast(parent->Self());
@@ -203,12 +176,6 @@ bool ControlAccessible::IsShowing()
     {
       return false;
     }
-    auto clipMode     = control.GetProperty(Actor::Property::CLIPPING_MODE).Get<bool>();
-    auto parentExtent = parent->GetExtents(Dali::Accessibility::CoordinateType::WINDOW);
-    if((clipMode != ClippingMode::DISABLED) && !parentExtent.Intersects(childExtent))
-    {
-      return false;
-    }
     parent = dynamic_cast<Toolkit::DevelControl::ControlAccessible*>(parent->GetParent());
   }
 
@@ -227,7 +194,7 @@ Dali::Accessibility::States ControlAccessible::CalculateStates()
   states[State::HIGHLIGHTABLE] = self.GetProperty<bool>(Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE);
   states[State::HIGHLIGHTED]   = GetCurrentlyHighlightedActor() == self;
   states[State::ENABLED]       = true;
-  states[State::SENSITIVE]     = true;
+  states[State::SENSITIVE]     = (Dali::DevelActor::IsHittable(self) && Dali::DevelActor::GetTouchRequired(self));
   states[State::VISIBLE]       = self.GetProperty<bool>(Actor::Property::VISIBLE);
   states[State::SHOWING]       = IsShowing();
   states[State::DEFUNCT]       = !self.GetProperty(Dali::DevelActor::Property::CONNECTED_TO_SCENE).Get<bool>();
@@ -242,36 +209,49 @@ Dali::Accessibility::States ControlAccessible::GetStates()
 
 Dali::Accessibility::Attributes ControlAccessible::GetAttributes() const
 {
-  std::unordered_map<std::string, std::string> attributeMap;
-  auto                                         control   = Dali::Toolkit::Control::DownCast(Self());
-  auto                                         attribute = control.GetProperty(Dali::Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES);
-  auto                                         map       = attribute.GetMap();
+  static const std::string automationIdKey = "automationId";
+  static const std::string classKey        = "class";
+
+  Accessibility::Attributes result;
+  Toolkit::Control          control        = Toolkit::Control::DownCast(Self());
+  Dali::Property::Value     property       = control.GetProperty(DevelControl::Property::ACCESSIBILITY_ATTRIBUTES);
+  Dali::Property::Map*      attributeMap   = property.GetMap();
+  std::size_t               attributeCount = attributeMap ? attributeMap->Count() : 0U;
 
-  if(map)
+  for(std::size_t i = 0; i < attributeCount; i++)
   {
-    auto mapSize = map->Count();
+    Dali::Property::Key mapKey = attributeMap->GetKeyAt(i);
+    std::string         mapValue;
 
-    for(unsigned int i = 0; i < mapSize; i++)
+    if(mapKey.type == Dali::Property::Key::STRING && attributeMap->GetValue(i).Get(mapValue))
     {
-      auto mapKey = map->GetKeyAt(i);
-      if(mapKey.type == Dali::Property::Key::STRING)
-      {
-        std::string mapValue;
-        if(map->GetValue(i).Get(mapValue))
-        {
-          attributeMap.emplace(std::move(mapKey.stringKey), std::move(mapValue));
-        }
-      }
+      result.emplace(std::move(mapKey.stringKey), std::move(mapValue));
     }
   }
 
-  auto automationId = control.GetProperty<std::string>(Dali::Toolkit::DevelControl::Property::AUTOMATION_ID);
+  auto automationId = control.GetProperty<std::string>(DevelControl::Property::AUTOMATION_ID);
   if(!automationId.empty())
   {
-    attributeMap.emplace("automationId", std::move(automationId));
+    result.emplace(automationIdKey, std::move(automationId));
   }
 
-  return attributeMap;
+  // Add "class" if not present already
+  if(result.find(classKey) == result.end())
+  {
+    Dali::TypeInfo typeInfo;
+    Self().GetTypeInfo(typeInfo);
+    if(typeInfo)
+    {
+      const std::string& typeName = typeInfo.GetName();
+
+      result.emplace(classKey, typeName);
+
+      // Save the 'typeName' so we don't have to calculate it again
+      DevelControl::AppendAccessibilityAttribute(control, classKey, typeName);
+    }
+  }
+
+  return result;
 }
 
 bool ControlAccessible::IsHidden() const
@@ -321,6 +301,22 @@ void ControlAccessible::UnregisterPositionPropertyNotification()
   controlImpl.UnregisterAccessibilityPositionPropertyNotification();
 }
 
+void ControlAccessible::RegisterPropertySetSignal()
+{
+  auto                     control         = Dali::Toolkit::Control::DownCast(Self());
+  Internal::Control&       internalControl = Toolkit::Internal::GetImplementation(control);
+  Internal::Control::Impl& controlImpl     = Internal::Control::Impl::Get(internalControl);
+  controlImpl.RegisterAccessibilityPropertySetSignal();
+}
+
+void ControlAccessible::UnregisterPropertySetSignal()
+{
+  auto                     control         = Dali::Toolkit::Control::DownCast(Self());
+  Internal::Control&       internalControl = Toolkit::Internal::GetImplementation(control);
+  Internal::Control::Impl& controlImpl     = Internal::Control::Impl::Get(internalControl);
+  controlImpl.UnregisterAccessibilityPropertySetSignal();
+}
+
 bool ControlAccessible::GrabHighlight()
 {
   Dali::Actor self                = Self();
@@ -370,6 +366,7 @@ bool ControlAccessible::GrabHighlight()
   SetCurrentlyHighlightedActor(self);
   EmitHighlighted(true);
   RegisterPositionPropertyNotification();
+  RegisterPropertySetSignal();
 
   return true;
 }
@@ -385,6 +382,7 @@ bool ControlAccessible::ClearHighlight()
 
   if(GetCurrentlyHighlightedActor() == self)
   {
+    UnregisterPropertySetSignal();
     UnregisterPositionPropertyNotification();
     self.Remove(mCurrentHighlightActor.GetHandle());
     mCurrentHighlightActor = {};