2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/events/tap-gesture/tap-gesture-recognizer.h>
24 #include <dali/public-api/math/vector2.h>
26 #include <dali/integration-api/events/touch-event-integ.h>
29 #include <dali/internal/event/events/gesture-requests.h>
30 #include <dali/internal/event/common/scene-impl.h>
40 // TODO: Set these according to DPI
41 const float MAXIMUM_MOTION_ALLOWED = 20.0f;
42 const unsigned long MAXIMUM_TIME_ALLOWED = 500u;
43 } // unnamed namespace
45 TapGestureRecognizer::TapGestureRecognizer( Observer& observer, Vector2 screenSize, const TapGestureRequest& request)
46 : GestureRecognizer( screenSize, Gesture::Tap ),
49 mMinimumTapsRequired(request.minTaps),
50 mMaximumTapsRequired(request.maxTaps),
58 TapGestureRecognizer::~TapGestureRecognizer()
62 void TapGestureRecognizer::SendEvent(const Integration::TouchEvent& event)
64 GestureRecognizerPtr ptr(this); // To keep us from being destroyed during the life-time of this method
66 if (event.GetPointCount() == 1)
68 const Integration::Point& point = event.points[0];
69 PointState::Type pointState = point.GetState();
75 if (pointState == PointState::DOWN)
77 SetupForTouchDown( event, point );
84 uint32_t deltaBetweenTouchDownTouchUp = event.time - mTouchTime;
86 if ( pointState == PointState::UP )
88 if ( deltaBetweenTouchDownTouchUp < MAXIMUM_TIME_ALLOWED )
90 mLastTapTime = mTouchTime;
91 EmitSingleTap( event.time, point );
99 else if (pointState == PointState::INTERRUPTED)
108 if ( pointState == PointState::UP )
110 uint32_t deltaBetweenTouchDownTouchUp = event.time - mTouchTime;
112 if ( deltaBetweenTouchDownTouchUp < MAXIMUM_TIME_ALLOWED )
114 // This is a possible multiple tap, so has it been quick enough?
115 uint32_t timeDelta = event.time - mLastTapTime;
116 if( timeDelta > MAXIMUM_TIME_ALLOWED ) // If exceeded time between taps then just a single tap
118 mLastTapTime = event.time;
119 EmitSingleTap(event.time, point);
125 EmitGesture( Gesture::Started, event.time );
129 else // Delta between touch down and touch up too long to be considered a Tap event
134 else if (pointState == PointState::DOWN)
136 const Vector2& screen( point.GetScreenPosition() );
137 Vector2 distanceDelta(std::abs(mTouchPosition.x - screen.x),
138 std::abs(mTouchPosition.y - screen.y));
140 uint32_t timeDelta = event.time - mLastTapTime;
142 if (distanceDelta.x > MAXIMUM_MOTION_ALLOWED ||
143 distanceDelta.y > MAXIMUM_MOTION_ALLOWED ||
144 timeDelta > MAXIMUM_TIME_ALLOWED )
146 SetupForTouchDown( event, point );
150 EmitPossibleState( event );
168 // We have entered a multi-touch event so emit registered gestures if required.
169 EmitGesture(Gesture::Started, event.time);
173 void TapGestureRecognizer::SetupForTouchDown( const Integration::TouchEvent& event, const Integration::Point& point )
175 mTouchPosition = point.GetScreenPosition();
176 mTouchTime = event.time;
180 EmitPossibleState( event );
183 void TapGestureRecognizer::EmitPossibleState( const Integration::TouchEvent& event )
185 TapGestureEvent tapEvent( Gesture::Possible );
186 tapEvent.point = mTouchPosition;
187 tapEvent.time = event.time;
189 ProcessEvent( tapEvent );
193 void TapGestureRecognizer::Update(const GestureRequest& request)
195 const TapGestureRequest& tap = static_cast<const TapGestureRequest&>(request);
197 mMinimumTapsRequired = tap.minTaps;
198 mMaximumTapsRequired = tap.maxTaps;
201 void TapGestureRecognizer::EmitGesture( Gesture::State state, uint32_t time )
203 if ( (state == Gesture::Cancelled) ||
204 (mTapsRegistered >= mMinimumTapsRequired && mTapsRegistered <= mMaximumTapsRequired) )
207 TapGestureEvent event( state );
208 EmitTap( time, event );
212 void TapGestureRecognizer::EmitSingleTap( uint32_t time, const Integration::Point& point )
214 TapGestureEvent event( Gesture::Started );
215 const Vector2& screen( point.GetScreenPosition() );
216 Vector2 distanceDelta(std::abs(mTouchPosition.x - screen.x),
217 std::abs(mTouchPosition.y - screen.y));
219 if (distanceDelta.x > MAXIMUM_MOTION_ALLOWED ||
220 distanceDelta.y > MAXIMUM_MOTION_ALLOWED )
222 event.state = Gesture::Cancelled;
224 mTapsRegistered = 1u;
225 EmitTap( time, event );
228 void TapGestureRecognizer::EmitTap( uint32_t time, TapGestureEvent& event )
230 event.numberOfTaps = mTapsRegistered;
231 event.point = mTouchPosition;
234 ProcessEvent( event );
237 void TapGestureRecognizer::ProcessEvent( TapGestureEvent& event )
241 // Create another handle so the recognizer cannot be destroyed during process function
242 GestureRecognizerPtr recognizerHandle = this;
243 mObserver.Process(*mScene, event);
247 } // namespace Internal