(Accessibility) Lazy creation accessibility data 20/323520/13
authorEunki Hong <eunkiki.hong@samsung.com>
Tue, 29 Apr 2025 14:40:39 +0000 (23:40 +0900)
committerEunki Hong <eunkiki.hong@samsung.com>
Mon, 12 May 2025 01:59:46 +0000 (01:59 +0000)
Let we make accessibility data for control initialize only if we need.

It will sightly reduce the memory per each control if we don't use accessibility feature ever.

Change-Id: I5c1901c3207f9dd2e6620fe506be02715a94da4e
Signed-off-by: Eunki Hong <eunkiki.hong@samsung.com>
12 files changed:
automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Accessible.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls-BridgeUp.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-Accessibility-Controls.cpp
dali-toolkit/devel-api/controls/control-accessible.cpp
dali-toolkit/devel-api/controls/control-devel.cpp
dali-toolkit/internal/controls/control/control-accessibility-data.cpp
dali-toolkit/internal/controls/control/control-accessibility-data.h
dali-toolkit/internal/controls/control/control-data-impl.cpp
dali-toolkit/internal/controls/control/control-data-impl.h
dali-toolkit/internal/controls/magnifier/magnifier-impl.cpp
dali-toolkit/internal/controls/magnifier/magnifier-impl.h
dali-toolkit/public-api/controls/control-impl.cpp

index 02ca1fa764fa36bb45c5fa6bde9150530d6ceb60..9f75d43e78929b669c221439ec32fe9e14d9fc86 100644 (file)
@@ -174,7 +174,7 @@ int utcDaliAccessibilityHidden(void)
   END_TEST;
 }
 
-int utcDaliAutomationId(void)
+int utcDaliAccessibilityAutomationId(void)
 {
   ToolkitTestApplication application;
   Dali::Property::Index  automationIdIndex = Toolkit::DevelControl::Property::AUTOMATION_ID;
@@ -185,9 +185,9 @@ int utcDaliAutomationId(void)
   auto* controlAccessible = Accessibility::Accessible::Get(control);
 
   // Check that there is no automationId initially
-  DALI_TEST_CHECK(control.GetProperty<std::string>(automationIdIndex).empty());
+  DALI_TEST_EQUALS(control.GetProperty<std::string>(automationIdIndex).empty(), true, TEST_LOCATION);
   auto attributes = controlAccessible->GetAttributes();
-  DALI_TEST_CHECK(attributes.find(automationIdKey) == attributes.end());
+  DALI_TEST_EQUALS(attributes.find(automationIdKey) == attributes.end(), true, TEST_LOCATION);
 
   // Set automationId
   control.SetProperty(automationIdIndex, automationIdValue);
@@ -195,21 +195,21 @@ int utcDaliAutomationId(void)
   // Check that automationId is set
   DALI_TEST_EQUALS(control.GetProperty<std::string>(automationIdIndex), automationIdValue, TEST_LOCATION);
   attributes = controlAccessible->GetAttributes();
-  DALI_TEST_CHECK(attributes.find(automationIdKey) != attributes.end());
+  DALI_TEST_EQUALS(attributes.find(automationIdKey) != attributes.end(), true, TEST_LOCATION);
   DALI_TEST_EQUALS(attributes[automationIdKey], automationIdValue, TEST_LOCATION);
 
   // Unset automationId
   control.SetProperty(automationIdIndex, "");
 
   // Check that there is no automationId
-  DALI_TEST_CHECK(control.GetProperty<std::string>(automationIdIndex).empty());
+  DALI_TEST_EQUALS(control.GetProperty<std::string>(automationIdIndex).empty(), true, TEST_LOCATION);
   attributes = controlAccessible->GetAttributes();
-  DALI_TEST_CHECK(attributes.find(automationIdKey) == attributes.end());
+  DALI_TEST_EQUALS(attributes.find(automationIdKey) == attributes.end(), true, TEST_LOCATION);
 
   END_TEST;
 }
 
