Make RenderEffect::OwnerControl as WeakHandle 16/316716/10
authorEunki, Hong <eunkiki.hong@samsung.com>
Tue, 27 Aug 2024 07:34:07 +0000 (16:34 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Fri, 30 Aug 2024 05:42:09 +0000 (14:42 +0900)
Let we make RenderEffect's owner control as WeakHandle<Control>.

It will remove cyclic reference of BaseHandle.

And also, let we don't touch WeakHandle of control itself
during destruction. It "might" not be valid during destruction.

Since RenderEffect have string-relationship with control now,
we can assume that if RenderEffect owned by some control, it will
never be destructed. So we don't need to touch owner.

Change-Id: Icc0fd614cbfd9f66dd5066cc60c51fc2f21907ce
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
automated-tests/src/dali-toolkit-internal/CMakeLists.txt
automated-tests/src/dali-toolkit-internal/utc-Dali-RenderEffect-internal.cpp [new file with mode: 0644]
dali-toolkit/internal/controls/render-effects/blur-effect-impl.h
dali-toolkit/internal/controls/render-effects/render-effect-impl.cpp
dali-toolkit/internal/controls/render-effects/render-effect-impl.h

index 5d7567b93c02a2a4376e075ffc90eba86b310820..c453a172ca245cbbc3d0556a8dd5ce8e54f731a1 100755 (executable)
@@ -20,6 +20,7 @@ SET(TC_SOURCES
  utc-Dali-LineHelperFunctions.cpp
  utc-Dali-LogicalModel.cpp
  utc-Dali-PropertyHelper.cpp
+ utc-Dali-RenderEffect-internal.cpp
  utc-Dali-SvgLoader.cpp
  utc-Dali-Text-AbstractStyleCharacterRun.cpp
  utc-Dali-Text-Characters.cpp
diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-RenderEffect-internal.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-RenderEffect-internal.cpp
new file mode 100644 (file)
index 0000000..9a3bbc6
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * 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.
+ * 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 <dali-toolkit-test-suite-utils.h>
+
+#include <dali-toolkit/internal/controls/render-effects/render-effect-impl.h>
+
+void utc_dali_toolkit_internal_render_effect_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_toolkit_internal_render_effect_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace Dali::Toolkit
+{
+namespace Internal
+{
+class TestRenderEffectImpl;
+} // namespace Internal
+
+class TestRenderEffect : public Dali::Toolkit::RenderEffect
+{
+public:
+  static TestRenderEffect New();
+  TestRenderEffect()                               = default;
+  TestRenderEffect(const TestRenderEffect& handle) = default;
+  ~TestRenderEffect()                              = default;
+
+public: // Not intended for use by Application developers
+  explicit TestRenderEffect(Internal::TestRenderEffectImpl* testRenderEffectImpl);
+};
+
+namespace Internal
+{
+class TestRenderEffectImpl;
+using TestRenderEffectImplPtr = IntrusivePtr<TestRenderEffectImpl>;
+class TestRenderEffectImpl : public RenderEffectImpl
+{
+public:
+  static TestRenderEffectImplPtr New()
+  {
+    TestRenderEffectImplPtr handle = new TestRenderEffectImpl();
+    handle->Initialize();
+    return handle;
+  }
+
+protected:
+  TestRenderEffectImpl()
+  : mOnActivated(false)
+  {
+  }
+  virtual ~TestRenderEffectImpl()
+  {
+  }
+
+  void OnInitialize() override
+  {
+  }
+
+  void OnActivate() override
+  {
+    mOnActivated = true;
+  }
+
+  void OnDeactivate() override
+  {
+    mOnActivated = false;
+  }
+
+public:
+  Dali::Toolkit::Control GetOwnerControl() const
+  {
+    return RenderEffectImpl::GetOwnerControl();
+  }
+
+public:
+  bool mOnActivated;
+};
+
+inline Dali::Toolkit::Internal::TestRenderEffectImpl& GetImplementation(Dali::Toolkit::TestRenderEffect& handle)
+{
+  BaseObject& object = handle.GetBaseObject();
+  return static_cast<Toolkit::Internal::TestRenderEffectImpl&>(object);
+}
+} // namespace Internal
+
+TestRenderEffect TestRenderEffect::New()
+{
+  Internal::TestRenderEffectImplPtr internal = Internal::TestRenderEffectImpl::New();
+  return TestRenderEffect(internal.Get());
+}
+
+TestRenderEffect::TestRenderEffect(Internal::TestRenderEffectImpl* testRenderEffectImpl)
+: RenderEffect(testRenderEffectImpl)
+{
+}
+} // namespace Dali::Toolkit
+
+using namespace Dali::Toolkit;
+
+int UtcDaliInternalRenderEffectNewP(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliInternalRenderEffectNewP");
+
+  Toolkit::TestRenderEffect testEffect = Toolkit::TestRenderEffect::New();
+  DALI_TEST_CHECK(testEffect);
+
+  // Check that effect is not activate yet.
+  Toolkit::Internal::TestRenderEffectImpl& impl = Toolkit::Internal::GetImplementation(testEffect);
+  DALI_TEST_EQUALS(impl.IsActivated(), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(impl.mOnActivated, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(impl.GetOwnerControl(), Toolkit::Control(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliInternalRenderEffectGetOwnerControl01(void)
+{
+  tet_infoline("UtcDaliInternalRenderEffecGetOwnerControl01");
+
+  Toolkit::TestRenderEffect testEffect = Toolkit::TestRenderEffect::New();
+  DALI_TEST_CHECK(testEffect);
+
+  // Check that effect is not activate yet.
+  Toolkit::Internal::TestRenderEffectImpl& impl = Toolkit::Internal::GetImplementation(testEffect);
+  DALI_TEST_EQUALS(impl.IsActivated(), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(impl.mOnActivated, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(impl.GetOwnerControl(), Toolkit::Control(), TEST_LOCATION);
+  {
+    ToolkitTestApplication application;
+
+    Integration::Scene scene = application.GetScene();
+
+    Control control = Control::New();
+    control.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+    control.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
+    scene.Add(control);
+
+    tet_printf("Test effect set, and activate due to control scene on.\n");
+    control.SetRenderEffect(testEffect);
+
+    DALI_TEST_EQUALS(impl.IsActivated(), true, TEST_LOCATION);
+    DALI_TEST_EQUALS(impl.mOnActivated, true, TEST_LOCATION);
+    DALI_TEST_EQUALS(impl.GetOwnerControl(), control, TEST_LOCATION);
+
+    control.Unparent();
+
+    DALI_TEST_EQUALS(impl.IsActivated(), false, TEST_LOCATION);
+    DALI_TEST_EQUALS(impl.mOnActivated, false, TEST_LOCATION);
+    DALI_TEST_EQUALS(impl.GetOwnerControl(), control, TEST_LOCATION);
+
+    scene.Add(control);
+
+    DALI_TEST_EQUALS(impl.IsActivated(), true, TEST_LOCATION);
+    DALI_TEST_EQUALS(impl.mOnActivated, true, TEST_LOCATION);
+    DALI_TEST_EQUALS(impl.GetOwnerControl(), control, TEST_LOCATION);
+
+    // Control released.
+
+    control.Unparent();
+    control.Reset();
+
+    tet_printf("Test effect owner control is empty after control destructed.\n");
+    DALI_TEST_CHECK(testEffect);
+
+    DALI_TEST_EQUALS(impl.IsActivated(), false, TEST_LOCATION);
+    DALI_TEST_EQUALS(impl.mOnActivated, false, TEST_LOCATION);
+    DALI_TEST_EQUALS(impl.GetOwnerControl(), Toolkit::Control(), TEST_LOCATION);
+
+    control = Control::New();
+    control.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+    control.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
+    scene.Add(control);
+
+    tet_printf("Test effect set again.\n");
+    control.SetRenderEffect(testEffect);
+
+    DALI_TEST_EQUALS(impl.IsActivated(), true, TEST_LOCATION);
+    DALI_TEST_EQUALS(impl.mOnActivated, true, TEST_LOCATION);
+    DALI_TEST_EQUALS(impl.GetOwnerControl(), control, TEST_LOCATION);
+
+    // Terminate application.
+  }
+
+  tet_printf("Test effect owner control is empty and deactivated after application destructed.\n");
+  DALI_TEST_CHECK(testEffect);
+
+  DALI_TEST_EQUALS(impl.IsActivated(), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(impl.mOnActivated, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(impl.GetOwnerControl(), Toolkit::Control(), TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliInternalRenderEffectGetOwnerControl02(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline("UtcDaliInternalRenderEffecGetOwnerControl02");
+
+  Integration::Scene scene = application.GetScene();
+
+  Control control1 = Control::New();
+  control1.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+  control1.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
+  scene.Add(control1);
+
+  Control control2 = Control::New();
+  control2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+  control2.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
+  scene.Add(control2);
+
+  Toolkit::TestRenderEffect testEffect = Toolkit::TestRenderEffect::New();
+  DALI_TEST_CHECK(testEffect);
+
+  // Check that effect is not activate yet.
+  Toolkit::Internal::TestRenderEffectImpl& impl = Toolkit::Internal::GetImplementation(testEffect);
+  DALI_TEST_EQUALS(impl.IsActivated(), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(impl.mOnActivated, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(impl.GetOwnerControl(), Toolkit::Control(), TEST_LOCATION);
+
+  tet_printf("Test effect set, and activate due to control scene on.\n");
+  control1.SetRenderEffect(testEffect);
+
+  DALI_TEST_EQUALS(impl.IsActivated(), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(impl.mOnActivated, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(impl.GetOwnerControl(), control1, TEST_LOCATION);
+
+  tet_printf("Test effect set to another control\n");
+  control2.SetRenderEffect(testEffect);
+
+  DALI_TEST_EQUALS(impl.IsActivated(), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(impl.mOnActivated, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(impl.GetOwnerControl(), control2, TEST_LOCATION);
+
+  tet_printf("Test control1 call ClearRenderEffect don't have any effort to effect\n");
+  control1.ClearRenderEffect();
+
+  DALI_TEST_EQUALS(impl.IsActivated(), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(impl.mOnActivated, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(impl.GetOwnerControl(), control2, TEST_LOCATION);
+
+  tet_printf("Test control2 call ClearRenderEffect\n");
+  control2.ClearRenderEffect();
+
+  DALI_TEST_EQUALS(impl.IsActivated(), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(impl.mOnActivated, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(impl.GetOwnerControl(), Toolkit::Control(), TEST_LOCATION);
+
+  tet_printf("Reset control1 effect\n");
+  control1.SetRenderEffect(testEffect);
+
+  DALI_TEST_EQUALS(impl.IsActivated(), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(impl.mOnActivated, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(impl.GetOwnerControl(), control1, TEST_LOCATION);
+
+  tet_printf("Test control1 call SetRenderEffect with empty handle\n");
+  control1.SetRenderEffect(Toolkit::RenderEffect());
+
+  DALI_TEST_EQUALS(impl.IsActivated(), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(impl.mOnActivated, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(impl.GetOwnerControl(), Toolkit::Control(), TEST_LOCATION);
+
+  END_TEST;
+}
index 7234120b387dfd23a17761f9ee4e4c66cc001b4a..d9db0518efcb8f9276d2c8bc60cbf0f244596f54 100644 (file)
@@ -35,10 +35,9 @@ namespace Dali
 {
 namespace Toolkit
 {
-class BlurEffectImpl;
-
 namespace Internal
 {
+class BlurEffectImpl;
 using BlurEffectImplPtr = IntrusivePtr<BlurEffectImpl>;
 
 class BlurEffectImpl : public RenderEffectImpl
index f5e38e4ada5b26a7b54414fa66ec16f30edcbb98..6c58cdd7fec7505a23cd6893ef33be7919efb1ae 100644 (file)
@@ -54,35 +54,38 @@ RenderEffectImpl::RenderEffectImpl()
 
 RenderEffectImpl::~RenderEffectImpl()
 {
-  DALI_LOG_INFO(gRenderEffectLogFilter, Debug::Verbose, "[RenderEffect:%p] Destructor. [ID:%d]\n", this, mOwnerControl ? mOwnerControl.GetProperty<int>(Actor::Property::ID) : -1);
-  if(mOwnerControl)
-  {
-    mOwnerControl.ClearRenderEffect();
-  }
+  DALI_LOG_INFO(gRenderEffectLogFilter, Debug::Verbose, "[RenderEffect:%p] Destructor.\n", this);
+
+  // Reset weak handle first. (Since it might not valid during destruction.)
+  mOwnerControl.Reset();
+
+  // Don't call Deactivate here, since we cannot call virtual function during destruction.
+  // Deactivate already be called at Control's destructor, and InheritVisibilityChanged signal.
 }
 
 void RenderEffectImpl::SetOwnerControl(Dali::Toolkit::Control control)
 {
-  if(mOwnerControl != control)
+  Dali::Toolkit::Control ownerControl = mOwnerControl.GetHandle();
+  if(ownerControl != control)
   {
     // Clear previous owner control
     ClearOwnerControl();
 
-    mOwnerControl = control;
+    mOwnerControl = (ownerControl = control);
 
-    DALI_LOG_INFO(gRenderEffectLogFilter, Debug::General, "[RenderEffect:%p] SetOwnerControl [ID:%d]\n", this, mOwnerControl ? mOwnerControl.GetProperty<int>(Actor::Property::ID) : -1);
+    DALI_LOG_INFO(gRenderEffectLogFilter, Debug::General, "[RenderEffect:%p] SetOwnerControl [ID:%d]\n", this, ownerControl ? ownerControl.GetProperty<int>(Actor::Property::ID) : -1);
 
-    if(mOwnerControl)
+    if(ownerControl)
     {
-      mTargetSize = mOwnerControl.GetProperty<Vector2>(Actor::Property::SIZE);
+      mTargetSize = ownerControl.GetProperty<Vector2>(Actor::Property::SIZE);
       if(!mRenderer)
       {
         mRenderer = CreateRenderer(SHADER_RENDER_EFFECT_VERT, SHADER_RENDER_EFFECT_FRAG);
       }
 
-      mOwnerControl.InheritedVisibilityChangedSignal().Connect(this, &RenderEffectImpl::OnControlInheritedVisibilityChanged);
+      ownerControl.InheritedVisibilityChangedSignal().Connect(this, &RenderEffectImpl::OnControlInheritedVisibilityChanged);
 
-      mSizeNotification = mOwnerControl.AddPropertyNotification(Actor::Property::SIZE, StepCondition(SIZE_STEP_CONDITION));
+      mSizeNotification = ownerControl.AddPropertyNotification(Actor::Property::SIZE, StepCondition(SIZE_STEP_CONDITION));
       mSizeNotification.NotifySignal().Connect(this, &RenderEffectImpl::OnSizeSet);
 
       Activate(); // Dev note : Activate after set the owner control.
@@ -92,17 +95,18 @@ void RenderEffectImpl::SetOwnerControl(Dali::Toolkit::Control control)
 
 void RenderEffectImpl::ClearOwnerControl()
 {
-  DALI_LOG_INFO(gRenderEffectLogFilter, Debug::General, "[RenderEffect:%p] ClearOwnerControl [ID:%d]\n", this, mOwnerControl ? mOwnerControl.GetProperty<int>(Actor::Property::ID) : -1);
-  if(mOwnerControl)
-  {
-    Deactivate(); // Dev note : Deactivate before clearing the owner control.
+  Deactivate(); // Dev note : Deactivate before clearing the owner control.
 
-    mOwnerControl.InheritedVisibilityChangedSignal().Disconnect(this, &RenderEffectImpl::OnControlInheritedVisibilityChanged);
+  Dali::Toolkit::Control ownerControl = mOwnerControl.GetHandle();
+  DALI_LOG_INFO(gRenderEffectLogFilter, Debug::General, "[RenderEffect:%p] ClearOwnerControl [ID:%d]\n", this, ownerControl ? ownerControl.GetProperty<int>(Actor::Property::ID) : -1);
+  if(ownerControl)
+  {
+    ownerControl.InheritedVisibilityChangedSignal().Disconnect(this, &RenderEffectImpl::OnControlInheritedVisibilityChanged);
 
-    mOwnerControl.RemovePropertyNotification(mSizeNotification);
+    ownerControl.RemovePropertyNotification(mSizeNotification);
     mSizeNotification.Reset();
 
-    auto previousOwnerControl = mOwnerControl;
+    auto previousOwnerControl = ownerControl;
     mOwnerControl.Reset();
 
     // Make previous owner don't have render effect, after make we don't have owner control now.
@@ -122,7 +126,7 @@ void RenderEffectImpl::Initialize()
 
 Toolkit::Control RenderEffectImpl::GetOwnerControl() const
 {
-  return mOwnerControl;
+  return mOwnerControl.GetHandle();
 }
 
 Renderer RenderEffectImpl::GetTargetRenderer() const
@@ -139,7 +143,8 @@ void RenderEffectImpl::Activate()
 {
   if(!IsActivated() && IsActivateValid())
   {
-    DALI_LOG_INFO(gRenderEffectLogFilter, Debug::General, "[RenderEffect:%p] Activated! [ID:%d]\n", this, mOwnerControl ? mOwnerControl.GetProperty<int>(Actor::Property::ID) : -1);
+    Dali::Toolkit::Control ownerControl = mOwnerControl.GetHandle();
+    DALI_LOG_INFO(gRenderEffectLogFilter, Debug::General, "[RenderEffect:%p] Activated! [ID:%d]\n", this, ownerControl ? ownerControl.GetProperty<int>(Actor::Property::ID) : -1);
     mIsActivated = true;
 
     // Activate logic for subclass.
@@ -151,7 +156,8 @@ void RenderEffectImpl::Deactivate()
 {
   if(IsActivated() || !IsActivateValid())
   {
-    DALI_LOG_INFO(gRenderEffectLogFilter, Debug::General, "[RenderEffect:%p] Deactivated! [ID:%d]\n", this, mOwnerControl ? mOwnerControl.GetProperty<int>(Actor::Property::ID) : -1);
+    Dali::Toolkit::Control ownerControl = mOwnerControl.GetHandle();
+    DALI_LOG_INFO(gRenderEffectLogFilter, Debug::General, "[RenderEffect:%p] Deactivated! [ID:%d]\n", this, ownerControl ? ownerControl.GetProperty<int>(Actor::Property::ID) : -1);
     mIsActivated = false;
 
     // Deactivate logic for subclass.
@@ -168,9 +174,10 @@ bool RenderEffectImpl::IsActivateValid() const
   // TODO : Currently we don't check SceneHolder's visibility.
   bool ret = false;
 
-  if(mOwnerControl && mOwnerControl.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
+  Dali::Toolkit::Control ownerControl = mOwnerControl.GetHandle();
+  if(ownerControl && ownerControl.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
   {
-    Integration::SceneHolder sceneHolder = Integration::SceneHolder::Get(mOwnerControl);
+    Integration::SceneHolder sceneHolder = Integration::SceneHolder::Get(ownerControl);
     if(sceneHolder)
     {
       ret = true;
@@ -178,7 +185,7 @@ bool RenderEffectImpl::IsActivateValid() const
       // Check visibility of owner control's parents.
       // TODO : We'd better check the control visibility at core side.
       // TODO : Window visibility will be consider at dali-core actor side in future.
-      Dali::Actor self = mOwnerControl;
+      Dali::Actor self = ownerControl;
       while(self)
       {
         if(!self.GetProperty<bool>(Dali::Actor::Property::VISIBLE))
@@ -191,16 +198,17 @@ bool RenderEffectImpl::IsActivateValid() const
     }
   }
 
-  DALI_LOG_INFO(gRenderEffectLogFilter, Debug::Concise, "[RenderEffect:%p] IsActivateValid? [ID:%d][ret:%d]\n", this, mOwnerControl ? mOwnerControl.GetProperty<int>(Actor::Property::ID) : -1, ret);
+  DALI_LOG_INFO(gRenderEffectLogFilter, Debug::Concise, "[RenderEffect:%p] IsActivateValid? [ID:%d][ret:%d]\n", this, ownerControl ? ownerControl.GetProperty<int>(Actor::Property::ID) : -1, ret);
 
   return ret;
 }
 
 void RenderEffectImpl::OnSizeSet(PropertyNotification& source)
 {
-  if(mOwnerControl)
+  Dali::Toolkit::Control ownerControl = mOwnerControl.GetHandle();
+  if(ownerControl)
   {
-    mTargetSize = mOwnerControl.GetCurrentProperty<Vector2>(Actor::Property::SIZE);
+    mTargetSize = ownerControl.GetCurrentProperty<Vector2>(Actor::Property::SIZE);
     if(IsActivated())
     {
       Deactivate();
@@ -211,7 +219,8 @@ void RenderEffectImpl::OnSizeSet(PropertyNotification& source)
 
 void RenderEffectImpl::OnControlInheritedVisibilityChanged(Actor actor, bool visible)
 {
-  DALI_LOG_INFO(gRenderEffectLogFilter, Debug::Concise, "[RenderEffect:%p] visibility changed [ID:%d][visible:%d]\n", this, mOwnerControl ? mOwnerControl.GetProperty<int>(Actor::Property::ID) : -1, visible);
+  Dali::Toolkit::Control ownerControl = mOwnerControl.GetHandle();
+  DALI_LOG_INFO(gRenderEffectLogFilter, Debug::Concise, "[RenderEffect:%p] visibility changed [ID:%d][visible:%d]\n", this, ownerControl ? ownerControl.GetProperty<int>(Actor::Property::ID) : -1, visible);
   if(visible)
   {
     Activate();
index 9e1eb4e952df53c67e6bccb3bb8fbe29df351ae5..3913bcbdcd0f18d8e30c136f3dd2bec4a60621e6 100644 (file)
@@ -95,7 +95,7 @@ protected:
   Vector2 GetTargetSize() const;
 
   /**
-   * @brief Get Owner control.
+   * @brief Get Owner control. It could be return empty handle if owner control is not set, or destroyed.
    * @return mOwnerControl
    */
   Toolkit::Control GetOwnerControl() const;
@@ -149,8 +149,9 @@ private:
   void OnControlInheritedVisibilityChanged(Actor actor, bool visible);
 
 private:
-  Dali::Renderer         mRenderer;     // An additional renderer for mOwnerControl
-  Dali::Toolkit::Control mOwnerControl; ///< TODO : Make it as WeakHandle if mSizeNotification reference issue is fixed.
+  Dali::Renderer mRenderer; // An additional renderer for mOwnerControl
+
+  Dali::WeakHandle<Dali::Toolkit::Control> mOwnerControl; ///< Weakhandle of owner control.
 
   PropertyNotification mSizeNotification; // Resize/Relayout signal.
   Vector2              mTargetSize;       // The final size of mOwnerControl