X Tutup
Skip to content

Add support for SDL3 joystick input driver for iOS#114316

Merged
Repiteo merged 1 commit intogodotengine:masterfrom
Nintorch:sdl-joypad-ios-visionos
Feb 18, 2026
Merged

Add support for SDL3 joystick input driver for iOS#114316
Repiteo merged 1 commit intogodotengine:masterfrom
Nintorch:sdl-joypad-ios-visionos

Conversation

@Nintorch
Copy link
Contributor

@Nintorch Nintorch commented Dec 24, 2025

Follow-up to #106218

I decided to split #109645 into several smaller PRs, starting with iOS and visionOS. (EDIT: not entirely sure this PR supports visionOS)
This PR adds support for SDL3 joystick input driver for the rest of the supported Apple platforms.

Also, it would be nice if someone could test if Input.has_joy_light() and Input.set_joy_light() work on iOS and visionOS with this PR. :D
I think they're supposed to work since JoystickSetLED function is implemented in the MFI joystick driver and a check for iOS version is included inside:

static bool IOS_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
{
@autoreleasepool {
SDL_JoystickDeviceItem *device = joystick->hwdata;
if (device == NULL) {
return SDL_SetError("Controller is no longer connected");
}
if (@available(macOS 10.16, iOS 14.0, tvOS 14.0, *)) {
GCController *controller = device->controller;
GCDeviceLight *light = controller.light;
if (light) {
light.color = [[GCColor alloc] initWithRed:(float)red / 255.0f
green:(float)green / 255.0f
blue:(float)blue / 255.0f];
return true;
}
}
}
return SDL_Unsupported();
}

