Ensure we do not destroy GestureRecognizers while we are still processing them 09/240709/3
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Mon, 10 Aug 2020 17:36:31 +0000 (18:36 +0100)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Wed, 12 Aug 2020 10:15:16 +0000 (10:15 +0000)
Change-Id: I0711d8664d84a931926cba1807ebac9a9e9389fc

automated-tests/src/dali/utc-Dali-LongPressGestureDetector.cpp
automated-tests/src/dali/utc-Dali-PanGestureDetector.cpp
automated-tests/src/dali/utc-Dali-PinchGestureDetector.cpp
automated-tests/src/dali/utc-Dali-RotationGestureDetector.cpp
automated-tests/src/dali/utc-Dali-TapGestureDetector.cpp
dali/internal/event/events/long-press-gesture/long-press-gesture-recognizer.cpp
dali/internal/event/events/pan-gesture/pan-gesture-recognizer.cpp
dali/internal/event/events/pinch-gesture/pinch-gesture-recognizer.cpp
dali/internal/event/events/rotation-gesture/rotation-gesture-recognizer.cpp
dali/internal/event/events/tap-gesture/tap-gesture-recognizer.cpp

index 5b29232..1053762 100644 (file)
@@ -1040,3 +1040,52 @@ int UtcDaliLongPressGestureInterruptedWhenTouchConsumed(void)
 
   END_TEST;
 }
+
+int UtcDaliLongPressGestureDisableDetectionDuringLongPressN(void)
+{
+  // Crash occurred when gesture-recognizer was deleted internally during a signal when the attached actor was detached
+
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetProperty( Actor::Property::SIZE, Vector2( 100.0f, 100.0f ) );
+  actor.SetProperty( Actor::Property::ANCHOR_POINT,AnchorPoint::TOP_LEFT);
+  application.GetScene().Add(actor);
+
+  // Add a detector
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  bool functorCalled = false;
+  detector.Attach( actor );
+  detector.DetectedSignal().Connect(
+      &application,
+      [&detector, &functorCalled](Actor actor, const LongPressGesture& gesture)
+      {
+        if( gesture.state == Gesture::Finished )
+        {
+          detector.Detach(actor);
+          functorCalled = true;
+        }
+      });
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Try the gesture, should not crash
+  try
+  {
+    TestGenerateLongPress( application, 50.0f, 10.0f );
+    TestEndLongPress( application, 50.0f, 10.0f );
+
+    DALI_TEST_CHECK( true ); // No crash, test has passed
+    DALI_TEST_EQUALS(functorCalled, true, TEST_LOCATION);
+  }
+  catch(...)
+  {
+    DALI_TEST_CHECK( false ); // If we crash, the test has failed
+  }
+
+  END_TEST;
+}
+
+
index e394526..f615f80 100644 (file)
@@ -2890,3 +2890,51 @@ int UtcDaliPanGestureInterruptedWhenTouchConsumed(void)
 
   END_TEST;
 }
+
+int UtcDaliPanGestureDisableDetectionDuringPanN(void)
+{
+  // Crash occurred when gesture-recognizer was deleted internally during a signal when the attached actor was detached
+
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetProperty( Actor::Property::SIZE, Vector2( 100.0f, 100.0f ) );
+  actor.SetProperty( Actor::Property::ANCHOR_POINT,AnchorPoint::TOP_LEFT);
+  application.GetScene().Add(actor);
+
+  // Add a pan detector
+  PanGestureDetector detector = PanGestureDetector::New();
+  bool functorCalled = false;
+  detector.Attach( actor );
+  detector.DetectedSignal().Connect(
+      &application,
+      [&detector, &functorCalled](Actor actor, const PanGesture& pan)
+      {
+        if( pan.state == Gesture::Finished )
+        {
+          detector.Detach(actor);
+          functorCalled = true;
+        }
+      });
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Try the gesture, should not crash
+  try
+  {
+    uint32_t time = 100;
+    TestStartPan( application, Vector2( 10.0f, 20.0f ), Vector2( 26.0f, 20.0f ), time );
+    TestEndPan( application, Vector2(26.0f, 20.0f) );
+
+    DALI_TEST_CHECK( true ); // No crash, test has passed
+    DALI_TEST_EQUALS(functorCalled, true, TEST_LOCATION);
+  }
+  catch(...)
+  {
+    DALI_TEST_CHECK( false ); // If we crash, the test has failed
+  }
+
+  END_TEST;
+}
index 64d1c03..c8f30b2 100644 (file)
@@ -1166,3 +1166,53 @@ int UtcDaliPinchGestureInterruptedWhenTouchConsumed(void)
   END_TEST;
 }
 
