- Now they are in ndkHelper:: name space - Changed module name to ndk_helper - Changed some static members to class var or stand alone function - Added syncronization for JNIHelper.cpp - For a documentation, I will work with doc writer for future improvement Change-Id: I0055061a4f53b1904cde2e0339550ee277b35fc5 Addressed most of feedbacks, - Switched coding standard to Chrome style - Update JNI helper, and documented - Fixed other issues that is pointed out Change-Id: Icc729a55ed8dd613759f34a3fc35cb4949d2d205
351 lines
10 KiB
C++
351 lines
10 KiB
C++
/*
|
|
* Copyright 2013 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "gestureDetector.h"
|
|
|
|
//--------------------------------------------------------------------------------
|
|
// gestureDetector.cpp
|
|
//--------------------------------------------------------------------------------
|
|
namespace ndk_helper
|
|
{
|
|
|
|
//--------------------------------------------------------------------------------
|
|
// includes
|
|
//--------------------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------------------
|
|
// GestureDetector
|
|
//--------------------------------------------------------------------------------
|
|
GestureDetector::GestureDetector()
|
|
{
|
|
dp_factor_ = 1.f;
|
|
}
|
|
|
|
void GestureDetector::SetConfiguration( AConfiguration* config )
|
|
{
|
|
dp_factor_ = 160.f / AConfiguration_getDensity( config );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------
|
|
// TapDetector
|
|
//--------------------------------------------------------------------------------
|
|
GESTURE_STATE TapDetector::Detect( const AInputEvent* motion_event )
|
|
{
|
|
if( AMotionEvent_getPointerCount( motion_event ) > 1 )
|
|
{
|
|
//Only support single touch
|
|
return false;
|
|
}
|
|
|
|
int32_t action = AMotionEvent_getAction( motion_event );
|
|
unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
|
|
switch( flags )
|
|
{
|
|
case AMOTION_EVENT_ACTION_DOWN:
|
|
down_pointer_id_ = AMotionEvent_getPointerId( motion_event, 0 );
|
|
down_x_ = AMotionEvent_getX( motion_event, 0 );
|
|
down_y_ = AMotionEvent_getY( motion_event, 0 );
|
|
break;
|
|
case AMOTION_EVENT_ACTION_UP:
|
|
{
|
|
int64_t eventTime = AMotionEvent_getEventTime( motion_event );
|
|
int64_t downTime = AMotionEvent_getDownTime( motion_event );
|
|
if( eventTime - downTime <= TAP_TIMEOUT )
|
|
{
|
|
if( down_pointer_id_ == AMotionEvent_getPointerId( motion_event, 0 ) )
|
|
{
|
|
float x = AMotionEvent_getX( motion_event, 0 ) - down_x_;
|
|
float y = AMotionEvent_getY( motion_event, 0 ) - down_y_;
|
|
if( x * x + y * y < TOUCH_SLOP * TOUCH_SLOP * dp_factor_ )
|
|
{
|
|
LOGI( "TapDetector: Tap detected" );
|
|
return GESTURE_STATE_ACTION;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return GESTURE_STATE_NONE;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------
|
|
// DoubletapDetector
|
|
//--------------------------------------------------------------------------------
|
|
GESTURE_STATE DoubletapDetector::Detect( const AInputEvent* motion_event )
|
|
{
|
|
if( AMotionEvent_getPointerCount( motion_event ) > 1 )
|
|
{
|
|
//Only support single double tap
|
|
return false;
|
|
}
|
|
|
|
bool tap_detected = tap_detector_.Detect( motion_event );
|
|
|
|
int32_t action = AMotionEvent_getAction( motion_event );
|
|
unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
|
|
switch( flags )
|
|
{
|
|
case AMOTION_EVENT_ACTION_DOWN:
|
|
{
|
|
int64_t eventTime = AMotionEvent_getEventTime( motion_event );
|
|
if( eventTime - last_tap_time_ <= DOUBLE_TAP_TIMEOUT )
|
|
{
|
|
float x = AMotionEvent_getX( motion_event, 0 ) - last_tap_x_;
|
|
float y = AMotionEvent_getY( motion_event, 0 ) - last_tap_y_;
|
|
if( x * x + y * y < DOUBLE_TAP_SLOP * DOUBLE_TAP_SLOP * dp_factor_ )
|
|
{
|
|
LOGI( "DoubletapDetector: Doubletap detected" );
|
|
return GESTURE_STATE_ACTION;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case AMOTION_EVENT_ACTION_UP:
|
|
if( tap_detected )
|
|
{
|
|
last_tap_time_ = AMotionEvent_getEventTime( motion_event );
|
|
last_tap_x_ = AMotionEvent_getX( motion_event, 0 );
|
|
last_tap_y_ = AMotionEvent_getY( motion_event, 0 );
|
|
}
|
|
break;
|
|
}
|
|
return GESTURE_STATE_NONE;
|
|
}
|
|
|
|
void DoubletapDetector::SetConfiguration( AConfiguration* config )
|
|
{
|
|
dp_factor_ = 160.f / AConfiguration_getDensity( config );
|
|
tap_detector_.SetConfiguration( config );
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------
|
|
// PinchDetector
|
|
//--------------------------------------------------------------------------------
|
|
|
|
int32_t PinchDetector::FindIndex( const AInputEvent* event, int32_t id )
|
|
{
|
|
int32_t count = AMotionEvent_getPointerCount( event );
|
|
for( uint32_t i = 0; i < count; ++i )
|
|
{
|
|
if( id == AMotionEvent_getPointerId( event, i ) )
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
GESTURE_STATE PinchDetector::Detect( const AInputEvent* event )
|
|
{
|
|
GESTURE_STATE ret = GESTURE_STATE_NONE;
|
|
int32_t action = AMotionEvent_getAction( event );
|
|
uint32_t flags = action & AMOTION_EVENT_ACTION_MASK;
|
|
event_ = event;
|
|
|
|
int32_t count = AMotionEvent_getPointerCount( event );
|
|
switch( flags )
|
|
{
|
|
case AMOTION_EVENT_ACTION_DOWN:
|
|
vec_pointers_.push_back( AMotionEvent_getPointerId( event, 0 ) );
|
|
break;
|
|
case AMOTION_EVENT_ACTION_POINTER_DOWN:
|
|
{
|
|
int32_t iIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
|
|
>> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
|
vec_pointers_.push_back( AMotionEvent_getPointerId( event, iIndex ) );
|
|
if( count == 2 )
|
|
{
|
|
//Start new pinch
|
|
ret = GESTURE_STATE_START;
|
|
}
|
|
}
|
|
break;
|
|
case AMOTION_EVENT_ACTION_UP:
|
|
vec_pointers_.pop_back();
|
|
break;
|
|
case AMOTION_EVENT_ACTION_POINTER_UP:
|
|
{
|
|
int32_t index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
|
|
>> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
|
int32_t released_pointer_id = AMotionEvent_getPointerId( event, index );
|
|
|
|
std::vector<int32_t>::iterator it = vec_pointers_.begin();
|
|
std::vector<int32_t>::iterator it_end = vec_pointers_.end();
|
|
int32_t i = 0;
|
|
for( ; it != it_end; ++it, ++i )
|
|
{
|
|
if( *it == released_pointer_id )
|
|
{
|
|
vec_pointers_.erase( it );
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( i <= 1 )
|
|
{
|
|
//Reset pinch or drag
|
|
if( count != 2 )
|
|
{
|
|
//Start new pinch
|
|
ret = GESTURE_STATE_START | GESTURE_STATE_END;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case AMOTION_EVENT_ACTION_MOVE:
|
|
switch( count )
|
|
{
|
|
case 1:
|
|
break;
|
|
default:
|
|
//Multi touch
|
|
ret = GESTURE_STATE_MOVE;
|
|
break;
|
|
}
|
|
break;
|
|
case AMOTION_EVENT_ACTION_CANCEL:
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool PinchDetector::GetPointers( Vec2& v1, Vec2& v2 )
|
|
{
|
|
if( vec_pointers_.size() < 2 )
|
|
return false;
|
|
|
|
int32_t index = FindIndex( event_, vec_pointers_[0] );
|
|
if( index == -1 )
|
|
return false;
|
|
|
|
float x = AMotionEvent_getX( event_, index );
|
|
float y = AMotionEvent_getY( event_, index );
|
|
|
|
index = FindIndex( event_, vec_pointers_[1] );
|
|
if( index == -1 )
|
|
return false;
|
|
|
|
float x2 = AMotionEvent_getX( event_, index );
|
|
float y2 = AMotionEvent_getY( event_, index );
|
|
|
|
v1 = Vec2( x, y );
|
|
v2 = Vec2( x2, y2 );
|
|
|
|
return true;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------
|
|
// DragDetector
|
|
//--------------------------------------------------------------------------------
|
|
|
|
int32_t DragDetector::FindIndex( const AInputEvent* event, int32_t id )
|
|
{
|
|
int32_t count = AMotionEvent_getPointerCount( event );
|
|
for( uint32_t i = 0; i < count; ++i )
|
|
{
|
|
if( id == AMotionEvent_getPointerId( event, i ) )
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
GESTURE_STATE DragDetector::Detect( const AInputEvent* event )
|
|
{
|
|
GESTURE_STATE ret = GESTURE_STATE_NONE;
|
|
int32_t action = AMotionEvent_getAction( event );
|
|
int32_t index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
|
|
>> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
|
|
uint32_t flags = action & AMOTION_EVENT_ACTION_MASK;
|
|
event_ = event;
|
|
|
|
int32_t count = AMotionEvent_getPointerCount( event );
|
|
switch( flags )
|
|
{
|
|
case AMOTION_EVENT_ACTION_DOWN:
|
|
vec_pointers_.push_back( AMotionEvent_getPointerId( event, 0 ) );
|
|
ret = GESTURE_STATE_START;
|
|
break;
|
|
case AMOTION_EVENT_ACTION_POINTER_DOWN:
|
|
vec_pointers_.push_back( AMotionEvent_getPointerId( event, index ) );
|
|
break;
|
|
case AMOTION_EVENT_ACTION_UP:
|
|
vec_pointers_.pop_back();
|
|
ret = GESTURE_STATE_END;
|
|
break;
|
|
case AMOTION_EVENT_ACTION_POINTER_UP:
|
|
{
|
|
int32_t released_pointer_id = AMotionEvent_getPointerId( event, index );
|
|
|
|
std::vector<int32_t>::iterator it = vec_pointers_.begin();
|
|
std::vector<int32_t>::iterator it_end = vec_pointers_.end();
|
|
int32_t i = 0;
|
|
for( ; it != it_end; ++it, ++i )
|
|
{
|
|
if( *it == released_pointer_id )
|
|
{
|
|
vec_pointers_.erase( it );
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( i <= 1 )
|
|
{
|
|
//Reset pinch or drag
|
|
if( count == 2 )
|
|
{
|
|
ret = GESTURE_STATE_START;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case AMOTION_EVENT_ACTION_MOVE:
|
|
switch( count )
|
|
{
|
|
case 1:
|
|
//Drag
|
|
ret = GESTURE_STATE_MOVE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case AMOTION_EVENT_ACTION_CANCEL:
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool DragDetector::GetPointer( Vec2& v )
|
|
{
|
|
if( vec_pointers_.size() < 1 )
|
|
return false;
|
|
|
|
int32_t iIndex = FindIndex( event_, vec_pointers_[0] );
|
|
if( iIndex == -1 )
|
|
return false;
|
|
|
|
float x = AMotionEvent_getX( event_, iIndex );
|
|
float y = AMotionEvent_getY( event_, iIndex );
|
|
|
|
v = Vec2( x, y );
|
|
|
|
return true;
|
|
}
|
|
|
|
} //namespace ndkHelper
|
|
|