2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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.
18 #include <dali/integration-api/events/touch-event-combiner.h>
24 #include <dali/integration-api/events/touch-event-integ.h>
25 #include <dali/public-api/common/dali-common.h>
35 const unsigned long DEFAULT_MINIMUM_MOTION_TIME( 1u );
36 const Vector2 DEFAULT_MINIMUM_MOTION_DISTANCE( 1.0f, 1.0f );
37 } // unnamed namespace
39 struct TouchEventCombiner::PointInfo
45 * @param[in] touchPoint The point to add.
46 * @param[in] pointTime The time of the point event.
48 PointInfo( const TouchPoint& touchPoint, unsigned long pointTime )
49 : point( touchPoint ),
56 TouchPoint point; ///< The point.
57 unsigned long time; ///< The time the point event took place.
60 TouchEventCombiner::TouchEventCombiner()
61 : mMinMotionTime( DEFAULT_MINIMUM_MOTION_TIME ),
62 mMinMotionDistance( DEFAULT_MINIMUM_MOTION_DISTANCE )
66 TouchEventCombiner::TouchEventCombiner( unsigned long minMotionTime, float minMotionXDistance, float minMotionYDistance )
67 : mMinMotionTime( minMotionTime ),
68 mMinMotionDistance( minMotionXDistance, minMotionYDistance )
70 DALI_ASSERT_ALWAYS( minMotionXDistance >= 0.0f && minMotionYDistance >= 0.0f && "Negative values not allowed\n" );
73 TouchEventCombiner::TouchEventCombiner( unsigned long minMotionTime, Vector2 minMotionDistance )
74 : mMinMotionTime( minMotionTime ),
75 mMinMotionDistance( minMotionDistance )
77 DALI_ASSERT_ALWAYS( minMotionDistance.x >= 0.0f && minMotionDistance.y >= 0.0f && "Negative values not allowed\n" );
80 TouchEventCombiner::~TouchEventCombiner()
84 bool TouchEventCombiner::GetNextTouchEvent( const TouchPoint& point, unsigned long time, TouchEvent& touchEvent )
86 bool dispatchEvent( false );
88 switch ( point.state )
90 case TouchPoint::Down:
92 touchEvent.time = time;
93 bool addToContainer( true );
95 // Iterate through already stored touch points and add to TouchEvent
96 for ( PointInfoContainer::iterator iter = mPressedPoints.begin(), endIter = mPressedPoints.end(); iter != endIter; ++iter )
98 if ( iter->point.deviceId != point.deviceId )
100 iter->point.state = TouchPoint::Stationary;
104 // System has sent us two down points for the same point ID, update our stored data to latest.
105 // We do not want to emit another down event for this Point Device ID.
107 addToContainer = false;
111 touchEvent.AddPoint( iter->point );
114 // Add new touch point to the list and to the TouchEvent
117 mPressedPoints.push_back( PointInfo( point, time ) );
118 touchEvent.AddPoint( point );
119 dispatchEvent = true; // Only dispatch event if just added to container
127 touchEvent.time = time;
129 // Find pressed touch point in local list (while also adding the stored points to the touchEvent)
130 PointInfoContainer::iterator match( mPressedPoints.end() );
131 for ( PointInfoContainer::iterator iter = mPressedPoints.begin(), endIter = mPressedPoints.end(); iter != endIter; ++iter )
133 if ( point.deviceId == iter->point.deviceId )
137 // Add new point to the TouchEvent
138 touchEvent.AddPoint( point );
142 iter->point.state = TouchPoint::Stationary;
143 touchEvent.AddPoint( iter->point );
147 if ( match != mPressedPoints.end() )
149 mPressedPoints.erase( match );
150 dispatchEvent = true; // We should only dispatch events if the point was actually pressed in this window
155 case TouchPoint::Motion:
157 if ( !mPressedPoints.empty() )
159 touchEvent.time = time;
161 PointInfoContainer::iterator match = mPressedPoints.end();
162 for ( PointInfoContainer::iterator iter = mPressedPoints.begin(), endIter = mPressedPoints.end(); iter != endIter; ++iter )
164 if ( point.deviceId == iter->point.deviceId )
166 unsigned long timeDiff( time - iter->time );
168 if ( timeDiff < mMinMotionTime )
170 // Motion event sent too soon after previous event so ignore
174 if ( ( abs( point.screen.x - iter->point.screen.x ) < mMinMotionDistance.x ) &&
175 ( abs( point.screen.y - iter->point.screen.y ) < mMinMotionDistance.y ) )
177 // Not enough positional change from last event so ignore
183 // Add new touch point to the TouchEvent
184 touchEvent.AddPoint( point );
188 iter->point.state = TouchPoint::Stationary;
189 touchEvent.AddPoint( iter->point );
193 if ( match != mPressedPoints.end() )
195 PointInfo matchedPoint( point, time );
196 std::swap( *match, matchedPoint );
198 dispatchEvent = true;
204 case TouchPoint::Interrupted:
208 // We should still tell core about the interruption.
209 touchEvent.AddPoint( point );
210 dispatchEvent = true;
218 return dispatchEvent;
221 void TouchEventCombiner::SetMinimumMotionTimeThreshold( unsigned long minTime )
223 mMinMotionTime = minTime;
226 void TouchEventCombiner::SetMinimumMotionDistanceThreshold( float minDistance )
228 DALI_ASSERT_ALWAYS( minDistance >= 0.0f && "Negative values not allowed\n" );
230 mMinMotionDistance.x = mMinMotionDistance.y = minDistance;
233 void TouchEventCombiner::SetMinimumMotionDistanceThreshold( float minXDistance, float minYDistance )
235 DALI_ASSERT_ALWAYS( minXDistance >= 0.0f && minYDistance >= 0.0f && "Negative values not allowed\n" );
237 mMinMotionDistance.x = minXDistance;
238 mMinMotionDistance.y = minYDistance;
241 void TouchEventCombiner::SetMinimumMotionDistanceThreshold( Vector2 minDistance )
243 DALI_ASSERT_ALWAYS( minDistance.x >= 0.0f && minDistance.y >= 0.0f && "Negative values not allowed\n" );
245 mMinMotionDistance = minDistance;
248 unsigned long TouchEventCombiner::GetMinimumMotionTimeThreshold() const
250 return mMinMotionTime;
253 Vector2 TouchEventCombiner::GetMinimumMotionDistanceThreshold() const
255 return mMinMotionDistance;
258 void TouchEventCombiner::Reset()
260 mPressedPoints.clear();
263 } // namespace Integration