--- /dev/null
+#ifndef TEST_TOUCH_DATA_UTILS_H
+#define TEST_TOUCH_DATA_UTILS_H
+
+/*
+ * 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.
+ * 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/public-api/actors/actor.h>
+
+/**
+ * Functor to be connected to an Actor's TouchSignal.
+ * Allows the user to specify whether the functor should return true (consumed) or false.
+ */
+struct TouchDataFunctorConsumeSetter
+{
+ TouchDataFunctorConsumeSetter( bool& consume )
+ : mConsume( consume )
+ {
+ }
+
+ bool operator()(Dali::Actor actor, const Dali::TouchData& touch)
+ {
+ return mConsume;
+ }
+
+private:
+ bool& mConsume;
+};
+
+#endif // TEST_TOUCH_DATA_UTILS_H
+
#include <dali/devel-api/events/long-press-gesture-detector-devel.h>
#include <dali-test-suite-utils.h>
#include <test-touch-utils.h>
+#include <test-touch-data-utils.h>
using namespace Dali;
END_TEST;
}
+
+int UtcDaliLongPressGestureInterruptedWhenTouchConsumed(void)
+{
+ 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);
+
+ bool consume = false;
+ TouchDataFunctorConsumeSetter touchFunctor(consume);
+ actor.TouchSignal().Connect(&application,touchFunctor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ SignalData data;
+ GestureReceivedFunctor functor(data);
+
+ LongPressGestureDetector detector = LongPressGestureDetector::New();
+ detector.Attach(actor);
+ detector.DetectedSignal().Connect(&application, functor);
+
+ // Start gesture within the actor's area, we should receive the gesture as the touch is NOT being consumed
+ TestGenerateLongPress( application, 50.0f, 50.0f );
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+ TestEndLongPress(application, 50.0f,50.0f);
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Another gesture in the same location, this time we will not receive it as touch is being consumed
+ consume = true;
+ TestGenerateLongPress( application, 50.0f, 50.0f );
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+ TestEndLongPress(application, 50.0f,50.0f);
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+ END_TEST;
+}
#include <dali/integration-api/input-options.h>
#include <dali-test-suite-utils.h>
#include <test-touch-utils.h>
+#include <test-touch-data-utils.h>
using namespace Dali;
END_TEST;
}
+
+int UtcDaliPanGestureInterruptedWhenTouchConsumed(void)
+{
+ 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);
+
+ bool consume = false;
+ TouchDataFunctorConsumeSetter touchFunctor(consume);
+ actor.TouchSignal().Connect(&application,touchFunctor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ SignalData data;
+ GestureReceivedFunctor functor(data);
+
+ PanGestureDetector detector = PanGestureDetector::New();
+ detector.Attach(actor);
+ detector.DetectedSignal().Connect(&application, functor);
+
+ // Start gesture within the actor's area, we should receive the pan as the touch is NOT being consumed
+ uint32_t time = 100;
+ TestStartPan( application, Vector2( 10.0f, 20.0f ), Vector2( 26.0f, 20.0f ), time );
+
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION);
+ data.Reset();
+
+ // Continue the gesture within the actor's area, but now the touch consumes thus cancelling the gesture
+ consume = true;
+
+ TestMovePan( application, Vector2(26.0f, 4.0f), time );
+ time += TestGetFrameInterval();
+
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(Gesture::Cancelled, data.receivedGesture.state, TEST_LOCATION);
+
+ END_TEST;
+}
#include <dali/integration-api/render-task-list-integ.h>
#include <dali-test-suite-utils.h>
#include <test-touch-utils.h>
+#include <test-touch-data-utils.h>
using namespace Dali;
END_TEST;
}
+
+int UtcDaliPinchGestureInterruptedWhenTouchConsumed(void)
+{
+ 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);
+
+ bool consume = false;
+ TouchDataFunctorConsumeSetter touchFunctor(consume);
+ actor.TouchSignal().Connect(&application,touchFunctor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ SignalData data;
+ GestureReceivedFunctor functor(data);
+
+ PinchGestureDetector detector = PinchGestureDetector::New();
+ 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
+ TestStartPinch( 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(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION);
+ data.Reset();
+
+ // Continue the gesture within the actor's area, but now the touch consumes thus cancelling the gesture
+ consume = true;
+
+ TestContinuePinch( application, Vector2( 112.0f, 100.0f ), Vector2( 112.0f, 124.0f ),
+ Vector2( 5.0f, 5.0f ), Vector2( 35.0f, 35.0f ), 200 );
+
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(Gesture::Cancelled, data.receivedGesture.state, TEST_LOCATION);
+ data.Reset();
+
+ // Start another pinch, we should not even get the callback this time
+ TestStartPinch( 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;
+}
+
#include <dali/devel-api/events/rotation-gesture-detector.h>
#include <dali-test-suite-utils.h>
#include <test-touch-utils.h>
+#include <test-touch-data-utils.h>
using namespace Dali;
END_TEST;
}
+int UtcDaliRotationGestureInterruptedWhenTouchConsumed(void)
+{
+ 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);
+
+ bool consume = false;
+ TouchDataFunctorConsumeSetter touchFunctor(consume);
+ actor.TouchSignal().Connect(&application,touchFunctor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ SignalData data;
+ GestureReceivedFunctor functor(data);
+
+ RotationGestureDetector detector = RotationGestureDetector::New();
+ 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
+ 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(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION);
+ data.Reset();
+
+ // Continue the gesture within the actor's area, but now the touch consumes thus cancelling the gesture
+ consume = true;
+
+ TestContinueRotation( application, Vector2( 10.0f, 20.0f ), Vector2( 30.0f, 20.0f ),
+ Vector2( 15.0f, 20.0f ), Vector2( 25.0f, 20.0f ), 500 );
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(Gesture::Cancelled, data.receivedGesture.state, TEST_LOCATION);
+ data.Reset();
+
+ // Start another pinch, 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;
+}
#include <dali/integration-api/render-task-list-integ.h>
#include <dali-test-suite-utils.h>
#include <test-touch-utils.h>
+#include <test-touch-data-utils.h>
using namespace Dali;
END_TEST;
}
+
+int UtcDaliTapGestureInterruptedWhenTouchConsumed(void)
+{
+ 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);
+
+ bool consume = false;
+ TouchDataFunctorConsumeSetter touchFunctor(consume);
+ actor.TouchSignal().Connect(&application,touchFunctor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ SignalData data;
+ GestureReceivedFunctor functor(data);
+
+ TapGestureDetector detector = TapGestureDetector::New();
+ detector.Attach(actor);
+ detector.DetectedSignal().Connect(&application, functor);
+
+ // Start gesture within the actor's area, we should receive the gesture as the touch is NOT being consumed
+ TestGenerateTap( application, 50.0f, 50.0f );
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Another gesture in the same location, this time we will not receive it as touch is being consumed
+ consume = true;
+ TestGenerateTap( application, 50.0f, 50.0f );
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ END_TEST;
+}
/*
- * 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.
{
case Event::Touch:
{
- mTouchEventProcessor.ProcessTouchEvent( static_cast<const Integration::TouchEvent&>(*event) );
- mGestureEventProcessor.ProcessTouchEvent(mScene, static_cast<const Integration::TouchEvent&>(*event));
+ Integration::TouchEvent& touchEvent = static_cast<Integration::TouchEvent&>(*event);
+ const bool consumed = mTouchEventProcessor.ProcessTouchEvent( touchEvent );
+
+ // If touch is consumed, then gestures should be cancelled
+ // Do this by sending an interrupted event to the GestureEventProcessor
+ if( consumed )
+ {
+ Integration::Point& point = touchEvent.GetPoint(0);
+ point.SetState( PointState::INTERRUPTED );
+ }
+
+ mGestureEventProcessor.ProcessTouchEvent(mScene, touchEvent);
break;
}
/*
- * 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.
const Integration::Point& currentPoint1 = event.points[0];
const Integration::Point& currentPoint2 = event.points[1];
- if (currentPoint1.GetState() == PointState::UP || currentPoint2.GetState() == PointState::UP)
+ if (currentPoint1.GetState() == PointState::UP || currentPoint2.GetState() == PointState::UP || currentPoint1.GetState() == PointState::INTERRUPTED)
{
// One of our touch points has an Up event so change our state back to Clear.
mState = Clear;
case Started:
{
- if (pointCount != 2)
+ if(event.points[0].GetState() == PointState::INTERRUPTED)
+ {
+ // System interruption occurred, pinch should be cancelled
+ mTouchEvents.clear();
+ SendPinch(Gesture::Cancelled, event);
+ mState = Clear;
+ mTouchEvents.clear();
+ }
+ else if (pointCount != 2)
{
// Send pinch finished event
SendPinch(Gesture::Finished, event);
/*
- * 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.
const Integration::Point& currentPoint1 = event.points[0];
const Integration::Point& currentPoint2 = event.points[1];
- if( currentPoint1.GetState() == PointState::UP || currentPoint2.GetState() == PointState::UP )
+ if( currentPoint1.GetState() == PointState::UP || currentPoint2.GetState() == PointState::UP || currentPoint1.GetState() == PointState::INTERRUPTED )
{
// One of our touch points has an Up event so change our state back to Clear.
mState = Clear;
case Started:
{
- if( pointCount != 2 )
+ if(event.points[0].GetState() == PointState::INTERRUPTED)
+ {
+ // System interruption occurred, rotation should be cancelled
+ mTouchEvents.clear();
+ SendRotation(Gesture::Cancelled, event);
+ mState = Clear;
+ mTouchEvents.clear();
+ }
+ else if( pointCount != 2 )
{
// Send rotation finished event
SendRotation( Gesture::Finished, event );
DALI_LOG_TRACE_METHOD( gLogFilter );
}
-void TouchEventProcessor::ProcessTouchEvent( const Integration::TouchEvent& event )
+bool TouchEventProcessor::ProcessTouchEvent( const Integration::TouchEvent& event )
{
DALI_LOG_TRACE_METHOD( gLogFilter );
DALI_ASSERT_ALWAYS( !event.points.empty() && "Empty TouchEvent sent from Integration\n" );
touchData->AddPoint( currentPoint );
mScene.EmitTouchedSignal( touchEvent, touchDataHandle );
- return; // No need for hit testing
+ return false; // No need for hit testing & already an interrupted event so just return false
}
// 2) Hit Testing.
// 3) Recursively deliver events to the actor and its parents, until the event is consumed or the stage is reached.
+ bool consumed = false;
+
// Emit the touch signal
Dali::Actor consumedActor;
if ( currentRenderTask )
{
consumedActor = EmitTouchSignals( touchData->GetPoint( 0 ).GetHitActor(), touchEvent, touchDataHandle );
+ consumed = consumedActor ? true : false;
}
Integration::Point& primaryPoint = touchData->GetPoint( 0 );
}
}
+ consumed |= leaveEventConsumer ? true : false;
+
// Check if the motion event has been consumed by another actor's listener. In this case, the previously
// consumed actor's listeners may need to be informed (through a leave event).
// Further checks here to ensure we do not signal the same actor twice for the same event.
}
}
}
+
+ return consumed;
}
void TouchEventProcessor::OnObservedActorDisconnected( Actor* actor )
/**
* This function is called by the event processor whenever a touch event occurs.
* @param[in] event The touch event that has occurred.
+ * @return true if consumed
*/
- void ProcessTouchEvent( const Integration::TouchEvent& event );
+ bool ProcessTouchEvent( const Integration::TouchEvent& event );
private:
struct Degree;
class Quaternion;
class Layer;
-struct KeyEvent;
class TouchData;
struct TouchEvent;
struct HoverEvent;
* - If the consumed actor on hover-start is not the same as the consumed actor on hover-finished, then
* hover signals are also emitted from the hover-started actor with an "Interrupted" state.
*
- * <h3>Key Events:</h3>
- *
- * Key events are received by an actor once set to grab key events, only one actor can be set as focused.
- *
* @nosubgrouping
*
* Signals
* @endcode
* The return value of True, indicates that the touch event has been consumed.
* Otherwise the signal will be emitted on the next sensitive parent of the actor.
+ * A true return will also cancel any ongoing gestures.
* @SINCE_1_1.37
* @return The signal to connect to
* @pre The Actor has been initialized.