Просмотр исходного кода

Added detection of touch devices before first touch events happen on Android.

On Android available touch devices are now added with video initialization (like
the keyboard). This fixes SDL_GetNumTouchDevices() returning 0 before any touch
events happened although there is a touch screen available. The adding of touch
devices after a touch event was received is still active to allow connecting
devices later (if this is possible) and to provide a fallback if the new init
did not work somehow. For the implementation JNI was used and API level 9 is
required. There seems to be nothing in the Android NDK's input header (input.h)
to implement everything on C side without communication with Java side.
Philipp Wiesemann 11 лет назад
Родитель
Сommit
0db36f51aa

+ 20 - 0
android-project/src/org/libsdl/app/SDLActivity.java

@@ -1,5 +1,7 @@
 package org.libsdl.app;
 
+import java.util.Arrays;
+
 import android.app.*;
 import android.content.*;
 import android.view.*;
@@ -386,6 +388,24 @@ public class SDLActivity extends Activity {
             mAudioTrack = null;
         }
     }
+
+    // Input
+
+    /**
+     * @return an array which may be empty but is never null.
+     */
+    public static int[] inputGetInputDeviceIds(int sources) {
+        int[] ids = InputDevice.getDeviceIds();
+        int[] filtered = new int[ids.length];
+        int used = 0;
+        for (int i = 0; i < ids.length; ++i) {
+            InputDevice device = InputDevice.getDevice(ids[i]);
+            if ((device != null) && ((device.getSources() & sources) != 0)) {
+                filtered[used++] = device.getId();
+            }
+        }
+        return Arrays.copyOf(filtered, used);
+    }
 }
 
 /**

+ 26 - 0
src/core/android/SDL_android.c

@@ -1186,6 +1186,32 @@ int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seco
     return 0;
 }
 
+/* returns number of found touch devices as return value and ids in parameter ids */
+int Android_JNI_GetTouchDeviceIds(int **ids) {
+    JNIEnv *env = Android_JNI_GetEnv();
+    jint sources = 4098; /* == InputDevice.SOURCE_TOUCHSCREEN */
+    jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass, "inputGetInputDeviceIds", "(I)[I");
+    jintArray array = (jintArray) (*env)->CallStaticObjectMethod(env, mActivityClass, mid, sources);
+    int number = 0;
+    *ids = NULL;
+    if (array) {
+        number = (int) (*env)->GetArrayLength(env, array);
+        if (0 < number) {
+            jint* elements = (*env)->GetIntArrayElements(env, array, NULL);
+            if (elements) {
+                int i;
+                *ids = SDL_malloc(number * sizeof (*ids[0]));
+                for (i = 0; i < number; ++i) { /* not assuming sizeof (jint) == sizeof (int) */
+                    *ids[i] = elements[i];
+                }
+                (*env)->ReleaseIntArrayElements(env, array, elements, JNI_ABORT);
+            }
+        }
+        (*env)->DeleteLocalRef(env, array);
+    }
+    return number;
+}
+
 /* sends message to be handled on the UI event dispatch thread */
 int Android_JNI_SendMessage(int command, int param)
 {

+ 3 - 0
src/core/android/SDL_android.h

@@ -65,6 +65,9 @@ SDL_bool Android_JNI_HasClipboardText();
 /* Power support */
 int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent);
 
+/* Touch support */
+int Android_JNI_GetTouchDeviceIds(int **ids);
+
 /* Threads */
 #include <jni.h>
 JNIEnv *Android_JNI_GetEnv(void);

+ 14 - 0
src/video/android/SDL_androidtouch.c

@@ -31,6 +31,7 @@
 
 #include "SDL_androidtouch.h"
 
+#include "../../core/android/SDL_android.h"
 
 #define ACTION_DOWN 0
 #define ACTION_UP 1
@@ -53,6 +54,19 @@ static void Android_GetWindowCoordinates(float x, float y,
     *window_y = (int)(y * window_h);
 }
 
+void Android_InitTouch(void)
+{
+    int i;
+    int* ids;
+    int number = Android_JNI_GetTouchDeviceIds(&ids);
+    if (0 < number) {
+        for (i = 0; i < number; ++i) {
+            SDL_AddTouch((SDL_TouchID) ids[i], ""); /* no error handling */
+        }
+        SDL_free(ids);
+    }
+}
+
 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;

+ 1 - 0
src/video/android/SDL_androidtouch.h

@@ -22,6 +22,7 @@
 
 #include "SDL_androidvideo.h"
 
+extern void Android_InitTouch(void);
 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: */

+ 3 - 0
src/video/android/SDL_androidvideo.c

@@ -36,6 +36,7 @@
 #include "SDL_androidclipboard.h"
 #include "SDL_androidevents.h"
 #include "SDL_androidkeyboard.h"
+#include "SDL_androidtouch.h"
 #include "SDL_androidwindow.h"
 
 #define ANDROID_VID_DRIVER_NAME "Android"
@@ -165,6 +166,8 @@ Android_VideoInit(_THIS)
 
     Android_InitKeyboard();
 
+    Android_InitTouch();
+
     /* We're done! */
     return 0;
 }