Added support for external mouse in Samsung DeX mode relative mode doesn't work, but absolute coordinates are functional
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
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 3cf84c6..e04d1c8 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
@@ -670,6 +670,17 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
*/
public static boolean supportsRelativeMouse()
{
+ // ChromeOS doesn't provide relative mouse motion via the Android 7 APIs
+ if (isChromebook()) {
+ return false;
+ }
+
+ // Samsung DeX mode doesn't support relative mice properly under Android 7 APIs,
+ // and simply returns no data under Android 8 APIs.
+ if (isDeXMode()) {
+ return false;
+ }
+
return SDLActivity.getMotionListener().supportsRelativeMouse();
}
@@ -678,6 +689,10 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
*/
public static boolean setRelativeMouseEnabled(boolean enabled)
{
+ if (enabled && !supportsRelativeMouse()) {
+ return false;
+ }
+
return SDLActivity.getMotionListener().setRelativeMouseEnabled(enabled);
}
@@ -716,6 +731,23 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
/**
* This method is called by SDL using JNI.
*/
+ public static boolean isDeXMode() {
+ if (Build.VERSION.SDK_INT < 24) {
+ return false;
+ }
+ try {
+ final Configuration config = getContext().getResources().getConfiguration();
+ final Class configClass = config.getClass();
+ return configClass.getField("SEM_DESKTOP_MODE_ENABLED").getInt(configClass)
+ == configClass.getField("semDesktopModeEnabled").getInt(config);
+ } catch(Exception ignored) {
+ return false;
+ }
+ }
+
+ /**
+ * This method is called by SDL using JNI.
+ */
public static DisplayMetrics getDisplayDPI() {
return getContext().getResources().getDisplayMetrics();
}
@@ -1313,7 +1345,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
setOnGenericMotionListener(SDLActivity.getMotionListener());
}
- if (Build.VERSION.SDK_INT >= 26) {
+ if ((Build.VERSION.SDK_INT >= 26) && !SDLActivity.isDeXMode()) {
setOnCapturedPointerListener(new SDLCapturedPointerListener_API26());
}
@@ -1544,7 +1576,8 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
float x,y,p;
// !!! FIXME: dump this SDK check after 2.0.4 ships and require API14.
- if (event.getSource() == InputDevice.SOURCE_MOUSE && SDLActivity.mSeparateMouseAndTouch) {
+ // 12290 = Samsung DeX mode desktop mouse
+ if ((event.getSource() == InputDevice.SOURCE_MOUSE || event.getSource() == 12290) && SDLActivity.mSeparateMouseAndTouch) {
if (Build.VERSION.SDK_INT < 14) {
mouseButton = 1; // all mouse buttons are the left button
} else {
diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java b/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java
index f97dd20..bd6a2ad 100644
--- a/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java
+++ b/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java
@@ -692,6 +692,7 @@ class SDLGenericMotionListener_API26 extends SDLGenericMotionListener_API24 {
return SDLControllerManager.handleJoystickMotionEvent(event);
case InputDevice.SOURCE_MOUSE:
+ case 12290: // DeX desktop mouse cursor is a separate non-standard input type.
if (!SDLActivity.mSeparateMouseAndTouch) {
break;
}
diff --git a/include/SDL_system.h b/include/SDL_system.h
index 6d6832d..06fce35 100644
--- a/include/SDL_system.h
+++ b/include/SDL_system.h
@@ -131,6 +131,11 @@ extern DECLSPEC SDL_bool SDLCALL SDL_IsAndroidTV(void);
extern DECLSPEC SDL_bool SDLCALL SDL_IsChromebook(void);
/**
+ \brief Return true is the application is running on a Samsung DeX docking station
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsDeXMode(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 29a55a9..f5f5d13 100644
--- a/src/core/android/SDL_android.c
+++ b/src/core/android/SDL_android.c
@@ -215,6 +215,7 @@ static jmethodID midSetOrientation;
static jmethodID midGetContext;
static jmethodID midIsAndroidTV;
static jmethodID midIsChromebook;
+static jmethodID midIsDeXMode;
static jmethodID midInputGetInputDeviceIds;
static jmethodID midSendMessage;
static jmethodID midShowTextInput;
@@ -320,6 +321,8 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass c
"isAndroidTV","()Z");
midIsChromebook = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
"isChromebook", "()Z");
+ midIsDeXMode = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+ "isDeXMode", "()Z");
midInputGetInputDeviceIds = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
"inputGetInputDeviceIds", "(I)[I");
midSendMessage = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
@@ -354,7 +357,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv* mEnv, jclass c
!midClipboardSetText || !midClipboardGetText || !midClipboardHasText ||
!midOpenAPKExpansionInputStream || !midGetManifestEnvironmentVariables || !midGetDisplayDPI ||
!midCreateCustomCursor || !midSetCustomCursor || !midSetSystemCursor || !midSupportsRelativeMouse || !midSetRelativeMouseEnabled ||
- !midIsChromebook) {
+ !midIsChromebook || !midIsDeXMode) {
__android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLActivity.java?");
}
@@ -2036,6 +2039,12 @@ SDL_bool SDL_IsChromebook(void)
return (*env)->CallStaticBooleanMethod(env, mActivityClass, midIsChromebook);
}
+SDL_bool SDL_IsDeXMode(void)
+{
+ JNIEnv *env = Android_JNI_GetEnv();
+ return (*env)->CallStaticBooleanMethod(env, mActivityClass, midIsDeXMode);
+}
+
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 8d32232..84730f4 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -673,3 +673,4 @@
#define SDL_LinuxSetThreadPriority SDL_LinuxSetThreadPriority_REAL
#define SDL_HasAVX512F SDL_HasAVX512F_REAL
#define SDL_IsChromebook SDL_IsChromebook_REAL
+#define SDL_IsDeXMode SDL_IsDeXMode_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index 3d2a1a3..a95428a 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -714,4 +714,5 @@ SDL_DYNAPI_PROC(int,SDL_LinuxSetThreadPriority,(Sint64 a, int b),(a,b),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_HasAVX512F,(void),(),return)
#ifdef __ANDROID__
SDL_DYNAPI_PROC(SDL_bool,SDL_IsChromebook,(void),(),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_IsDeXMode,(void),(),return)
#endif
diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c
index 135292e..55d248e 100644
--- a/src/events/SDL_mouse.c
+++ b/src/events/SDL_mouse.c
@@ -721,6 +721,9 @@ SDL_SetRelativeMouseMode(SDL_bool enabled)
} else if (mouse->SetRelativeMouseMode(enabled) < 0) {
if (enabled) {
/* Fall back to warp mode if native relative mode failed */
+ if (!mouse->WarpMouse) {
+ return SDL_SetError("No relative mode implementation available");
+ }
mouse->relative_mode_warp = SDL_TRUE;
}
}