Compare commits

...

6 Commits

Author SHA1 Message Date
Ryan C. Gordon
6d35168a63 thread: Remove semaphore in thread creation.
This was added so that the new thread definitely has its threadid set, via
SDL_GetCurrentThreadID(), before SDL_CreatThread returns, but this broke
Emscripten, which can't wait on a newly-created thread, since the thread won't
start until a later mainloop iteration.

Now we have the creating thread set this id in SDL_SYS_CreateThread, where
platform-specific logic can figure out how to calculate the new thread's ID
from the parent thread, without using SDL_GetCurrentThreadID().

Fixes #15509.

(cherry picked from commit 922b872b4f)
2026-05-05 00:54:08 -04:00
Nintorch
3013f975ac Fix JoyCon mappings on Android
(cherry picked from commit 3c1636a958)
2026-05-04 11:49:45 -07:00
Nintorch
52b6bceedf Add support for joystick motion sensors on Android
(cherry picked from commit c699512adc)
2026-05-03 15:11:59 -07:00
Frank Praznik
5c107908ff wayland: Pass the inverted flag for horizontal scroll events
Natural scrolling affects both axes, and the compositor may not send the vertical axis orientation if the frame has no vertical scroll motion, so purely horizontal events need to be flagged as inverted as well.

(cherry picked from commit 3ee0439ae5)
2026-05-03 17:45:46 -04:00
Nintorch
c239edd6e0 Fix Xbox controller names in MFI joystick backend (#15499)
controller.vendorName returns a generic name for Xbox controllers ("Controller"), so we have to give them proper names.

(cherry picked from commit c805a4d632)
2026-05-03 09:26:38 -07:00
Sam Lantinga
796782fc89 Updated to version 3.4.9 for development 2026-05-01 19:49:54 -07:00
24 changed files with 363 additions and 146 deletions

View File

@@ -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)

View File

@@ -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>

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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]);
}
}

View File

@@ -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

View File

@@ -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.

View File

@@ -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();

View File

@@ -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);

View File

@@ -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"

View File

@@ -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

View File

@@ -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)

View File

@@ -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;

View File

@@ -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, *)) {

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;