Browse Source

update SDL3 codepaths to work with 3.1.

Sasha Szpakowski 10 months ago
parent
commit
dda7603d0d

+ 1 - 1
src/common/macos.mm

@@ -129,7 +129,7 @@ void setWindowSRGBColorSpace(SDL_Window *window)
 		{
 #if SDL_VERSION_ATLEAST(3, 0, 0)
 			SDL_PropertiesID props = SDL_GetWindowProperties(window);
-			NSWindow *window = (__bridge NSWindow *) SDL_GetProperty(props, SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, nullptr);
+			NSWindow *window = (__bridge NSWindow *) SDL_GetPointerProperty(props, SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, nullptr);
 			window.colorSpace = [NSColorSpace sRGBColorSpace];
 #else
 			SDL_SysWMinfo info = {};

+ 35 - 2
src/modules/event/sdl/Event.cpp

@@ -135,7 +135,12 @@ static void normalizedToDPICoords(double *x, double *y)
 // SDL's event watch callbacks trigger when the event is actually posted inside
 // SDL, unlike with SDL_PollEvents. This is useful for some events which require
 // handling inside the function which triggered them on some backends.
-static int SDLCALL watchAppEvents(void * /*udata*/, SDL_Event *event)
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+static bool
+#else
+static int
+#endif
+SDLCALL watchAppEvents(void * /*udata*/, SDL_Event *event)
 {
 	auto gfx = Module::getInstance<graphics::Graphics>(Module::M_GRAPHICS);
 
@@ -159,7 +164,11 @@ static int SDLCALL watchAppEvents(void * /*udata*/, SDL_Event *event)
 Event::Event()
 	: love::event::Event("love.event.sdl")
 {
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	if (!SDL_InitSubSystem(SDL_INIT_EVENTS))
+#else
 	if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0)
+#endif
 		throw love::Exception("Could not initialize SDL events subsystem (%s)", SDL_GetError());
 
 	SDL_AddEventWatch(watchAppEvents, this);
@@ -167,7 +176,11 @@ Event::Event()
 
 Event::~Event()
 {
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	SDL_RemoveEventWatch(watchAppEvents, this);
+#else
 	SDL_DelEventWatch(watchAppEvents, this);
+#endif
 	SDL_QuitSubSystem(SDL_INIT_EVENTS);
 }
 
@@ -194,7 +207,11 @@ Message *Event::wait()
 
 	SDL_Event e;
 
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	if (!SDL_WaitEvent(&e))
+#else
 	if (SDL_WaitEvent(&e) != 1)
+#endif
 		return nullptr;
 
 	return convert(e);
@@ -256,11 +273,19 @@ Message *Event::convert(const SDL_Event &e)
 				break;
 		}
 
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+		love::keyboard::sdl::Keyboard::getConstant(e.key.key, key);
+#else
 		love::keyboard::sdl::Keyboard::getConstant(e.key.keysym.sym, key);
+#endif
 		if (!love::keyboard::Keyboard::getConstant(key, txt))
 			txt = "unknown";
 
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+		love::keyboard::sdl::Keyboard::getConstant(e.key.scancode, scancode);
+#else
 		love::keyboard::sdl::Keyboard::getConstant(e.key.keysym.scancode, scancode);
+#endif
 		if (!love::keyboard::Keyboard::getConstant(scancode, txt2))
 			txt2 = "unknown";
 
@@ -270,11 +295,19 @@ Message *Event::convert(const SDL_Event &e)
 		msg = new Message("keypressed", vargs);
 		break;
 	case SDL_EVENT_KEY_UP:
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+		love::keyboard::sdl::Keyboard::getConstant(e.key.key, key);
+#else
 		love::keyboard::sdl::Keyboard::getConstant(e.key.keysym.sym, key);
+#endif
 		if (!love::keyboard::Keyboard::getConstant(key, txt))
 			txt = "unknown";
 
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+		love::keyboard::sdl::Keyboard::getConstant(e.key.scancode, scancode);
+#else
 		love::keyboard::sdl::Keyboard::getConstant(e.key.keysym.scancode, scancode);
+#endif
 		if (!love::keyboard::Keyboard::getConstant(scancode, txt2))
 			txt2 = "unknown";
 
@@ -551,7 +584,7 @@ Message *Event::convert(const SDL_Event &e)
 			{
 				SDL_Sensor *sensor = (SDL_Sensor *) s;
 #if SDL_VERSION_ATLEAST(3, 0, 0)
-				SDL_SensorID id = SDL_GetSensorInstanceID(sensor);
+				SDL_SensorID id = SDL_GetSensorID(sensor);
 #else
 				SDL_SensorID id = SDL_SensorGetInstanceID(sensor);
 #endif

+ 4 - 0
src/modules/filesystem/wrap_Filesystem.cpp

@@ -934,7 +934,11 @@ int extloader(lua_State *L)
 		}
 	}
 
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	SDL_SharedObject *handle = nullptr;
+#else
 	void *handle = nullptr;
+#endif
 	auto *inst = instance();
 
 #ifdef LOVE_ANDROID

+ 8 - 8
src/modules/joystick/sdl/JoystickModule.cpp

@@ -44,7 +44,7 @@ JoystickModule::JoystickModule()
 	: love::joystick::JoystickModule("love.joystick.sdl")
 {
 #if SDL_VERSION_ATLEAST(3, 0, 0)
-	if (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) < 0)
+	if (!SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD))
 #else
 	if (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0)
 #endif
@@ -60,8 +60,8 @@ JoystickModule::JoystickModule()
 
 	// Start joystick event watching. Joysticks are automatically added and
 	// removed via love.event.
-	SDL_SetJoystickEventsEnabled(SDL_TRUE);
-	SDL_SetGamepadEventsEnabled(SDL_TRUE);
+	SDL_SetJoystickEventsEnabled(true);
+	SDL_SetGamepadEventsEnabled(true);
 #else
 	for (int i = 0; i < SDL_NumJoysticks(); i++)
 		addJoystick(i);