-int utcDaliImgSrc(void)
+int utcDaliAccessibilityImgSrc(void)
 {
   ToolkitTestApplication application;
   const std::string      imageSrcKey = "imgSrc";
index 6a1f249ff0c41cc1b54742751343cb2de9ea2013..414576fcfbb51dc126332b9b7c32f0088743690a 100644 (file)
@@ -1,3 +1,20 @@
+/**
+ * Copyright (c) 2025 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
 #include <automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/accessibility-test-utils.h>
 #include <automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/dbus-wrapper.h>
 #include <automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-timer.h>
@@ -16,6 +33,7 @@
 #include <dali/devel-api/atspi-interfaces/action.h>
 #include <dali/devel-api/atspi-interfaces/component.h>
 #include <dali/devel-api/common/stage.h>
+
 #include <cstdlib>
 
 using namespace Dali::Toolkit;
@@ -31,7 +49,17 @@ const auto flushCoalescableMessage = [](Dali::ToolkitTestApplication& applicatio
     timer.MockEmitSignal();
   }
 };
+
+static void TestVoidCallback()
+{
+}
+
+static void Wait(ToolkitTestApplication& application)
+{
+  application.SendNotification();
+  application.Render(16);
 }
+} // namespace
 
 void utc_dali_toolkit_accessibility_control_bridgeup_startup(void)
 {
@@ -1491,10 +1519,6 @@ int UtcDaliAccessibilityActivateFallbackToLegacy(void)
   END_TEST;
 }
 
-void TestVoidCallback()
-{
-}
-
 int UtcDaliAccessibilitySignals(void)
 {
   ToolkitTestApplication application;
@@ -1516,12 +1540,6 @@ int UtcDaliAccessibilitySignals(void)
   END_TEST;
 }
 
-static void Wait(ToolkitTestApplication& application)
-{
-  application.SendNotification();
-  application.Render(16);
-}
-
 int UtcDaliAccessibilityScrollToChildScrollView(void)
 {
   ToolkitTestApplication application;
@@ -2112,7 +2130,7 @@ int UtcDaliAccessibleRemovalOnActorDestoyed(void)
   END_TEST;
 }
 
-int UtcDaliIncludeHidden(void)
+int UtcDaliAccessibleIncludeHidden(void)
 {
   ToolkitTestApplication application;
 
@@ -2151,6 +2169,8 @@ int UtcDaliIncludeHidden(void)
   END_TEST;
 }
 
+namespace
+{
 enum class MatchType : int32_t
 {
   INVALID,
@@ -2309,8 +2329,9 @@ static Accessibility::Collection::MatchRule GetMatchRule(std::vector<Accessibili
     static_cast<int32_t>(MatchType::INVALID),
     false};
 }
+} // namespace
 
-int UtcDaliGetMatches(void)
+int UtcDaliAccessibleGetMatches(void)
 {
   const int              N = 48;
   ToolkitTestApplication application;
@@ -2336,7 +2357,7 @@ int UtcDaliGetMatches(void)
   END_TEST;
 }
 
-int UtcDaliGetMatchesInMatches(void)
+int UtcDaliAccessibleGetMatchesInMatches(void)
 {
   const int              N = 48;
   ToolkitTestApplication application;
@@ -2364,7 +2385,7 @@ int UtcDaliGetMatchesInMatches(void)
   END_TEST;
 }
 
-int UtcDaliDumpTree(void)
+int UtcDaliAccessibleDumpTree(void)
 {
   ToolkitTestApplication application;
 
@@ -2434,4 +2455,3 @@ int UtcDaliWebViewCheckResumeOnAccessibilityMode(void)
 
   END_TEST;
 }
-
index b2bd5440b37040f49c2295b4540b36e71deabd73..d12660fd50e7859972bcc1ad11562a6bdf1d4c5f 100644 (file)
@@ -1,3 +1,20 @@
+/**
+ * Copyright (c) 2025 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
 #include <automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/accessibility-test-utils.h>
 #include <dali-toolkit-test-suite-utils.h>
 #include <dali-toolkit/dali-toolkit.h>
 #include <dali/devel-api/atspi-interfaces/hyperlink.h>
 #include <dali/devel-api/atspi-interfaces/hypertext.h>
 #include <dali/devel-api/atspi-interfaces/text.h>
+#include <dali/public-api/common/vector-wrapper.h>
 
 #include <automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/dbus-wrapper.h>
 
+#include <tuple>
+
 using namespace Dali::Toolkit;
 
 void utc_dali_accessibility_controls_startup(void)
@@ -79,7 +99,11 @@ int UtcDaliControlAccessibileBlockAccessibleCreation(void)
 {
   ToolkitTestApplication application;
 
-  auto control = Control::New();
+  Dali::Accessibility::ReadingInfoTypes infoTypes{};
+  Dali::Accessibility::RelationType     relationType{Accessibility::RelationType::NULL_OF};
+
+  auto control  = Control::New();
+  auto control2 = Control::New();
 
   // Default is true.
   DALI_TEST_EQUALS(DevelControl::IsCreateAccessibleEnabled(control), true, TEST_LOCATION);
@@ -93,10 +117,33 @@ int UtcDaliControlAccessibileBlockAccessibleCreation(void)
     // Should not throw exception even if accessible is not created.
     DALI_TEST_EQUALS(DevelControl::ClearAccessibilityHighlight(control), false, TEST_LOCATION);
     DALI_TEST_EQUALS(DevelControl::GrabAccessibilityHighlight(control), false, TEST_LOCATION);
-
     DevelControl::GetAccessibilityStates(control);
     DevelControl::NotifyAccessibilityStateChange(control, Dali::Accessibility::States{}, false);
     DevelControl::NotifyAccessibilityStateChange(control, Dali::Accessibility::States{}, true);
+    DevelControl::EmitAccessibilityStateChanged(control, Accessibility::State::SHOWING, 0);
+    DevelControl::EmitAccessibilityStateChanged(control, Accessibility::State::SHOWING, 1);
+    DevelControl::AppendAccessibilityRelation(control, control2, relationType);
+    DevelControl::RemoveAccessibilityRelation(control, control2, relationType);
+    DevelControl::GetAccessibilityRelations(control);
+    DevelControl::ClearAccessibilityRelations(control);
+    DevelControl::AppendAccessibilityAttribute(control, "dummy", "i_am_dummy");
+    DevelControl::RemoveAccessibilityAttribute(control, "dummy");
+    DevelControl::ClearAccessibilityAttributes(control);
+    DevelControl::SetAccessibilityReadingInfoType(control, infoTypes);
+    DevelControl::GetAccessibilityReadingInfoType(control);
+
+    // Signal relative API.
+    DevelControl::AccessibilityActivateSignal(control);
+    DevelControl::AccessibilityReadingSkippedSignal(control);
+    DevelControl::AccessibilityReadingPausedSignal(control);
+    DevelControl::AccessibilityReadingResumedSignal(control);
+    DevelControl::AccessibilityReadingCancelledSignal(control);
+    DevelControl::AccessibilityReadingStoppedSignal(control);
+    DevelControl::AccessibilityGetNameSignal(control);
+    DevelControl::AccessibilityGetDescriptionSignal(control);
+    DevelControl::AccessibilityDoGestureSignal(control);
+    DevelControl::AccessibilityActionSignal(control);
+
     DALI_TEST_CHECK(true);
   }
   catch(...)
@@ -120,6 +167,29 @@ int UtcDaliControlAccessibileBlockAccessibleCreation(void)
     DevelControl::GetAccessibilityStates(control);
     DevelControl::NotifyAccessibilityStateChange(control, Dali::Accessibility::States{}, false);
     DevelControl::NotifyAccessibilityStateChange(control, Dali::Accessibility::States{}, true);
+    DevelControl::EmitAccessibilityStateChanged(control, Accessibility::State::SHOWING, 0);
+    DevelControl::EmitAccessibilityStateChanged(control, Accessibility::State::SHOWING, 1);
+    DevelControl::AppendAccessibilityRelation(control, control2, relationType);
+    DevelControl::RemoveAccessibilityRelation(control, control2, relationType);
+    DevelControl::GetAccessibilityRelations(control);
+    DevelControl::ClearAccessibilityRelations(control);
+    DevelControl::AppendAccessibilityAttribute(control, "dummy", "i_am_dummy");
+    DevelControl::RemoveAccessibilityAttribute(control, "dummy");
+    DevelControl::ClearAccessibilityAttributes(control);
+    DevelControl::SetAccessibilityReadingInfoType(control, infoTypes);
+    DevelControl::GetAccessibilityReadingInfoType(control);
+
+    // Signal relative API.
+    DevelControl::AccessibilityActivateSignal(control);
+    DevelControl::AccessibilityReadingSkippedSignal(control);
+    DevelControl::AccessibilityReadingPausedSignal(control);
+    DevelControl::AccessibilityReadingResumedSignal(control);
+    DevelControl::AccessibilityReadingCancelledSignal(control);
+    DevelControl::AccessibilityReadingStoppedSignal(control);
+    DevelControl::AccessibilityGetNameSignal(control);
+    DevelControl::AccessibilityGetDescriptionSignal(control);
+    DevelControl::AccessibilityDoGestureSignal(control);
+    DevelControl::AccessibilityActionSignal(control);
     DALI_TEST_CHECK(true);
   }
   catch(...)
index 75be8e50d9b9c176df3f78e524aaac00f5da06f2..e69fdd0bbef9d7e9b35b3bda5cddb32ffec80b36 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -236,13 +236,14 @@ std::string ControlAccessible::GetName() const
   Internal::Control::Impl& controlImpl     = Internal::Control::Impl::Get(internalControl);
   std::string              name;
 
-  if(!controlImpl.mAccessibilityData->mAccessibilityGetNameSignal.Empty())
+  auto* accessibilityData = controlImpl.GetAccessibilityData();
+  if(DALI_LIKELY(accessibilityData) && !accessibilityData->mAccessibilityGetNameSignal.Empty())
   {
-    controlImpl.mAccessibilityData->mAccessibilityGetNameSignal.Emit(name);
+    accessibilityData->mAccessibilityGetNameSignal.Emit(name);
   }
-  else if(!controlImpl.mAccessibilityData->mAccessibilityProps.name.empty())
+  else if(DALI_LIKELY(accessibilityData) && !accessibilityData->mAccessibilityProps.name.empty())
   {
-    name = controlImpl.mAccessibilityData->mAccessibilityProps.name;
+    name = accessibilityData->mAccessibilityProps.name;
   }
   else if(auto raw = GetNameRaw(); !raw.empty())
   {
@@ -269,13 +270,14 @@ std::string ControlAccessible::GetDescription() const
   Internal::Control::Impl& controlImpl     = Internal::Control::Impl::Get(internalControl);
   std::string              description;
 
-  if(!controlImpl.mAccessibilityData->mAccessibilityGetDescriptionSignal.Empty())
+  auto* accessibilityData = controlImpl.GetAccessibilityData();
+  if(DALI_LIKELY(accessibilityData) && !accessibilityData->mAccessibilityGetDescriptionSignal.Empty())
   {
-    controlImpl.mAccessibilityData->mAccessibilityGetDescriptionSignal.Emit(description);
+    accessibilityData->mAccessibilityGetDescriptionSignal.Emit(description);
   }
-  else if(!controlImpl.mAccessibilityData->mAccessibilityProps.description.empty())
+  else if(DALI_LIKELY(accessibilityData) && !accessibilityData->mAccessibilityProps.description.empty())
   {
-    description = controlImpl.mAccessibilityData->mAccessibilityProps.description;
+    description = accessibilityData->mAccessibilityProps.description;
   }
   else
   {
@@ -340,17 +342,39 @@ void ControlAccessible::ApplyAccessibilityProps(Dali::Accessibility::States& sta
   Internal::Control&       internalControl = Toolkit::Internal::GetImplementation(control);
   Internal::Control::Impl& controlImpl     = Internal::Control::Impl::Get(internalControl);
 
+  DevelControl::AccessibilityStates controlStates;
+
+  int32_t rawRole = control.GetProperty<int32_t>(Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE);
+
+  bool             isModal       = false;
+  TriStateProperty highlightable = TriStateProperty::AUTO;
+
+  const auto* accessibilityData = controlImpl.GetAccessibilityData();
+  if(DALI_LIKELY(accessibilityData))
+  {
+    const auto& props = accessibilityData->mAccessibilityProps;
+
+    controlStates = props.states;
+    isModal       = props.isModal;
+    highlightable = props.isHighlightable;
+  }
+  else
+  {
+    // Default states
+    // TODO : Couldn't we get this value from Internal::Control::Impl::AccessibilityData::GetDefaultControlAccessibilityStates();
+    controlStates[AccessibilityState::ENABLED] = true;
+  }
+
   // Apply states
-  const auto& props       = controlImpl.mAccessibilityData->mAccessibilityProps;
-  states[State::ENABLED]  = props.states[AccessibilityState::ENABLED];
-  states[State::SELECTED] = props.states[AccessibilityState::SELECTED];
-  states[State::CHECKED]  = props.states[AccessibilityState::CHECKED];
-  states[State::BUSY]     = props.states[AccessibilityState::BUSY];
-  states[State::EXPANDED] = props.states[AccessibilityState::EXPANDED];
+  states[State::ENABLED]  = controlStates[AccessibilityState::ENABLED];
+  states[State::SELECTED] = controlStates[AccessibilityState::SELECTED];
+  states[State::CHECKED]  = controlStates[AccessibilityState::CHECKED];
+  states[State::BUSY]     = controlStates[AccessibilityState::BUSY];
+  states[State::EXPANDED] = controlStates[AccessibilityState::EXPANDED];
 
   // Apply traits
-  states[State::MODAL]         = props.isModal || IsModalRole(props.role);
-  states[State::HIGHLIGHTABLE] = IsHighlightable(props.isHighlightable, props.role);
+  states[State::MODAL]         = isModal || IsModalRole(rawRole);
+  states[State::HIGHLIGHTABLE] = IsHighlightable(highlightable, rawRole);
 }
 
 Dali::Accessibility::States ControlAccessible::CalculateStates()
@@ -441,7 +465,8 @@ bool ControlAccessible::IsHidden() const
   Internal::Control&       internalControl = Toolkit::Internal::GetImplementation(control);
   Internal::Control::Impl& controlImpl     = Internal::Control::Impl::Get(internalControl);
 
-  return controlImpl.mAccessibilityData->mAccessibilityProps.isHidden;
+  const auto* accessibilityData = controlImpl.GetAccessibilityData();
+  return DALI_LIKELY(accessibilityData) ? accessibilityData->mAccessibilityProps.isHidden : false;
 }
 
 bool ControlAccessible::GrabFocus()
@@ -470,7 +495,8 @@ void ControlAccessible::RegisterPositionPropertyNotification()
   auto                     control         = Dali::Toolkit::Control::DownCast(Self());
   Internal::Control&       internalControl = Toolkit::Internal::GetImplementation(control);
   Internal::Control::Impl& controlImpl     = Internal::Control::Impl::Get(internalControl);
-  controlImpl.mAccessibilityData->RegisterAccessibilityPositionPropertyNotification();
+
+  controlImpl.GetOrCreateAccessibilityData().RegisterAccessibilityPositionPropertyNotification();
 }
 
 void ControlAccessible::UnregisterPositionPropertyNotification()
@@ -478,7 +504,8 @@ void ControlAccessible::UnregisterPositionPropertyNotification()
   auto                     control         = Dali::Toolkit::Control::DownCast(Self());
   Internal::Control&       internalControl = Toolkit::Internal::GetImplementation(control);
   Internal::Control::Impl& controlImpl     = Internal::Control::Impl::Get(internalControl);
-  controlImpl.mAccessibilityData->UnregisterAccessibilityPositionPropertyNotification();
+
+  controlImpl.GetOrCreateAccessibilityData().UnregisterAccessibilityPositionPropertyNotification();
 }
 
 void ControlAccessible::RegisterPropertySetSignal()
@@ -486,9 +513,11 @@ 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.mAccessibilityData->RegisterAccessibilityPropertySetSignal();
 
-  mStatesSnapshot = controlImpl.mAccessibilityData->mAccessibilityProps.states;
+  auto& accessibilityData = controlImpl.GetOrCreateAccessibilityData();
+  accessibilityData.RegisterAccessibilityPropertySetSignal();
+
+  mStatesSnapshot = accessibilityData.mAccessibilityProps.states;
 }
 
 void ControlAccessible::UnregisterPropertySetSignal()
@@ -496,7 +525,8 @@ 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.mAccessibilityData->UnregisterAccessibilityPropertySetSignal();
+
+  controlImpl.GetOrCreateAccessibilityData().UnregisterAccessibilityPropertySetSignal();
 
   mStatesSnapshot = {};
 }
@@ -629,10 +659,11 @@ bool ControlAccessible::DoGesture(const Dali::Accessibility::GestureInfo& gestur
   Internal::Control&       internalControl = Toolkit::Internal::GetImplementation(control);
   Internal::Control::Impl& controlImpl     = Internal::Control::Impl::Get(internalControl);
 
-  if(!controlImpl.mAccessibilityData->mAccessibilityDoGestureSignal.Empty())
+  auto* accessibilityData = controlImpl.GetAccessibilityData();
+  if(DALI_LIKELY(accessibilityData) && !accessibilityData->mAccessibilityDoGestureSignal.Empty())
   {
     auto ret = std::make_pair(gestureInfo, false);
-    controlImpl.mAccessibilityData->mAccessibilityDoGestureSignal.Emit(ret);
+    accessibilityData->mAccessibilityDoGestureSignal.Emit(ret);
     return ret.second;
   }
 
index 284b53558eb583b26ee680ad83ba3dce521b4057..a497f51f24d41729e8dbd5f6287453e64f516e08 100644 (file)
@@ -147,88 +147,100 @@ Dali::Property GetVisualProperty(Control control, Dali::Property::Index index, D
 
 Toolkit::DevelControl::AccessibilityActivateSignalType& AccessibilityActivateSignal(Toolkit::Control control)
 {
-  return GetControlImplementation(control).mAccessibilityData->mAccessibilityActivateSignal;
+  return GetControlImplementation(control).GetOrCreateAccessibilityData().mAccessibilityActivateSignal;
 }
 
 Toolkit::DevelControl::AccessibilityReadingSkippedSignalType& AccessibilityReadingSkippedSignal(Toolkit::Control control)
 {
-  return GetControlImplementation(control).mAccessibilityData->mAccessibilityReadingSkippedSignal;
+  return GetControlImplementation(control).GetOrCreateAccessibilityData().mAccessibilityReadingSkippedSignal;
 }
 
 Toolkit::DevelControl::AccessibilityReadingPausedSignalType& AccessibilityReadingPausedSignal(Toolkit::Control control)
 {
-  return GetControlImplementation(control).mAccessibilityData->mAccessibilityReadingPausedSignal;
+  return GetControlImplementation(control).GetOrCreateAccessibilityData().mAccessibilityReadingPausedSignal;
 }
 
 Toolkit::DevelControl::AccessibilityReadingResumedSignalType& AccessibilityReadingResumedSignal(Toolkit::Control control)
 {
-  return GetControlImplementation(control).mAccessibilityData->mAccessibilityReadingResumedSignal;
+  return GetControlImplementation(control).GetOrCreateAccessibilityData().mAccessibilityReadingResumedSignal;
 }
 
 Toolkit::DevelControl::AccessibilityReadingCancelledSignalType& AccessibilityReadingCancelledSignal(Toolkit::Control control)
 {
-  return GetControlImplementation(control).mAccessibilityData->mAccessibilityReadingCancelledSignal;
+  return GetControlImplementation(control).GetOrCreateAccessibilityData().mAccessibilityReadingCancelledSignal;
 }
 
 Toolkit::DevelControl::AccessibilityReadingStoppedSignalType& AccessibilityReadingStoppedSignal(Toolkit::Control control)
 {
-  return GetControlImplementation(control).mAccessibilityData->mAccessibilityReadingStoppedSignal;
+  return GetControlImplementation(control).GetOrCreateAccessibilityData().mAccessibilityReadingStoppedSignal;
 }
 
 Toolkit::DevelControl::AccessibilityGetNameSignalType& AccessibilityGetNameSignal(Toolkit::Control control)
 {
-  return GetControlImplementation(control).mAccessibilityData->mAccessibilityGetNameSignal;
+  return GetControlImplementation(control).GetOrCreateAccessibilityData().mAccessibilityGetNameSignal;
 }
 
 Toolkit::DevelControl::AccessibilityGetDescriptionSignalType& AccessibilityGetDescriptionSignal(Toolkit::Control control)
 {
-  return GetControlImplementation(control).mAccessibilityData->mAccessibilityGetDescriptionSignal;
+  return GetControlImplementation(control).GetOrCreateAccessibilityData().mAccessibilityGetDescriptionSignal;
 }
 
 Toolkit::DevelControl::AccessibilityDoGestureSignalType& AccessibilityDoGestureSignal(Toolkit::Control control)
 {
-  return GetControlImplementation(control).mAccessibilityData->mAccessibilityDoGestureSignal;
+  return GetControlImplementation(control).GetOrCreateAccessibilityData().mAccessibilityDoGestureSignal;
 }
 
 Toolkit::DevelControl::AccessibilityActionSignalType& AccessibilityActionSignal(Toolkit::Control control)
 {
-  return GetControlImplementation(control).mAccessibilityData->mAccessibilityActionSignal;
+  return GetControlImplementation(control).GetOrCreateAccessibilityData().mAccessibilityActionSignal;
 }
 
 void AppendAccessibilityRelation(Toolkit::Control control, Dali::Actor destination, Dali::Accessibility::RelationType relation)
 {
   if(auto destinationAccessible = Accessibility::Accessible::Get(destination))
   {
-    GetControlImplementation(control).mAccessibilityData->mAccessibilityProps.relations[relation].insert(destinationAccessible);
+    GetControlImplementation(control).GetOrCreateAccessibilityData().mAccessibilityProps.relations[relation].insert(destinationAccessible);
   }
 }
 
 void RemoveAccessibilityRelation(Toolkit::Control control, Dali::Actor destination, Dali::Accessibility::RelationType relation)
 {
-  if(auto destinationAccessible = Accessibility::Accessible::Get(destination))
+  auto& controlImpl = GetControlImplementation(control);
+
+  auto* accessibilityData = controlImpl.GetAccessibilityData();
+  if(DALI_LIKELY(accessibilityData))
   {
-    auto& relations = GetControlImplementation(control).mAccessibilityData->mAccessibilityProps.relations;
+    if(auto destinationAccessible = Accessibility::Accessible::Get(destination))
+    {
+      auto& relations = accessibilityData->mAccessibilityProps.relations;
 
-    relations[relation].erase(destinationAccessible);
+      relations[relation].erase(destinationAccessible);
 
-    if(relations[relation].empty())
-    {
-      relations.erase(relation);
+      if(relations[relation].empty())
+      {
+        relations.erase(relation);
+      }
     }
   }
 }
 
 std::vector<Accessibility::Relation> GetAccessibilityRelations(Toolkit::Control control)
 {
-  const auto&                          relations = GetControlImplementation(control).mAccessibilityData->mAccessibilityProps.relations;
   std::vector<Accessibility::Relation> result;
 
-  for(auto& relation : relations)
+  auto& controlImpl = GetControlImplementation(control);
+
+  const auto* accessibilityData = controlImpl.GetAccessibilityData();
+  if(DALI_LIKELY(accessibilityData))
   {
-    auto& targets = relation.second;
+    const auto& relations = accessibilityData->mAccessibilityProps.relations;
+    for(const auto& relation : relations)
+    {
+      const auto& targets = relation.second;
 
-    result.emplace_back(Accessibility::Relation{relation.first, {}});
-    std::copy(targets.begin(), targets.end(), std::back_inserter(result.back().mTargets));
+      result.emplace_back(Accessibility::Relation{relation.first, {}});
+      std::copy(targets.begin(), targets.end(), std::back_inserter(result.back().mTargets));
+    }
   }
 
   return result;
@@ -236,7 +248,13 @@ std::vector<Accessibility::Relation> GetAccessibilityRelations(Toolkit::Control
 
 void ClearAccessibilityRelations(Toolkit::Control control)
 {
-  GetControlImplementation(control).mAccessibilityData->mAccessibilityProps.relations.clear();
+  auto& controlImpl = GetControlImplementation(control);
+
+  auto* accessibilityData = controlImpl.GetAccessibilityData();
+  if(DALI_LIKELY(accessibilityData))
+  {
+    accessibilityData->mAccessibilityProps.relations.clear();
+  }
 }
 
 void AppendAccessibilityAttribute(Toolkit::Control control, const std::string& key, const std::string& value)
index 0e1a7d457e89c278e2f82e3f02d85c19f8c2c596..c6f77f2ba17d003fcc03292350eb4fda187e9d66 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -69,6 +69,18 @@ static bool IsShowingGeometryOnScreen(Dali::Rect<> rect)
 {
   return rect.width > 0 && rect.height > 0;
 }
+
+static constexpr uint32_t DEFAULT_READING_INFO_TYPES_RAW_DATA = (1u << static_cast<uint32_t>(Dali::Accessibility::ReadingInfoType::NAME)) |
+                                                                (1u << static_cast<uint32_t>(Dali::Accessibility::ReadingInfoType::ROLE)) |
+                                                                (1u << static_cast<uint32_t>(Dali::Accessibility::ReadingInfoType::DESCRIPTION)) |
+                                                                (1u << static_cast<uint32_t>(Dali::Accessibility::ReadingInfoType::STATE));
+
+static constexpr uint32_t DEFAULT_DEVEL_CONTROL_ACCESSIBILITY_STATES_RAW_DATA = (1u << static_cast<uint32_t>(DevelControl::AccessibilityState::ENABLED)) |
+                                                                                (0u << static_cast<uint32_t>(DevelControl::AccessibilityState::SELECTED)) |
+                                                                                (0u << static_cast<uint32_t>(DevelControl::AccessibilityState::CHECKED)) |
+                                                                                (0u << static_cast<uint32_t>(DevelControl::AccessibilityState::BUSY)) |
+                                                                                (0u << static_cast<uint32_t>(DevelControl::AccessibilityState::EXPANDED));
+
 } // unnamed namespace
 
 Control::Impl::AccessibilityData::AccessibilityData(Control& controlImpl)
@@ -77,25 +89,9 @@ Control::Impl::AccessibilityData::AccessibilityData(Control& controlImpl)
   mAccessibilityDoGestureSignal(),
   mControlImpl(controlImpl),
   mIsAccessibilityPositionPropertyNotificationSet(false),
-  mIsAccessibilityPropertySetSignalRegistered(false),
-  mAccessibleCreatable(true)
+  mIsAccessibilityPropertySetSignalRegistered(false)
 {
-  Accessibility::Accessible::RegisterExternalAccessibleGetter([](Dali::Actor actor) -> std::pair<std::shared_ptr<Accessibility::Accessible>, bool> {
-    auto control = Toolkit::Control::DownCast(actor);
-    if(!control)
-    {
-      return {nullptr, true};
-    }
-
-    auto& controlImpl = Toolkit::Internal::GetImplementation(control);
-    if(controlImpl.mImpl->IsCreateAccessibleEnabled())
-    {
-      return {std::shared_ptr<DevelControl::ControlAccessible>(controlImpl.CreateAccessibleObject()), true};
-    }
-
-    return {nullptr, false};
-  });
-  mAccessibilityProps.states[DevelControl::AccessibilityState::ENABLED] = true;
+  mAccessibilityProps.states = GetDefaultControlAccessibilityStates();
 }
 
 void Control::Impl::AccessibilityData::AppendAccessibilityAttribute(const std::string& key, const std::string value)
@@ -259,12 +255,7 @@ Dali::Accessibility::ReadingInfoTypes Control::Impl::AccessibilityData::GetAcces
   }
   else
   {
-    Dali::Accessibility::ReadingInfoTypes types;
-    types[Dali::Accessibility::ReadingInfoType::NAME]        = true;
-    types[Dali::Accessibility::ReadingInfoType::ROLE]        = true;
-    types[Dali::Accessibility::ReadingInfoType::DESCRIPTION] = true;
-    types[Dali::Accessibility::ReadingInfoType::STATE]       = true;
-    return types;
+    return GetDefaultReadingInfoTypes();
   }
 
   if(value.empty())
@@ -347,19 +338,14 @@ std::shared_ptr<Toolkit::DevelControl::ControlAccessible> Control::Impl::Accessi
   return std::dynamic_pointer_cast<DevelControl::ControlAccessible>(Accessibility::Accessible::GetOwningPtr(mControlImpl.Self()));
 }
 
-bool Control::Impl::AccessibilityData::IsAccessibleCreated() const
-{
-  return !!Accessibility::Bridge::GetCurrentBridge()->GetAccessible(mControlImpl.Self());
-}
-
-void Control::Impl::AccessibilityData::EnableCreateAccessible(bool enable)
+Dali::Accessibility::ReadingInfoTypes Control::Impl::AccessibilityData::GetDefaultReadingInfoTypes()
 {
-  mAccessibleCreatable = enable;
+  return Dali::Accessibility::ReadingInfoTypes{DEFAULT_READING_INFO_TYPES_RAW_DATA};
 }
 
-bool Control::Impl::AccessibilityData::IsCreateAccessibleEnabled() const
+Toolkit::DevelControl::AccessibilityStates Control::Impl::AccessibilityData::GetDefaultControlAccessibilityStates()
 {
-  return mAccessibleCreatable;
+  return Toolkit::DevelControl::AccessibilityStates{DEFAULT_DEVEL_CONTROL_ACCESSIBILITY_STATES_RAW_DATA};
 }
 
 } // namespace Internal
index 271eef2ac7252bbb9208ec056db5146960617c5e..f60c114ea15e78d72e5207be336fdc85f3e1ef24 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_CONTROL_ACCESSIBILITY_DATA_H
 
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -63,32 +63,36 @@ public:
   Dali::Accessibility::ReadingInfoTypes GetAccessibilityReadingInfoType() const;
 
   /**
-   * @copydoc Dali::Toolkit::Internal::Control::Impl::CheckHighlightedObjectGeometry()
+   * @brief Checks highlighted object geometry if it is showing or not
    */
   void CheckHighlightedObjectGeometry();
 
   /**
-   * @copydoc Dali::Toolkit::Internal::Control::Impl::RegisterAccessibilityPositionPropertyNotification()
+   * @brief Register property notification to check highlighted object position
    */
   void RegisterAccessibilityPositionPropertyNotification();
 
   /**
-   * @copydoc Dali::Toolkit::Internal::Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
+   * @brief Remove property notification added by RegisterAccessibilityPositionPropertyNotification
    */
   void UnregisterAccessibilityPositionPropertyNotification();
 
   /**
-   * @copydoc Dali::Toolkit::Internal::Control::Impl::RegisterAccessibilityPropertySetSignal()
+   * @brief Register PropertySet signal to check highlighted object name and description
    */
   void RegisterAccessibilityPropertySetSignal();
 
   /**
-   * @copydoc Dali::Toolkit::Internal::Control::Impl::UnregisterAccessibilityPropertySetSignal()
+   * @brief Remove PropertySet signal added by RegisterAccessibilityPropertySetSignal
    */
   void UnregisterAccessibilityPropertySetSignal();
 
   /**
-   * @copydoc Dali::Toolkit::Internal::Control::Impl::OnAccessibilityPropertySet()
+   * @brief Signal callback of PropertySet when this object is become highlighted, so RegisterAccessibilityPropertySetSignal called.
+   *
+   * @param[in] handle Handle of the control.
+   * @param[in] index The index of property.
+   * @param[in] value The value of property.
    */
   void OnAccessibilityPropertySet(Dali::Handle& handle, Dali::Property::Index index, const Dali::Property::Value& value);
 
@@ -97,20 +101,16 @@ public:
    */
   std::shared_ptr<Toolkit::DevelControl::ControlAccessible> GetAccessibleObject();
 
+public:
   /**
-   * @copydoc Dali::Toolkit::Internal::Control::Impl::IsAccessibleCreated()
-   */
-  bool IsAccessibleCreated() const;
-
-  /**
-   * @copydoc Dali::Toolkit::Internal::Control::Impl::EnableCreateAccessible()
+   * @brief Helper function to get default reading info type attributes
    */
-  void EnableCreateAccessible(bool enable);
+  static Dali::Accessibility::ReadingInfoTypes GetDefaultReadingInfoTypes();
 
   /**
-   * @copydoc Dali::Toolkit::Internal::Control::Impl::IsCreateAccessibleEnabled()
+   * @brief Helper function to get control's default state attributes
    */
-  bool IsCreateAccessibleEnabled() const;
+  static Toolkit::DevelControl::AccessibilityStates GetDefaultControlAccessibilityStates();
 
 public:
   Toolkit::DevelControl::AccessibilityActivateSignalType         mAccessibilityActivateSignal;
@@ -128,18 +128,30 @@ public:
 
   struct AccessibilityProps
   {
-    std::string                                                                       name{};
-    std::string                                                                       description{};
-    std::string                                                                       value{};
-    std::string                                                                       automationId{};
-    int32_t                                                                           role{static_cast<int32_t>(DevelControl::AccessibilityRole::NONE)};
+    AccessibilityProps()
+    : isHighlightable(TriStateProperty::AUTO),
+      isHidden(false),
+      isScrollable(false),
+      isModal(false)
+    {
+    }
+
+    AccessibilityProps(const AccessibilityProps&) = default;
+    AccessibilityProps(AccessibilityProps&&)      = default;
+
+    std::string name{};
+    std::string description{};
+    std::string value{};
+    std::string automationId{};
+
     DevelControl::AccessibilityStates                                                 states{};
-    std::map<Dali::Accessibility::RelationType, std::set<Accessibility::Accessible*>> relations;
+    std::map<Dali::Accessibility::RelationType, std::set<Accessibility::Accessible*>> relations{};
     Property::Map                                                                     extraAttributes{};
-    TriStateProperty                                                                  isHighlightable{TriStateProperty::AUTO};
-    bool                                                                              isHidden{false};
-    bool                                                                              isScrollable{false};
-    bool                                                                              isModal{false};
+
+    TriStateProperty isHighlightable : 3;
+    bool             isHidden : 1;
+    bool             isScrollable : 1;
+    bool             isModal : 1;
   } mAccessibilityProps;
 
 private:
@@ -151,7 +163,6 @@ private:
 
   bool mIsAccessibilityPositionPropertyNotificationSet : 1;
   bool mIsAccessibilityPropertySetSignalRegistered : 1;
-  bool mAccessibleCreatable : 1;
 };
 } // namespace Internal
 } // namespace Toolkit