+int UtcDaliPinchGestureDisableDetectionDuringPinchN(void)
+{
+  // Crash sometimes occurred when gesture-recognizer was deleted internally during a signal when the attached actor was detached
+
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetProperty( Actor::Property::SIZE, Vector2( 100.0f, 100.0f ) );
+  actor.SetProperty( Actor::Property::ANCHOR_POINT,AnchorPoint::TOP_LEFT);
+  application.GetScene().Add(actor);
+
+  // Add a detector
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  bool functorCalled = false;
+  detector.Attach( actor );
+  detector.DetectedSignal().Connect(
+      &application,
+      [&detector, &functorCalled](Actor actor, const PinchGesture& gesture)
+      {
+        if( gesture.state == Gesture::Finished )
+        {
+          detector.Detach(actor);
+          functorCalled = true;
+        }
+      });
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Try the gesture, should not crash
+  try
+  {
+    TestStartPinch( application,  Vector2( 2.0f, 20.0f ), Vector2( 38.0f, 20.0f ),
+                                  Vector2( 10.0f, 20.0f ), Vector2( 30.0f, 20.0f ), 100 );
+    TestContinuePinch( application, Vector2( 112.0f, 100.0f ), Vector2( 112.0f, 124.0f ),
+                                    Vector2( 5.0f, 5.0f ), Vector2( 35.0f, 35.0f ), 200 );
+    TestEndPinch( application,  Vector2( 10.0f, 20.0f ), Vector2( 30.0f, 20.0f ),
+                                Vector2( 19.0f, 20.0f ), Vector2( 21.0f, 20.0f ), 1000);
+
+    DALI_TEST_CHECK( true ); // No crash, test has passed
+    DALI_TEST_EQUALS(functorCalled, true, TEST_LOCATION);
+  }
+  catch(...)
+  {
+    DALI_TEST_CHECK( false ); // If we crash, the test has failed
+  }
+
+  END_TEST;
+}
index 00eb270..0219e84 100644 (file)
@@ -1130,7 +1130,7 @@ int UtcDaliRotationGestureInterruptedWhenTouchConsumed(void)
   detector.Attach(actor);
   detector.DetectedSignal().Connect(&application, functor);
 
-  // Start gesture within the actor's area, we should receive the pinch as the touch is NOT being consumed
+  // Start gesture within the actor's area, we should receive the rotation as the touch is NOT being consumed
   TestStartRotation( application,  Vector2( 2.0f, 20.0f ), Vector2( 38.0f, 20.0f ),
                                    Vector2( 10.0f, 20.0f ), Vector2( 30.0f, 20.0f ), 100 );
 
@@ -1147,10 +1147,62 @@ int UtcDaliRotationGestureInterruptedWhenTouchConsumed(void)
   DALI_TEST_EQUALS(Gesture::Cancelled, data.receivedGesture.state, TEST_LOCATION);
   data.Reset();
 
-  // Start another pinch, we should not even get the callback this time
+  // Start another rotation, we should not even get the callback this time
   TestStartRotation( application,  Vector2( 2.0f, 20.0f ), Vector2( 38.0f, 20.0f ),
                                    Vector2( 10.0f, 20.0f ), Vector2( 30.0f, 20.0f ), 100 );
   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
 
   END_TEST;
 }
+
+int UtcDaliRotationGestureDisableDetectionDuringRotationN(void)
+{
+  // Crash sometimes occurred when gesture-recognizer was deleted internally during a signal when the attached actor was detached
+
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetProperty( Actor::Property::SIZE, Vector2( 100.0f, 100.0f ) );
+  actor.SetProperty( Actor::Property::ANCHOR_POINT,AnchorPoint::TOP_LEFT);
+  application.GetScene().Add(actor);
+
+  // Add a detector
+  RotationGestureDetector detector = RotationGestureDetector::New();
+  bool functorCalled = false;
+  detector.Attach( actor );
+  detector.DetectedSignal().Connect(
+      &application,
+      [&detector, &functorCalled](Actor actor, const RotationGesture& gesture)
+      {
+        if( gesture.state == Gesture::Finished )
+        {
+          detector.Detach(actor);
+          functorCalled = true;
+        }
+      });
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Try the gesture, should not crash
+  try
+  {
+    TestStartRotation( application,  Vector2( 2.0f, 20.0f ), Vector2( 38.0f, 20.0f ),
+                                  Vector2( 10.0f, 20.0f ), Vector2( 30.0f, 20.0f ), 100 );
+    TestContinueRotation( application, Vector2( 112.0f, 100.0f ), Vector2( 112.0f, 124.0f ),
+                                    Vector2( 5.0f, 5.0f ), Vector2( 35.0f, 35.0f ), 200 );
+    TestEndRotation( application,  Vector2( 10.0f, 20.0f ), Vector2( 30.0f, 20.0f ),
+                                Vector2( 19.0f, 20.0f ), Vector2( 21.0f, 20.0f ), 1000);
+
+    DALI_TEST_CHECK( true ); // No crash, test has passed
+    DALI_TEST_EQUALS(functorCalled, true, TEST_LOCATION);
+  }
+  catch(...)
+  {
+    DALI_TEST_CHECK( false ); // If we crash, the test has failed
+  }
+
+  END_TEST;
+}
+
index 9295aa0..cf86531 100644 (file)
@@ -952,3 +952,47 @@ int UtcDaliTapGestureInterruptedWhenTouchConsumed(void)
 
   END_TEST;
 }
