2 * Copyright (c) 2019 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-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 if (event.GetPointCount() == 1)
66 const Integration::Point& point = event.points[0];
67 PointState::Type pointState = point.GetState();
73 if (pointState == PointState::DOWN)
75 SetupForTouchDown( event, point );
82 uint32_t deltaBetweenTouchDownTouchUp = event.time - mTouchTime;
84 if ( pointState == PointState::UP )
86 if ( deltaBetweenTouchDownTouchUp < MAXIMUM_TIME_ALLOWED )
88 mLastTapTime = mTouchTime;
89 EmitSingleTap( event.time, point );
97 else if (pointState == PointState::INTERRUPTED)
106 if ( pointState == PointState::UP )
108 uint32_t deltaBetweenTouchDownTouchUp = event.time - mTouchTime;
110 if ( deltaBetweenTouchDownTouchUp < MAXIMUM_TIME_ALLOWED )
112 // This is a possible multiple tap, so has it been quick enough?
113 uint32_t timeDelta = event.time - mLastTapTime;
114 if( timeDelta > MAXIMUM_TIME_ALLOWED ) // If exceeded time between taps then just a single tap
116 mLastTapTime = event.time;
117 EmitSingleTap(event.time, point);
123 EmitGesture( Gesture::Started, event.time );
127 else // Delta between touch down and touch up too long to be considered a Tap event
132 else if (pointState == PointState::DOWN)
134 const Vector2& screen( point.GetScreenPosition() );
135 Vector2 distanceDelta(abs(mTouchPosition.x - screen.x),
136 abs(mTouchPosition.y - screen.y));
138 uint32_t timeDelta = event.time - mLastTapTime;
140 if (distanceDelta.x > MAXIMUM_MOTION_ALLOWED ||
141 distanceDelta.y > MAXIMUM_MOTION_ALLOWED ||
142 timeDelta > MAXIMUM_TIME_ALLOWED )
144 SetupForTouchDown( event, point );
148 EmitPossibleState( event );
166 // We have entered a multi-touch event so emit registered gestures if required.
167 EmitGesture(Gesture::Started, event.time);
171 void TapGestureRecognizer::SetupForTouchDown( const Integration::TouchEvent& event, const Integration::Point& point )
173 mTouchPosition = point.GetScreenPosition();
174 mTouchTime = event.time;
178 EmitPossibleState( event );
181 void TapGestureRecognizer::EmitPossibleState( const Integration::TouchEvent& event )
183 TapGestureEvent tapEvent( Gesture::Possible );
184 tapEvent.point = mTouchPosition;
185 tapEvent.time = event.time;
187 ProcessEvent( tapEvent );
191 void TapGestureRecognizer::Update(const GestureRequest& request)
193 const TapGestureRequest& tap = static_cast<const TapGestureRequest&>(request);
195 mMinimumTapsRequired = tap.minTaps;
196 mMaximumTapsRequired = tap.maxTaps;
199 void TapGestureRecognizer::EmitGesture( Gesture::State state, uint32_t time )
201 if ( (state == Gesture::Cancelled) ||
202 (mTapsRegistered >= mMinimumTapsRequired && mTapsRegistered <= mMaximumTapsRequired) )
205 TapGestureEvent event( state );
206 EmitTap( time, event );
210 void TapGestureRecognizer::EmitSingleTap( uint32_t time, const Integration::Point& point )
212 TapGestureEvent event( Gesture::Started );
213 const Vector2& screen( point.GetScreenPosition() );
214 Vector2 distanceDelta(abs(mTouchPosition.x - screen.x),
215 abs(mTouchPosition.y - screen.y));
217 if (distanceDelta.x > MAXIMUM_MOTION_ALLOWED ||
218 distanceDelta.y > MAXIMUM_MOTION_ALLOWED )
220 event.state = Gesture::Cancelled;
222 mTapsRegistered = 1u;
223 EmitTap( time, event );
226 void TapGestureRecognizer::EmitTap( uint32_t time, TapGestureEvent& event )
228 event.numberOfTaps = mTapsRegistered;
229 event.point = mTouchPosition;
232 ProcessEvent( event );
235 void TapGestureRecognizer::ProcessEvent( TapGestureEvent& event )
239 // Create another handle so the recognizer cannot be destroyed during process function
240 GestureRecognizerPtr recognizerHandle = this;
241 mObserver.Process(*mScene, event);
245 } // namespace Internal