TODO:

  • Rebase
  • Check if joypad LED works (Sorry, I can't check myself :( ) (it does)
  • Check if joypad motion sensors work (Sorry, I can't check myself :( ) (at the moment, they don't)
  • Include bruvzg's SDL code fix
  • Documentation
  • Report SDL not detecting controller motion sensors on iOS
  • Return true for Input.has_joy_motion_sensors() if only one of the motion sensors is available
  • Document Input.get_joy_accelerometer() and Input.get_joy_gravity() being unsupported on iOS due to OS limitations.

@Nintorch Nintorch requested review from a team as code owners December 24, 2025 12:39
@Nintorch Nintorch changed the title Add support for SDL joystick input driver for iOS and visionOS Add support for SDL3 joystick input driver for iOS and visionOS Dec 24, 2025
@Chaosus Chaosus added this to the 4.7 milestone Dec 24, 2025
@Alex2782
Copy link
Member

I only have a Mac mini. I can't test it on iOS/VisionOS.

CC @godotengine/ios

@Nintorch Nintorch requested a review from a team February 18, 2026 04:26
@bruvzg bruvzg self-requested a review February 18, 2026 08:10
@bruvzg
Copy link
Member

bruvzg commented Feb 18, 2026

Tried it on iOS (10.gen iPad, iOS 26.3), and no controllers are detected (tested with Dual Sense and Xbox One controllers, both BT and wired connection).

@Nintorch
Copy link
Contributor Author

Nintorch commented Feb 18, 2026

Thank you for your review, bruvzg! I will try to fix this issue!

@bruvzg
Copy link
Member

bruvzg commented Feb 18, 2026

Relevant part from the log:

drivers/sdl/joypad_sdl.cpp:67:initialize(): Application didn't initialize properly, did you include SDL_main.h in the file containing your main() function? Condition "!SDL_Init(0x00000200u | 0x00002000u)" is true. Returning: FAILED
drivers/apple_embedded/os_apple_embedded.mm:176:initialize_joypads(): Couldn't initialize SDL joypad input driver. Couldn't initialize SDL joypad input driver.

@bruvzg
Copy link
Member

bruvzg commented Feb 18, 2026

#elif defined(SDL_PLATFORM_IOS)
        /* On iOS SDL provides a main function that creates an application delegate
           and starts the iOS application run loop.

           To use it, just #include SDL_main.h in the source file that contains your
           main() function.

           See src/video/uikit/SDL_uikitappdelegate.m for more details.
         */
        #define SDL_MAIN_NEEDED

Some noted:

  • There's no C++ main in iOS, it's using Swift Application.
  • We have own app delegate and main loop and can't use one provided by SDL, so SDL likely should be changed to use our loop.

@bruvzg
Copy link
Member

bruvzg commented Feb 18, 2026

Simply commenting #define SDL_MAIN_NEEDED line seems to be sufficient to make it work (at least it inits, controller is detected and input works), and nothing in the SDL delegate files seems to be relevant for the input. I'll check is light and vibration works a bit later.

@bruvzg
Copy link
Member

bruvzg commented Feb 18, 2026

With the following patch (and rebase to master):

diff --git a/thirdparty/sdl/include/SDL3/SDL_main.h b/thirdparty/sdl/include/SDL3/SDL_main.h
index 905d78e964..46e20445aa 100644
--- a/thirdparty/sdl/include/SDL3/SDL_main.h
+++ b/thirdparty/sdl/include/SDL3/SDL_main.h
@@ -174,7 +174,7 @@

            See src/video/uikit/SDL_uikitappdelegate.m for more details.
          */
-        #define SDL_MAIN_NEEDED
+       // #define SDL_MAIN_NEEDED

     #elif defined(SDL_PLATFORM_ANDROID)
         /* On Android SDL provides a Java class in SDLActivity.java that is the
  • Connecting / disconnecting controllers work.
  • Input work.
  • Vibrations work.
  • Light detection and color work.

@Nintorch
Copy link
Contributor Author

Thank you very much! I will include your fix in the PR later today!
May I ask if DualSense motion sensors get detected too? You can check those by using Input.has_joy_motion_sensors(), Input.set_joy_motion_sensors_enabled() and then getting the values from Input.get_joy_accelerometer(), Input.get_joy_gravity() and Input.get_joy_gyroscope().

@bruvzg
Copy link
Member

bruvzg commented Feb 18, 2026

May I ask if DualSense motion sensors get detected too?

No, Input.has_joy_motion_sensors() return false, all gets return zeros.

@Nintorch
Copy link
Contributor Author

Does it return false in _ready() or in _process() too?

@bruvzg
Copy link
Member

bruvzg commented Feb 18, 2026

Only checked it with _process() (has_ and get_ output constantly printed out) + button calling Input.set_joy_motion_sensors_enabled(idx, true). Same test app works on macOS.

@Nintorch
Copy link
Contributor Author

I see, thank you for testing! It seems to me like an issue with SDL, I will try to report the issue in their repository soon.

@bruvzg
Copy link
Member

bruvzg commented Feb 18, 2026

It seems it only supports SDL_SENSOR_GYRO but not SDL_SENSOR_ACCEL, this corresponds to the system API data, which also return false for https://developer.apple.com/documentation/gamecontroller/gcmotion/hasgravityanduseracceleration?language=objc. So it's not a SDL bug, but either iOS limitation, or issue with specific controller (maybe incompatible firmware).

@Nintorch
Copy link
Contributor Author

I'm not entirely sure SDL (and this PR) supports controllers for visionOS, so I think it's probably a good idea to mark it as only for iOS for now.
But if later it turns out it does, I think we can update the documentation/this PR accordingly. If not, we can create a Godot proposal to support controllers on visionOS.

@Nintorch Nintorch changed the title Add support for SDL3 joystick input driver for iOS and visionOS Add support for SDL3 joystick input driver for iOS Feb 18, 2026
@bruvzg
Copy link
Member

bruvzg commented Feb 18, 2026

I'm not entirely sure SDL (and this PR) supports controllers for visionOS, so I think it's probably a good idea to mark it as only for iOS for now.

OS API should be the same, but I have not way to test it.

@Nintorch Nintorch force-pushed the sdl-joypad-ios-visionos branch from b8a7a46 to 73fcc0d Compare February 18, 2026 15:39
@Nintorch
Copy link
Contributor Author

With the following patch (and rebase to master):

diff --git a/thirdparty/sdl/include/SDL3/SDL_main.h b/thirdparty/sdl/include/SDL3/SDL_main.h
index 905d78e964..46e20445aa 100644
--- a/thirdparty/sdl/include/SDL3/SDL_main.h
+++ b/thirdparty/sdl/include/SDL3/SDL_main.h
@@ -174,7 +174,7 @@

            See src/video/uikit/SDL_uikitappdelegate.m for more details.
          */
-        #define SDL_MAIN_NEEDED
+       // #define SDL_MAIN_NEEDED

     #elif defined(SDL_PLATFORM_ANDROID)
         /* On Android SDL provides a Java class in SDLActivity.java that is the
  • Connecting / disconnecting controllers work.
  • Input work.
  • Vibrations work.
  • Light detection and color work.

I defined SDL_MAIN_HANDLED in SDL_build_config_private.h, it should have the same effect as applying your patch, but without creating a new patch file. See also:

#ifndef SDL_MAIN_HANDLED
#if defined(SDL_PLATFORM_PRIVATE_MAIN)
/* Private platforms may have their own ideas about entry points. */
#include "SDL_main_private.h"
#elif defined(SDL_PLATFORM_WIN32)
/* On Windows SDL provides WinMain(), which parses the command line and passes
the arguments to your main function.
If you provide your own WinMain(), you may define SDL_MAIN_HANDLED
*/
#define SDL_MAIN_AVAILABLE
#elif defined(SDL_PLATFORM_GDK)
/* On GDK, SDL provides a main function that initializes the game runtime.
If you prefer to write your own WinMain-function instead of having SDL
provide one that calls your main() function,
#define SDL_MAIN_HANDLED before #include'ing SDL_main.h
and call the SDL_RunApp function from your entry point.
*/
#define SDL_MAIN_NEEDED
#elif defined(SDL_PLATFORM_IOS)
/* On iOS SDL provides a main function that creates an application delegate
and starts the iOS application run loop.
To use it, just #include SDL_main.h in the source file that contains your
main() function.
See src/video/uikit/SDL_uikitappdelegate.m for more details.
*/
#define SDL_MAIN_NEEDED

Copy link
Member

@bruvzg bruvzg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Retested all features, everything seems to work (including Input.get_joy_gyroscope()). Code looks good.

@Repiteo Repiteo merged commit afa6d60 into godotengine:master Feb 18, 2026
20 checks passed
@Repiteo
Copy link
Contributor

Repiteo commented Feb 18, 2026

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

X Tutup