mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-05-05 07:32:46 +02:00
Compare commits
6 Commits
release-3.
...
release-3.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d35168a63 | ||
|
|
3013f975ac | ||
|
|
52b6bceedf | ||
|
|
5c107908ff | ||
|
|
c239edd6e0 | ||
|
|
796782fc89 |
@@ -5,7 +5,7 @@ if(NOT DEFINED CMAKE_BUILD_TYPE)
|
||||
endif()
|
||||
|
||||
# See docs/release_checklist.md
|
||||
project(SDL3 LANGUAGES C VERSION "3.4.8")
|
||||
project(SDL3 LANGUAGES C VERSION "3.4.9")
|
||||
|
||||
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
||||
set(SDL3_MAINPROJECT ON)
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>3.4.8</string>
|
||||
<string>3.4.9</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>SDLX</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>3.4.8</string>
|
||||
<string>3.4.9</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -3162,7 +3162,7 @@
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
DEPLOYMENT_POSTPROCESSING = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 401.0.0;
|
||||
DYLIB_CURRENT_VERSION = 401.8.0;
|
||||
DYLIB_CURRENT_VERSION = 401.9.0;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_ALTIVEC_EXTENSIONS = YES;
|
||||
@@ -3197,7 +3197,7 @@
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
MARKETING_VERSION = 3.4.8;
|
||||
MARKETING_VERSION = 3.4.9;
|
||||
OTHER_LDFLAGS = "$(CONFIG_FRAMEWORK_LDFLAGS)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3;
|
||||
PRODUCT_NAME = SDL3;
|
||||
@@ -3228,7 +3228,7 @@
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 401.0.0;
|
||||
DYLIB_CURRENT_VERSION = 401.8.0;
|
||||
DYLIB_CURRENT_VERSION = 401.9.0;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
@@ -3260,7 +3260,7 @@
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.13;
|
||||
MARKETING_VERSION = 3.4.8;
|
||||
MARKETING_VERSION = 3.4.9;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_LDFLAGS = "$(CONFIG_FRAMEWORK_LDFLAGS)";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Title SDL 3.4.8
|
||||
Title SDL 3.4.9
|
||||
Version 1
|
||||
Description SDL Library for macOS (http://www.libsdl.org)
|
||||
DefaultLocation /Library/Frameworks
|
||||
|
||||
@@ -61,7 +61,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
private static final String TAG = "SDL";
|
||||
private static final int SDL_MAJOR_VERSION = 3;
|
||||
private static final int SDL_MINOR_VERSION = 4;
|
||||
private static final int SDL_MICRO_VERSION = 8;
|
||||
private static final int SDL_MICRO_VERSION = 9;
|
||||
/*
|
||||
// Display InputType.SOURCE/CLASS of events and devices
|
||||
//
|
||||
@@ -1478,14 +1478,16 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
// Furthermore, it's possible a game controller has SOURCE_KEYBOARD and
|
||||
// SOURCE_JOYSTICK, while its key events arrive from the keyboard source
|
||||
// So, retrieve the device itself and check all of its sources
|
||||
if (SDLControllerManager.isDeviceSDLJoystick(deviceId)) {
|
||||
//
|
||||
// Echo events (event.getRepeatCount() > 0) should be ignored
|
||||
if (SDLControllerManager.isDeviceSDLJoystick(deviceId) && event.getRepeatCount() == 0) {
|
||||
// Note that we process events with specific key codes here
|
||||
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||
if (SDLControllerManager.onNativePadDown(deviceId, keyCode)) {
|
||||
if (SDLControllerManager.onNativePadDown(deviceId, keyCode, event.getScanCode())) {
|
||||
return true;
|
||||
}
|
||||
} else if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||
if (SDLControllerManager.onNativePadUp(deviceId, keyCode)) {
|
||||
if (SDLControllerManager.onNativePadUp(deviceId, keyCode, event.getScanCode())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,10 @@ import android.hardware.lights.Light;
|
||||
import android.hardware.lights.LightsRequest;
|
||||
import android.hardware.lights.LightsManager;
|
||||
import android.hardware.lights.LightState;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.os.VibrationEffect;
|
||||
@@ -30,16 +34,18 @@ public class SDLControllerManager
|
||||
static native void nativeAddJoystick(int device_id, String name, String desc,
|
||||
int vendor_id, int product_id,
|
||||
int button_mask,
|
||||
int naxes, int axis_mask, int nhats, boolean can_rumble, boolean has_rgb_led);
|
||||
int naxes, int axis_mask, int nhats, boolean can_rumble, boolean has_rgb_led,
|
||||
boolean has_accelerometer, boolean has_gyroscope);
|
||||
static native void nativeRemoveJoystick(int device_id);
|
||||
static native void nativeAddHaptic(int device_id, String name);
|
||||
static native void nativeRemoveHaptic(int device_id);
|
||||
static public native boolean onNativePadDown(int device_id, int keycode);
|
||||
static public native boolean onNativePadUp(int device_id, int keycode);
|
||||
static public native boolean onNativePadDown(int device_id, int keycode, int scancode);
|
||||
static public native boolean onNativePadUp(int device_id, int keycode, int scancode);
|
||||
static native void onNativeJoy(int device_id, int axis,
|
||||
float value);
|
||||
static native void onNativeHat(int device_id, int hat_id,
|
||||
int x, int y);
|
||||
static native void onNativeJoySensor(int device_id, int sensor_type, long sensor_timestamp, float x, float y, float z);
|
||||
|
||||
protected static SDLJoystickHandler mJoystickHandler;
|
||||
protected static SDLHapticHandler mHapticHandler;
|
||||
@@ -81,6 +87,13 @@ public class SDLControllerManager
|
||||
mJoystickHandler.setLED(device_id, red, green, blue);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
static void joystickSetSensorsEnabled(int device_id, boolean enabled) {
|
||||
mJoystickHandler.setSensorsEnabled(device_id, enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
@@ -153,6 +166,10 @@ class SDLJoystickHandler {
|
||||
ArrayList<InputDevice.MotionRange> hats;
|
||||
ArrayList<Light> lights;
|
||||
LightsManager.LightsSession lightsSession;
|
||||
SensorManager sensorManager;
|
||||
SDLJoySensorListener sensorListener;
|
||||
Sensor accelerometerSensor;
|
||||
Sensor gyroscopeSensor;
|
||||
}
|
||||
static class RangeComparator implements Comparator<InputDevice.MotionRange> {
|
||||
@Override
|
||||
@@ -241,6 +258,8 @@ class SDLJoystickHandler {
|
||||
|
||||
boolean can_rumble = false;
|
||||
boolean has_rgb_led = false;
|
||||
boolean has_accelerometer = false;
|
||||
boolean has_gyroscope = false;
|
||||
if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {
|
||||
VibratorManager vibratorManager = joystickDevice.getVibratorManager();
|
||||
int[] vibrators = vibratorManager.getVibratorIds();
|
||||
@@ -258,12 +277,26 @@ class SDLJoystickHandler {
|
||||
joystick.lightsSession = lightsManager.openSession();
|
||||
has_rgb_led = true;
|
||||
}
|
||||
SensorManager sensorManager = joystickDevice.getSensorManager();
|
||||
if (sensorManager != null) {
|
||||
joystick.sensorManager = sensorManager;
|
||||
joystick.sensorListener = new SDLJoySensorListener(joystick.device_id);
|
||||
joystick.accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
||||
if (joystick.accelerometerSensor != null) {
|
||||
has_accelerometer = true;
|
||||
}
|
||||
joystick.gyroscopeSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
|
||||
if (joystick.gyroscopeSensor != null) {
|
||||
has_gyroscope = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mJoysticks.add(joystick);
|
||||
SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc,
|
||||
getVendorId(joystickDevice), getProductId(joystickDevice),
|
||||
getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, can_rumble, has_rgb_led);
|
||||
getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, can_rumble, has_rgb_led,
|
||||
has_accelerometer, has_gyroscope);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -508,6 +541,31 @@ class SDLJoystickHandler {
|
||||
}
|
||||
joystick.lightsSession.requestLights(lightsRequest.build());
|
||||
}
|
||||
|
||||
void setSensorsEnabled(int device_id, boolean enabled) {
|
||||
if (Build.VERSION.SDK_INT < 31 /* Android 12.0 (S) */) {
|
||||
return;
|
||||
}
|
||||
SDLJoystick joystick = getJoystick(device_id);
|
||||
if (joystick == null || joystick.sensorManager == null) {
|
||||
return;
|
||||
}
|
||||
if (enabled) {
|
||||
if (joystick.accelerometerSensor != null) {
|
||||
joystick.sensorManager.registerListener(joystick.sensorListener, joystick.accelerometerSensor, SensorManager.SENSOR_DELAY_GAME, null);
|
||||
}
|
||||
if (joystick.gyroscopeSensor != null) {
|
||||
joystick.sensorManager.registerListener(joystick.sensorListener, joystick.gyroscopeSensor, SensorManager.SENSOR_DELAY_GAME, null);
|
||||
}
|
||||
} else {
|
||||
if (joystick.accelerometerSensor != null) {
|
||||
joystick.sensorManager.unregisterListener(joystick.sensorListener, joystick.accelerometerSensor);
|
||||
}
|
||||
if (joystick.gyroscopeSensor != null) {
|
||||
joystick.sensorManager.unregisterListener(joystick.sensorListener, joystick.gyroscopeSensor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SDLHapticHandler_API31 extends SDLHapticHandler {
|
||||
@@ -933,3 +991,19 @@ class SDLGenericMotionListener_API29 extends SDLGenericMotionListener_API26 {
|
||||
return penDevice.isExternal() ? SDL_PEN_DEVICE_TYPE_INDIRECT : SDL_PEN_DEVICE_TYPE_DIRECT;
|
||||
}
|
||||
}
|
||||
|
||||
class SDLJoySensorListener implements SensorEventListener {
|
||||
int device_id;
|
||||
|
||||
public SDLJoySensorListener(int device_id) {
|
||||
this.device_id = device_id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
|
||||
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent event) {
|
||||
SDLControllerManager.onNativeJoySensor(device_id, event.sensor.getType(), event.timestamp, event.values[0], event.values[1], event.values[2]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Main include header for the SDL library, version 3.4.8
|
||||
* Main include header for the SDL library, version 3.4.9
|
||||
*
|
||||
* It is almost always best to include just this one header instead of
|
||||
* picking out individual headers included here. There are exceptions to
|
||||
|
||||
@@ -62,7 +62,7 @@ extern "C" {
|
||||
*
|
||||
* \since This macro is available since SDL 3.2.0.
|
||||
*/
|
||||
#define SDL_MICRO_VERSION 8
|
||||
#define SDL_MICRO_VERSION 9
|
||||
|
||||
/**
|
||||
* This macro turns the version numbers into a numeric value.
|
||||
|
||||
@@ -298,11 +298,11 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(
|
||||
|
||||
JNIEXPORT jboolean JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown)(
|
||||
JNIEnv *env, jclass jcls,
|
||||
jint device_id, jint keycode);
|
||||
jint device_id, jint keycode, jint scancode);
|
||||
|
||||
JNIEXPORT jboolean JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp)(
|
||||
JNIEnv *env, jclass jcls,
|
||||
jint device_id, jint keycode);
|
||||
jint device_id, jint keycode, jint scancode);
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoy)(
|
||||
JNIEnv *env, jclass jcls,
|
||||
@@ -312,10 +312,15 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat)(
|
||||
JNIEnv *env, jclass jcls,
|
||||
jint device_id, jint hat_id, jint x, jint y);
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoySensor)(
|
||||
JNIEnv *env, jclass jcls,
|
||||
jint device_id, jint sensor_type, jlong sensor_timestamp, jfloat x, jfloat y, jfloat z);
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)(
|
||||
JNIEnv *env, jclass jcls,
|
||||
jint device_id, jstring device_name, jstring device_desc, jint vendor_id, jint product_id,
|
||||
jint button_mask, jint naxes, jint axis_mask, jint nhats, jboolean can_rumble, jboolean has_rgb_led);
|
||||
jint button_mask, jint naxes, jint axis_mask, jint nhats,
|
||||
jboolean can_rumble, jboolean has_rgb_led, jboolean has_accelerometer, jboolean has_gyroscope);
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick)(
|
||||
JNIEnv *env, jclass jcls,
|
||||
@@ -331,11 +336,12 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic)(
|
||||
|
||||
static JNINativeMethod SDLControllerManager_tab[] = {
|
||||
{ "nativeSetupJNI", "()V", SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI) },
|
||||
{ "onNativePadDown", "(II)Z", SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown) },
|
||||
{ "onNativePadUp", "(II)Z", SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp) },
|
||||
{ "onNativePadDown", "(III)Z", SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown) },
|
||||
{ "onNativePadUp", "(III)Z", SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp) },
|
||||
{ "onNativeJoy", "(IIF)V", SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoy) },
|
||||
{ "onNativeHat", "(IIII)V", SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat) },
|
||||
{ "nativeAddJoystick", "(ILjava/lang/String;Ljava/lang/String;IIIIIIZZ)V", SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick) },
|
||||
{ "onNativeJoySensor", "(IIJFFF)V", SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoySensor) },
|
||||
{ "nativeAddJoystick", "(ILjava/lang/String;Ljava/lang/String;IIIIIIZZZZ)V", SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick) },
|
||||
{ "nativeRemoveJoystick", "(I)V", SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick) },
|
||||
{ "nativeAddHaptic", "(ILjava/lang/String;)V", SDL_JAVA_CONTROLLER_INTERFACE(nativeAddHaptic) },
|
||||
{ "nativeRemoveHaptic", "(I)V", SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic) }
|
||||
@@ -408,6 +414,7 @@ static jclass mControllerManagerClass;
|
||||
// method signatures
|
||||
static jmethodID midPollInputDevices;
|
||||
static jmethodID midJoystickSetLED;
|
||||
static jmethodID midJoystickSetSensorsEnabled;
|
||||
static jmethodID midPollHapticDevices;
|
||||
static jmethodID midHapticRun;
|
||||
static jmethodID midHapticRumble;
|
||||
@@ -756,6 +763,8 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(JNIEnv *env
|
||||
"pollInputDevices", "()V");
|
||||
midJoystickSetLED = (*env)->GetStaticMethodID(env, mControllerManagerClass,
|
||||
"joystickSetLED", "(IIII)V");
|
||||
midJoystickSetSensorsEnabled = (*env)->GetStaticMethodID(env, mControllerManagerClass,
|
||||
"joystickSetSensorsEnabled", "(IZ)V");
|
||||
midPollHapticDevices = (*env)->GetStaticMethodID(env, mControllerManagerClass,
|
||||
"pollHapticDevices", "()V");
|
||||
midHapticRun = (*env)->GetStaticMethodID(env, mControllerManagerClass,
|
||||
@@ -765,7 +774,7 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(JNIEnv *env
|
||||
midHapticStop = (*env)->GetStaticMethodID(env, mControllerManagerClass,
|
||||
"hapticStop", "(I)V");
|
||||
|
||||
if (!midPollInputDevices || !midJoystickSetLED || !midPollHapticDevices || !midHapticRun || !midHapticRumble || !midHapticStop) {
|
||||
if (!midPollInputDevices || !midJoystickSetLED || !midJoystickSetSensorsEnabled || !midPollHapticDevices || !midHapticRun || !midHapticRumble || !midHapticStop) {
|
||||
__android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLControllerManager.java?");
|
||||
}
|
||||
|
||||
@@ -1150,10 +1159,10 @@ SDL_JAVA_AUDIO_INTERFACE(nativeRemoveAudioDevice)(JNIEnv *env, jclass jcls, jboo
|
||||
// Paddown
|
||||
JNIEXPORT jboolean JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown)(
|
||||
JNIEnv *env, jclass jcls,
|
||||
jint device_id, jint keycode)
|
||||
jint device_id, jint keycode, jint scancode)
|
||||
{
|
||||
#ifdef SDL_JOYSTICK_ANDROID
|
||||
return Android_OnPadDown(device_id, keycode);
|
||||
return Android_OnPadDown(device_id, keycode, scancode);
|
||||
#else
|
||||
return false;
|
||||
#endif // SDL_JOYSTICK_ANDROID
|
||||
@@ -1162,10 +1171,10 @@ JNIEXPORT jboolean JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown)(
|
||||
// Padup
|
||||
JNIEXPORT jboolean JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp)(
|
||||
JNIEnv *env, jclass jcls,
|
||||
jint device_id, jint keycode)
|
||||
jint device_id, jint keycode, jint scancode)
|
||||
{
|
||||
#ifdef SDL_JOYSTICK_ANDROID
|
||||
return Android_OnPadUp(device_id, keycode);
|
||||
return Android_OnPadUp(device_id, keycode, scancode);
|
||||
#else
|
||||
return false;
|
||||
#endif // SDL_JOYSTICK_ANDROID
|
||||
@@ -1191,17 +1200,29 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat)(
|
||||
#endif // SDL_JOYSTICK_ANDROID
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoySensor)(
|
||||
JNIEnv *env, jclass jcls,
|
||||
jint device_id, jint sensor_type, jlong sensor_timestamp, jfloat x, jfloat y, jfloat z)
|
||||
{
|
||||
#ifdef SDL_JOYSTICK_ANDROID
|
||||
// In Java there's no Uint64 type, so pass Sint64 as if it was Uint64.
|
||||
Android_OnJoySensor(device_id, sensor_type, sensor_timestamp, x, y, z);
|
||||
#endif // SDL_JOYSTICK_ANDROID
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)(
|
||||
JNIEnv *env, jclass jcls,
|
||||
jint device_id, jstring device_name, jstring device_desc,
|
||||
jint vendor_id, jint product_id,
|
||||
jint button_mask, jint naxes, jint axis_mask, jint nhats, jboolean can_rumble, jboolean has_rgb_led)
|
||||
jint button_mask, jint naxes, jint axis_mask, jint nhats, jboolean can_rumble, jboolean has_rgb_led,
|
||||
jboolean has_accelerometer, jboolean has_gyroscope)
|
||||
{
|
||||
#ifdef SDL_JOYSTICK_ANDROID
|
||||
const char *name = (*env)->GetStringUTFChars(env, device_name, NULL);
|
||||
const char *desc = (*env)->GetStringUTFChars(env, device_desc, NULL);
|
||||
|
||||
Android_AddJoystick(device_id, name, desc, vendor_id, product_id, button_mask, naxes, axis_mask, nhats, can_rumble, has_rgb_led);
|
||||
Android_AddJoystick(device_id, name, desc, vendor_id, product_id, button_mask, naxes, axis_mask, nhats,
|
||||
can_rumble, has_rgb_led, has_accelerometer, has_gyroscope);
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, device_name, name);
|
||||
(*env)->ReleaseStringUTFChars(env, device_desc, desc);
|
||||
@@ -2626,6 +2647,12 @@ void Android_JNI_JoystickSetLED(int device_id, int red, int green, int blue)
|
||||
(*env)->CallStaticVoidMethod(env, mControllerManagerClass, midJoystickSetLED, device_id, red, green, blue);
|
||||
}
|
||||
|
||||
void Android_JNI_JoystickSetSensorsEnabled(int device_id, bool enabled)
|
||||
{
|
||||
JNIEnv *env = Android_JNI_GetEnv();
|
||||
(*env)->CallStaticVoidMethod(env, mControllerManagerClass, midJoystickSetSensorsEnabled, device_id, (enabled == 1));
|
||||
}
|
||||
|
||||
void Android_JNI_PollHapticDevices(void)
|
||||
{
|
||||
JNIEnv *env = Android_JNI_GetEnv();
|
||||
|
||||
@@ -105,6 +105,7 @@ int Android_JNI_GetPowerInfo(int *plugged, int *charged, int *battery, int *seco
|
||||
// Joystick support
|
||||
void Android_JNI_PollInputDevices(void);
|
||||
void Android_JNI_JoystickSetLED(int device_id, int red, int green, int blue);
|
||||
void Android_JNI_JoystickSetSensorsEnabled(int device_id, bool enabled);
|
||||
|
||||
// Haptic support
|
||||
void Android_JNI_PollHapticDevices(void);
|
||||
|
||||
@@ -9,8 +9,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 3,4,8,0
|
||||
PRODUCTVERSION 3,4,8,0
|
||||
FILEVERSION 3,4,9,0
|
||||
PRODUCTVERSION 3,4,9,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
FILEFLAGS 0x0L
|
||||
FILEOS 0x40004L
|
||||
@@ -23,12 +23,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "\0"
|
||||
VALUE "FileDescription", "SDL\0"
|
||||
VALUE "FileVersion", "3, 4, 8, 0\0"
|
||||
VALUE "FileVersion", "3, 4, 9, 0\0"
|
||||
VALUE "InternalName", "SDL\0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2026 Sam Lantinga\0"
|
||||
VALUE "OriginalFilename", "SDL3.dll\0"
|
||||
VALUE "ProductName", "Simple DirectMedia Layer\0"
|
||||
VALUE "ProductVersion", "3, 4, 8, 0\0"
|
||||
VALUE "ProductVersion", "3, 4, 9, 0\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -712,91 +712,116 @@ static GamepadMapping_t *SDL_CreateMappingForAndroidGamepad(SDL_GUID guid)
|
||||
char mapping_string[1024];
|
||||
int button_mask;
|
||||
int axis_mask;
|
||||
Uint16 vendor, product;
|
||||
|
||||
SDL_strlcpy(mapping_string, "none,", sizeof(mapping_string));
|
||||
|
||||
button_mask = SDL_Swap16LE(*(Uint16 *)(&guid.data[sizeof(guid.data) - 4]));
|
||||
axis_mask = SDL_Swap16LE(*(Uint16 *)(&guid.data[sizeof(guid.data) - 2]));
|
||||
if (!button_mask && !axis_mask) {
|
||||
// Accelerometer, shouldn't have a gamepad mapping
|
||||
return NULL;
|
||||
}
|
||||
if (!(button_mask & face_button_mask)) {
|
||||
// We don't know what buttons or axes are supported, don't make up a mapping
|
||||
return NULL;
|
||||
}
|
||||
SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL);
|
||||
if (vendor == USB_VENDOR_NINTENDO) {
|
||||
if (product == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT || product == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT) {
|
||||
// FIXME: Should we have a separate hint for non-HIDAPI JoyCon handling?
|
||||
// Android doesn't report JoyCon SL/SR presses for some reason, so no horizontal triggers/vertical paddles
|
||||
if (SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS, false)) {
|
||||
// Vertical mode
|
||||
if (product == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT) {
|
||||
SDL_strlcat(mapping_string, "Nintendo Switch Joy-Con (L),back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,misc1:b18,", sizeof(mapping_string));
|
||||
} else {
|
||||
SDL_strlcat(mapping_string, "Nintendo Switch Joy-Con (R),a:b0,b:b1,guide:b5,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a0,righty:a1,start:b6,x:b3,y:b2,", sizeof(mapping_string));
|
||||
}
|
||||
} else {
|
||||
// Mini gamepad mode
|
||||
if (product == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT) {
|
||||
SDL_strlcat(mapping_string, "Nintendo Switch Joy-Con (L),a:b13,b:b12,guide:b18,leftstick:b7,leftx:a1,lefty:a0~,start:b4,x:b11,y:b14,paddle2:b9,paddle4:b15,", sizeof(mapping_string));
|
||||
} else {
|
||||
SDL_strlcat(mapping_string, "Nintendo Switch Joy-Con (R),a:b1,b:b2,guide:b5,leftstick:b8,leftx:a1~,lefty:a0,start:b6,x:b0,y:b3,paddle1:b10,paddle3:b16,", sizeof(mapping_string));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
button_mask = SDL_Swap16LE(*(Uint16 *)(&guid.data[sizeof(guid.data) - 4]));
|
||||
axis_mask = SDL_Swap16LE(*(Uint16 *)(&guid.data[sizeof(guid.data) - 2]));
|
||||
if (!button_mask && !axis_mask) {
|
||||
// Accelerometer, shouldn't have a gamepad mapping
|
||||
return NULL;
|
||||
}
|
||||
if (!(button_mask & face_button_mask)) {
|
||||
// We don't know what buttons or axes are supported, don't make up a mapping
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_strlcpy(mapping_string, "none,*,", sizeof(mapping_string));
|
||||
SDL_strlcpy(mapping_string, "*,", sizeof(mapping_string));
|
||||
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_SOUTH)) {
|
||||
SDL_strlcat(mapping_string, "a:b0,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_EAST)) {
|
||||
SDL_strlcat(mapping_string, "b:b1,", sizeof(mapping_string));
|
||||
} else if (button_mask & (1 << SDL_GAMEPAD_BUTTON_BACK)) {
|
||||
// Use the back button as "B" for easy UI navigation with TV remotes
|
||||
SDL_strlcat(mapping_string, "b:b4,", sizeof(mapping_string));
|
||||
button_mask &= ~(1 << SDL_GAMEPAD_BUTTON_BACK);
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_WEST)) {
|
||||
SDL_strlcat(mapping_string, "x:b2,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_NORTH)) {
|
||||
SDL_strlcat(mapping_string, "y:b3,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_BACK)) {
|
||||
SDL_strlcat(mapping_string, "back:b4,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_GUIDE)) {
|
||||
// The guide button generally isn't functional (or acts as a home button) on most Android gamepads before Android 11
|
||||
if (SDL_GetAndroidSDKVersion() >= 30 /* Android 11 */) {
|
||||
SDL_strlcat(mapping_string, "guide:b5,", sizeof(mapping_string));
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_SOUTH)) {
|
||||
SDL_strlcat(mapping_string, "a:b0,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_EAST)) {
|
||||
SDL_strlcat(mapping_string, "b:b1,", sizeof(mapping_string));
|
||||
} else if (button_mask & (1 << SDL_GAMEPAD_BUTTON_BACK)) {
|
||||
// Use the back button as "B" for easy UI navigation with TV remotes
|
||||
SDL_strlcat(mapping_string, "b:b4,", sizeof(mapping_string));
|
||||
button_mask &= ~(1 << SDL_GAMEPAD_BUTTON_BACK);
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_WEST)) {
|
||||
SDL_strlcat(mapping_string, "x:b2,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_NORTH)) {
|
||||
SDL_strlcat(mapping_string, "y:b3,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_BACK)) {
|
||||
SDL_strlcat(mapping_string, "back:b4,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_GUIDE)) {
|
||||
// The guide button generally isn't functional (or acts as a home button) on most Android gamepads before Android 11
|
||||
if (SDL_GetAndroidSDKVersion() >= 30 /* Android 11 */) {
|
||||
SDL_strlcat(mapping_string, "guide:b5,", sizeof(mapping_string));
|
||||
}
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_START)) {
|
||||
SDL_strlcat(mapping_string, "start:b6,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_STICK)) {
|
||||
SDL_strlcat(mapping_string, "leftstick:b7,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_STICK)) {
|
||||
SDL_strlcat(mapping_string, "rightstick:b8,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_SHOULDER)) {
|
||||
SDL_strlcat(mapping_string, "leftshoulder:b9,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER)) {
|
||||
SDL_strlcat(mapping_string, "rightshoulder:b10,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_DPAD_UP)) {
|
||||
SDL_strlcat(mapping_string, "dpup:b11,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_DPAD_DOWN)) {
|
||||
SDL_strlcat(mapping_string, "dpdown:b12,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_DPAD_LEFT)) {
|
||||
SDL_strlcat(mapping_string, "dpleft:b13,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_DPAD_RIGHT)) {
|
||||
SDL_strlcat(mapping_string, "dpright:b14,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_LEFTX)) {
|
||||
SDL_strlcat(mapping_string, "leftx:a0,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_LEFTY)) {
|
||||
SDL_strlcat(mapping_string, "lefty:a1,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_RIGHTX)) {
|
||||
SDL_strlcat(mapping_string, "rightx:a2,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_RIGHTY)) {
|
||||
SDL_strlcat(mapping_string, "righty:a3,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_LEFT_TRIGGER)) {
|
||||
SDL_strlcat(mapping_string, "lefttrigger:a4,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_RIGHT_TRIGGER)) {
|
||||
SDL_strlcat(mapping_string, "righttrigger:a5,", sizeof(mapping_string));
|
||||
}
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_START)) {
|
||||
SDL_strlcat(mapping_string, "start:b6,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_STICK)) {
|
||||
SDL_strlcat(mapping_string, "leftstick:b7,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_STICK)) {
|
||||
SDL_strlcat(mapping_string, "rightstick:b8,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_SHOULDER)) {
|
||||
SDL_strlcat(mapping_string, "leftshoulder:b9,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER)) {
|
||||
SDL_strlcat(mapping_string, "rightshoulder:b10,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_DPAD_UP)) {
|
||||
SDL_strlcat(mapping_string, "dpup:b11,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_DPAD_DOWN)) {
|
||||
SDL_strlcat(mapping_string, "dpdown:b12,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_DPAD_LEFT)) {
|
||||
SDL_strlcat(mapping_string, "dpleft:b13,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_DPAD_RIGHT)) {
|
||||
SDL_strlcat(mapping_string, "dpright:b14,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_LEFTX)) {
|
||||
SDL_strlcat(mapping_string, "leftx:a0,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_LEFTY)) {
|
||||
SDL_strlcat(mapping_string, "lefty:a1,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_RIGHTX)) {
|
||||
SDL_strlcat(mapping_string, "rightx:a2,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_RIGHTY)) {
|
||||
SDL_strlcat(mapping_string, "righty:a3,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_LEFT_TRIGGER)) {
|
||||
SDL_strlcat(mapping_string, "lefttrigger:a4,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_RIGHT_TRIGGER)) {
|
||||
SDL_strlcat(mapping_string, "righttrigger:a5,", sizeof(mapping_string));
|
||||
}
|
||||
|
||||
return SDL_PrivateAddMappingForGUID(guid, mapping_string, &existing, SDL_GAMEPAD_MAPPING_PRIORITY_DEFAULT);
|
||||
}
|
||||
#endif // SDL_PLATFORM_ANDROID
|
||||
|
||||
@@ -29,8 +29,10 @@
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
#include "../../core/android/SDL_android.h"
|
||||
#include "../hidapi/SDL_hidapijoystick_c.h"
|
||||
#include "../usb_ids.h"
|
||||
|
||||
#include "android/keycodes.h"
|
||||
#include <linux/input-event-codes.h>
|
||||
|
||||
// As of platform android-14, android/keycodes.h is missing these defines
|
||||
#ifndef AKEYCODE_BUTTON_1
|
||||
@@ -170,6 +172,31 @@ static int keycode_to_SDL(int keycode)
|
||||
return button;
|
||||
}
|
||||
|
||||
static int scancode_to_SDL(int scancode)
|
||||
{
|
||||
int button = 0;
|
||||
switch (scancode) {
|
||||
// D-Pad buttons on the left JoyCon
|
||||
case BTN_DPAD_UP:
|
||||
button = SDL_GAMEPAD_BUTTON_DPAD_UP;
|
||||
break;
|
||||
case BTN_DPAD_DOWN:
|
||||
button = SDL_GAMEPAD_BUTTON_DPAD_DOWN;
|
||||
break;
|
||||
case BTN_DPAD_LEFT:
|
||||
button = SDL_GAMEPAD_BUTTON_DPAD_LEFT;
|
||||
break;
|
||||
case BTN_DPAD_RIGHT:
|
||||
button = SDL_GAMEPAD_BUTTON_DPAD_RIGHT;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
SDL_assert(button < ANDROID_MAX_NBUTTONS);
|
||||
return button;
|
||||
}
|
||||
|
||||
static SDL_Scancode button_to_scancode(int button)
|
||||
{
|
||||
switch (button) {
|
||||
@@ -195,11 +222,14 @@ static SDL_Scancode button_to_scancode(int button)
|
||||
return SDL_SCANCODE_UNKNOWN;
|
||||
}
|
||||
|
||||
bool Android_OnPadDown(int device_id, int keycode)
|
||||
bool Android_OnPadDown(int device_id, int keycode, int scancode)
|
||||
{
|
||||
Uint64 timestamp = SDL_GetTicksNS();
|
||||
SDL_joylist_item *item;
|
||||
int button = keycode_to_SDL(keycode);
|
||||
if (button < 0) {
|
||||
button = scancode_to_SDL(scancode);
|
||||
}
|
||||
if (button >= 0) {
|
||||
SDL_LockJoysticks();
|
||||
item = JoystickByDeviceId(device_id);
|
||||
@@ -215,11 +245,14 @@ bool Android_OnPadDown(int device_id, int keycode)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Android_OnPadUp(int device_id, int keycode)
|
||||
bool Android_OnPadUp(int device_id, int keycode, int scancode)
|
||||
{
|
||||
Uint64 timestamp = SDL_GetTicksNS();
|
||||
SDL_joylist_item *item;
|
||||
int button = keycode_to_SDL(keycode);
|
||||
if (button < 0) {
|
||||
button = scancode_to_SDL(scancode);
|
||||
}
|
||||
if (button >= 0) {
|
||||
SDL_LockJoysticks();
|
||||
item = JoystickByDeviceId(device_id);
|
||||
@@ -306,7 +339,37 @@ bool Android_OnHat(int device_id, int hat_id, int x, int y)
|
||||
return false;
|
||||
}
|
||||
|
||||
void Android_AddJoystick(int device_id, const char *name, const char *desc, int vendor_id, int product_id, int button_mask, int naxes, int axis_mask, int nhats, bool can_rumble, bool has_rgb_led)
|
||||
void Android_OnJoySensor(int device_id, int sensor_type, Uint64 sensor_timestamp, float x, float y, float z)
|
||||
{
|
||||
Uint64 timestamp = SDL_GetTicksNS();
|
||||
SDL_joylist_item *item;
|
||||
SDL_SensorType sensor;
|
||||
float data[3];
|
||||
|
||||
if (sensor_type == 1) { // Sensor.TYPE_ACCELEROMETER
|
||||
sensor = SDL_SENSOR_ACCEL;
|
||||
} else if (sensor_type == 4) { // Sensor.TYPE_GYROSCOPE
|
||||
sensor = SDL_SENSOR_GYRO;
|
||||
} else {
|
||||
// Unsupported sensor
|
||||
return;
|
||||
}
|
||||
|
||||
// The axes of sensor events and their signs are the same as SDL's, so no conversion required
|
||||
data[0] = x;
|
||||
data[1] = y;
|
||||
data[2] = z;
|
||||
|
||||
SDL_LockJoysticks();
|
||||
item = JoystickByDeviceId(device_id);
|
||||
if (item && item->joystick) {
|
||||
SDL_SendJoystickSensor(timestamp, item->joystick, sensor, sensor_timestamp, data, 3);
|
||||
}
|
||||
SDL_UnlockJoysticks();
|
||||
}
|
||||
|
||||
void Android_AddJoystick(int device_id, const char *name, const char *desc, int vendor_id, int product_id, int button_mask, int naxes, int axis_mask, int nhats,
|
||||
bool can_rumble, bool has_rgb_led, bool has_accelerometer, bool has_gyroscope)
|
||||
{
|
||||
SDL_joylist_item *item;
|
||||
SDL_GUID guid;
|
||||
@@ -337,8 +400,9 @@ void Android_AddJoystick(int device_id, const char *name, const char *desc, int
|
||||
SDL_Log("Joystick: %s, descriptor %s, vendor = 0x%.4x, product = 0x%.4x, %d axes, %d hats", name, desc, vendor_id, product_id, naxes, nhats);
|
||||
#endif
|
||||
|
||||
if (nhats > 0) {
|
||||
if (nhats > 0 || (vendor_id == USB_VENDOR_NINTENDO && product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT)) {
|
||||
// Hat is translated into DPAD buttons
|
||||
// D-Pad on the left JoyCon is a special case, it's not recognized via keycodes or hats, only scancodes
|
||||
button_mask |= ((1 << SDL_GAMEPAD_BUTTON_DPAD_UP) |
|
||||
(1 << SDL_GAMEPAD_BUTTON_DPAD_DOWN) |
|
||||
(1 << SDL_GAMEPAD_BUTTON_DPAD_LEFT) |
|
||||
@@ -382,6 +446,8 @@ void Android_AddJoystick(int device_id, const char *name, const char *desc, int
|
||||
item->nhats = nhats;
|
||||
item->can_rumble = can_rumble;
|
||||
item->has_rgb_led = has_rgb_led;
|
||||
item->has_accelerometer = has_accelerometer;
|
||||
item->has_gyroscope = has_accelerometer;
|
||||
item->device_instance = SDL_GetNextObjectID();
|
||||
if (!SDL_joylist_tail) {
|
||||
SDL_joylist = SDL_joylist_tail = item;
|
||||
@@ -587,6 +653,13 @@ static bool ANDROID_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
||||
SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RGB_LED_BOOLEAN, true);
|
||||
}
|
||||
|
||||
if (item->has_accelerometer) {
|
||||
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 0.0f);
|
||||
}
|
||||
if (item->has_gyroscope) {
|
||||
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 0.0f);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -631,7 +704,15 @@ static bool ANDROID_JoystickSendEffect(SDL_Joystick *joystick, const void *data,
|
||||
|
||||
static bool ANDROID_JoystickSetSensorsEnabled(SDL_Joystick *joystick, bool enabled)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
SDL_joylist_item *item = (SDL_joylist_item *)joystick->hwdata;
|
||||
if (!item) {
|
||||
return SDL_SetError("SetSensorsEnabled failed, device disconnected");
|
||||
}
|
||||
if (!item->has_accelerometer && !item->has_gyroscope) {
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
Android_JNI_JoystickSetSensorsEnabled(item->device_id, enabled);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ANDROID_JoystickUpdate(SDL_Joystick *joystick)
|
||||
|
||||
@@ -28,11 +28,13 @@
|
||||
|
||||
#include "../SDL_sysjoystick.h"
|
||||
|
||||
extern bool Android_OnPadDown(int device_id, int keycode);
|
||||
extern bool Android_OnPadUp(int device_id, int keycode);
|
||||
extern bool Android_OnPadDown(int device_id, int keycode, int scancode);
|
||||
extern bool Android_OnPadUp(int device_id, int keycode, int scancode);
|
||||
extern bool Android_OnJoy(int device_id, int axisnum, float value);
|
||||
extern bool Android_OnHat(int device_id, int hat_id, int x, int y);
|
||||
extern void Android_AddJoystick(int device_id, const char *name, const char *desc, int vendor_id, int product_id, int button_mask, int naxes, int axis_mask, int nhats, bool can_rumble, bool has_rgb_led);
|
||||
extern void Android_OnJoySensor(int device_id, int sensor_type, Uint64 sensor_timestamp, float x, float y, float z);
|
||||
extern void Android_AddJoystick(int device_id, const char *name, const char *desc, int vendor_id, int product_id, int button_mask, int naxes, int axis_mask, int nhats,
|
||||
bool can_rumble, bool has_rgb_led, bool has_accelerometer, bool has_gyroscope);
|
||||
extern void Android_RemoveJoystick(int device_id);
|
||||
|
||||
// A linked list of available joysticks
|
||||
@@ -47,6 +49,8 @@ typedef struct SDL_joylist_item
|
||||
int dpad_state;
|
||||
bool can_rumble;
|
||||
bool has_rgb_led;
|
||||
bool has_accelerometer;
|
||||
bool has_gyroscope;
|
||||
|
||||
struct SDL_joylist_item *next;
|
||||
} SDL_joylist_item;
|
||||
|
||||
@@ -340,8 +340,6 @@ static bool IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle
|
||||
name = "MFi Gamepad";
|
||||
}
|
||||
|
||||
device->name = SDL_CreateJoystickName(0, 0, NULL, name);
|
||||
|
||||
#ifdef DEBUG_CONTROLLER_PROFILE
|
||||
NSLog(@"Product name: %@\n", controller.vendorName);
|
||||
NSLog(@"Product category: %@\n", controller.productCategory);
|
||||
@@ -428,12 +426,19 @@ static bool IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle
|
||||
if (device->has_xbox_paddles) {
|
||||
// Assume Xbox One Elite Series 2 Controller unless/until GCController flows VID/PID
|
||||
product = USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH;
|
||||
|
||||
// controller.vendorName returns a generic name for Xbox controllers ("Controller"),
|
||||
// and controller.productCategory only returns "Xbox One" for those controllers,
|
||||
// so we give them proper names based on the ones from SDL_gamepad_db.h
|
||||
name = "Xbox One Elite 2 Controller";
|
||||
} else if (device->has_xbox_share_button) {
|
||||
// Assume Xbox Series X Controller unless/until GCController flows VID/PID
|
||||
product = USB_PRODUCT_XBOX_SERIES_X_BLE;
|
||||
name = "Xbox Series X Controller";
|
||||
} else {
|
||||
// Assume Xbox One S Bluetooth Controller unless/until GCController flows VID/PID
|
||||
product = USB_PRODUCT_XBOX_ONE_S_REV1_BLUETOOTH;
|
||||
name = "Xbox One Wireless Controller";
|
||||
}
|
||||
} else if (device->is_ps4) {
|
||||
// Assume DS4 Slim unless/until GCController flows VID/PID
|
||||
@@ -611,6 +616,8 @@ static bool IOS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCControlle
|
||||
// We don't know how to get input events from this device
|
||||
return false;
|
||||
}
|
||||
|
||||
device->name = SDL_CreateJoystickName(0, 0, NULL, name);
|
||||
|
||||
Uint16 signature;
|
||||
if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
|
||||
|
||||
@@ -335,11 +335,6 @@ void SDL_RunThread(SDL_Thread *thread)
|
||||
// Perform any system-dependent setup - this function may not fail
|
||||
SDL_SYS_SetupThread(thread->name);
|
||||
|
||||
// Get the thread id
|
||||
thread->threadid = SDL_GetCurrentThreadID();
|
||||
|
||||
SDL_SignalSemaphore(thread->ready_sem); // the thread is officially ready to run!
|
||||
|
||||
// Run the function
|
||||
*statusloc = userfunc(userdata);
|
||||
|
||||
@@ -396,13 +391,6 @@ SDL_Thread *SDL_CreateThreadWithPropertiesRuntime(SDL_PropertiesID props,
|
||||
}
|
||||
}
|
||||
|
||||
thread->ready_sem = SDL_CreateSemaphore(0);
|
||||
if (!thread->ready_sem) {
|
||||
SDL_free(thread->name);
|
||||
SDL_free(thread);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
thread->userfunc = fn;
|
||||
thread->userdata = userdata;
|
||||
thread->stacksize = stacksize;
|
||||
@@ -413,16 +401,11 @@ SDL_Thread *SDL_CreateThreadWithPropertiesRuntime(SDL_PropertiesID props,
|
||||
if (!SDL_SYS_CreateThread(thread, pfnBeginThread, pfnEndThread)) {
|
||||
// Oops, failed. Gotta free everything
|
||||
SDL_SetObjectValid(thread, SDL_OBJECT_TYPE_THREAD, false);
|
||||
SDL_DestroySemaphore(thread->ready_sem);
|
||||
SDL_free(thread->name);
|
||||
SDL_free(thread);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_WaitSemaphore(thread->ready_sem);
|
||||
SDL_DestroySemaphore(thread->ready_sem);
|
||||
thread->ready_sem = NULL;
|
||||
|
||||
// Everything is running now
|
||||
return thread;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,6 @@ struct SDL_Thread
|
||||
SDL_error errbuf;
|
||||
char *name;
|
||||
size_t stacksize; // 0 for default, >0 for user-specified stack size.
|
||||
SDL_Semaphore *ready_sem; // signals when the thread is set up and about to start running.
|
||||
int(SDLCALL *userfunc)(void *);
|
||||
void *userdata;
|
||||
void *data;
|
||||
|
||||
@@ -72,6 +72,10 @@ bool SDL_SYS_CreateThread(SDL_Thread *thread,
|
||||
return SDL_SetError("Couldn't create thread");
|
||||
}
|
||||
|
||||
u32 thread_ID = 0;
|
||||
svcGetThreadId(&thread_ID, threadGetHandle(thread->handle));
|
||||
thread->threadid = (SDL_ThreadID) thread_ID;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,6 +95,9 @@ bool SDL_SYS_CreateThread(SDL_Thread *thread,
|
||||
if (StartThread(thread->handle, thread) < 0) {
|
||||
return SDL_SetError("StartThread() failed");
|
||||
}
|
||||
|
||||
thread->threadid = (SDL_ThreadID) thread->handle;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,8 @@ bool SDL_SYS_CreateThread(SDL_Thread *thread,
|
||||
return SDL_SetError("sceKernelCreateThread() failed");
|
||||
}
|
||||
|
||||
thread->threadid = (SDL_ThreadID) thread->handle;
|
||||
|
||||
sceKernelStartThread(thread->handle, 4, &thread);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -116,6 +116,8 @@ bool SDL_SYS_CreateThread(SDL_Thread *thread,
|
||||
return SDL_SetError("Not enough resources to create thread");
|
||||
}
|
||||
|
||||
thread->threadid = (SDL_ThreadID) thread->handle; // the SDL thread ID is just the pthread_t.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,8 @@ bool SDL_SYS_CreateThread(SDL_Thread *thread,
|
||||
return SDL_SetError("sceKernelCreateThread() failed");
|
||||
}
|
||||
|
||||
thread->threadid = (SDL_ThreadID) thread->handle;
|
||||
|
||||
sceKernelStartThread(thread->handle, 4, &thread);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -77,15 +77,18 @@ bool SDL_SYS_CreateThread(SDL_Thread *thread,
|
||||
thread->handle = (SYS_ThreadHandle)((size_t)pfnBeginThread(NULL, (unsigned int)thread->stacksize,
|
||||
RunThreadViaBeginThreadEx,
|
||||
thread, flags, &threadid));
|
||||
thread->threadid = (SDL_ThreadID) threadid;
|
||||
} else {
|
||||
DWORD threadid = 0;
|
||||
thread->handle = CreateThread(NULL, thread->stacksize,
|
||||
RunThreadViaCreateThread,
|
||||
thread, flags, &threadid);
|
||||
thread->threadid = (SDL_ThreadID) threadid;
|
||||
}
|
||||
if (!thread->handle) {
|
||||
return SDL_SetError("Not enough resources to create thread");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1169,9 +1169,7 @@ static void pointer_handle_axis_relative_direction(void *data, struct wl_pointer
|
||||
uint32_t axis, uint32_t axis_relative_direction)
|
||||
{
|
||||
SDL_WaylandSeat *seat = data;
|
||||
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (axis_relative_direction) {
|
||||
case WL_POINTER_AXIS_RELATIVE_DIRECTION_IDENTICAL:
|
||||
seat->pointer.pending_frame.axis.direction = SDL_MOUSEWHEEL_NORMAL;
|
||||
|
||||
Reference in New Issue
Block a user