index f8e89e576e9025118df006690e2fe624a83adf56..4e09bacf92d080d1198bf10403bb42e48654e71c 100644 (file)
@@ -44,6 +44,7 @@
 #include <dali-toolkit/devel-api/controls/control-devel.h>
 #include <dali-toolkit/devel-api/controls/control-wrapper-impl.h>
 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
+#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
 #include <dali-toolkit/internal/styling/style-manager-impl.h>
 #include <dali-toolkit/internal/visuals/transition-data-impl.h>
 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
@@ -52,8 +53,6 @@
 #include <dali-toolkit/public-api/visuals/color-visual-properties.h>
 #include <dali-toolkit/public-api/visuals/visual-properties.h>
 
-#include <dali-toolkit/devel-api/visuals/visual-actions-devel.h>
-
 namespace Dali
 {
 namespace Toolkit
@@ -426,14 +425,15 @@ Control::Impl::Impl(Control& controlImpl)
   mInputMethodContext(),
   mIdleCallback(nullptr),
   mFlags(Control::ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
+  mAccessibilityRole{static_cast<int32_t>(DevelControl::AccessibilityRole::NONE)},
   mIsKeyboardNavigationSupported(false),
   mIsKeyboardFocusGroup(false),
   mIsEmittingResourceReadySignal(false),
   mIdleCallbackRegistered(false),
   mDispatchKeyEvents(true),
+  mAccessibleCreatable(true),
   mProcessorRegistered(false)
 {
-  mAccessibilityData = std::make_unique<AccessibilityData>(mControlImpl);
 }
 
 Control::Impl::~Impl()
@@ -947,7 +947,10 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         std::string name;
         if(value.Get(name))
         {
-          controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.name = std::move(name);
+          if(DALI_LIKELY(controlImpl.mImpl->GetAccessibilityData()) || !name.empty())
+          {
+            controlImpl.mImpl->GetOrCreateAccessibilityData().mAccessibilityProps.name = std::move(name);
+          }
         }
         break;
       }
@@ -957,7 +960,10 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         std::string text;
         if(value.Get(text))
         {
-          controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.description = std::move(text);
+          if(DALI_LIKELY(controlImpl.mImpl->GetAccessibilityData()) || !text.empty())
+          {
+            controlImpl.mImpl->GetOrCreateAccessibilityData().mAccessibilityProps.description = std::move(text);
+          }
         }
         break;
       }
