From: Adeel Kazmi Date: Mon, 10 Aug 2020 17:36:31 +0000 (+0100) Subject: Ensure we do not destroy GestureRecognizers while we are still processing them X-Git-Tag: dali_1.9.25~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e42df3603845e1c4707175052c30f1e1b56729ff;p=platform%2Fcore%2Fuifw%2Fdali-core.git Ensure we do not destroy GestureRecognizers while we are still processing them Change-Id: I0711d8664d84a931926cba1807ebac9a9e9389fc --- diff --git a/automated-tests/src/dali/utc-Dali-LongPressGestureDetector.cpp b/automated-tests/src/dali/utc-Dali-LongPressGestureDetector.cpp index 5b29232..1053762 100644 --- a/automated-tests/src/dali/utc-Dali-LongPressGestureDetector.cpp +++ b/automated-tests/src/dali/utc-Dali-LongPressGestureDetector.cpp @@ -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; +} + + diff --git a/automated-tests/src/dali/utc-Dali-PanGestureDetector.cpp b/automated-tests/src/dali/utc-Dali-PanGestureDetector.cpp index e394526..f615f80 100644 --- a/automated-tests/src/dali/utc-Dali-PanGestureDetector.cpp +++ b/automated-tests/src/dali/utc-Dali-PanGestureDetector.cpp @@ -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; +} diff --git a/automated-tests/src/dali/utc-Dali-PinchGestureDetector.cpp b/automated-tests/src/dali/utc-Dali-PinchGestureDetector.cpp index 64d1c03..c8f30b2 100644 --- a/automated-tests/src/dali/utc-Dali-PinchGestureDetector.cpp +++ b/automated-tests/src/dali/utc-Dali-PinchGestureDetector.cpp @@ -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; +} diff --git a/automated-tests/src/dali/utc-Dali-RotationGestureDetector.cpp b/automated-tests/src/dali/utc-Dali-RotationGestureDetector.cpp index 00eb270..0219e84 100644 --- a/automated-tests/src/dali/utc-Dali-RotationGestureDetector.cpp +++ b/automated-tests/src/dali/utc-Dali-RotationGestureDetector.cpp @@ -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; +} + diff --git a/automated-tests/src/dali/utc-Dali-TapGestureDetector.cpp b/automated-tests/src/dali/utc-Dali-TapGestureDetector.cpp index 9295aa0..cf86531 100644 --- a/automated-tests/src/dali/utc-Dali-TapGestureDetector.cpp +++ b/automated-tests/src/dali/utc-Dali-TapGestureDetector.cpp @@ -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; +} + diff --git a/dali/internal/event/events/long-press-gesture/long-press-gesture-recognizer.cpp b/dali/internal/event/events/long-press-gesture/long-press-gesture-recognizer.cpp index de9fe1b..8713045 100644 --- a/dali/internal/event/events/long-press-gesture/long-press-gesture-recognizer.cpp +++ b/dali/internal/event/events/long-press-gesture/long-press-gesture-recognizer.cpp @@ -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) { diff --git a/dali/internal/event/events/pan-gesture/pan-gesture-recognizer.cpp b/dali/internal/event/events/pan-gesture/pan-gesture-recognizer.cpp index 0b56574..51a91a5 100644 --- a/dali/internal/event/events/pan-gesture/pan-gesture-recognizer.cpp +++ b/dali/internal/event/events/pan-gesture/pan-gesture-recognizer.cpp @@ -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) { diff --git a/dali/internal/event/events/pinch-gesture/pinch-gesture-recognizer.cpp b/dali/internal/event/events/pinch-gesture/pinch-gesture-recognizer.cpp index 808c4ad..de2bd4f 100644 --- a/dali/internal/event/events/pinch-gesture/pinch-gesture-recognizer.cpp +++ b/dali/internal/event/events/pinch-gesture/pinch-gesture-recognizer.cpp @@ -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) { diff --git a/dali/internal/event/events/rotation-gesture/rotation-gesture-recognizer.cpp b/dali/internal/event/events/rotation-gesture/rotation-gesture-recognizer.cpp index d190d6d..6de3490 100644 --- a/dali/internal/event/events/rotation-gesture/rotation-gesture-recognizer.cpp +++ b/dali/internal/event/events/rotation-gesture/rotation-gesture-recognizer.cpp @@ -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 ) { diff --git a/dali/internal/event/events/tap-gesture/tap-gesture-recognizer.cpp b/dali/internal/event/events/tap-gesture/tap-gesture-recognizer.cpp index f4e058a..c8707dc 100644 --- a/dali/internal/event/events/tap-gesture/tap-gesture-recognizer.cpp +++ b/dali/internal/event/events/tap-gesture/tap-gesture-recognizer.cpp @@ -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];