@@ -215,7 +215,7 @@ bool JoystickModule::setGamepadMapping(const std::string &guid, Joystick::Gamepa
 		throw love::Exception("Invalid joystick GUID: %s", guid.c_str());
 
 #if SDL_VERSION_ATLEAST(3, 0, 0)
-	SDL_JoystickGUID sdlguid = SDL_GetJoystickGUIDFromString(guid.c_str());
+	SDL_GUID sdlguid = SDL_StringToGUID(guid.c_str());
 	std::string mapstr;
 
 	char *sdlmapstr = SDL_GetGamepadMappingForGUID(sdlguid);
@@ -468,8 +468,8 @@ std::string JoystickModule::getDeviceGUID(int64 deviceid) const
 		return std::string("");
 
 	// SDL's GUIDs identify *classes* of devices, instead of unique devices.
-	SDL_JoystickGUID guid = SDL_GetJoystickInstanceGUID((SDL_JoystickID)deviceid);
-	SDL_GetJoystickGUIDString(guid, guidstr, sizeof(guidstr));
+	SDL_GUID guid = SDL_GetJoystickGUIDForID((SDL_JoystickID)deviceid);
+	SDL_GUIDToString(guid, guidstr, sizeof(guidstr));
 #else
 	int deviceindex = (int) deviceid;
 	if (deviceindex < 0 || deviceindex >= SDL_NumJoysticks())
@@ -548,7 +548,7 @@ void JoystickModule::loadGamepadMappings(const std::string &mappings)
 std::string JoystickModule::getGamepadMappingString(const std::string &guid) const
 {
 #if SDL_VERSION_ATLEAST(3, 0, 0)
-	SDL_JoystickGUID sdlguid = SDL_GetJoystickGUIDFromString(guid.c_str());
+	SDL_GUID sdlguid = SDL_StringToGUID(guid.c_str());
 	char *sdlmapping = SDL_GetGamepadMappingForGUID(sdlguid);
 #else
 	SDL_JoystickGUID sdlguid = SDL_JoystickGetGUIDFromString(guid.c_str());
@@ -577,7 +577,7 @@ std::string JoystickModule::saveGamepadMappings()
 	for (const auto &g : recentGamepadGUIDs)
 	{
 #if SDL_VERSION_ATLEAST(3, 0, 0)
-		SDL_JoystickGUID sdlguid = SDL_GetJoystickGUIDFromString(g.first.c_str());
+		SDL_GUID sdlguid = SDL_StringToGUID(g.first.c_str());
 		char *sdlmapping = SDL_GetGamepadMappingForGUID(sdlguid);
 #else
 		SDL_JoystickGUID sdlguid = SDL_JoystickGetGUIDFromString(g.first.c_str());

+ 13 - 11
src/modules/joystick/sdl/JoystickSDL3.cpp

@@ -29,6 +29,8 @@
 
 #if SDL_VERSION_ATLEAST(3, 0, 0)
 
+#include <SDL_guid.h>
+
 // C++
 #include <algorithm>
 #include <limits>
@@ -62,13 +64,13 @@ bool Joystick::open(int64 deviceid)
 
 	if (joyhandle)
 	{
-		instanceid = SDL_GetJoystickInstanceID(joyhandle);
+		instanceid = SDL_GetJoystickID(joyhandle);
 
 		// SDL_JoystickGetGUIDString uses 32 bytes plus the null terminator.
 		char cstr[33];
 
-		SDL_JoystickGUID sdlguid = SDL_GetJoystickGUID(joyhandle);
-		SDL_GetJoystickGUIDString(sdlguid, cstr, (int) sizeof(cstr));
+		SDL_GUID sdlguid = SDL_GetJoystickGUID(joyhandle);
+		SDL_GUIDToString(sdlguid, cstr, (int) sizeof(cstr));
 
 		pguid = std::string(cstr);
 
@@ -212,7 +214,7 @@ bool Joystick::isDown(const std::vector<int> &buttonlist) const
 		if (button < 0 || button >= numbuttons)
 			continue;
 
-		if (SDL_GetJoystickButton(joyhandle, button) == 1)
+		if (SDL_GetJoystickButton(joyhandle, button))
 			return true;
 	}
 
@@ -304,7 +306,7 @@ bool Joystick::isGamepadDown(const std::vector<GamepadButton> &blist) const
 		if (!getConstant(button, sdlbutton))
 			continue;
 
-		if (SDL_GetGamepadButton(controller, sdlbutton) == 1)
+		if (SDL_GetGamepadButton(controller, sdlbutton))
 			return true;
 	}
 
@@ -382,7 +384,7 @@ std::string Joystick::getGamepadMappingString() const
 
 	if (sdlmapping == nullptr)
 	{
-		SDL_JoystickGUID sdlguid = SDL_GetJoystickGUIDFromString(pguid.c_str());
+		SDL_GUID sdlguid = SDL_StringToGUID(pguid.c_str());
 		sdlmapping = SDL_GetGamepadMappingForGUID(sdlguid);
 	}
 
@@ -445,7 +447,7 @@ bool Joystick::isVibrationSupported()
 		return false;
 
 	SDL_PropertiesID props = SDL_GetJoystickProperties(joyhandle);
-	return SDL_GetBooleanProperty(props, SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, SDL_FALSE);
+	return SDL_GetBooleanProperty(props, SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, false);
 }
 
 bool Joystick::setVibration(float left, float right, float duration)
@@ -489,7 +491,7 @@ bool Joystick::hasSensor(Sensor::SensorType type) const
 	if (!isGamepad())
 		return false;
 
-	return SDL_GamepadHasSensor(controller, SDLSensor::convert(type)) == SDL_TRUE;
+	return SDL_GamepadHasSensor(controller, SDLSensor::convert(type));
 #else
 	return false;
 #endif
@@ -503,7 +505,7 @@ bool Joystick::isSensorEnabled(Sensor::SensorType type) const
 	if (!isGamepad())
 		return false;
 
-	return SDL_GamepadSensorEnabled(controller, SDLSensor::convert(type)) == SDL_TRUE;
+	return SDL_GamepadSensorEnabled(controller, SDLSensor::convert(type));
 #else
 	return false;
 #endif
@@ -517,7 +519,7 @@ void Joystick::setSensorEnabled(Sensor::SensorType type, bool enabled)
 	if (!isGamepad())
 		throw love::Exception("Sensor is only supported on gamepad");
 
-	if (SDL_SetGamepadSensorEnabled(controller, SDLSensor::convert(type), enabled ? SDL_TRUE : SDL_FALSE) != 0)
+	if (!SDL_SetGamepadSensorEnabled(controller, SDLSensor::convert(type), enabled))
 	{
 		const char *name = nullptr;
 		SDLSensor::getConstant(type, name);
@@ -547,7 +549,7 @@ std::vector<float> Joystick::getSensorData(Sensor::SensorType type) const
 		throw love::Exception("\"%s\" gamepad sensor is not enabled", name);
 	}
 
-	if (SDL_GetGamepadSensorData(controller, SDLSensor::convert(type), data.data(), (int) data.size()) != 0)
+	if (!SDL_GetGamepadSensorData(controller, SDLSensor::convert(type), data.data(), (int) data.size()))
 	{
 		const char *name = nullptr;
 		SDLSensor::getConstant(type, name);

+ 90 - 1
src/modules/keyboard/sdl/Keyboard.cpp

@@ -36,6 +36,16 @@ namespace keyboard
 namespace sdl
 {
 
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+static SDL_Window *getSDLWindow()
+{
+	auto window = Module::getInstance<window::Window>(Module::M_WINDOW);
+	if (window)
+		return (SDL_Window *) window->getHandle();
+	return nullptr;
+}
+#endif
+
 Keyboard::Keyboard()
 	: love::keyboard::Keyboard("love.keyboard.sdl")
 	, key_repeat(false)
@@ -54,14 +64,22 @@ bool Keyboard::hasKeyRepeat() const
 
 bool Keyboard::isDown(const std::vector<Key> &keylist) const
 {
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	const bool *state = SDL_GetKeyboardState(nullptr);
+#else
 	const Uint8 *state = SDL_GetKeyboardState(nullptr);
+#endif
 
 	for (Key key : keylist)
 	{
 		SDL_Keycode sdlkey = SDLK_UNKNOWN;
 		if (getConstant(key, sdlkey))
 		{
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+			SDL_Scancode scancode = SDL_GetScancodeFromKey(sdlkey, nullptr);
+#else
 			SDL_Scancode scancode = SDL_GetScancodeFromKey(sdlkey);
+#endif
 			if (state[scancode])
 				return true;
 		}
@@ -72,7 +90,11 @@ bool Keyboard::isDown(const std::vector<Key> &keylist) const
 
 bool Keyboard::isScancodeDown(const std::vector<Scancode> &scancodelist) const
 {
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	const bool *state = SDL_GetKeyboardState(nullptr);
+#else
 	const Uint8 *state = SDL_GetKeyboardState(nullptr);
+#endif
 
 	for (Scancode scancode : scancodelist)
 	{
@@ -122,7 +144,11 @@ Keyboard::Key Keyboard::getKeyFromScancode(Scancode scancode) const
 	SDL_Scancode sdlscancode = SDL_SCANCODE_UNKNOWN;
 	scancodes.find(scancode, sdlscancode);
 
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	SDL_Keycode sdlkey = SDL_GetKeyFromScancode(sdlscancode, SDL_KMOD_NONE, false);
+#else
 	SDL_Keycode sdlkey = SDL_GetKeyFromScancode(sdlscancode);
+#endif
 
 	Key key = KEY_UNKNOWN;
 	getConstant(sdlkey, key);
@@ -136,7 +162,11 @@ Keyboard::Scancode Keyboard::getScancodeFromKey(Key key) const
 	SDL_Keycode sdlkey = SDLK_UNKNOWN;
 	if (getConstant(key, sdlkey))
 	{
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+		SDL_Scancode sdlscancode = SDL_GetScancodeFromKey(sdlkey, nullptr);
+#else
 		SDL_Scancode sdlscancode = SDL_GetScancodeFromKey(sdlkey);
+#endif
 		scancodes.find(sdlscancode, scancode);
 	}
 
@@ -145,10 +175,20 @@ Keyboard::Scancode Keyboard::getScancodeFromKey(Key key) const
 
 void Keyboard::setTextInput(bool enable)
 {
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	SDL_Window *window = getSDLWindow();
+	if (window == nullptr)
+		return;
+	if (enable)
+		SDL_StartTextInput(window);
+	else
+		SDL_StopTextInput(window);
+#else
 	if (enable)
 		SDL_StartTextInput();
 	else
 		SDL_StopTextInput();
+#endif
 }
 
 void Keyboard::setTextInput(bool enable, double x, double y, double w, double h)
@@ -163,7 +203,14 @@ void Keyboard::setTextInput(bool enable, double x, double y, double w, double h)
 	}
 
 	SDL_Rect rect = {(int) x, (int) y, (int) w, (int) h};
+
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	SDL_Window *sdlwindow = getSDLWindow();
+	if (sdlwindow != nullptr)
+		SDL_SetTextInputArea(sdlwindow, &rect, 0);
+#else
 	SDL_SetTextInputRect(&rect);
+#endif
 
 	setTextInput(enable);
 }
@@ -171,7 +218,10 @@ void Keyboard::setTextInput(bool enable, double x, double y, double w, double h)
 bool Keyboard::hasTextInput() const
 {
 #if SDL_VERSION_ATLEAST(3, 0, 0)
-	return SDL_TextInputActive();
+	SDL_Window *window = getSDLWindow();
+	if (window == nullptr)
+		return false;
+	return SDL_TextInputActive(window);
 #else
 	return SDL_IsTextInputActive() != SDL_FALSE;
 #endif
@@ -179,7 +229,11 @@ bool Keyboard::hasTextInput() const
 
 bool Keyboard::hasScreenKeyboard() const
 {
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	return SDL_HasScreenKeyboardSupport();
+#else
 	return SDL_HasScreenKeyboardSupport() != SDL_FALSE;
+#endif
 }
 
 bool Keyboard::getConstant(Key in, SDL_Keycode &out)
@@ -363,6 +417,14 @@ std::map<Keyboard::Key, SDL_Keycode> Keyboard::keyToSDLKey =
 
 	{ KEY_MODE, SDLK_MODE },
 
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	{ KEY_AUDIONEXT, SDLK_MEDIA_NEXT_TRACK },
+	{ KEY_AUDIOPREV, SDLK_MEDIA_PREVIOUS_TRACK },
+	{ KEY_AUDIOSTOP, SDLK_MEDIA_STOP },
+	{ KEY_AUDIOPLAY, SDLK_MEDIA_PLAY },
+	{ KEY_AUDIOMUTE, SDLK_MUTE },
+	{ KEY_MEDIASELECT, SDLK_MEDIA_SELECT },
+#else
 	{ KEY_AUDIONEXT, SDLK_AUDIONEXT },
 	{ KEY_AUDIOPREV, SDLK_AUDIOPREV },
 	{ KEY_AUDIOSTOP, SDLK_AUDIOSTOP },
@@ -373,6 +435,7 @@ std::map<Keyboard::Key, SDL_Keycode> Keyboard::keyToSDLKey =
 	{ KEY_MAIL, SDLK_MAIL },
 	{ KEY_CALCULATOR, SDLK_CALCULATOR },
 	{ KEY_COMPUTER, SDLK_COMPUTER },
+#endif
 	{ KEY_APP_SEARCH, SDLK_AC_SEARCH },
 	{ KEY_APP_HOME, SDLK_AC_HOME },
 	{ KEY_APP_BACK, SDLK_AC_BACK },
@@ -381,6 +444,9 @@ std::map<Keyboard::Key, SDL_Keycode> Keyboard::keyToSDLKey =
 	{ KEY_APP_REFRESH, SDLK_AC_REFRESH },
 	{ KEY_APP_BOOKMARKS, SDLK_AC_BOOKMARKS },
 
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	{ KEY_EJECT, SDLK_MEDIA_EJECT },
+#else
 	{ KEY_BRIGHTNESSDOWN, SDLK_BRIGHTNESSDOWN },
 	{ KEY_BRIGHTNESSUP, SDLK_BRIGHTNESSUP },
 	{ KEY_DISPLAYSWITCH, SDLK_DISPLAYSWITCH },
@@ -388,12 +454,17 @@ std::map<Keyboard::Key, SDL_Keycode> Keyboard::keyToSDLKey =
 	{ KEY_KBDILLUMDOWN, SDLK_KBDILLUMDOWN },
 	{ KEY_KBDILLUMUP, SDLK_KBDILLUMUP },
 	{ KEY_EJECT, SDLK_EJECT },
+#endif
 	{ KEY_SLEEP, SDLK_SLEEP },
 };
 
 std::map<SDL_Keycode, Keyboard::Key> Keyboard::sdlKeyToKey;
 
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+EnumMap<Keyboard::Scancode, SDL_Scancode, SDL_SCANCODE_COUNT>::Entry Keyboard::scancodeEntries[] =
+#else
 EnumMap<Keyboard::Scancode, SDL_Scancode, SDL_NUM_SCANCODES>::Entry Keyboard::scancodeEntries[] =
+#endif
 {
 	{SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN},
 
@@ -624,6 +695,14 @@ EnumMap<Keyboard::Scancode, SDL_Scancode, SDL_NUM_SCANCODES>::Entry Keyboard::sc
 
 	{SCANCODE_MODE, SDL_SCANCODE_MODE},
 
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	{SCANCODE_AUDIONEXT, SDL_SCANCODE_MEDIA_NEXT_TRACK},
+	{SCANCODE_AUDIOPREV, SDL_SCANCODE_MEDIA_PREVIOUS_TRACK},
+	{SCANCODE_AUDIOSTOP, SDL_SCANCODE_MEDIA_STOP},
+	{SCANCODE_AUDIOPLAY, SDL_SCANCODE_MEDIA_PLAY},
+	{SCANCODE_AUDIOMUTE, SDL_SCANCODE_MUTE},
+	{SCANCODE_MEDIASELECT, SDL_SCANCODE_MEDIA_SELECT},
+#else
 	{SCANCODE_AUDIONEXT, SDL_SCANCODE_AUDIONEXT},
 	{SCANCODE_AUDIOPREV, SDL_SCANCODE_AUDIOPREV},
 	{SCANCODE_AUDIOSTOP, SDL_SCANCODE_AUDIOSTOP},
@@ -634,6 +713,7 @@ EnumMap<Keyboard::Scancode, SDL_Scancode, SDL_NUM_SCANCODES>::Entry Keyboard::sc
 	{SCANCODE_MAIL, SDL_SCANCODE_MAIL},
 	{SCANCODE_CALCULATOR, SDL_SCANCODE_CALCULATOR},
 	{SCANCODE_COMPUTER, SDL_SCANCODE_COMPUTER},
+#endif
 	{SCANCODE_AC_SEARCH, SDL_SCANCODE_AC_SEARCH},
 	{SCANCODE_AC_HOME, SDL_SCANCODE_AC_HOME},
 	{SCANCODE_AC_BACK, SDL_SCANCODE_AC_BACK},
@@ -642,6 +722,10 @@ EnumMap<Keyboard::Scancode, SDL_Scancode, SDL_NUM_SCANCODES>::Entry Keyboard::sc
 	{SCANCODE_AC_REFRESH, SDL_SCANCODE_AC_REFRESH},
 	{SCANCODE_AC_BOOKMARKS, SDL_SCANCODE_AC_BOOKMARKS},
 
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	{SCANCODE_EJECT, SDL_SCANCODE_MEDIA_EJECT},
+	{SCANCODE_SLEEP, SDL_SCANCODE_SLEEP},
+#else
 	{SCANCODE_BRIGHTNESSDOWN, SDL_SCANCODE_BRIGHTNESSDOWN},
 	{SCANCODE_BRIGHTNESSUP, SDL_SCANCODE_BRIGHTNESSUP},
 	{SCANCODE_DISPLAYSWITCH, SDL_SCANCODE_DISPLAYSWITCH},
@@ -653,9 +737,14 @@ EnumMap<Keyboard::Scancode, SDL_Scancode, SDL_NUM_SCANCODES>::Entry Keyboard::sc
 
 	{SCANCODE_APP1, SDL_SCANCODE_APP1},
 	{SCANCODE_APP2, SDL_SCANCODE_APP2},
+#endif
 };
 
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+EnumMap<Keyboard::Scancode, SDL_Scancode, SDL_SCANCODE_COUNT> Keyboard::scancodes(Keyboard::scancodeEntries, sizeof(Keyboard::scancodeEntries));
+#else
 EnumMap<Keyboard::Scancode, SDL_Scancode, SDL_NUM_SCANCODES> Keyboard::scancodes(Keyboard::scancodeEntries, sizeof(Keyboard::scancodeEntries));
+#endif
 
 } // sdl
 } // keyboard

+ 6 - 0
src/modules/keyboard/sdl/Keyboard.h

@@ -27,6 +27,7 @@
 
 // SDL
 #include <SDL_keyboard.h>
+#include <SDL_version.h>
 
 #include <map>
 
@@ -72,8 +73,13 @@ private:
 	static std::map<Key, SDL_Keycode> keyToSDLKey;
 	static std::map<SDL_Keycode, Key> sdlKeyToKey;
 
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	static EnumMap<Scancode, SDL_Scancode, SDL_SCANCODE_COUNT>::Entry scancodeEntries[];
+	static EnumMap<Scancode, SDL_Scancode, SDL_SCANCODE_COUNT> scancodes;
+#else
 	static EnumMap<Scancode, SDL_Scancode, SDL_NUM_SCANCODES>::Entry scancodeEntries[];
 	static EnumMap<Scancode, SDL_Scancode, SDL_NUM_SCANCODES> scancodes;
+#endif
 
 }; // Keyboard
 

+ 16 - 1
src/modules/mouse/sdl/Cursor.cpp

@@ -41,7 +41,7 @@ Cursor::Cursor(image::ImageData *data, int hotx, int hoty)
 	int pitch = w * 4;
 
 #if SDL_VERSION_ATLEAST(3, 0, 0)
-	SDL_Surface *surface = SDL_CreateSurfaceFrom(data->getData(), w, h, pitch, SDL_PIXELFORMAT_RGBA8888);
+	SDL_Surface *surface = SDL_CreateSurfaceFrom(w, h, SDL_PIXELFORMAT_RGBA8888, data->getData(), pitch);
 #else
 	Uint32 rmask, gmask, bmask, amask;
 #ifdef LOVE_BIG_ENDIAN
@@ -117,6 +117,20 @@ Cursor::SystemCursor Cursor::getSystemType() const
 
 EnumMap<Cursor::SystemCursor, SDL_SystemCursor, Cursor::CURSOR_MAX_ENUM>::Entry Cursor::systemCursorEntries[] =
 {
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	{Cursor::CURSOR_ARROW, SDL_SYSTEM_CURSOR_DEFAULT},
+	{Cursor::CURSOR_IBEAM, SDL_SYSTEM_CURSOR_TEXT},
+	{Cursor::CURSOR_WAIT, SDL_SYSTEM_CURSOR_WAIT},
+	{Cursor::CURSOR_CROSSHAIR, SDL_SYSTEM_CURSOR_CROSSHAIR},
+	{Cursor::CURSOR_WAITARROW, SDL_SYSTEM_CURSOR_PROGRESS},
+	{Cursor::CURSOR_SIZENWSE, SDL_SYSTEM_CURSOR_NWSE_RESIZE},
+	{Cursor::CURSOR_SIZENESW, SDL_SYSTEM_CURSOR_NW_RESIZE},
+	{Cursor::CURSOR_SIZEWE, SDL_SYSTEM_CURSOR_EW_RESIZE},
+	{Cursor::CURSOR_SIZENS, SDL_SYSTEM_CURSOR_NS_RESIZE},
+	{Cursor::CURSOR_SIZEALL, SDL_SYSTEM_CURSOR_MOVE},
+	{Cursor::CURSOR_NO, SDL_SYSTEM_CURSOR_NOT_ALLOWED},
+	{Cursor::CURSOR_HAND, SDL_SYSTEM_CURSOR_POINTER},
+#else
 	{Cursor::CURSOR_ARROW, SDL_SYSTEM_CURSOR_ARROW},
 	{Cursor::CURSOR_IBEAM, SDL_SYSTEM_CURSOR_IBEAM},
 	{Cursor::CURSOR_WAIT, SDL_SYSTEM_CURSOR_WAIT},
@@ -129,6 +143,7 @@ EnumMap<Cursor::SystemCursor, SDL_SystemCursor, Cursor::CURSOR_MAX_ENUM>::Entry
 	{Cursor::CURSOR_SIZEALL, SDL_SYSTEM_CURSOR_SIZEALL},
 	{Cursor::CURSOR_NO, SDL_SYSTEM_CURSOR_NO},
 	{Cursor::CURSOR_HAND, SDL_SYSTEM_CURSOR_HAND},
+#endif
 };
 
 EnumMap<Cursor::SystemCursor, SDL_SystemCursor, Cursor::CURSOR_MAX_ENUM> Cursor::systemCursors(Cursor::systemCursorEntries, sizeof(Cursor::systemCursorEntries));

+ 28 - 0
src/modules/mouse/sdl/Mouse.cpp

@@ -33,6 +33,16 @@ namespace mouse
 namespace sdl
 {
 
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+static SDL_Window *getSDLWindow()
+{
+	auto window = Module::getInstance<window::Window>(Module::M_WINDOW);
+	if (window)
+		return (SDL_Window *) window->getHandle();
+	return nullptr;
+}
+#endif
+
 // SDL reports mouse coordinates in the window coordinate system in OS X, but
 // we want them in pixel coordinates (may be different with high-DPI enabled.)
 static void windowToDPICoords(double *x, double *y)
@@ -248,7 +258,11 @@ bool Mouse::isDown(const std::vector<int> &buttons) const
 			break;
 		}
 
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+		if (buttonstate & SDL_BUTTON_MASK(button))
+#else
 		if (buttonstate & SDL_BUTTON(button))
+#endif
 			return true;
 	}
 
@@ -282,12 +296,26 @@ bool Mouse::isGrabbed() const
 
 bool Mouse::setRelativeMode(bool relative)
 {
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	SDL_Window *sdlwindow = getSDLWindow();
+	if (sdlwindow == nullptr)
+		return false;
+	return SDL_SetWindowRelativeMouseMode(sdlwindow, relative);
+#else
 	return SDL_SetRelativeMouseMode(relative ? SDL_TRUE : SDL_FALSE) == 0;
+#endif
 }
 
 bool Mouse::getRelativeMode() const
 {
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	SDL_Window *sdlwindow = getSDLWindow();
+	if (sdlwindow == nullptr)
+		return false;
+	return SDL_GetWindowRelativeMouseMode(sdlwindow);
+#else
 	return SDL_GetRelativeMouseMode() != SDL_FALSE;
+#endif
 }
 
 } // sdl

