// EXTERNAL INCLUDES
#include <algorithm>
+#include <cmath> // abs<float>
// INTERNAL INCLUDES
#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/hover-event-integ.h>
#include <dali/public-api/common/dali-common.h>
namespace Dali
* @param[in] touchPoint The point to add.
* @param[in] pointTime The time of the point event.
*/
- PointInfo( const TouchPoint& touchPoint, unsigned long pointTime )
+ PointInfo( const Point& touchPoint, unsigned long pointTime )
: point( touchPoint ),
time( pointTime )
{
// Data
- TouchPoint point; ///< The point.
+ Point point; ///< The point.
unsigned long time; ///< The time the point event took place.
};
{
}
-bool TouchEventCombiner::GetNextTouchEvent( const TouchPoint& point, unsigned long time, TouchEvent& touchEvent )
+TouchEventCombiner::EventDispatchType TouchEventCombiner::GetNextTouchEvent( const Point& point, unsigned long time, TouchEvent& touchEvent, HoverEvent& hoverEvent )
{
- bool dispatchEvent( false );
+ TouchEventCombiner::EventDispatchType dispatchEvent( TouchEventCombiner::DispatchNone );
+ const PointState::Type state = point.GetState();
+ const int deviceId = point.GetDeviceId();
- switch ( point.state )
+ switch ( state )
{
- case TouchPoint::Down:
+ case PointState::STARTED:
{
touchEvent.time = time;
bool addToContainer( true );
// Iterate through already stored touch points and add to TouchEvent
for ( PointInfoContainer::iterator iter = mPressedPoints.begin(), endIter = mPressedPoints.end(); iter != endIter; ++iter )
{
- if ( iter->point.deviceId != point.deviceId )
+ if ( iter->point.GetDeviceId() != deviceId )
{
- iter->point.state = TouchPoint::Stationary;
+ iter->point.SetState( PointState::STATIONARY );
}
else
{
{
mPressedPoints.push_back( PointInfo( point, time ) );
touchEvent.AddPoint( point );
- dispatchEvent = true; // Only dispatch event if just added to container
+ dispatchEvent = TouchEventCombiner::DispatchTouch; // Only dispatch touch event if just added to container
+
+ // Check whether hover event was dispatched previously
+ if ( !mHoveredPoints.empty() )
+ {
+ hoverEvent.time = time;
+
+ PointInfoContainer::iterator match( mHoveredPoints.end() );
+ for ( PointInfoContainer::iterator iter = mHoveredPoints.begin(), endIter = mHoveredPoints.end(); iter != endIter; ++iter )
+ {
+ if ( deviceId == iter->point.GetDeviceId() )
+ {
+ match = iter;
+ // Add new point to the HoverEvent
+ iter->point.SetState( PointState::FINISHED );
+ hoverEvent.AddPoint( iter->point );
+ }
+ else
+ {
+ iter->point.SetState( PointState::STATIONARY );
+ hoverEvent.AddPoint( iter->point );
+ }
+ }
+
+ if ( match != mHoveredPoints.end() )
+ {
+ mHoveredPoints.erase( match );
+ dispatchEvent = TouchEventCombiner::DispatchBoth; // We should only dispatch hover events if the point was actually hovered in this window
+ }
+ }
}
break;
}
- case TouchPoint::Up:
+ case PointState::FINISHED:
{
touchEvent.time = time;
PointInfoContainer::iterator match( mPressedPoints.end() );
for ( PointInfoContainer::iterator iter = mPressedPoints.begin(), endIter = mPressedPoints.end(); iter != endIter; ++iter )
{
- if ( point.deviceId == iter->point.deviceId )
+ if ( deviceId == iter->point.GetDeviceId() )
{
match = iter;
}
else
{
- iter->point.state = TouchPoint::Stationary;
+ iter->point.SetState( PointState::STATIONARY );
touchEvent.AddPoint( iter->point );
}
}
if ( match != mPressedPoints.end() )
{
mPressedPoints.erase( match );
- dispatchEvent = true; // We should only dispatch events if the point was actually pressed in this window
+ dispatchEvent = TouchEventCombiner::DispatchTouch; // We should only dispatch touch events if the point was actually pressed in this window
+
+ // Iterate through already stored touch points for HoverEvent and delete them
+ for ( PointInfoContainer::iterator iter = mHoveredPoints.begin(), endIter = mHoveredPoints.end(); iter != endIter; ++iter )
+ {
+ if ( iter->point.GetDeviceId() == deviceId )
+ {
+ iter = mHoveredPoints.erase( iter );
+ }
+ }
}
break;
}
- case TouchPoint::Motion:
+ case PointState::MOTION:
{
+ bool fromNewDeviceId = false;
+
if ( !mPressedPoints.empty() )
{
touchEvent.time = time;
+ bool ignore = false;
PointInfoContainer::iterator match = mPressedPoints.end();
+ const Vector2& pointScreenPosition = point.GetScreenPosition();
for ( PointInfoContainer::iterator iter = mPressedPoints.begin(), endIter = mPressedPoints.end(); iter != endIter; ++iter )
{
- if ( point.deviceId == iter->point.deviceId )
+ if ( deviceId == iter->point.GetDeviceId() )
{
unsigned long timeDiff( time - iter->time );
if ( timeDiff < mMinMotionTime )
{
// Motion event sent too soon after previous event so ignore
+ ignore = true;
break;
}
- if ( ( abs( point.screen.x - iter->point.screen.x ) < mMinMotionDistance.x ) &&
- ( abs( point.screen.y - iter->point.screen.y ) < mMinMotionDistance.y ) )
+ const Vector2& currentScreenPosition = iter->point.GetScreenPosition();
+ if ( ( std::abs( pointScreenPosition.x - currentScreenPosition.x ) < mMinMotionDistance.x ) &&
+ ( std::abs( pointScreenPosition.y - currentScreenPosition.y ) < mMinMotionDistance.y ) )
{
// Not enough positional change from last event so ignore
+ ignore = true;
break;
}
}
else
{
- iter->point.state = TouchPoint::Stationary;
+ iter->point.SetState( PointState::STATIONARY );
touchEvent.AddPoint( iter->point );
}
}
PointInfo matchedPoint( point, time );
std::swap( *match, matchedPoint );
- dispatchEvent = true;
+ dispatchEvent = TouchEventCombiner::DispatchTouch; // Dispatch touch event
+ }
+ else if(!ignore)
+ {
+ fromNewDeviceId = true;
+ }
+ }
+
+ // Dispatch hover event if no previous down event received or the motion event comes from a new device ID
+ if(mPressedPoints.empty() || fromNewDeviceId)
+ {
+ hoverEvent.time = time;
+
+ // Iterate through already stored touch points and add to HoverEvent
+ bool ignore = false;
+ PointInfoContainer::iterator match = mHoveredPoints.end();
+ const Vector2& pointScreenPosition = point.GetScreenPosition();
+ for ( PointInfoContainer::iterator iter = mHoveredPoints.begin(), endIter = mHoveredPoints.end(); iter != endIter; ++iter )
+ {
+ if ( iter->point.GetDeviceId() == deviceId )
+ {
+ unsigned long timeDiff( time - iter->time );
+
+ if ( timeDiff < mMinMotionTime )
+ {
+ // Motion event sent too soon after previous event so ignore
+ ignore = true;
+ break;
+ }
+
+ const Vector2& currentScreenPosition = iter->point.GetScreenPosition();
+ if ( ( std::abs( pointScreenPosition.x - currentScreenPosition.x ) < mMinMotionDistance.x ) &&
+ ( std::abs( pointScreenPosition.y - currentScreenPosition.y ) < mMinMotionDistance.y ) )
+ {
+ // Not enough positional change from last event so ignore
+ ignore = true;
+ break;
+ }
+
+ match = iter;
+
+ // Add new touch point to the HoverEvent
+ hoverEvent.AddPoint( point );
+ }
+ else
+ {
+ iter->point.SetState( PointState::STATIONARY );
+ hoverEvent.AddPoint( iter->point );
+ }
+ }
+
+ // Add new hover point to the list and to the HoverEvent
+ if ( !ignore ) // Only dispatch hover event when it should not be ignored
+ {
+ if( match == mHoveredPoints.end() )
+ {
+ Point hoverPoint(point);
+ hoverPoint.SetState( PointState::STARTED ); // The first hover event received
+ mHoveredPoints.push_back( PointInfo( hoverPoint, time ) );
+ hoverEvent.AddPoint( hoverPoint );
+ }
+ else
+ {
+ PointInfo matchedPoint( point, time );
+ std::swap( *match, matchedPoint );
+ }
+
+ if(dispatchEvent == TouchEventCombiner::DispatchTouch)
+ {
+ dispatchEvent = TouchEventCombiner::DispatchBoth;
+ }
+ else
+ {
+ dispatchEvent = TouchEventCombiner::DispatchHover;
+ }
}
}
break;
}
- case TouchPoint::Interrupted:
+ case PointState::INTERRUPTED:
{
Reset();
// We should still tell core about the interruption.
touchEvent.AddPoint( point );
- dispatchEvent = true;
+ hoverEvent.AddPoint( point );
+ dispatchEvent = TouchEventCombiner::DispatchBoth;
break;
}
void TouchEventCombiner::Reset()
{
mPressedPoints.clear();
+ mHoveredPoints.clear();
}
} // namespace Integration