Commit 2dedbc72626453587606f096f886d76f09775378

Sam Lantinga 2018-06-05T12:46:11

Add Android support for relative mouse mode to SDL.

diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c
index c5bec90..c4b3423 100644
--- a/src/core/android/SDL_android.c
+++ b/src/core/android/SDL_android.c
@@ -102,7 +102,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeTouch)(
 
 JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeMouse)(
         JNIEnv* env, jclass jcls,
-        jint button, jint action, jfloat x, jfloat y);
+        jint button, jint action, jfloat x, jfloat y, jboolean relative);
 
 JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeAccel)(
         JNIEnv* env, jclass jcls,
@@ -226,6 +226,8 @@ static jmethodID midGetDisplayDPI;
 static jmethodID midCreateCustomCursor;
 static jmethodID midSetCustomCursor;
 static jmethodID midSetSystemCursor;
+static jmethodID midSupportsRelativeMouse;
+static jmethodID midSetRelativeMouseEnabled;
 
 /* audio manager */
 static jclass mAudioManagerClass;
@@ -339,12 +341,15 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass c
     midSetCustomCursor = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, "setCustomCursor", "(I)Z");
     midSetSystemCursor = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, "setSystemCursor", "(I)Z");
 
+    midSupportsRelativeMouse = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, "supportsRelativeMouse", "()Z");
+    midSetRelativeMouseEnabled = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, "setRelativeMouseEnabled", "(Z)Z");
+
     if (!midGetNativeSurface ||
        !midSetActivityTitle || !midSetWindowStyle || !midSetOrientation || !midGetContext || !midIsAndroidTV || !midInputGetInputDeviceIds ||
        !midSendMessage || !midShowTextInput || !midIsScreenKeyboardShown ||
        !midClipboardSetText || !midClipboardGetText || !midClipboardHasText ||
        !midOpenAPKExpansionInputStream || !midGetManifestEnvironmentVariables || !midGetDisplayDPI ||
-       !midCreateCustomCursor || !midSetCustomCursor || !midSetSystemCursor) {
+       !midCreateCustomCursor || !midSetCustomCursor || !midSetSystemCursor || !midSupportsRelativeMouse || !midSetRelativeMouseEnabled) {
         __android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLActivity.java?");
     }
 
@@ -682,9 +687,9 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeTouch)(
 /* Mouse */
 JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeMouse)(
                                     JNIEnv* env, jclass jcls,
-                                    jint button, jint action, jfloat x, jfloat y)
+                                    jint button, jint action, jfloat x, jfloat y, jboolean relative)
 {
-    Android_OnMouse(button, action, x, y);
+    Android_OnMouse(button, action, x, y, relative);
 }
 
 /* Accelerometer */
@@ -2202,6 +2207,19 @@ SDL_bool Android_JNI_SetSystemCursor(int cursorID)
     return (*mEnv)->CallStaticBooleanMethod(mEnv, mActivityClass, midSetSystemCursor, cursorID);
 }
 
+SDL_bool Android_JNI_SupportsRelativeMouse()
+{
+    JNIEnv *mEnv = Android_JNI_GetEnv();
+    return (*mEnv)->CallStaticBooleanMethod(mEnv, mActivityClass, midSupportsRelativeMouse);
+}
+
+SDL_bool Android_JNI_SetRelativeMouseEnabled(SDL_bool enabled)
+{
+    JNIEnv *mEnv = Android_JNI_GetEnv();
+    return (*mEnv)->CallStaticBooleanMethod(mEnv, mActivityClass, midSetRelativeMouseEnabled, (enabled == 1));
+}
+
+
 #endif /* __ANDROID__ */
 
 /* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/core/android/SDL_android.h b/src/core/android/SDL_android.h
index 5eb727d..6b3dfcb 100644
--- a/src/core/android/SDL_android.h
+++ b/src/core/android/SDL_android.h
@@ -107,6 +107,10 @@ int Android_JNI_CreateCustomCursor(SDL_Surface *surface, int hot_x, int hot_y);
 SDL_bool Android_JNI_SetCustomCursor(int cursorID);
 SDL_bool Android_JNI_SetSystemCursor(int cursorID);
 
+/* Relative mouse support */
+SDL_bool Android_JNI_SupportsRelativeMouse();
+SDL_bool Android_JNI_SetRelativeMouseEnabled(SDL_bool enabled);
+
 /* Ends C function definitions when using C++ */
 #ifdef __cplusplus
 /* *INDENT-OFF* */
diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c
index 4f4e62f..135292e 100644
--- a/src/events/SDL_mouse.c
+++ b/src/events/SDL_mouse.c
@@ -688,6 +688,7 @@ static SDL_bool
 ShouldUseRelativeModeWarp(SDL_Mouse *mouse)
 {
     if (!mouse->SetRelativeMouseMode) {
+        SDL_assert(mouse->WarpMouse);   /* Need this functionality for relative mode warp implementation */
         return SDL_TRUE;
     }
 
diff --git a/src/video/android/SDL_androidmouse.c b/src/video/android/SDL_androidmouse.c
index 13c6271..c79792d 100644
--- a/src/video/android/SDL_androidmouse.c
+++ b/src/video/android/SDL_androidmouse.c
@@ -137,6 +137,20 @@ Android_ShowCursor(SDL_Cursor * cursor)
     return 0;
 }
 
+static int
+Android_SetRelativeMouseMode(SDL_bool enabled)
+{
+    if (!Android_JNI_SupportsRelativeMouse()) {
+        return SDL_Unsupported();
+    }
+
+    if (!Android_JNI_SetRelativeMouseEnabled(enabled)) {
+        return SDL_Unsupported();
+    }
+
+    return 0;
+}
+
 void
 Android_InitMouse(void)
 {
@@ -146,6 +160,7 @@ Android_InitMouse(void)
     mouse->CreateSystemCursor = Android_CreateSystemCursor;
     mouse->ShowCursor = Android_ShowCursor;
     mouse->FreeCursor = Android_FreeCursor;
+    mouse->SetRelativeMouseMode = Android_SetRelativeMouseMode;
 
     SDL_SetDefaultCursor(Android_CreateDefaultCursor());
 
@@ -172,7 +187,7 @@ TranslateButton(int state)
 }
 
 void
-Android_OnMouse(int state, int action, float x, float y)
+Android_OnMouse(int state, int action, float x, float y, SDL_bool relative)
 {
     int changes;
     Uint8 button;
@@ -186,7 +201,7 @@ Android_OnMouse(int state, int action, float x, float y)
             changes = state & ~last_state;
             button = TranslateButton(changes);
             last_state = state;
-            SDL_SendMouseMotion(Android_Window, 0, 0, x, y);
+            SDL_SendMouseMotion(Android_Window, 0, relative, x, y);
             SDL_SendMouseButton(Android_Window, 0, SDL_PRESSED, button);
             break;
 
@@ -194,13 +209,13 @@ Android_OnMouse(int state, int action, float x, float y)
             changes = last_state & ~state;
             button = TranslateButton(changes);
             last_state = state;
-            SDL_SendMouseMotion(Android_Window, 0, 0, x, y);
+            SDL_SendMouseMotion(Android_Window, 0, relative, x, y);
             SDL_SendMouseButton(Android_Window, 0, SDL_RELEASED, button);
             break;
 
         case ACTION_MOVE:
         case ACTION_HOVER_MOVE:
-            SDL_SendMouseMotion(Android_Window, 0, 0, x, y);
+            SDL_SendMouseMotion(Android_Window, 0, relative, x, y);
             break;
 
         case ACTION_SCROLL:
diff --git a/src/video/android/SDL_androidmouse.h b/src/video/android/SDL_androidmouse.h
index f201fad..9aa71f5 100644
--- a/src/video/android/SDL_androidmouse.h
+++ b/src/video/android/SDL_androidmouse.h
@@ -25,7 +25,7 @@
 #include "SDL_androidvideo.h"
 
 extern void Android_InitMouse(void);
-extern void Android_OnMouse( int button, int action, float x, float y);
+extern void Android_OnMouse(int button, int action, float x, float y, SDL_bool relative);
 
 #endif /* SDL_androidmouse_h_ */