+ 7 - 3
src/modules/sensor/sdl/Sensor.cpp

@@ -36,7 +36,11 @@ Sensor::Sensor()
 	: love::sensor::Sensor("love.sensor.sdl")
 	, sensors()
 {
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	if (!SDL_InitSubSystem(SDL_INIT_SENSOR))
+#else
 	if (SDL_InitSubSystem(SDL_INIT_SENSOR) < 0)
+#endif
 		throw love::Exception("Could not initialize SDL sensor subsystem (%s)", SDL_GetError());
 }
 
@@ -52,7 +56,7 @@ bool Sensor::hasSensor(SensorType type)
 	SDL_SensorID *sensorIDs = SDL_GetSensors(&count);
 	for (int i = 0; i < count; i++)
 	{
-		if (convert(SDL_GetSensorInstanceType(sensorIDs[i])) == type)
+		if (convert(SDL_GetSensorTypeForID(sensorIDs[i])) == type)
 		{
 			SDL_free(sensorIDs);
 			return true;
@@ -93,7 +97,7 @@ void Sensor::setEnabled(SensorType type, bool enable)
 		SDL_SensorID *sensorIDs = SDL_GetSensors(&count);
 		for (int i = 0; i < count; i++)
 		{
-			if (convert(SDL_GetSensorInstanceType(sensorIDs[i])) == type)
+			if (convert(SDL_GetSensorTypeForID(sensorIDs[i])) == type)
 			{
 				SDL_Sensor *sensorHandle = SDL_OpenSensor(sensorIDs[i]);
 
@@ -144,7 +148,7 @@ std::vector<float> Sensor::getData(SensorType type)
 	std::vector<float> values(3);
 
 #if SDL_VERSION_ATLEAST(3, 0, 0)
-	if (SDL_GetSensorData(sensors[type], values.data(), (int) values.size()) != 0)
+	if (!SDL_GetSensorData(sensors[type], values.data(), (int) values.size()))
 #else
 	if (SDL_SensorGetData(sensors[type], values.data(), (int) values.size()) != 0)
 #endif

+ 17 - 1
src/modules/system/sdl/System.cpp

@@ -45,7 +45,11 @@ System::System()
 
 int System::getProcessorCount() const
 {
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	return SDL_GetNumLogicalCPUCores();
+#else
 	return SDL_GetCPUCount();
+#endif
 }
 
 bool System::isWindowOpen() const
@@ -95,7 +99,19 @@ std::vector<std::string> System::getPreferredLocales() const
 {
 	std::vector<std::string> result;
 
-#if SDL_VERSION_ATLEAST(2, 0, 14)
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	int count = 0;
+	SDL_Locale **locales = SDL_GetPreferredLocales(&count);
+	for (int i = 0; i < count; i++)
+	{
+		SDL_Locale *locale = locales[i];
+		if (locale->country)
+			result.push_back(std::string(locale->language) + "_" + std::string(locale->country));
+		else
+			result.push_back(locale->language);
+	}
+	SDL_free(locales);
+#elif SDL_VERSION_ATLEAST(2, 0, 14)
 	SDL_Locale *locales = SDL_GetPreferredLocales();
 
 	if (locales)

+ 5 - 2
src/modules/thread/sdl/threads.cpp

@@ -92,9 +92,12 @@ bool Conditional::wait(thread::Mutex *_mutex, int timeout)
 	Mutex *mutex = (Mutex *) _mutex;
 #if SDL_VERSION_ATLEAST(3, 0, 0)
 	if (timeout < 0)
-		return !SDL_WaitCondition(cond, mutex->mutex);
+	{
+		SDL_WaitCondition(cond, mutex->mutex);
+		return true;
+	}
 	else
-		return (SDL_WaitConditionTimeout(cond, mutex->mutex, timeout) == 0);
+		return SDL_WaitConditionTimeout(cond, mutex->mutex, timeout);
 #else
 	if (timeout < 0)
 		return !SDL_CondWait(cond, mutex->mutex);

+ 2 - 1
src/modules/thread/sdl/threads.h

@@ -24,8 +24,9 @@
 #include "common/config.h"
 #include "thread/threads.h"
 
-#include <SDL_thread.h>
 #include <SDL_version.h>
+#include <SDL_thread.h>
+#include <SDL_mutex.h>
 
 namespace love
 {

+ 51 - 21
src/modules/window/sdl/Window.cpp

@@ -101,7 +101,11 @@ Window::Window()
 	, displayedWindowError(false)
 	, contextAttribs()
 {
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	if (!SDL_InitSubSystem(SDL_INIT_VIDEO))
+#else
 	if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
+#endif
 		throw love::Exception("Could not initialize SDL video subsystem (%s)", SDL_GetError());
 
 	// Make sure the screensaver doesn't activate by default.
@@ -317,7 +321,11 @@ bool Window::createWindowAndContext(int x, int y, int w, int h, Uint32 windowfla
 	{
 		if (glcontext)
 		{
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+			SDL_GL_DestroyContext(glcontext);
+#else
 			SDL_GL_DeleteContext(glcontext);
+#endif
 			glcontext = nullptr;
 		}
 
@@ -370,7 +378,11 @@ bool Window::createWindowAndContext(int x, int y, int w, int h, Uint32 windowfla
 			// Make sure the context's version is at least what we requested.
 			if (glcontext && !checkGLVersion(*attribs, glversion))
 			{
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+				SDL_GL_DestroyContext(glcontext);
+#else
 				SDL_GL_DeleteContext(glcontext);
+#endif
 				glcontext = nullptr;
 			}
 
@@ -580,7 +592,7 @@ bool Window::setWindow(int width, int height, WindowSettings *settings)
 
 	Uint32 sdlflags = 0;
 #if SDL_VERSION_ATLEAST(3, 0, 0)
-	const SDL_DisplayMode *fsmode = nullptr;
+	SDL_DisplayMode fsmode = {};
 #else
 	SDL_DisplayMode fsmode = {0, width, height, 0, nullptr};
 #endif
@@ -593,17 +605,17 @@ bool Window::setWindow(int width, int height, WindowSettings *settings)
 		if (f.fstype == FULLSCREEN_EXCLUSIVE)
 		{
 			SDL_DisplayID display = displays.ids[f.displayindex];
-			fsmode = SDL_GetClosestFullscreenDisplayMode(display, width, height, 0, isHighDPIAllowed());
-			if (fsmode == nullptr)
+			if (!SDL_GetClosestFullscreenDisplayMode(display, width, height, 0, isHighDPIAllowed(), &fsmode))
 			{
 				// GetClosestDisplayMode will fail if we request a size larger
 				// than the largest available display mode, so we'll try to use
 				// the largest (first) mode in that case.
 				int modecount = 0;
-				const SDL_DisplayMode **modes = SDL_GetFullscreenDisplayModes(display, &modecount);
-				fsmode = modecount > 0 ? modes[0] : nullptr;
+				SDL_DisplayMode **modes = SDL_GetFullscreenDisplayModes(display, &modecount);
+				if (modecount > 0)
+					fsmode = *modes[0];
 				SDL_free(modes);
-				if (fsmode == nullptr)
+				if (fsmode.w == 0 || fsmode.h == 0)
 					return false;
 			}
 		}
@@ -639,8 +651,11 @@ bool Window::setWindow(int width, int height, WindowSettings *settings)
 	if (isOpen())
 	{
 #if SDL_VERSION_ATLEAST(3, 0, 0)
-		SDL_SetWindowFullscreenMode(window, fsmode);
-		if (SDL_SetWindowFullscreen(window, (sdlflags & SDL_WINDOW_FULLSCREEN) != 0) == 0 && renderer == graphics::RENDERER_OPENGL)
+		if (fsmode.w > 0 && fsmode.h > 0)
+			SDL_SetWindowFullscreenMode(window, &fsmode);
+		else
+			SDL_SetWindowFullscreenMode(window, nullptr);
+		if (SDL_SetWindowFullscreen(window, (sdlflags & SDL_WINDOW_FULLSCREEN) != 0) && renderer == graphics::RENDERER_OPENGL)
 #else
 		if (f.fullscreen && f.fstype == FULLSCREEN_EXCLUSIVE)
 			SDL_SetWindowDisplayMode(window, &fsmode);
@@ -651,10 +666,10 @@ bool Window::setWindow(int width, int height, WindowSettings *settings)
 		SDL_SetWindowSize(window, width, height);
 
 		if (this->settings.resizable != f.resizable)
-			SDL_SetWindowResizable(window, f.resizable ? SDL_TRUE : SDL_FALSE);
+			SDL_SetWindowResizable(window, f.resizable);
 
 		if (this->settings.borderless != f.borderless)
-			SDL_SetWindowBordered(window, f.borderless ? SDL_FALSE : SDL_TRUE);
+			SDL_SetWindowBordered(window, f.borderless);
 	}
 	else
 	{
@@ -691,8 +706,11 @@ bool Window::setWindow(int width, int height, WindowSettings *settings)
 
 		if (f.fullscreen)
 		{
-			SDL_SetWindowFullscreenMode(window, fsmode);
-			SDL_SetWindowFullscreen(window, SDL_TRUE);
+			if (fsmode.w > 0 && fsmode.h > 0)
+				SDL_SetWindowFullscreenMode(window, &fsmode);
+			else
+				SDL_SetWindowFullscreenMode(window, nullptr);
+			SDL_SetWindowFullscreen(window, true);
 		}
 #else
 		if (!createWindowAndContext(x, y, width, height, sdlflags, renderer))
@@ -774,7 +792,7 @@ bool Window::onSizeChanged(int width, int height)
 #endif
 
 #if SDL_VERSION_ATLEAST(3, 0, 0)
-	if (SDL_GetWindowSizeInPixels(window, &pixelWidth, &pixelHeight) < 0)
+	if (SDL_GetWindowSizeInPixels(window, &pixelWidth, &pixelHeight))
 #else
 	// TODO: Use SDL_GetWindowSizeInPixels here when supported.
 	if (glcontext != nullptr)
@@ -938,7 +956,11 @@ void Window::close(bool allowExceptions)
 
 	if (glcontext)
 	{
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+		SDL_GL_DestroyContext(glcontext);
+#else
 		SDL_GL_DeleteContext(glcontext);
+#endif
 		glcontext = nullptr;
 	}
 
@@ -980,7 +1002,7 @@ bool Window::setFullscreen(bool fullscreen, FullscreenType fstype)
 	newsettings.fstype = fstype;
 
 #if SDL_VERSION_ATLEAST(3, 0, 0)
-	SDL_bool sdlflags = fullscreen;
+	bool sdlflags = fullscreen;
 	if (fullscreen)
 	{
 		if (fstype == FULLSCREEN_DESKTOP)
@@ -988,9 +1010,9 @@ bool Window::setFullscreen(bool fullscreen, FullscreenType fstype)
 		else
 		{
 			SDL_DisplayID displayid = SDL_GetDisplayForWindow(window);
-			const SDL_DisplayMode *mode = SDL_GetClosestFullscreenDisplayMode(displayid, windowWidth, windowHeight, 0, isHighDPIAllowed());
-			if (mode != nullptr)
-				SDL_SetWindowFullscreenMode(window, mode);
+			SDL_DisplayMode mode = {};
+			if (SDL_GetClosestFullscreenDisplayMode(displayid, windowWidth, windowHeight, 0, isHighDPIAllowed(), &mode))
+				SDL_SetWindowFullscreenMode(window, &mode);
 		}
 	}
 #else
@@ -1018,7 +1040,11 @@ bool Window::setFullscreen(bool fullscreen, FullscreenType fstype)
 	love::android::setImmersive(fullscreen);
 #endif
 
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	if (SDL_SetWindowFullscreen(window, sdlflags))
+#else
 	if (SDL_SetWindowFullscreen(window, sdlflags) == 0)
+#endif
 	{
 		if (glcontext)
 			SDL_GL_MakeCurrent(window, glcontext);
@@ -1083,7 +1109,7 @@ std::vector<Window::WindowSize> Window::getFullscreenSizes(int displayindex) con
 
 #if SDL_VERSION_ATLEAST(3, 0, 0)
 	int count = 0;
-	const SDL_DisplayMode **modes = SDL_GetFullscreenDisplayModes(GetSDLDisplayIDForIndex(displayindex), &count);
+	SDL_DisplayMode **modes = SDL_GetFullscreenDisplayModes(GetSDLDisplayIDForIndex(displayindex), &count);
 
 	for (int i = 0; i < count; i++)
 	{
@@ -1283,7 +1309,7 @@ bool Window::setIcon(love::image::ImageData *imgd)
 	int pitch = w * bytesperpixel;
 
 #if SDL_VERSION_ATLEAST(3, 0, 0)
-	SDL_Surface *sdlicon = SDL_CreateSurfaceFrom(imgd->getData(), w, h, pitch, SDL_PIXELFORMAT_RGBA8888);
+	SDL_Surface *sdlicon = SDL_CreateSurfaceFrom(w, h, SDL_PIXELFORMAT_RGBA8888, imgd->getData(), pitch);
 #else
 	SDL_Surface *sdlicon = SDL_CreateRGBSurfaceFrom(imgd->getData(), w, h, bytesperpixel * 8, pitch, rmask, gmask, bmask, amask);
 #endif
@@ -1392,7 +1418,7 @@ void Window::setDisplaySleepEnabled(bool enable)
 bool Window::isDisplaySleepEnabled() const
 {
 #if SDL_VERSION_ATLEAST(3, 0, 0)
-	return SDL_ScreenSaverEnabled() != SDL_FALSE;
+	return SDL_ScreenSaverEnabled();
 #else
 	return SDL_IsScreenSaverEnabled() != SDL_FALSE;
 #endif
@@ -1535,7 +1561,7 @@ void Window::setMouseGrab(bool grab)
 	mouseGrabbed = grab;
 	if (window)
 #if SDL_VERSION_ATLEAST(3, 0, 0)
-		SDL_SetWindowMouseGrab(window, (SDL_bool) grab);
+		SDL_SetWindowMouseGrab(window, grab);
 #else
 		SDL_SetWindowGrab(window, (SDL_bool) grab);
 #endif
@@ -1694,7 +1720,11 @@ bool Window::showMessageBox(const std::string &title, const std::string &message
 	SDL_MessageBoxFlags flags = convertMessageBoxType(type);
 	SDL_Window *sdlwindow = attachtowindow ? window : nullptr;
 
+#if SDL_VERSION_ATLEAST(3, 0, 0)
+	return SDL_ShowSimpleMessageBox(flags, title.c_str(), message.c_str(), sdlwindow);
+#else
 	return SDL_ShowSimpleMessageBox(flags, title.c_str(), message.c_str(), sdlwindow) >= 0;
+#endif
 }
 
 int Window::showMessageBox(const MessageBoxData &data)