@@ -967,7 +973,7 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         int32_t role;
         if(value.Get(role))
         {
-          controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.role = role;
+          controlImpl.mImpl->mAccessibilityRole = role;
         }
         break;
       }
@@ -977,7 +983,7 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         bool highlightable;
         if(value.Get(highlightable))
         {
-          controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.isHighlightable = highlightable ? TriStateProperty::TRUE : TriStateProperty::FALSE;
+          controlImpl.mImpl->GetOrCreateAccessibilityData().mAccessibilityProps.isHighlightable = highlightable ? TriStateProperty::TRUE : TriStateProperty::FALSE;
         }
         break;
       }
@@ -985,9 +991,12 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
       case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
       {
         const Property::Map* map = value.GetMap();
-        if(map && !map->Empty())
+        if(map)
         {
-          controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.extraAttributes = *map;
+          if(DALI_LIKELY(controlImpl.mImpl->GetAccessibilityData()) || !map->Empty())
+          {
+            controlImpl.mImpl->GetOrCreateAccessibilityData().mAccessibilityProps.extraAttributes = *map;
+          }
         }
         break;
       }
@@ -1007,15 +1016,20 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         bool hidden;
         if(value.Get(hidden))
         {
-          controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.isHidden = hidden;
-
-          auto accessible = controlImpl.GetAccessibleObject();
-          if(DALI_LIKELY(accessible))
+          const auto* accessibilityData = controlImpl.mImpl->GetAccessibilityData();
+          const bool  originalHidden    = DALI_LIKELY(accessibilityData) ? accessibilityData->mAccessibilityProps.isHidden : false;
+          if(originalHidden != hidden)
           {
-            auto* parent = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
-            if(parent)
+            controlImpl.mImpl->GetOrCreateAccessibilityData().mAccessibilityProps.isHidden = hidden;
+
+            auto accessible = controlImpl.GetAccessibleObject();
+            if(DALI_LIKELY(accessible))
             {
-              parent->OnChildrenChanged();
+              auto* parent = dynamic_cast<Dali::Accessibility::ActorAccessible*>(accessible->GetParent());
+              if(parent)
+              {
+                parent->OnChildrenChanged();
+              }
             }
           }
         }