+
+int UtcDaliTapGestureDisableDetectionDuringTapN(void)
+{
+  // Crash sometimes occurred when gesture-recognizer was deleted internally during a signal when the attached actor was detached
+
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetProperty( Actor::Property::SIZE, Vector2( 100.0f, 100.0f ) );
+  actor.SetProperty( Actor::Property::ANCHOR_POINT,AnchorPoint::TOP_LEFT);
+  application.GetScene().Add(actor);
+
+  // Add a detector
+  TapGestureDetector detector = TapGestureDetector::New();
+  bool functorCalled = false;
+  detector.Attach( actor );
+  detector.DetectedSignal().Connect(
+      &application,
+      [&detector, &functorCalled](Actor actor, const TapGesture& gesture)
+      {
+        detector.Detach(actor);
+        functorCalled = true;
+      });
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Try the gesture, should not crash
+  try
+  {
+    TestGenerateTap( application, 50.0f, 10.0f );
+
+    DALI_TEST_CHECK( true ); // No crash, test has passed
+    DALI_TEST_EQUALS(functorCalled, true, TEST_LOCATION);
+  }
+  catch(...)
+  {
+    DALI_TEST_CHECK( false ); // If we crash, the test has failed
+  }
+
+  END_TEST;
+}
+
index de9fe1b..8713045 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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.
@@ -67,6 +67,7 @@ void LongPressGestureRecognizer::SendEvent(const Integration::TouchEvent& event)
 {
   unsigned int pointCount( event.GetPointCount() );
   Dali::Integration::PlatformAbstraction& platformAbstraction = ThreadLocalStorage::Get().GetPlatformAbstraction();
+  GestureRecognizerPtr ptr(this); // To keep us from being destroyed during the life-time of this method
 
   switch (mState)
   {
index 0b56574..51a91a5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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.
@@ -81,6 +81,7 @@ PanGestureRecognizer::~PanGestureRecognizer()
 void PanGestureRecognizer::SendEvent(const Integration::TouchEvent& event)
 {
   PointState::Type primaryPointState(event.points[0].GetState());
+  GestureRecognizerPtr ptr(this); // To keep us from being destroyed during the life-time of this method
 
   if (primaryPointState == PointState::INTERRUPTED)
   {
index 808c4ad..de2bd4f 100644 (file)
@@ -90,6 +90,7 @@ void PinchGestureRecognizer::SetMinimumPinchDistance(float value)
 void PinchGestureRecognizer::SendEvent(const Integration::TouchEvent& event)
 {
   int pointCount = event.GetPointCount();
+  GestureRecognizerPtr ptr(this); // To keep us from being destroyed during the life-time of this method
 
   switch (mState)
   {
index d190d6d..6de3490 100644 (file)
@@ -69,6 +69,7 @@ RotationGestureRecognizer::RotationGestureRecognizer( Observer& observer, uint32
 void RotationGestureRecognizer::SendEvent( const Integration::TouchEvent& event )
 {
   int pointCount = event.GetPointCount();
+  GestureRecognizerPtr ptr(this); // To keep us from being destroyed during the life-time of this method
 
   switch( mState )
   {
index f4e058a..c8707dc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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.
@@ -61,6 +61,8 @@ TapGestureRecognizer::~TapGestureRecognizer()
 
 void TapGestureRecognizer::SendEvent(const Integration::TouchEvent& event)
 {
+  GestureRecognizerPtr ptr(this); // To keep us from being destroyed during the life-time of this method
+
   if (event.GetPointCount() == 1)
   {
     const Integration::Point& point = event.points[0];