Home | History | Annotate | Download | only in ndk_helper
      1 /*
      2  * Copyright 2013 The Android Open Source Project
      3  *
      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
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     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.
     15  */
     16 
     17 #include "gestureDetector.h"
     18 
     19 //--------------------------------------------------------------------------------
     20 // gestureDetector.cpp
     21 //--------------------------------------------------------------------------------
     22 namespace ndk_helper
     23 {
     24 
     25 //--------------------------------------------------------------------------------
     26 // includes
     27 //--------------------------------------------------------------------------------
     28 
     29 //--------------------------------------------------------------------------------
     30 // GestureDetector
     31 //--------------------------------------------------------------------------------
     32 GestureDetector::GestureDetector()
     33 {
     34     dp_factor_ = 1.f;
     35 }
     36 
     37 void GestureDetector::SetConfiguration( AConfiguration* config )
     38 {
     39     dp_factor_ = 160.f / AConfiguration_getDensity( config );
     40 }
     41 
     42 //--------------------------------------------------------------------------------
     43 // TapDetector
     44 //--------------------------------------------------------------------------------
     45 GESTURE_STATE TapDetector::Detect( const AInputEvent* motion_event )
     46 {
     47     if( AMotionEvent_getPointerCount( motion_event ) > 1 )
     48     {
     49         //Only support single touch
     50         return false;
     51     }
     52 
     53     int32_t action = AMotionEvent_getAction( motion_event );
     54     unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
     55     switch( flags )
     56     {
     57     case AMOTION_EVENT_ACTION_DOWN:
     58         down_pointer_id_ = AMotionEvent_getPointerId( motion_event, 0 );
     59         down_x_ = AMotionEvent_getX( motion_event, 0 );
     60         down_y_ = AMotionEvent_getY( motion_event, 0 );
     61         break;
     62     case AMOTION_EVENT_ACTION_UP:
     63     {
     64         int64_t eventTime = AMotionEvent_getEventTime( motion_event );
     65         int64_t downTime = AMotionEvent_getDownTime( motion_event );
     66         if( eventTime - downTime <= TAP_TIMEOUT )
     67         {
     68             if( down_pointer_id_ == AMotionEvent_getPointerId( motion_event, 0 ) )
     69             {
     70                 float x = AMotionEvent_getX( motion_event, 0 ) - down_x_;
     71                 float y = AMotionEvent_getY( motion_event, 0 ) - down_y_;
     72                 if( x * x + y * y < TOUCH_SLOP * TOUCH_SLOP * dp_factor_ )
     73                 {
     74                     LOGI( "TapDetector: Tap detected" );
     75                     return GESTURE_STATE_ACTION;
     76                 }
     77             }
     78         }
     79         break;
     80     }
     81     }
     82     return GESTURE_STATE_NONE;
     83 }
     84 
     85 //--------------------------------------------------------------------------------
     86 // DoubletapDetector
     87 //--------------------------------------------------------------------------------
     88 GESTURE_STATE DoubletapDetector::Detect( const AInputEvent* motion_event )
     89 {
     90     if( AMotionEvent_getPointerCount( motion_event ) > 1 )
     91     {
     92         //Only support single double tap
     93         return false;
     94     }
     95 
     96     bool tap_detected = tap_detector_.Detect( motion_event );
     97 
     98     int32_t action = AMotionEvent_getAction( motion_event );
     99     unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
    100     switch( flags )
    101     {
    102     case AMOTION_EVENT_ACTION_DOWN:
    103     {
    104         int64_t eventTime = AMotionEvent_getEventTime( motion_event );
    105         if( eventTime - last_tap_time_ <= DOUBLE_TAP_TIMEOUT )
    106         {
    107             float x = AMotionEvent_getX( motion_event, 0 ) - last_tap_x_;
    108             float y = AMotionEvent_getY( motion_event, 0 ) - last_tap_y_;
    109             if( x * x + y * y < DOUBLE_TAP_SLOP * DOUBLE_TAP_SLOP * dp_factor_ )
    110             {
    111                 LOGI( "DoubletapDetector: Doubletap detected" );
    112                 return GESTURE_STATE_ACTION;
    113             }
    114         }
    115         break;
    116     }
    117     case AMOTION_EVENT_ACTION_UP:
    118         if( tap_detected )
    119         {
    120             last_tap_time_ = AMotionEvent_getEventTime( motion_event );
    121             last_tap_x_ = AMotionEvent_getX( motion_event, 0 );
    122             last_tap_y_ = AMotionEvent_getY( motion_event, 0 );
    123         }
    124         break;
    125     }
    126     return GESTURE_STATE_NONE;
    127 }
    128 
    129 void DoubletapDetector::SetConfiguration( AConfiguration* config )
    130 {
    131     dp_factor_ = 160.f / AConfiguration_getDensity( config );
    132     tap_detector_.SetConfiguration( config );
    133 }
    134 
    135 //--------------------------------------------------------------------------------
    136 // PinchDetector
    137 //--------------------------------------------------------------------------------
    138 
    139 int32_t PinchDetector::FindIndex( const AInputEvent* event, int32_t id )
    140 {
    141     int32_t count = AMotionEvent_getPointerCount( event );
    142     for( uint32_t i = 0; i < count; ++i )
    143     {
    144         if( id == AMotionEvent_getPointerId( event, i ) )
    145             return i;
    146     }
    147     return -1;
    148 }
    149 
    150 GESTURE_STATE PinchDetector::Detect( const AInputEvent* event )
    151 {
    152     GESTURE_STATE ret = GESTURE_STATE_NONE;
    153     int32_t action = AMotionEvent_getAction( event );
    154     uint32_t flags = action & AMOTION_EVENT_ACTION_MASK;
    155     event_ = event;
    156 
    157     int32_t count = AMotionEvent_getPointerCount( event );
    158     switch( flags )
    159     {
    160     case AMOTION_EVENT_ACTION_DOWN:
    161         vec_pointers_.push_back( AMotionEvent_getPointerId( event, 0 ) );
    162         break;
    163     case AMOTION_EVENT_ACTION_POINTER_DOWN:
    164     {
    165         int32_t iIndex = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
    166                 >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
    167         vec_pointers_.push_back( AMotionEvent_getPointerId( event, iIndex ) );
    168         if( count == 2 )
    169         {
    170             //Start new pinch
    171             ret = GESTURE_STATE_START;
    172         }
    173     }
    174         break;
    175     case AMOTION_EVENT_ACTION_UP:
    176         vec_pointers_.pop_back();
    177         break;
    178     case AMOTION_EVENT_ACTION_POINTER_UP:
    179     {
    180         int32_t index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
    181                 >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
    182         int32_t released_pointer_id = AMotionEvent_getPointerId( event, index );
    183 
    184         std::vector<int32_t>::iterator it = vec_pointers_.begin();
    185         std::vector<int32_t>::iterator it_end = vec_pointers_.end();
    186         int32_t i = 0;
    187         for( ; it != it_end; ++it, ++i )
    188         {
    189             if( *it == released_pointer_id )
    190             {
    191                 vec_pointers_.erase( it );
    192                 break;
    193             }
    194         }
    195 
    196         if( i <= 1 )
    197         {
    198             //Reset pinch or drag
    199             if( count != 2 )
    200             {
    201                 //Start new pinch
    202                 ret = GESTURE_STATE_START | GESTURE_STATE_END;
    203             }
    204         }
    205     }
    206         break;
    207     case AMOTION_EVENT_ACTION_MOVE:
    208         switch( count )
    209         {
    210         case 1:
    211             break;
    212         default:
    213             //Multi touch
    214             ret = GESTURE_STATE_MOVE;
    215             break;
    216         }
    217         break;
    218     case AMOTION_EVENT_ACTION_CANCEL:
    219         break;
    220     }
    221 
    222     return ret;
    223 }
    224 
    225 bool PinchDetector::GetPointers( Vec2& v1, Vec2& v2 )
    226 {
    227     if( vec_pointers_.size() < 2 )
    228         return false;
    229 
    230     int32_t index = FindIndex( event_, vec_pointers_[0] );
    231     if( index == -1 )
    232         return false;
    233 
    234     float x = AMotionEvent_getX( event_, index );
    235     float y = AMotionEvent_getY( event_, index );
    236 
    237     index = FindIndex( event_, vec_pointers_[1] );
    238     if( index == -1 )
    239         return false;
    240 
    241     float x2 = AMotionEvent_getX( event_, index );
    242     float y2 = AMotionEvent_getY( event_, index );
    243 
    244     v1 = Vec2( x, y );
    245     v2 = Vec2( x2, y2 );
    246 
    247     return true;
    248 }
    249 
    250 //--------------------------------------------------------------------------------
    251 // DragDetector
    252 //--------------------------------------------------------------------------------
    253 
    254 int32_t DragDetector::FindIndex( const AInputEvent* event, int32_t id )
    255 {
    256     int32_t count = AMotionEvent_getPointerCount( event );
    257     for( uint32_t i = 0; i < count; ++i )
    258     {
    259         if( id == AMotionEvent_getPointerId( event, i ) )
    260             return i;
    261     }
    262     return -1;
    263 }
    264 
    265 GESTURE_STATE DragDetector::Detect( const AInputEvent* event )
    266 {
    267     GESTURE_STATE ret = GESTURE_STATE_NONE;
    268     int32_t action = AMotionEvent_getAction( event );
    269     int32_t index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
    270             >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
    271     uint32_t flags = action & AMOTION_EVENT_ACTION_MASK;
    272     event_ = event;
    273 
    274     int32_t count = AMotionEvent_getPointerCount( event );
    275     switch( flags )
    276     {
    277     case AMOTION_EVENT_ACTION_DOWN:
    278         vec_pointers_.push_back( AMotionEvent_getPointerId( event, 0 ) );
    279         ret = GESTURE_STATE_START;
    280         break;
    281     case AMOTION_EVENT_ACTION_POINTER_DOWN:
    282         vec_pointers_.push_back( AMotionEvent_getPointerId( event, index ) );
    283         break;
    284     case AMOTION_EVENT_ACTION_UP:
    285         vec_pointers_.pop_back();
    286         ret = GESTURE_STATE_END;
    287         break;
    288     case AMOTION_EVENT_ACTION_POINTER_UP:
    289     {
    290         int32_t released_pointer_id = AMotionEvent_getPointerId( event, index );
    291 
    292         std::vector<int32_t>::iterator it = vec_pointers_.begin();
    293         std::vector<int32_t>::iterator it_end = vec_pointers_.end();
    294         int32_t i = 0;
    295         for( ; it != it_end; ++it, ++i )
    296         {
    297             if( *it == released_pointer_id )
    298             {
    299                 vec_pointers_.erase( it );
    300                 break;
    301             }
    302         }
    303 
    304         if( i <= 1 )
    305         {
    306             //Reset pinch or drag
    307             if( count == 2 )
    308             {
    309                 ret = GESTURE_STATE_START;
    310             }
    311         }
    312         break;
    313     }
    314     case AMOTION_EVENT_ACTION_MOVE:
    315         switch( count )
    316         {
    317         case 1:
    318             //Drag
    319             ret = GESTURE_STATE_MOVE;
    320             break;
    321         default:
    322             break;
    323         }
    324         break;
    325     case AMOTION_EVENT_ACTION_CANCEL:
    326         break;
    327     }
    328 
    329     return ret;
    330 }
    331 
    332 bool DragDetector::GetPointer( Vec2& v )
    333 {
    334     if( vec_pointers_.size() < 1 )
    335         return false;
    336 
    337     int32_t iIndex = FindIndex( event_, vec_pointers_[0] );
    338     if( iIndex == -1 )
    339         return false;
    340 
    341     float x = AMotionEvent_getX( event_, iIndex );
    342     float y = AMotionEvent_getY( event_, iIndex );
    343 
    344     v = Vec2( x, y );
    345 
    346     return true;
    347 }
    348 
    349 }   //namespace ndkHelper
    350 
    351