@@ -1045,7 +1059,10 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         std::string automationId;
         if(value.Get(automationId))
         {
-          controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.automationId = std::move(automationId);
+          if(DALI_LIKELY(controlImpl.mImpl->GetAccessibilityData()) || !automationId.empty())
+          {
+            controlImpl.mImpl->GetOrCreateAccessibilityData().mAccessibilityProps.automationId = std::move(automationId);
+          }
         }
         break;
       }
@@ -1055,7 +1072,10 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         std::string accessibilityValue;
         if(value.Get(accessibilityValue))
         {
-          controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.value = std::move(accessibilityValue);
+          if(DALI_LIKELY(controlImpl.mImpl->GetAccessibilityData()) || !accessibilityValue.empty())
+          {
+            controlImpl.mImpl->GetOrCreateAccessibilityData().mAccessibilityProps.value = std::move(accessibilityValue);
+          }
         }
         break;
       }
@@ -1065,7 +1085,10 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         bool isScrollable;
         if(value.Get(isScrollable))
         {
-          controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.isScrollable = isScrollable;
+          if(DALI_LIKELY(controlImpl.mImpl->GetAccessibilityData()) || isScrollable)
+          {
+            controlImpl.mImpl->GetOrCreateAccessibilityData().mAccessibilityProps.isScrollable = isScrollable;
+          }
         }
         break;
       }
