Added detection of touch devices before first touch events happen on Android.
authorPhilipp Wiesemann <philipp.wiesemann@arcor.de>
Sat, 05 Oct 2013 17:08:19 +0200
changeset 7786cfc1285375e1
parent 7785 d01823d85840
child 7787 e6f3e8fc96ea
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.
android-project/src/org/libsdl/app/SDLActivity.java
src/core/android/SDL_android.c
src/core/android/SDL_android.h
src/video/android/SDL_androidtouch.c
src/video/android/SDL_androidtouch.h
src/video/android/SDL_androidvideo.c
     1.1 --- a/android-project/src/org/libsdl/app/SDLActivity.java	Sat Oct 05 12:29:05 2013 -0700
     1.2 +++ b/android-project/src/org/libsdl/app/SDLActivity.java	Sat Oct 05 17:08:19 2013 +0200
     1.3 @@ -1,5 +1,7 @@
     1.4  package org.libsdl.app;
     1.5  
     1.6 +import java.util.Arrays;
     1.7 +
     1.8  import android.app.*;
     1.9  import android.content.*;
    1.10  import android.view.*;
    1.11 @@ -386,6 +388,24 @@
    1.12              mAudioTrack = null;
    1.13          }
    1.14      }
    1.15 +
    1.16 +    // Input
    1.17 +
    1.18 +    /**
    1.19 +     * @return an array which may be empty but is never null.
    1.20 +     */
    1.21 +    public static int[] inputGetInputDeviceIds(int sources) {
    1.22 +        int[] ids = InputDevice.getDeviceIds();
    1.23 +        int[] filtered = new int[ids.length];
    1.24 +        int used = 0;
    1.25 +        for (int i = 0; i < ids.length; ++i) {
    1.26 +            InputDevice device = InputDevice.getDevice(ids[i]);
    1.27 +            if ((device != null) && ((device.getSources() & sources) != 0)) {
    1.28 +                filtered[used++] = device.getId();
    1.29 +            }
    1.30 +        }
    1.31 +        return Arrays.copyOf(filtered, used);
    1.32 +    }
    1.33  }
    1.34  
    1.35  /**
     2.1 --- a/src/core/android/SDL_android.c	Sat Oct 05 12:29:05 2013 -0700
     2.2 +++ b/src/core/android/SDL_android.c	Sat Oct 05 17:08:19 2013 +0200
     2.3 @@ -1186,6 +1186,32 @@
     2.4      return 0;
     2.5  }
     2.6  
     2.7 +/* returns number of found touch devices as return value and ids in parameter ids */
     2.8 +int Android_JNI_GetTouchDeviceIds(int **ids) {
     2.9 +    JNIEnv *env = Android_JNI_GetEnv();
    2.10 +    jint sources = 4098; /* == InputDevice.SOURCE_TOUCHSCREEN */
    2.11 +    jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass, "inputGetInputDeviceIds", "(I)[I");
    2.12 +    jintArray array = (jintArray) (*env)->CallStaticObjectMethod(env, mActivityClass, mid, sources);
    2.13 +    int number = 0;
    2.14 +    *ids = NULL;
    2.15 +    if (array) {
    2.16 +        number = (int) (*env)->GetArrayLength(env, array);
    2.17 +        if (0 < number) {
    2.18 +            jint* elements = (*env)->GetIntArrayElements(env, array, NULL);
    2.19 +            if (elements) {
    2.20 +                int i;
    2.21 +                *ids = SDL_malloc(number * sizeof (*ids[0]));
    2.22 +                for (i = 0; i < number; ++i) { /* not assuming sizeof (jint) == sizeof (int) */
    2.23 +                    *ids[i] = elements[i];
    2.24 +                }
    2.25 +                (*env)->ReleaseIntArrayElements(env, array, elements, JNI_ABORT);
    2.26 +            }
    2.27 +        }
    2.28 +        (*env)->DeleteLocalRef(env, array);
    2.29 +    }
    2.30 +    return number;
    2.31 +}
    2.32 +
    2.33  /* sends message to be handled on the UI event dispatch thread */
    2.34  int Android_JNI_SendMessage(int command, int param)
    2.35  {
     3.1 --- a/src/core/android/SDL_android.h	Sat Oct 05 12:29:05 2013 -0700
     3.2 +++ b/src/core/android/SDL_android.h	Sat Oct 05 17:08:19 2013 +0200
     3.3 @@ -65,6 +65,9 @@
     3.4  /* Power support */
     3.5  int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent);
     3.6  
     3.7 +/* Touch support */
     3.8 +int Android_JNI_GetTouchDeviceIds(int **ids);
     3.9 +
    3.10  /* Threads */
    3.11  #include <jni.h>
    3.12  JNIEnv *Android_JNI_GetEnv(void);
     4.1 --- a/src/video/android/SDL_androidtouch.c	Sat Oct 05 12:29:05 2013 -0700
     4.2 +++ b/src/video/android/SDL_androidtouch.c	Sat Oct 05 17:08:19 2013 +0200
     4.3 @@ -31,6 +31,7 @@
     4.4  
     4.5  #include "SDL_androidtouch.h"
     4.6  
     4.7 +#include "../../core/android/SDL_android.h"
     4.8  
     4.9  #define ACTION_DOWN 0
    4.10  #define ACTION_UP 1
    4.11 @@ -53,6 +54,19 @@
    4.12      *window_y = (int)(y * window_h);
    4.13  }
    4.14  
    4.15 +void Android_InitTouch(void)
    4.16 +{
    4.17 +    int i;
    4.18 +    int* ids;
    4.19 +    int number = Android_JNI_GetTouchDeviceIds(&ids);
    4.20 +    if (0 < number) {
    4.21 +        for (i = 0; i < number; ++i) {
    4.22 +            SDL_AddTouch((SDL_TouchID) ids[i], ""); /* no error handling */
    4.23 +        }
    4.24 +        SDL_free(ids);
    4.25 +    }
    4.26 +}
    4.27 +
    4.28  void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p)
    4.29  {
    4.30      SDL_TouchID touchDeviceId = 0;
     5.1 --- a/src/video/android/SDL_androidtouch.h	Sat Oct 05 12:29:05 2013 -0700
     5.2 +++ b/src/video/android/SDL_androidtouch.h	Sat Oct 05 17:08:19 2013 +0200
     5.3 @@ -22,6 +22,7 @@
     5.4  
     5.5  #include "SDL_androidvideo.h"
     5.6  
     5.7 +extern void Android_InitTouch(void);
     5.8  extern void Android_OnTouch( int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p);
     5.9  
    5.10  /* vi: set ts=4 sw=4 expandtab: */
     6.1 --- a/src/video/android/SDL_androidvideo.c	Sat Oct 05 12:29:05 2013 -0700
     6.2 +++ b/src/video/android/SDL_androidvideo.c	Sat Oct 05 17:08:19 2013 +0200
     6.3 @@ -36,6 +36,7 @@
     6.4  #include "SDL_androidclipboard.h"
     6.5  #include "SDL_androidevents.h"
     6.6  #include "SDL_androidkeyboard.h"
     6.7 +#include "SDL_androidtouch.h"
     6.8  #include "SDL_androidwindow.h"
     6.9  
    6.10  #define ANDROID_VID_DRIVER_NAME "Android"
    6.11 @@ -165,6 +166,8 @@
    6.12  
    6.13      Android_InitKeyboard();
    6.14  
    6.15 +    Android_InitTouch();
    6.16 +
    6.17      /* We're done! */
    6.18      return 0;
    6.19  }