Added support for multitouch on Android.
authorRyan C. Gordon <icculus@icculus.org>
Thu, 13 Oct 2011 01:21:35 -0400
changeset 5982 f324bd81b52c
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
--- a/android-project/src/org/libsdl/app/SDLActivity.java	Thu Oct 13 01:08:30 2011 -0400
+++ b/android-project/src/org/libsdl/app/SDLActivity.java	Thu Oct 13 01:21:35 2011 -0400
@@ -93,7 +93,8 @@
     public static native void onNativeResize(int x, int y, int format);
     public static native void onNativeKeyDown(int keycode);
     public static native void onNativeKeyUp(int keycode);
-    public static native void onNativeTouch(int action, float x, 
+    public static native void onNativeTouch(int touchDevId, int pointerFingerId,
+                                            int action, float x, 
                                             float y, float p);
     public static native void onNativeAccel(float x, float y, float z);
     public static native void nativeRunAudioThread();
@@ -459,16 +460,34 @@
 
     // Touch events
     public boolean onTouch(View v, MotionEvent event) {
-    
-        int action = event.getAction();
-        float x = event.getX();
-        float y = event.getY();
-        float p = event.getPressure();
+        {
+             final int touchDevId = event.getDeviceId();
+             final int pointerCount = event.getPointerCount();
+             // touchId, pointerId, action, x, y, pressure
+             int actionPointerIndex = event.getActionIndex();
+             int pointerFingerId = event.getPointerId(actionPointerIndex);
+             int action = event.getActionMasked();
+
+             float x = event.getX(actionPointerIndex);
+             float y = event.getY(actionPointerIndex);
+             float p = event.getPressure(actionPointerIndex);
 
-        // TODO: Anything else we need to pass?        
-        SDLActivity.onNativeTouch(action, x, y, p);
-        return true;
-    }
+             if (action == MotionEvent.ACTION_MOVE && pointerCount > 1) {
+                // TODO send motion to every pointer if its position has
+                // changed since prev event.
+                for (int i = 0; i < pointerCount; i++) {
+                    pointerFingerId = event.getPointerId(i);
+                    x = event.getX(i);
+                    y = event.getY(i);
+                    p = event.getPressure(i);
+                    SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
+                }
+             } else {
+                SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
+             }
+        }
+      return true;
+   } 
 
     // Sensor events
     public void enableSensor(int sensortype, boolean enabled) {
--- a/src/core/android/SDL_android.cpp	Thu Oct 13 01:08:30 2011 -0400
+++ b/src/core/android/SDL_android.cpp	Thu Oct 13 01:21:35 2011 -0400
@@ -123,9 +123,10 @@
 // Touch
 extern "C" void Java_org_libsdl_app_SDLActivity_onNativeTouch(
                                     JNIEnv* env, jclass jcls,
+                                    jint touch_device_id_in, jint pointer_finger_id_in,
                                     jint action, jfloat x, jfloat y, jfloat p)
 {
-    Android_OnTouch(action, x, y, p);
+    Android_OnTouch(touch_device_id_in, pointer_finger_id_in, action, x, y, p);
 }
 
 // Accelerometer
--- a/src/video/android/SDL_androidtouch.c	Thu Oct 13 01:08:30 2011 -0400
+++ b/src/video/android/SDL_androidtouch.c	Thu Oct 13 01:21:35 2011 -0400
@@ -24,6 +24,7 @@
 
 #include "SDL_events.h"
 #include "../../events/SDL_mouse_c.h"
+#include "../../events/SDL_touch_c.h"
 
 #include "SDL_androidtouch.h"
 
@@ -33,27 +34,55 @@
 #define ACTION_MOVE 2
 #define ACTION_CANCEL 3
 #define ACTION_OUTSIDE 4
+// The following two are deprecated but it seems they are still emitted (instead the corresponding ACTION_UP/DOWN) as of Android 3.2
+#define ACTION_POINTER_1_DOWN 5
+#define ACTION_POINTER_1_UP 6
 
-void Android_OnTouch(int action, float x, float y, float p)
+void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p) 
 {
+    SDL_TouchID touchDeviceId = 0;
+    SDL_FingerID fingerId = 0;
+    
     if (!Android_Window) {
         return;
     }
+    
+    touchDeviceId = (SDL_TouchID)touch_device_id_in;
+    if (!SDL_GetTouch(touchDeviceId)) {
+        SDL_Touch touch;
+        memset( &touch, 0, sizeof(touch) );
+        touch.id = touchDeviceId;
+        touch.x_min = 0.0f;
+        touch.x_max = (float)Android_ScreenWidth;
+        touch.native_xres = touch.x_max - touch.x_min;
+        touch.y_min = 0.0f;
+        touch.y_max = (float)Android_ScreenHeight;
+        touch.native_yres = touch.y_max - touch.y_min;
+        touch.pressure_min = 0.0f;
+        touch.pressure_max = 1.0f;
+        touch.native_pressureres = touch.pressure_max - touch.pressure_min;
+        if (SDL_AddTouch(&touch, "") < 0) {
+             SDL_Log("error: can't add touch %s, %d", __FILE__, __LINE__);
+        }
+    }
 
-    if ((action != ACTION_CANCEL) && (action != ACTION_OUTSIDE)) {
-        SDL_SetMouseFocus(Android_Window);
-        SDL_SendMouseMotion(Android_Window, 0, (int)x, (int)y);
-        switch(action) {
+    
+    fingerId = (SDL_FingerID)pointer_finger_id_in;
+    switch (action) {
         case ACTION_DOWN:
-            SDL_SendMouseButton(Android_Window, SDL_PRESSED, SDL_BUTTON_LEFT);
+        case ACTION_POINTER_1_DOWN:
+            SDL_SendFingerDown(touchDeviceId, fingerId, SDL_TRUE, x, y, p);
+            break;
+        case ACTION_MOVE:
+            SDL_SendTouchMotion(touchDeviceId, fingerId, SDL_FALSE, x, y, p);
             break;
         case ACTION_UP:
-            SDL_SendMouseButton(Android_Window, SDL_RELEASED, SDL_BUTTON_LEFT);
+        case ACTION_POINTER_1_UP:
+            SDL_SendFingerDown(touchDeviceId, fingerId, SDL_FALSE, x, y, p);
             break;
-        }
-    } else {
-        SDL_SetMouseFocus(NULL);
-    }
+        default:
+            break;
+    } 
 }
 
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/android/SDL_androidtouch.h	Thu Oct 13 01:08:30 2011 -0400
+++ b/src/video/android/SDL_androidtouch.h	Thu Oct 13 01:21:35 2011 -0400
@@ -22,6 +22,6 @@
 
 #include "SDL_androidvideo.h"
 
-extern void Android_OnTouch(int action, float x, float y, float p);
+extern void Android_OnTouch( int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p);
 
 /* vi: set ts=4 sw=4 expandtab: */