@@ -1075,7 +1098,10 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         int32_t states;
         if(value.Get(states))
         {
-          controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.states = Toolkit::DevelControl::AccessibilityStates{static_cast<uint32_t>(states)};
+          if(DALI_LIKELY(controlImpl.mImpl->GetAccessibilityData()) || states != static_cast<int32_t>(AccessibilityData::GetDefaultControlAccessibilityStates().GetRawData32()))
+          {
+            controlImpl.mImpl->GetOrCreateAccessibilityData().mAccessibilityProps.states = Toolkit::DevelControl::AccessibilityStates{static_cast<uint32_t>(states)};
+          }
         }
         break;
       }
@@ -1085,7 +1111,10 @@ void Control::Impl::SetProperty(BaseObject* object, Property::Index index, const
         bool isModal;
         if(value.Get(isModal))
         {
-          controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.isModal = isModal;
+          if(DALI_LIKELY(controlImpl.mImpl->GetAccessibilityData()) || isModal)
+          {
+            controlImpl.mImpl->GetOrCreateAccessibilityData().mAccessibilityProps.isModal = isModal;
+          }
         }
         break;
       }
@@ -1338,31 +1367,35 @@ Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index i
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_NAME:
       {
-        value = controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.name;
+        const auto* accessibilityData = controlImpl.mImpl->GetAccessibilityData();
+        value                         = DALI_LIKELY(accessibilityData) ? accessibilityData->mAccessibilityProps.name : "";
         break;
       }
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_DESCRIPTION:
       {
-        value = controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.description;
+        const auto* accessibilityData = controlImpl.mImpl->GetAccessibilityData();
+        value                         = DALI_LIKELY(accessibilityData) ? accessibilityData->mAccessibilityProps.description : "";
         break;
       }
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_ROLE:
       {
-        value = controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.role;
+        value = controlImpl.mImpl->mAccessibilityRole;
         break;
       }
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIGHLIGHTABLE:
       {
-        value = controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.isHighlightable == TriStateProperty::TRUE ? true : false;
+        const auto* accessibilityData = controlImpl.mImpl->GetAccessibilityData();
+        value                         = (DALI_LIKELY(accessibilityData) && accessibilityData->mAccessibilityProps.isHighlightable == TriStateProperty::TRUE) ? true : false;
         break;
       }
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_ATTRIBUTES:
       {
-        value = controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.extraAttributes;
+        const auto* accessibilityData = controlImpl.mImpl->GetAccessibilityData();
+        value                         = DALI_LIKELY(accessibilityData) ? accessibilityData->mAccessibilityProps.extraAttributes : Property::Map();
         break;
       }
 
