2 * Copyright (c) 2014 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/integration-api/events/touch-event-combiner.h>
25 #include <dali/integration-api/events/touch-event-integ.h>
26 #include <dali/public-api/common/dali-common.h>
36 const unsigned long DEFAULT_MINIMUM_MOTION_TIME( 1u );
37 const Vector2 DEFAULT_MINIMUM_MOTION_DISTANCE( 1.0f, 1.0f );
38 } // unnamed namespace
40 struct TouchEventCombiner::PointInfo
46 * @param[in] touchPoint The point to add.
47 * @param[in] pointTime The time of the point event.
49 PointInfo( const TouchPoint& touchPoint, unsigned long pointTime )
50 : point( touchPoint ),
57 TouchPoint point; ///< The point.
58 unsigned long time; ///< The time the point event took place.
61 TouchEventCombiner::TouchEventCombiner()
62 : mMinMotionTime( DEFAULT_MINIMUM_MOTION_TIME ),
63 mMinMotionDistance( DEFAULT_MINIMUM_MOTION_DISTANCE )
67 TouchEventCombiner::TouchEventCombiner( unsigned long minMotionTime, float minMotionXDistance, float minMotionYDistance )
68 : mMinMotionTime( minMotionTime ),
69 mMinMotionDistance( minMotionXDistance, minMotionYDistance )
71 DALI_ASSERT_ALWAYS( minMotionXDistance >= 0.0f && minMotionYDistance >= 0.0f && "Negative values not allowed\n" );
74 TouchEventCombiner::TouchEventCombiner( unsigned long minMotionTime, Vector2 minMotionDistance )
75 : mMinMotionTime( minMotionTime ),
76 mMinMotionDistance( minMotionDistance )
78 DALI_ASSERT_ALWAYS( minMotionDistance.x >= 0.0f && minMotionDistance.y >= 0.0f && "Negative values not allowed\n" );
81 TouchEventCombiner::~TouchEventCombiner()
85 bool TouchEventCombiner::GetNextTouchEvent( const TouchPoint& point, unsigned long time, TouchEvent& touchEvent )
87 bool dispatchEvent( false );
89 switch ( point.state )
91 case TouchPoint::Down:
93 touchEvent.time = time;
94 bool addToContainer( true );
96 // Iterate through already stored touch points and add to TouchEvent
97 for ( PointInfoContainer::iterator iter = mPressedPoints.begin(), endIter = mPressedPoints.end(); iter != endIter; ++iter )
99 if ( iter->point.deviceId != point.deviceId )
101 iter->point.state = TouchPoint::Stationary;
105 // System has sent us two down points for the same point ID, update our stored data to latest.
106 // We do not want to emit another down event for this Point Device ID.
108 addToContainer = false;
112 touchEvent.AddPoint( iter->point );
115 // Add new touch point to the list and to the TouchEvent
118 mPressedPoints.push_back( PointInfo( point, time ) );
119 touchEvent.AddPoint( point );
120 dispatchEvent = true; // Only dispatch event if just added to container
128 touchEvent.time = time;
130 // Find pressed touch point in local list (while also adding the stored points to the touchEvent)
131 PointInfoContainer::iterator match( mPressedPoints.end() );
132 for ( PointInfoContainer::iterator iter = mPressedPoints.begin(), endIter = mPressedPoints.end(); iter != endIter; ++iter )
134 if ( point.deviceId == iter->point.deviceId )
138 // Add new point to the TouchEvent
139 touchEvent.AddPoint( point );
143 iter->point.state = TouchPoint::Stationary;
144 touchEvent.AddPoint( iter->point );
148 if ( match != mPressedPoints.end() )
150 mPressedPoints.erase( match );
151 dispatchEvent = true; // We should only dispatch events if the point was actually pressed in this window
156 case TouchPoint::Motion:
158 if ( !mPressedPoints.empty() )
160 touchEvent.time = time;
162 PointInfoContainer::iterator match = mPressedPoints.end();
163 for ( PointInfoContainer::iterator iter = mPressedPoints.begin(), endIter = mPressedPoints.end(); iter != endIter; ++iter )
165 if ( point.deviceId == iter->point.deviceId )
167 unsigned long timeDiff( time - iter->time );
169 if ( timeDiff < mMinMotionTime )
171 // Motion event sent too soon after previous event so ignore
175 if ( ( abs( point.screen.x - iter->point.screen.x ) < mMinMotionDistance.x ) &&
176 ( abs( point.screen.y - iter->point.screen.y ) < mMinMotionDistance.y ) )
178 // Not enough positional change from last event so ignore
184 // Add new touch point to the TouchEvent
185 touchEvent.AddPoint( point );
189 iter->point.state = TouchPoint::Stationary;
190 touchEvent.AddPoint( iter->point );
194 if ( match != mPressedPoints.end() )
196 PointInfo matchedPoint( point, time );
197 std::swap( *match, matchedPoint );
199 dispatchEvent = true;
205 case TouchPoint::Interrupted:
209 // We should still tell core about the interruption.
210 touchEvent.AddPoint( point );
211 dispatchEvent = true;
219 return dispatchEvent;
222 void TouchEventCombiner::SetMinimumMotionTimeThreshold( unsigned long minTime )
224 mMinMotionTime = minTime;
227 void TouchEventCombiner::SetMinimumMotionDistanceThreshold( float minDistance )
229 DALI_ASSERT_ALWAYS( minDistance >= 0.0f && "Negative values not allowed\n" );
231 mMinMotionDistance.x = mMinMotionDistance.y = minDistance;
234 void TouchEventCombiner::SetMinimumMotionDistanceThreshold( float minXDistance, float minYDistance )
236 DALI_ASSERT_ALWAYS( minXDistance >= 0.0f && minYDistance >= 0.0f && "Negative values not allowed\n" );
238 mMinMotionDistance.x = minXDistance;
239 mMinMotionDistance.y = minYDistance;
242 void TouchEventCombiner::SetMinimumMotionDistanceThreshold( Vector2 minDistance )
244 DALI_ASSERT_ALWAYS( minDistance.x >= 0.0f && minDistance.y >= 0.0f && "Negative values not allowed\n" );
246 mMinMotionDistance = minDistance;
249 unsigned long TouchEventCombiner::GetMinimumMotionTimeThreshold() const
251 return mMinMotionTime;
254 Vector2 TouchEventCombiner::GetMinimumMotionDistanceThreshold() const
256 return mMinMotionDistance;
259 void TouchEventCombiner::Reset()
261 mPressedPoints.clear();
264 } // namespace Integration