From ff8c9538bcb7be6144f6bfe98a4e41879ce0c986 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 12 Jul 2018 13:28:13 -0700 Subject: [PATCH] Allow trapping the back button so right mouse click can work on some Android systems (thanks Rachel!) Also, added a function SDL_AndroidBackButton() so applications can respond to the back button directly --- Android.mk | 0 .../main/java/org/libsdl/app/SDLActivity.java | 37 +++++++++++++++++++ include/SDL_hints.h | 17 +++++++++ include/SDL_system.h | 5 +++ src/core/android/SDL_android.c | 11 +++++- src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 3 ++ 7 files changed, 73 insertions(+), 1 deletion(-) mode change 100644 => 100755 Android.mk diff --git a/Android.mk b/Android.mk old mode 100644 new mode 100755 diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index e04d1c8f22a46..5dbe5acac1747 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -362,6 +362,43 @@ protected void onDestroy() { SDLActivity.initialize(); } + @Override + public void onBackPressed() { + // Check if we want to block the back button in case of mouse right click. + // + // If we do, the normal hardware back button will no longer work and people have to use home, + // but the mouse right click will work. + // + String trapBack = SDLActivity.nativeGetHint("SDL_ANDROID_TRAP_BACK_BUTTON"); + if ((trapBack != null) && trapBack.equals("1")) { + // Exit and let the mouse handler handle this button (if appropriate) + return; + } + + // Default system back button behavior. + super.onBackPressed(); + } + + // Called by JNI from SDL. + public static void manualBackButton() { + mSingleton.pressBackButton(); + } + + // Used to get us onto the activity's main thread + public void pressBackButton() { + runOnUiThread(new Runnable() { + @Override + public void run() { + SDLActivity.this.superOnBackPressed(); + } + }); + } + + // Used to access the system back behavior. + public void superOnBackPressed() { + super.onBackPressed(); + } + @Override public boolean dispatchKeyEvent(KeyEvent event) { diff --git a/include/SDL_hints.h b/include/SDL_hints.h index 3834640f2dfbe..cb8bed2c0cdc0 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -752,6 +752,23 @@ extern "C" { */ #define SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH "SDL_ANDROID_SEPARATE_MOUSE_AND_TOUCH" + /** + * \brief A variable to control whether we trap the Android back button to handle it manually. + * This is necessary for the right mouse button to work on some Android devices, or + * to be able to trap the back button for use in your code reliably. If set to true, + * the back button will show up as an SDL_KEYDOWN / SDL_KEYUP pair with a keycode of + * SDL_SCANCODE_AC_BACK. + * + * The variable can be set to the following values: + * "0" - Back button will be handled as usual for system. (default) + * "1" - Back button will be trapped, allowing you to handle the key press + * manually. (This will also let right mouse click work on systems + * where the right mouse button functions as back.) + * + * The value of this hint is used at runtime, so it can be changed at any time. + */ +#define SDL_HINT_ANDROID_TRAP_BACK_BUTTON "SDL_ANDROID_TRAP_BACK_BUTTON" + /** * \brief A variable to control whether the return key on the soft keyboard * should hide the soft keyboard on Android and iOS. diff --git a/include/SDL_system.h b/include/SDL_system.h index 06fce3537f583..14b4dbeae805c 100644 --- a/include/SDL_system.h +++ b/include/SDL_system.h @@ -135,6 +135,11 @@ extern DECLSPEC SDL_bool SDLCALL SDL_IsChromebook(void); */ extern DECLSPEC SDL_bool SDLCALL SDL_IsDeXMode(void); +/** + \brief Trigger the Android system back button behavior. + */ +extern DECLSPEC void SDLCALL SDL_AndroidBackButton(void); + /** See the official Android developer guide for more information: http://developer.android.com/guide/topics/data/data-storage.html diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c index f5f5d1389c165..7100dac342c74 100644 --- a/src/core/android/SDL_android.c +++ b/src/core/android/SDL_android.c @@ -216,6 +216,7 @@ static jmethodID midGetContext; static jmethodID midIsAndroidTV; static jmethodID midIsChromebook; static jmethodID midIsDeXMode; +static jmethodID midManualBackButton; static jmethodID midInputGetInputDeviceIds; static jmethodID midSendMessage; static jmethodID midShowTextInput; @@ -323,6 +324,8 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass c "isChromebook", "()Z"); midIsDeXMode = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, "isDeXMode", "()Z"); + midManualBackButton = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, + "manualBackButton", "()V"); midInputGetInputDeviceIds = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, "inputGetInputDeviceIds", "(I)[I"); midSendMessage = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, @@ -357,7 +360,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass c !midClipboardSetText || !midClipboardGetText || !midClipboardHasText || !midOpenAPKExpansionInputStream || !midGetManifestEnvironmentVariables || !midGetDisplayDPI || !midCreateCustomCursor || !midSetCustomCursor || !midSetSystemCursor || !midSupportsRelativeMouse || !midSetRelativeMouseEnabled || - !midIsChromebook || !midIsDeXMode) { + !midIsChromebook || !midIsDeXMode || !midManualBackButton) { __android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLActivity.java?"); } @@ -2045,6 +2048,12 @@ SDL_bool SDL_IsDeXMode(void) return (*env)->CallStaticBooleanMethod(env, mActivityClass, midIsDeXMode); } +void SDL_AndroidBackButton(void) +{ + JNIEnv *env = Android_JNI_GetEnv(); + return (*env)->CallStaticVoidMethod(env, mActivityClass, midManualBackButton); +} + const char * SDL_AndroidGetInternalStoragePath(void) { static char *s_AndroidInternalFilesPath = NULL; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 84730f49a0666..48243d681a945 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -674,3 +674,4 @@ #define SDL_HasAVX512F SDL_HasAVX512F_REAL #define SDL_IsChromebook SDL_IsChromebook_REAL #define SDL_IsDeXMode SDL_IsDeXMode_REAL +#define SDL_AndroidBackButton SDL_AndroidBackButton_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index a95428ad1f853..58246c30b6218 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -716,3 +716,6 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_HasAVX512F,(void),(),return) SDL_DYNAPI_PROC(SDL_bool,SDL_IsChromebook,(void),(),return) SDL_DYNAPI_PROC(SDL_bool,SDL_IsDeXMode,(void),(),return) #endif +#ifdef __ANDROID__ +SDL_DYNAPI_PROC(void,SDL_AndroidBackButton,(void),(),return) +#endif