@@ -1374,7 +1407,8 @@ Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index i
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_HIDDEN:
       {
-        value = controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.isHidden;
+        const auto* accessibilityData = controlImpl.mImpl->GetAccessibilityData();
+        value                         = DALI_LIKELY(accessibilityData) ? accessibilityData->mAccessibilityProps.isHidden : false;
         break;
       }
 
@@ -1392,31 +1426,36 @@ Property::Value Control::Impl::GetProperty(BaseObject* object, Property::Index i
 
       case Toolkit::DevelControl::Property::AUTOMATION_ID:
       {
-        value = controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.automationId;
+        const auto* accessibilityData = controlImpl.mImpl->GetAccessibilityData();
+        value                         = DALI_LIKELY(accessibilityData) ? accessibilityData->mAccessibilityProps.automationId : "";
         break;
       }
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_VALUE:
       {
-        value = controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.value;
+        const auto* accessibilityData = controlImpl.mImpl->GetAccessibilityData();
+        value                         = DALI_LIKELY(accessibilityData) ? accessibilityData->mAccessibilityProps.value : "";
         break;
       }
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_SCROLLABLE:
       {
-        value = controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.isScrollable;
+        const auto* accessibilityData = controlImpl.mImpl->GetAccessibilityData();
+        value                         = DALI_LIKELY(accessibilityData) ? accessibilityData->mAccessibilityProps.isScrollable : false;
         break;
       }
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_STATES:
       {
-        value = static_cast<int32_t>(controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.states.GetRawData32());
+        const auto* accessibilityData = controlImpl.mImpl->GetAccessibilityData();
+        value                         = static_cast<int32_t>((DALI_LIKELY(accessibilityData) ? accessibilityData->mAccessibilityProps.states : AccessibilityData::GetDefaultControlAccessibilityStates()).GetRawData32());
         break;
       }
 
       case Toolkit::DevelControl::Property::ACCESSIBILITY_IS_MODAL:
       {
-        value = controlImpl.mImpl->mAccessibilityData->mAccessibilityProps.isModal;
+        const auto* accessibilityData = controlImpl.mImpl->GetAccessibilityData();
+        value                         = DALI_LIKELY(accessibilityData) ? accessibilityData->mAccessibilityProps.isModal : false;
         break;
       }
 
@@ -1627,74 +1666,77 @@ bool Control::Impl::FilterKeyEvent(const KeyEvent& event)
   return consumed;
 }
 
-void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
-{
-  mAccessibilityData->AppendAccessibilityAttribute(key, value);
-}
-
-void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
-{
-  mAccessibilityData->RemoveAccessibilityAttribute(key);
-}
-
-void Control::Impl::ClearAccessibilityAttributes()
-{
-  mAccessibilityData->ClearAccessibilityAttributes();
-}
-
-void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
+Control::Impl::AccessibilityData& Control::Impl::GetOrCreateAccessibilityData()
 {
-  mAccessibilityData->SetAccessibilityReadingInfoType(types);
-}
-
-Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
-{
-  return mAccessibilityData->GetAccessibilityReadingInfoType();
+  if(DALI_UNLIKELY(!mAccessibilityData))
+  {
+    // Create only 1 times.
+    mAccessibilityData = std::make_unique<AccessibilityData>(mControlImpl);
+  }
+  DALI_ASSERT_DEBUG(mAccessibilityData && "AccessibilityData not created!");
+  return *mAccessibilityData;
 }
 
-void Control::Impl::CheckHighlightedObjectGeometry()
+Control::Impl::AccessibilityData* Control::Impl::GetAccessibilityData() const
 {
-  mAccessibilityData->CheckHighlightedObjectGeometry();
+  return mAccessibilityData.get();
 }
 
-void Control::Impl::RegisterAccessibilityPositionPropertyNotification()
+void Control::Impl::AppendAccessibilityAttribute(const std::string& key, const std::string value)
 {
-  mAccessibilityData->RegisterAccessibilityPositionPropertyNotification();
+  GetOrCreateAccessibilityData().AppendAccessibilityAttribute(key, value);
 }
 
-void Control::Impl::UnregisterAccessibilityPositionPropertyNotification()
+void Control::Impl::RemoveAccessibilityAttribute(const std::string& key)
 {
-  mAccessibilityData->UnregisterAccessibilityPositionPropertyNotification();
+  auto* accessibilityData = GetAccessibilityData();
+  if(DALI_LIKELY(accessibilityData))
+  {
+    accessibilityData->RemoveAccessibilityAttribute(key);
+  }
 }
 
-void Control::Impl::RegisterAccessibilityPropertySetSignal()
+void Control::Impl::ClearAccessibilityAttributes()
 {
-  mAccessibilityData->RegisterAccessibilityPropertySetSignal();
+  auto* accessibilityData = GetAccessibilityData();
+  if(DALI_LIKELY(accessibilityData))
+  {
+    accessibilityData->ClearAccessibilityAttributes();
+  }
 }
 
-void Control::Impl::UnregisterAccessibilityPropertySetSignal()
+void Control::Impl::SetAccessibilityReadingInfoType(const Dali::Accessibility::ReadingInfoTypes types)
 {
-  mAccessibilityData->UnregisterAccessibilityPropertySetSignal();
+  GetOrCreateAccessibilityData().SetAccessibilityReadingInfoType(types);
 }
 
-void Control::Impl::OnAccessibilityPropertySet(Dali::Handle& handle, Dali::Property::Index index, const Dali::Property::Value& value)
+Dali::Accessibility::ReadingInfoTypes Control::Impl::GetAccessibilityReadingInfoType() const
 {
-  mAccessibilityData->OnAccessibilityPropertySet(handle, index, value);
+  const auto* accessibilityData = GetAccessibilityData();
+  if(DALI_LIKELY(accessibilityData))
+  {
+    return accessibilityData->GetAccessibilityReadingInfoType();
+  }
+  else
+  {
+    // Return default ReadingInfoTypes
+    return AccessibilityData::GetDefaultReadingInfoTypes();
+  }
 }
 
 bool Control::Impl::IsAccessibleCreated() const
 {
-  return mAccessibilityData->IsAccessibleCreated();
+  return !!Accessibility::Bridge::GetCurrentBridge()->GetAccessible(mControlImpl.Self());
 }
 
 void Control::Impl::EnableCreateAccessible(bool enable)
 {
-  mAccessibilityData->EnableCreateAccessible(enable);
+  mAccessibleCreatable = enable;
 }
 
 bool Control::Impl::IsCreateAccessibleEnabled() const
 {
-  return mAccessibilityData->IsCreateAccessibleEnabled();
+  return mAccessibleCreatable;
 }
 
 void Control::Impl::ApplyFittingMode(const Vector2& size)
