Added support for multitouch on Android.
authorRyan C. Gordon <icculus@icculus.org>
Thu, 13 Oct 2011 01:21:35 -0400
changeset 5982f324bd81b52c
parent 5981 75caa8a7d559
child 5989 cd688ba5b7d4
Added support for multitouch on Android.

Fixes Bugzilla #1294.

Thanks to Gabriel Jacobo for the patch!
android-project/src/org/libsdl/app/SDLActivity.java
src/core/android/SDL_android.cpp
src/video/android/SDL_androidtouch.c
src/video/android/SDL_androidtouch.h
     1.1 --- a/android-project/src/org/libsdl/app/SDLActivity.java	Thu Oct 13 01:08:30 2011 -0400
     1.2 +++ b/android-project/src/org/libsdl/app/SDLActivity.java	Thu Oct 13 01:21:35 2011 -0400
     1.3 @@ -93,7 +93,8 @@
     1.4      public static native void onNativeResize(int x, int y, int format);
     1.5      public static native void onNativeKeyDown(int keycode);
     1.6      public static native void onNativeKeyUp(int keycode);
     1.7 -    public static native void onNativeTouch(int action, float x, 
     1.8 +    public static native void onNativeTouch(int touchDevId, int pointerFingerId,
     1.9 +                                            int action, float x, 
    1.10                                              float y, float p);
    1.11      public static native void onNativeAccel(float x, float y, float z);
    1.12      public static native void nativeRunAudioThread();
    1.13 @@ -459,16 +460,34 @@
    1.14  
    1.15      // Touch events
    1.16      public boolean onTouch(View v, MotionEvent event) {
    1.17 -    
    1.18 -        int action = event.getAction();
    1.19 -        float x = event.getX();
    1.20 -        float y = event.getY();
    1.21 -        float p = event.getPressure();
    1.22 +        {
    1.23 +             final int touchDevId = event.getDeviceId();
    1.24 +             final int pointerCount = event.getPointerCount();
    1.25 +             // touchId, pointerId, action, x, y, pressure
    1.26 +             int actionPointerIndex = event.getActionIndex();
    1.27 +             int pointerFingerId = event.getPointerId(actionPointerIndex);
    1.28 +             int action = event.getActionMasked();
    1.29  
    1.30 -        // TODO: Anything else we need to pass?        
    1.31 -        SDLActivity.onNativeTouch(action, x, y, p);
    1.32 -        return true;
    1.33 -    }
    1.34 +             float x = event.getX(actionPointerIndex);
    1.35 +             float y = event.getY(actionPointerIndex);
    1.36 +             float p = event.getPressure(actionPointerIndex);
    1.37 +
    1.38 +             if (action == MotionEvent.ACTION_MOVE && pointerCount > 1) {
    1.39 +                // TODO send motion to every pointer if its position has
    1.40 +                // changed since prev event.
    1.41 +                for (int i = 0; i < pointerCount; i++) {
    1.42 +                    pointerFingerId = event.getPointerId(i);
    1.43 +                    x = event.getX(i);
    1.44 +                    y = event.getY(i);
    1.45 +                    p = event.getPressure(i);
    1.46 +                    SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
    1.47 +                }
    1.48 +             } else {
    1.49 +                SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
    1.50 +             }
    1.51 +        }
    1.52 +      return true;
    1.53 +   } 
    1.54  
    1.55      // Sensor events
    1.56      public void enableSensor(int sensortype, boolean enabled) {
     2.1 --- a/src/core/android/SDL_android.cpp	Thu Oct 13 01:08:30 2011 -0400
     2.2 +++ b/src/core/android/SDL_android.cpp	Thu Oct 13 01:21:35 2011 -0400
     2.3 @@ -123,9 +123,10 @@
     2.4  // Touch
     2.5  extern "C" void Java_org_libsdl_app_SDLActivity_onNativeTouch(
     2.6                                      JNIEnv* env, jclass jcls,
     2.7 +                                    jint touch_device_id_in, jint pointer_finger_id_in,
     2.8                                      jint action, jfloat x, jfloat y, jfloat p)
     2.9  {
    2.10 -    Android_OnTouch(action, x, y, p);
    2.11 +    Android_OnTouch(touch_device_id_in, pointer_finger_id_in, action, x, y, p);
    2.12  }
    2.13  
    2.14  // Accelerometer
     3.1 --- a/src/video/android/SDL_androidtouch.c	Thu Oct 13 01:08:30 2011 -0400
     3.2 +++ b/src/video/android/SDL_androidtouch.c	Thu Oct 13 01:21:35 2011 -0400
     3.3 @@ -24,6 +24,7 @@
     3.4  
     3.5  #include "SDL_events.h"
     3.6  #include "../../events/SDL_mouse_c.h"
     3.7 +#include "../../events/SDL_touch_c.h"
     3.8  
     3.9  #include "SDL_androidtouch.h"
    3.10  
    3.11 @@ -33,27 +34,55 @@
    3.12  #define ACTION_MOVE 2
    3.13  #define ACTION_CANCEL 3
    3.14  #define ACTION_OUTSIDE 4
    3.15 +// The following two are deprecated but it seems they are still emitted (instead the corresponding ACTION_UP/DOWN) as of Android 3.2
    3.16 +#define ACTION_POINTER_1_DOWN 5
    3.17 +#define ACTION_POINTER_1_UP 6
    3.18  
    3.19 -void Android_OnTouch(int action, float x, float y, float p)
    3.20 +void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p) 
    3.21  {
    3.22 +    SDL_TouchID touchDeviceId = 0;
    3.23 +    SDL_FingerID fingerId = 0;
    3.24 +    
    3.25      if (!Android_Window) {
    3.26          return;
    3.27      }
    3.28 +    
    3.29 +    touchDeviceId = (SDL_TouchID)touch_device_id_in;
    3.30 +    if (!SDL_GetTouch(touchDeviceId)) {
    3.31 +        SDL_Touch touch;
    3.32 +        memset( &touch, 0, sizeof(touch) );
    3.33 +        touch.id = touchDeviceId;
    3.34 +        touch.x_min = 0.0f;
    3.35 +        touch.x_max = (float)Android_ScreenWidth;
    3.36 +        touch.native_xres = touch.x_max - touch.x_min;
    3.37 +        touch.y_min = 0.0f;
    3.38 +        touch.y_max = (float)Android_ScreenHeight;
    3.39 +        touch.native_yres = touch.y_max - touch.y_min;
    3.40 +        touch.pressure_min = 0.0f;
    3.41 +        touch.pressure_max = 1.0f;
    3.42 +        touch.native_pressureres = touch.pressure_max - touch.pressure_min;
    3.43 +        if (SDL_AddTouch(&touch, "") < 0) {
    3.44 +             SDL_Log("error: can't add touch %s, %d", __FILE__, __LINE__);
    3.45 +        }
    3.46 +    }
    3.47  
    3.48 -    if ((action != ACTION_CANCEL) && (action != ACTION_OUTSIDE)) {
    3.49 -        SDL_SetMouseFocus(Android_Window);
    3.50 -        SDL_SendMouseMotion(Android_Window, 0, (int)x, (int)y);
    3.51 -        switch(action) {
    3.52 +    
    3.53 +    fingerId = (SDL_FingerID)pointer_finger_id_in;
    3.54 +    switch (action) {
    3.55          case ACTION_DOWN:
    3.56 -            SDL_SendMouseButton(Android_Window, SDL_PRESSED, SDL_BUTTON_LEFT);
    3.57 +        case ACTION_POINTER_1_DOWN:
    3.58 +            SDL_SendFingerDown(touchDeviceId, fingerId, SDL_TRUE, x, y, p);
    3.59 +            break;
    3.60 +        case ACTION_MOVE:
    3.61 +            SDL_SendTouchMotion(touchDeviceId, fingerId, SDL_FALSE, x, y, p);
    3.62              break;
    3.63          case ACTION_UP:
    3.64 -            SDL_SendMouseButton(Android_Window, SDL_RELEASED, SDL_BUTTON_LEFT);
    3.65 +        case ACTION_POINTER_1_UP:
    3.66 +            SDL_SendFingerDown(touchDeviceId, fingerId, SDL_FALSE, x, y, p);
    3.67              break;
    3.68 -        }
    3.69 -    } else {
    3.70 -        SDL_SetMouseFocus(NULL);
    3.71 -    }
    3.72 +        default:
    3.73 +            break;
    3.74 +    } 
    3.75  }
    3.76  
    3.77  /* vi: set ts=4 sw=4 expandtab: */
     4.1 --- a/src/video/android/SDL_androidtouch.h	Thu Oct 13 01:08:30 2011 -0400
     4.2 +++ b/src/video/android/SDL_androidtouch.h	Thu Oct 13 01:21:35 2011 -0400
     4.3 @@ -22,6 +22,6 @@
     4.4  
     4.5  #include "SDL_androidvideo.h"
     4.6  
     4.7 -extern void Android_OnTouch(int action, float x, float y, float p);
     4.8 +extern void Android_OnTouch( int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p);
     4.9  
    4.10  /* vi: set ts=4 sw=4 expandtab: */