From 109544ca04345802834c815d92a658dba4042a41 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 21 Aug 2018 11:23:47 -0700 Subject: [PATCH] Add SDL_IsTablet() to Android and iOS SDL. --- .../main/java/org/libsdl/app/SDLActivity.java | 18 ++++++++++++++++++ include/SDL_system.h | 9 +++++++++ src/core/android/SDL_android.c | 11 ++++++++++- src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 3 +++ src/video/uikit/SDL_uikitvideo.m | 11 +++++++++++ 6 files changed, 52 insertions(+), 1 deletion(-) 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 6d745210f2914..a2df4a11611e6 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 @@ -5,6 +5,7 @@ import java.util.Arrays; import java.util.Hashtable; import java.lang.reflect.Method; +import java.lang.Math; import android.app.*; import android.content.*; @@ -776,6 +777,23 @@ public static boolean isAndroidTV() { return false; } + /** + * This method is called by SDL using JNI. + */ + public static boolean isTablet() { + DisplayMetrics metrics = new DisplayMetrics(); + Activity sdlActivity = (Activity)getContext(); + sdlActivity.getWindowManager().getDefaultDisplay().getMetrics(metrics); + + double dWidthInches = metrics.widthPixels / (double)metrics.densityDpi; + double dHeightInches = metrics.heightPixels / (double)metrics.densityDpi; + + double dDiagonal = Math.sqrt((dWidthInches * dWidthInches) + (dHeightInches * dHeightInches)); + + // If our diagonal size is seven inches or greater, we consider ourselves a tablet. + return (dDiagonal > 7.0); + } + /** * This method is called by SDL using JNI. */ diff --git a/include/SDL_system.h b/include/SDL_system.h index 14b4dbeae805c..00eb7a4759b19 100644 --- a/include/SDL_system.h +++ b/include/SDL_system.h @@ -174,6 +174,15 @@ extern DECLSPEC const char * SDLCALL SDL_AndroidGetExternalStoragePath(void); #endif /* __ANDROID__ */ +#if defined(__ANDROID__) || defined(__IPHONEOS__) + +/** + \brief Return true if the current device is a tablet. + */ +extern DECLSPEC SDL_bool SDLCALL SDL_IsTablet(void); + +#endif + /* Platform specific functions for WinRT */ #if defined(__WINRT__) && __WINRT__ diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c index 7100dac342c74..159e6d401e684 100644 --- a/src/core/android/SDL_android.c +++ b/src/core/android/SDL_android.c @@ -232,6 +232,7 @@ static jmethodID midSetCustomCursor; static jmethodID midSetSystemCursor; static jmethodID midSupportsRelativeMouse; static jmethodID midSetRelativeMouseEnabled; +static jmethodID midIsTablet; /* audio manager */ static jclass mAudioManagerClass; @@ -354,13 +355,15 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass c midSupportsRelativeMouse = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, "supportsRelativeMouse", "()Z"); midSetRelativeMouseEnabled = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, "setRelativeMouseEnabled", "(Z)Z"); + midIsTablet = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, "isTablet", "()Z"); + if (!midGetNativeSurface || !midSetActivityTitle || !midSetWindowStyle || !midSetOrientation || !midGetContext || !midIsAndroidTV || !midInputGetInputDeviceIds || !midSendMessage || !midShowTextInput || !midIsScreenKeyboardShown || !midClipboardSetText || !midClipboardGetText || !midClipboardHasText || !midOpenAPKExpansionInputStream || !midGetManifestEnvironmentVariables || !midGetDisplayDPI || !midCreateCustomCursor || !midSetCustomCursor || !midSetSystemCursor || !midSupportsRelativeMouse || !midSetRelativeMouseEnabled || - !midIsChromebook || !midIsDeXMode || !midManualBackButton) { + !midIsChromebook || !midIsDeXMode || !midManualBackButton || !midIsTablet) { __android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLActivity.java?"); } @@ -2048,6 +2051,12 @@ SDL_bool SDL_IsDeXMode(void) return (*env)->CallStaticBooleanMethod(env, mActivityClass, midIsDeXMode); } +SDL_bool SDL_IsTablet(void) +{ + JNIEnv *env = Android_JNI_GetEnv(); + return (*env)->CallStaticBooleanMethod(env, mActivityClass, midIsTablet); +} + void SDL_AndroidBackButton(void) { JNIEnv *env = Android_JNI_GetEnv(); diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 100b1d063704a..db8c8e259c1b8 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -680,3 +680,4 @@ #define SDL_wcsdup SDL_wcsdup_REAL #define SDL_GameControllerRumble SDL_GameControllerRumble_REAL #define SDL_JoystickRumble SDL_JoystickRumble_REAL +#define SDL_IsTablet SDL_IsTablet_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index c3983f89dd9a6..36342f097505b 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -722,3 +722,6 @@ SDL_DYNAPI_PROC(float,SDL_expf,(float a),(a),return) SDL_DYNAPI_PROC(wchar_t*,SDL_wcsdup,(const wchar_t *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GameControllerRumble,(SDL_GameController *a, Uint16 b, Uint16 c, Uint32 d),(a,b,c,d),return) SDL_DYNAPI_PROC(int,SDL_JoystickRumble,(SDL_Joystick *a, Uint16 b, Uint16 c, Uint32 d),(a,b,c,d),return) +#if defined(__ANDROID__) || defined(__IPHONEOS__) +SDL_DYNAPI_PROC(SDL_bool,SDL_IsTablet,(void),(),return) +#endif diff --git a/src/video/uikit/SDL_uikitvideo.m b/src/video/uikit/SDL_uikitvideo.m index e74339f420223..aec49a581a3dd 100644 --- a/src/video/uikit/SDL_uikitvideo.m +++ b/src/video/uikit/SDL_uikitvideo.m @@ -233,6 +233,17 @@ void SDL_NSLog(const char *text) NSLog(@"%s", text); } +/* + * iOS Tablet detection + * + * This doesn't really have aything to do with the interfaces of the SDL video + * subsystem, but we need to stuff this into an Objective-C source code file. + */ +SDL_bool SDL_IsTablet(void) +{ + return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad); +} + #endif /* SDL_VIDEO_DRIVER_UIKIT */ /* vi: set ts=4 sw=4 expandtab: */