Only in SDL: android-multitouch.patch diff -crB '--exclude=.hg' SDL-orig/android-project/default.properties SDL/android-project/default.properties *** SDL-orig/android-project/default.properties 2011-03-02 17:53:44.462726004 +0100 --- SDL/android-project/default.properties 2011-03-02 17:41:14.198726001 +0100 *************** *** 8,11 **** # project structure. # Project target. ! target=android-4 --- 8,11 ---- # project structure. # Project target. ! target=android-7 diff -crB '--exclude=.hg' SDL-orig/android-project/src/org/libsdl/app/SDLActivity.java SDL/android-project/src/org/libsdl/app/SDLActivity.java *** SDL-orig/android-project/src/org/libsdl/app/SDLActivity.java 2011-03-02 17:53:44.478726004 +0100 --- SDL/android-project/src/org/libsdl/app/SDLActivity.java 2011-03-02 18:05:03.586726001 +0100 *************** *** 95,100 **** --- 95,102 ---- public static native void onNativeKeyUp(int keycode); public static native void onNativeTouch(int action, float x, float y, float p); + public static native void onNativeMultiTouch(int action, float x, + float y, int pointerId, float pressure); public static native void onNativeAccel(float x, float y, float z); public static native void nativeRunAudioThread(); *************** *** 244,249 **** --- 246,266 ---- // Sensors private static SensorManager mSensorManager; + private static final int touchEventMax = 16; // Max multitouch pointers + private static touchEvent touchEvents[]; + private static boolean multiTouch = true; + private static class touchEvent + { + public boolean down = false; + public float x = 0; + public float y = 0; + public float pressure = 0; + } + static { + touchEvents = new touchEvent[touchEventMax]; + for( int i = 0; i < touchEventMax; i++ ) + touchEvents[i] = new touchEvent(); + } // Startup public SDLSurface(Context context) { *************** *** 456,461 **** --- 473,548 ---- // Touch events public boolean onTouch(View v, MotionEvent event) { + if (multiTouch) + { + int action = -1; + if( event.getAction() == MotionEvent.ACTION_UP ) + { + action = 1; + for( int i = 0; i < touchEventMax; i++ ) + { + if( touchEvents[i].down ) + { + touchEvents[i].down = false; + SDLActivity.onNativeMultiTouch(action, touchEvents[i].x, touchEvents[i].y, i, touchEvents[i].pressure); + } + } + } + if( event.getAction() == MotionEvent.ACTION_DOWN ) + { + action = 0; + for( int i = 0; i < event.getPointerCount(); i++ ) + { + int id = event.getPointerId(i); + if( id >= touchEventMax ) + id = touchEventMax-1; + touchEvents[id].down = true; + touchEvents[id].x = event.getX(i); + touchEvents[id].y = event.getY(i); + touchEvents[id].pressure = event.getPressure(i); + SDLActivity.onNativeMultiTouch(action, touchEvents[id].x, touchEvents[id].y, id, touchEvents[id].pressure); + } + } + + if( event.getAction() == MotionEvent.ACTION_MOVE ) + { + for( int i = 0; i < touchEventMax; i++ ) + { + int ii; + for( ii = 0; ii < event.getPointerCount(); ii++ ) + { + if( i == event.getPointerId(ii) ) + break; + } + if( ii >= event.getPointerCount() ) + { + // Up event + if( touchEvents[i].down ) + { + action = 1; + touchEvents[i].down = false; + SDLActivity.onNativeMultiTouch(action, touchEvents[i].x, touchEvents[i].y, i, touchEvents[i].pressure); + } + } + else + { + int id = event.getPointerId(ii); + if( id >= touchEventMax ) + id = touchEventMax-1; + if( touchEvents[id].down ) + action = 2; + else + action = 0; + touchEvents[id].down = true; + touchEvents[id].x = event.getX(i); + touchEvents[id].y = event.getY(i); + touchEvents[id].pressure = event.getPressure(i); + SDLActivity.onNativeMultiTouch(action, touchEvents[id].x, touchEvents[id].y, id, touchEvents[id].pressure); + } + } + } + return true; + } int action = event.getAction(); float x = event.getX(); float y = event.getY(); diff -crB '--exclude=.hg' SDL-orig/src/core/android/SDL_android.cpp SDL/src/core/android/SDL_android.cpp *** SDL-orig/src/core/android/SDL_android.cpp 2011-03-02 17:53:44.574726004 +0100 --- SDL/src/core/android/SDL_android.cpp 2011-03-02 13:33:13.000000000 +0100 *************** *** 44,51 **** /******************************************************************************* Globals *******************************************************************************/ ! static JNIEnv* mEnv = NULL; ! static JNIEnv* mAudioEnv = NULL; // Main activity static jclass mActivityClass; --- 44,50 ---- /******************************************************************************* Globals *******************************************************************************/ ! static JavaVM* mJVM = NULL; // Main activity static jclass mActivityClass; *************** *** 57,62 **** --- 56,62 ---- static jmethodID midAudioWriteShortBuffer; static jmethodID midAudioWriteByteBuffer; static jmethodID midAudioQuit; + static jmethodID midSetActivityTitle; // Accelerometer data storage static float fLastAccelerometer[3]; *************** *** 76,100 **** extern "C" void SDL_Android_Init(JNIEnv* env, jclass cls) { __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL_Android_Init()"); - mEnv = env; mActivityClass = cls; ! midCreateGLContext = mEnv->GetStaticMethodID(mActivityClass, "createGLContext","(II)Z"); ! midFlipBuffers = mEnv->GetStaticMethodID(mActivityClass, "flipBuffers","()V"); ! midAudioInit = mEnv->GetStaticMethodID(mActivityClass, "audioInit", "(IZZI)Ljava/lang/Object;"); ! midAudioWriteShortBuffer = mEnv->GetStaticMethodID(mActivityClass, "audioWriteShortBuffer", "([S)V"); ! midAudioWriteByteBuffer = mEnv->GetStaticMethodID(mActivityClass, "audioWriteByteBuffer", "([B)V"); ! midAudioQuit = mEnv->GetStaticMethodID(mActivityClass, "audioQuit", "()V"); if(!midCreateGLContext || !midFlipBuffers || !midAudioInit || ! !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioQuit) { __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL: Couldn't locate Java callbacks, check that they're named and typed correctly"); } } --- 76,102 ---- extern "C" void SDL_Android_Init(JNIEnv* env, jclass cls) { __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL_Android_Init()"); + env->GetJavaVM(&mJVM); mActivityClass = cls; ! midCreateGLContext = env->GetStaticMethodID(mActivityClass, "createGLContext","(II)Z"); ! midFlipBuffers = env->GetStaticMethodID(mActivityClass, "flipBuffers","()V"); ! midAudioInit = env->GetStaticMethodID(mActivityClass, "audioInit", "(IZZI)Ljava/lang/Object;"); ! midAudioWriteShortBuffer = env->GetStaticMethodID(mActivityClass, "audioWriteShortBuffer", "([S)V"); ! midAudioWriteByteBuffer = env->GetStaticMethodID(mActivityClass, "audioWriteByteBuffer", "([B)V"); ! midAudioQuit = env->GetStaticMethodID(mActivityClass, "audioQuit", "()V"); + midSetActivityTitle = env->GetStaticMethodID(mActivityClass,"setActivityTitle","(Ljava/lang/String;)V"); + if(!midCreateGLContext || !midFlipBuffers || !midAudioInit || ! !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioQuit ||!midSetActivityTitle) { __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL: Couldn't locate Java callbacks, check that they're named and typed correctly"); } } *************** *** 129,134 **** --- 131,144 ---- Android_OnTouch(action, x, y, p); } + // Multitouch + extern "C" void Java_org_libsdl_app_SDLActivity_onNativeMultiTouch( + JNIEnv *, jclass, + jint action, jfloat x, jfloat y, jint pointerId, jfloat p) + { + Android_OnMultiTouch(action, x, y, pointerId, p); + } + // Accelerometer extern "C" void Java_org_libsdl_app_SDLActivity_onNativeAccel( JNIEnv* env, jclass jcls, *************** *** 151,187 **** JNIEnv* env, jclass cls) { /* This is the audio thread, with a different environment */ - mAudioEnv = env; - Android_RunAudioThread(); } /******************************************************************************* Functions called by SDL into Java *******************************************************************************/ extern "C" SDL_bool Android_JNI_CreateContext(int majorVersion, int minorVersion) { ! if (mEnv->CallStaticBooleanMethod(mActivityClass, midCreateGLContext, majorVersion, minorVersion)) { return SDL_TRUE; } else { return SDL_FALSE; } } extern "C" void Android_JNI_SwapWindow() { ! mEnv->CallStaticVoidMethod(mActivityClass, midFlipBuffers); } extern "C" void Android_JNI_SetActivityTitle(const char *title) { ! jmethodID mid; ! ! mid = mEnv->GetStaticMethodID(mActivityClass,"setActivityTitle","(Ljava/lang/String;)V"); ! if (mid) { ! mEnv->CallStaticVoidMethod(mActivityClass, mid, mEnv->NewStringUTF(title)); ! } } extern "C" void Android_JNI_GetAccelerometerValues(float values[3]) --- 161,218 ---- JNIEnv* env, jclass cls) { /* This is the audio thread, with a different environment */ Android_RunAudioThread(); } + JNIEnv *getJNIEnv(SDL_bool &attached) + { + JNIEnv *env = NULL; + int status; + attached = SDL_FALSE; + status = mJVM->GetEnv((void **) &env, JNI_VERSION_1_4); + if(status < 0) { + status = mJVM->AttachCurrentThread(&env, NULL); + if(status < 0) { + __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL: failed to attach current thread!"); + return NULL; + } + attached = SDL_TRUE; + } + return env; + } /******************************************************************************* Functions called by SDL into Java *******************************************************************************/ extern "C" SDL_bool Android_JNI_CreateContext(int majorVersion, int minorVersion) { ! SDL_bool isAttached = SDL_FALSE; ! JNIEnv *env = getJNIEnv(isAttached); ! if (env && env->CallStaticBooleanMethod(mActivityClass, midCreateGLContext, majorVersion, minorVersion)) { ! if(isAttached) mJVM->DetachCurrentThread(); return SDL_TRUE; } else { + if(isAttached) mJVM->DetachCurrentThread(); return SDL_FALSE; } } extern "C" void Android_JNI_SwapWindow() { ! SDL_bool isAttached = SDL_FALSE; ! JNIEnv *env = getJNIEnv(isAttached); ! if (env) ! env->CallStaticVoidMethod(mActivityClass, midFlipBuffers); ! if(isAttached) mJVM->DetachCurrentThread(); } extern "C" void Android_JNI_SetActivityTitle(const char *title) { ! SDL_bool isAttached = SDL_FALSE; ! JNIEnv *env = getJNIEnv(isAttached); ! if (env) ! env->CallStaticVoidMethod(mActivityClass, midSetActivityTitle, env->NewStringUTF(title)); ! if(isAttached) mJVM->DetachCurrentThread(); } extern "C" void Android_JNI_GetAccelerometerValues(float values[3]) *************** *** 202,234 **** extern "C" int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames) { ! int audioBufferFrames; __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device"); audioBuffer16Bit = is16Bit; audioBufferStereo = channelCount > 1; ! audioBuffer = mEnv->CallStaticObjectMethod(mActivityClass, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames); if (audioBuffer == NULL) { __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: didn't get back a good audio buffer!"); return 0; } ! audioBuffer = mEnv->NewGlobalRef(audioBuffer); jboolean isCopy = JNI_FALSE; if (audioBuffer16Bit) { ! audioBufferPinned = mEnv->GetShortArrayElements((jshortArray)audioBuffer, &isCopy); ! audioBufferFrames = mEnv->GetArrayLength((jshortArray)audioBuffer); } else { ! audioBufferPinned = mEnv->GetByteArrayElements((jbyteArray)audioBuffer, &isCopy); ! audioBufferFrames = mEnv->GetArrayLength((jbyteArray)audioBuffer); } if (audioBufferStereo) { audioBufferFrames /= 2; } ! return audioBufferFrames; } extern "C" void * Android_JNI_GetAudioBuffer() --- 233,271 ---- extern "C" int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames) { ! SDL_bool isAttached = SDL_FALSE; ! JNIEnv *env = getJNIEnv(isAttached); + int audioBufferFrames; + if (!env) + return 0; __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device"); audioBuffer16Bit = is16Bit; audioBufferStereo = channelCount > 1; ! audioBuffer = env->CallStaticObjectMethod(mActivityClass, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames); if (audioBuffer == NULL) { __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: didn't get back a good audio buffer!"); + if(isAttached) mJVM->DetachCurrentThread(); return 0; } ! audioBuffer = env->NewGlobalRef(audioBuffer); jboolean isCopy = JNI_FALSE; if (audioBuffer16Bit) { ! audioBufferPinned = env->GetShortArrayElements((jshortArray)audioBuffer, &isCopy); ! audioBufferFrames = env->GetArrayLength((jshortArray)audioBuffer); } else { ! audioBufferPinned = env->GetByteArrayElements((jbyteArray)audioBuffer, &isCopy); ! audioBufferFrames = env->GetArrayLength((jbyteArray)audioBuffer); } if (audioBufferStereo) { audioBufferFrames /= 2; } ! if(isAttached) mJVM->DetachCurrentThread(); ! return audioBufferFrames; } extern "C" void * Android_JNI_GetAudioBuffer() *************** *** 238,263 **** extern "C" void Android_JNI_WriteAudioBuffer() { ! if (audioBuffer16Bit) { ! mAudioEnv->ReleaseShortArrayElements((jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT); ! mAudioEnv->CallStaticVoidMethod(mActivityClass, midAudioWriteShortBuffer, (jshortArray)audioBuffer); ! } else { ! mAudioEnv->ReleaseByteArrayElements((jbyteArray)audioBuffer, (jbyte *)audioBufferPinned, JNI_COMMIT); ! mAudioEnv->CallStaticVoidMethod(mActivityClass, midAudioWriteByteBuffer, (jbyteArray)audioBuffer); ! } /* JNI_COMMIT means the changes are committed to the VM but the buffer remains pinned */ } extern "C" void Android_JNI_CloseAudioDevice() { ! mEnv->CallStaticVoidMethod(mActivityClass, midAudioQuit); if (audioBuffer) { ! mEnv->DeleteGlobalRef(audioBuffer); audioBuffer = NULL; audioBufferPinned = NULL; } } /* vi: set ts=4 sw=4 expandtab: */ --- 275,311 ---- extern "C" void Android_JNI_WriteAudioBuffer() { ! SDL_bool isAttached = SDL_FALSE; ! JNIEnv *env = getJNIEnv(isAttached); ! if (env) ! { ! if (audioBuffer16Bit) { ! env->ReleaseShortArrayElements((jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT); ! env->CallStaticVoidMethod(mActivityClass, midAudioWriteShortBuffer, (jshortArray)audioBuffer); ! } else { ! env->ReleaseByteArrayElements((jbyteArray)audioBuffer, (jbyte *)audioBufferPinned, JNI_COMMIT); ! env->CallStaticVoidMethod(mActivityClass, midAudioWriteByteBuffer, (jbyteArray)audioBuffer); ! } ! } ! if(isAttached) mJVM->DetachCurrentThread(); /* JNI_COMMIT means the changes are committed to the VM but the buffer remains pinned */ } extern "C" void Android_JNI_CloseAudioDevice() { ! SDL_bool isAttached = SDL_FALSE; ! JNIEnv *env = getJNIEnv(isAttached); ! if (!env) ! return; ! env->CallStaticVoidMethod(mActivityClass, midAudioQuit); if (audioBuffer) { ! env->DeleteGlobalRef(audioBuffer); audioBuffer = NULL; audioBufferPinned = NULL; } + if(isAttached) mJVM->DetachCurrentThread(); } /* vi: set ts=4 sw=4 expandtab: */ diff -crB '--exclude=.hg' SDL-orig/src/video/android/SDL_androidtouch.c SDL/src/video/android/SDL_androidtouch.c *** SDL-orig/src/video/android/SDL_androidtouch.c 2011-03-02 17:53:44.678726002 +0100 --- SDL/src/video/android/SDL_androidtouch.c 2011-03-02 17:14:09.000000000 +0100 *************** *** 24,29 **** --- 24,30 ---- #include #include "SDL_events.h" + #include "../../events/SDL_touch_c.h" #include "../../events/SDL_mouse_c.h" #include "SDL_androidtouch.h" *************** *** 57,60 **** --- 58,82 ---- } } + void Android_OnMultiTouch(int action, float x, float y, int pointerId, float p) + { + if (!Android_Window) { + return; + } + + SDL_Event event; + if(action == ACTION_MOVE) + { + __android_log_print(ANDROID_LOG_ERROR, "SDL", "SDL_SendTouchMotion(%d, %d, %d, %f, %f, %f)", 0, pointerId, 0, x, y, p); + SDL_SendTouchMotion(0, pointerId, SDL_FALSE, x, y, p); + } + else + { + __android_log_print(ANDROID_LOG_ERROR, "SDL", "SDL_SendFingerDown(%d, %d, %d, %f, %f, %f)", 0, pointerId, (action == ACTION_DOWN ? 1 : 0), x, y, p); + SDL_bool down = (action == ACTION_DOWN ? SDL_TRUE : SDL_FALSE); + SDL_SendFingerDown(0, pointerId, down, x, y, p); + } + } + + /* vi: set ts=4 sw=4 expandtab: */ diff -crB '--exclude=.hg' SDL-orig/src/video/android/SDL_androidtouch.h SDL/src/video/android/SDL_androidtouch.h *** SDL-orig/src/video/android/SDL_androidtouch.h 2011-03-02 17:53:44.678726002 +0100 --- SDL/src/video/android/SDL_androidtouch.h 2011-03-02 13:26:47.000000000 +0100 *************** *** 25,28 **** --- 25,30 ---- extern void Android_OnTouch(int action, float x, float y, float p); + extern void Android_OnMultiTouch(int action, float x, float y, int pointerId, float p); + /* vi: set ts=4 sw=4 expandtab: */