@@ -1908,7 +1950,7 @@ bool Control::Impl::OnIdleCallback()
 
 std::shared_ptr<Toolkit::DevelControl::ControlAccessible> Control::Impl::GetAccessibleObject()
 {
-  return mAccessibilityData->GetAccessibleObject();
+  return GetOrCreateAccessibilityData().GetAccessibleObject();
 }
 
 void Control::Impl::RegisterProcessorOnce()
index 2ee794ea81219ffae94b8a8c52ed26edb8ea11b9..bf9245236b79b6c3f1784a7ae5c4c5ce721d684f 100644 (file)
@@ -305,6 +305,18 @@ public:
    */
   bool FilterKeyEvent(const KeyEvent& event);
 
+  /**
+   * @brief Get private AccessibilityData context for this impl. If not created yet, it will create new data.
+   * @return The l-value of AccessibilityData context.
+   */
+  [[nodiscard]] AccessibilityData& GetOrCreateAccessibilityData();
+
+  /**
+   * @brief Get private AccessibilityData context for this impl.
+   * @return The pointer of AccessibilityData context.
+   */
+  [[nodiscard]] AccessibilityData* GetAccessibilityData() const;
+
   /**
    * @brief Adds accessibility attribute
    * @param[in] key Attribute name to set
@@ -473,40 +485,6 @@ private:
    */
   bool OnIdleCallback();
 
-  /**
-   * @brief Checks highlighted object geometry if it is showing or not
-   */
-  void CheckHighlightedObjectGeometry();
-
-  /**
-   * @brief Register property notification to check highlighted object position
-   */
-  void RegisterAccessibilityPositionPropertyNotification();
-
-  /**
-   * @brief Remove property notification added by RegisterAccessibilityPositionPropertyNotification
-   */
-  void UnregisterAccessibilityPositionPropertyNotification();
-
-  /**
-   * @brief Register PropertySet signal to check highlighted object name and description
-   */
-  void RegisterAccessibilityPropertySetSignal();
-
-  /**
-   * @brief Remove PropertySet signal added by RegisterAccessibilityPropertySetSignal
-   */
-  void UnregisterAccessibilityPropertySetSignal();
-
-  /**
-   * @brief Signal callback of PropertySet when this object is become highlighted, so RegisterAccessibilityPropertySetSignal called.
-   *
-   * @param[in] handle Handle of the control.
-   * @param[in] index The index of property.
-   * @param[in] value The value of property.
-   */
-  void OnAccessibilityPropertySet(Dali::Handle& handle, Dali::Property::Index index, const Dali::Property::Value& value);
-
   /**
    * Set off-screen rendering.
    * @param[in] offScreenRenderingType enum OffScreenRenderingType
@@ -570,12 +548,18 @@ public:
   CallbackBase*      mIdleCallback; ///< The idle callback to emit the resource ready signal.
 
   ControlBehaviour mFlags : CONTROL_BEHAVIOUR_FLAG_COUNT; ///< Flags passed in from constructor.
-  bool             mIsKeyboardNavigationSupported : 1;    ///< Stores whether keyboard navigation is supported by the control.
-  bool             mIsKeyboardFocusGroup : 1;             ///< Stores whether the control is a focus group.
-  bool             mIsEmittingResourceReadySignal : 1;    ///< True during ResourceReady().
-  bool             mIdleCallbackRegistered : 1;           ///< True if need to emit the resource ready signal again.
-  bool             mDispatchKeyEvents : 1;                ///< Whether the actor emits key event signals
-  bool             mProcessorRegistered : 1;              ///< Whether the processor is registered.
+
+  // Frequencly touched accessibility relative values.
+  // Keep it on Impl to avoid AccessibilityData creation.
+  int32_t mAccessibilityRole : Dali::Log<static_cast<uint32_t>(DevelControl::AccessibilityRole::MAX_COUNT)>::value + 2;
+
+  bool mIsKeyboardNavigationSupported : 1; ///< Stores whether keyboard navigation is supported by the control.
+  bool mIsKeyboardFocusGroup : 1;          ///< Stores whether the control is a focus group.
+  bool mIsEmittingResourceReadySignal : 1; ///< True during ResourceReady().
+  bool mIdleCallbackRegistered : 1;        ///< True if need to emit the resource ready signal again.
+  bool mDispatchKeyEvents : 1;             ///< Whether the actor emits key event signals
+  bool mAccessibleCreatable : 1;           ///< Whether we can create new accessible or not.
+  bool mProcessorRegistered : 1;           ///< Whether the processor is registered.
 
   // Properties - these need to be members of Internal::Control::Impl as they access private methods/data of Internal::Control and Internal::Control::Impl.
   static const PropertyRegistration PROPERTY_1;
index e7ccdfa319c1a8169aa93c38a60df547f4e6d5fc..ab39b95a282f4ce3e169514e0e1a939f0370b5a3 100644 (file)
@@ -152,7 +152,11 @@ void Magnifier::SetSourceActor(Actor actor)
   mTask.SetSourceActor(actor);
 }
 
-void Magnifier::Initialize()
+Magnifier::~Magnifier()
+{
+}
+
+void Magnifier::OnInitialize()
 {
   Actor   self = Self();
   Vector2 stageSize(Stage::GetCurrent().GetSize());
@@ -221,10 +225,6 @@ void Magnifier::Initialize()
   self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::FILLER);
 }
 
-Magnifier::~Magnifier()
-{
-}
-
 void Magnifier::InitializeRenderTask()
 {
   Stage stage = Stage::GetCurrent();
index 7cf69403ca9909f6d5c4db8f43ed8de52ef48182..ba301abe4d06d608fe53bd6e9c72864fdf79bd7b 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TOOLKIT_INTERNAL_MAGNIFIER_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -112,17 +112,17 @@ protected:
    */
   Magnifier();
 
-  /**
-   * 2nd-phase initialization.
-   */
-  void Initialize();
-
   /**
    * A reference counted object may only be deleted by calling Unreference()
    */
   virtual ~Magnifier();
 
 private:
+  /**
+   * @copydoc Toolkit::Control::OnInitialize()
+   */
+  void OnInitialize() override;
+
   /**
    * Initializes the render task required to render contents.
    */
index e461b0b91012415109f88466d3380b92d1e879a7..9677334833edc6737d57dd681c35c758d24158a4 100644 (file)
@@ -85,6 +85,33 @@ void CreateClippingRenderer(Control& controlImpl)
   }
 }
 
+/**
+ * @brief Register external accessible getter function only 1 times per each programs.
+ * @note We could call this API only for main thread. So use static bool flag is enough than std::once_flag
+ */
+void RegisterControlAccessibleGetter()
+{
+  static bool onceFlag = false;
+  if(DALI_UNLIKELY(!onceFlag))
+  {
+    onceFlag = true;
+    Accessibility::Accessible::RegisterExternalAccessibleGetter([](Dali::Actor actor) -> std::pair<std::shared_ptr<Accessibility::Accessible>, bool> {
+      auto control = Toolkit::Control::DownCast(actor);
+      if(!control)
+      {
+        return {nullptr, true};
+      }
+
+      if(Toolkit::DevelControl::IsCreateAccessibleEnabled(control))
+      {
+        auto& controlImpl = Toolkit::Internal::GetImplementation(control);
+        return {std::shared_ptr<DevelControl::ControlAccessible>(controlImpl.CreateAccessibleObject()), true};
+      }
+
+      return {nullptr, false};
+    });
+  }
+}
 } // unnamed namespace
 
 Toolkit::Control Control::New()
@@ -469,11 +496,13 @@ Control::~Control()
 
 void Control::Initialize()
 {
-  if(DALI_LIKELY(!(mImpl->mFlags & DISABLE_VISUALS)))
+  if(!(mImpl->mFlags & DISABLE_VISUALS))
   {
     mImpl->InitializeVisualData();
   }
 
+  RegisterControlAccessibleGetter();
+
   // Call deriving classes so initialised before styling is applied to them.
   OnInitialize();