summaryrefslogtreecommitdiff
path: root/src/contrib/SDL-3.2.20/docs/README-migration.md
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2025-08-30 16:53:58 -0700
committer3gg <3gg@shellblade.net>2025-08-30 16:53:58 -0700
commit6aaedb813fa11ba0679c3051bc2eb28646b9506c (patch)
tree34acbfc9840e02cb4753e6306ea7ce978bf8b58e /src/contrib/SDL-3.2.20/docs/README-migration.md
parent8f228ade99dd3d4c8da9b78ade1815c9adf85c8f (diff)
Update to SDL3
Diffstat (limited to 'src/contrib/SDL-3.2.20/docs/README-migration.md')
-rw-r--r--src/contrib/SDL-3.2.20/docs/README-migration.md2295
1 files changed, 2295 insertions, 0 deletions
diff --git a/src/contrib/SDL-3.2.20/docs/README-migration.md b/src/contrib/SDL-3.2.20/docs/README-migration.md
new file mode 100644
index 0000000..deca6d0
--- /dev/null
+++ b/src/contrib/SDL-3.2.20/docs/README-migration.md
@@ -0,0 +1,2295 @@
1# Migrating to SDL 3.0
2
3This guide provides useful information for migrating applications from SDL 2.0 to SDL 3.0.
4
5Details on API changes are organized by SDL 2.0 header below.
6
7The file with your main() function should include <SDL3/SDL_main.h>, as that is no longer included in SDL.h.
8
9Functions that previously returned a negative error code now return bool.
10
11Code that used to look like this:
12```c
13 if (SDL_Function() < 0 || SDL_Function() == -1) {
14 /* Failure... */
15 }
16```
17or
18```c
19 if (SDL_Function() == 0) {
20 /* Success... */
21 }
22```
23or
24```c
25 if (!SDL_Function()) {
26 /* Success... */
27 }
28```
29should be changed to:
30```c
31 if (SDL_Function()) {
32 /* Success... */
33 } else {
34 /* Failure... */
35 }
36```
37This only applies to camel case functions, e.g. `SDL_[A-Z]*`. Lower case functions like SDL_strcmp() and SDL_memcmp() are unchanged, matching their C runtime counterpart.
38
39Many functions and symbols have been renamed. We have provided a handy Python script [rename_symbols.py](https://github.com/libsdl-org/SDL/blob/main/build-scripts/rename_symbols.py) to rename SDL2 functions to their SDL3 counterparts:
40```sh
41rename_symbols.py --all-symbols source_code_path
42```
43
44It's also possible to apply a semantic patch to migrate more easily to SDL3: [SDL_migration.cocci](https://github.com/libsdl-org/SDL/blob/main/build-scripts/SDL_migration.cocci)
45
46SDL headers should now be included as `#include <SDL3/SDL.h>`. Typically that's the only SDL header you'll need in your application unless you are using OpenGL or Vulkan functionality. SDL_image, SDL_mixer, SDL_net, SDL_ttf and SDL_rtf have also their preferred include path changed: for SDL_image, it becomes `#include <SDL3_image/SDL_image.h>`. We have provided a handy Python script [rename_headers.py](https://github.com/libsdl-org/SDL/blob/main/build-scripts/rename_headers.py) to rename SDL2 headers to their SDL3 counterparts:
47```sh
48rename_headers.py source_code_path
49```
50
51Some macros are renamed and/or removed in SDL3. We have provided a handy Python script [rename_macros.py](https://github.com/libsdl-org/SDL/blob/main/build-scripts/rename_macros.py) to replace these, and also add fixme comments on how to further improve the code:
52```sh
53rename_macros.py source_code_path
54```
55
56
57CMake users should use this snippet to include SDL support in their project:
58```cmake
59find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3)
60target_link_libraries(mygame PRIVATE SDL3::SDL3)
61```
62
63Autotools users should use this snippet to include SDL support in their project:
64```m4
65PKG_CHECK_MODULES([SDL3], [sdl3])
66```
67and then add `$SDL3_CFLAGS` to their project `CFLAGS` and `$SDL3_LIBS` to their project `LDFLAGS`.
68
69Makefile users can use this snippet to include SDL support in their project:
70```make
71CFLAGS += $(shell pkg-config sdl3 --cflags)
72LDFLAGS += $(shell pkg-config sdl3 --libs)
73```
74
75The SDL3test library has been renamed SDL3_test.
76
77The SDLmain library has been removed, it's been entirely replaced by SDL_main.h.
78
79The vi format comments have been removed from source code. Vim users can use the [editorconfig plugin](https://github.com/editorconfig/editorconfig-vim) to automatically set tab spacing for the SDL coding style.
80
81Installed SDL CMake configuration files no longer define `SDL3_PREFIX`, `SDL3_EXEC_PREFIX`, `SDL3_INCLUDE_DIR`, `SDL3_INCLUDE_DIRS`, `SDL3_BINDIR` or `SDL3_LIBDIR`. Users are expected to use [CMake generator expressions](https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#target-dependent-expressions) with `SDL3::SDL3`, `SDL3::SDL3-shared`, `SDL3::SDL3-static` or `SDL3::Headers`. By no longer defining these CMake variables, using a system SDL3 or using a vendoring SDL3 behave in the same way.
82
83## SDL_atomic.h
84
85The following structures have been renamed:
86- SDL_atomic_t => SDL_AtomicInt
87
88The following functions have been renamed:
89* SDL_AtomicAdd() => SDL_AddAtomicInt()
90* SDL_AtomicCAS() => SDL_CompareAndSwapAtomicInt()
91* SDL_AtomicCASPtr() => SDL_CompareAndSwapAtomicPointer()
92* SDL_AtomicGet() => SDL_GetAtomicInt()
93* SDL_AtomicGetPtr() => SDL_GetAtomicPointer()
94* SDL_AtomicLock() => SDL_LockSpinlock()
95* SDL_AtomicSet() => SDL_SetAtomicInt()
96* SDL_AtomicSetPtr() => SDL_SetAtomicPointer()
97* SDL_AtomicTryLock() => SDL_TryLockSpinlock()
98* SDL_AtomicUnlock() => SDL_UnlockSpinlock()
99
100## SDL_audio.h
101
102The audio subsystem in SDL3 is dramatically different than SDL2. The primary way to play audio is no longer an audio callback; instead you bind SDL_AudioStreams to devices; however, there is still a callback method available if needed.
103
104The SDL 1.2 audio compatibility API has also been removed, as it was a simplified version of the audio callback interface.
105
106SDL3 will not implicitly initialize the audio subsystem on your behalf if you open a device without doing so. Please explicitly call SDL_Init(SDL_INIT_AUDIO) at some point.
107
108SDL2 referred to audio devices that record sound as "capture" devices, and ones that play sound to speakers as "output" devices. In SDL3, we've changed this terminology to be "recording" devices and "playback" devices, which we hope is more clear.
109
110SDL3's audio subsystem offers an enormous amount of power over SDL2, but if you just want a simple migration of your existing code, you can ignore most of it. The simplest migration path from SDL2 looks something like this:
111
112In SDL2, you might have done something like this to play audio...
113
114```c
115 void SDLCALL MyAudioCallback(void *userdata, Uint8 * stream, int len)
116 {
117 /* Calculate a little more audio here, maybe using `userdata`, write it to `stream` */
118 }
119
120 /* ...somewhere near startup... */
121 SDL_AudioSpec my_desired_audio_format;
122 SDL_zero(my_desired_audio_format);
123 my_desired_audio_format.format = AUDIO_S16;
124 my_desired_audio_format.channels = 2;
125 my_desired_audio_format.freq = 44100;
126 my_desired_audio_format.samples = 1024;
127 my_desired_audio_format.callback = MyAudioCallback;
128 my_desired_audio_format.userdata = &my_audio_callback_user_data;
129 SDL_AudioDeviceID my_audio_device = SDL_OpenAudioDevice(NULL, 0, &my_desired_audio_format, NULL, 0);
130 SDL_PauseAudioDevice(my_audio_device, 0);
131```
132
133...in SDL3, you can do this...
134
135```c
136 void SDLCALL MyNewAudioCallback(void *userdata, SDL_AudioStream *stream, int additional_amount, int total_amount)
137 {
138 /* Calculate a little more audio here, maybe using `userdata`, write it to `stream`
139 *
140 * If you want to use the original callback, you could do something like this:
141 */
142 if (additional_amount > 0) {
143 Uint8 *data = SDL_stack_alloc(Uint8, additional_amount);
144 if (data) {
145 MyAudioCallback(userdata, data, additional_amount);
146 SDL_PutAudioStreamData(stream, data, additional_amount);
147 SDL_stack_free(data);
148 }
149 }
150 }
151
152 /* ...somewhere near startup... */
153 const SDL_AudioSpec spec = { SDL_AUDIO_S16, 2, 44100 };
154 SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, MyNewAudioCallback, &my_audio_callback_user_data);
155 SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream));
156```
157
158If you used SDL_QueueAudio instead of a callback in SDL2, this is also straightforward.
159
160```c
161 /* ...somewhere near startup... */
162 const SDL_AudioSpec spec = { SDL_AUDIO_S16, 2, 44100 };
163 SDL_AudioStream *stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, NULL, NULL);
164 SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(stream));
165
166 /* ...in your main loop... */
167 /* calculate a little more audio into `buf`, add it to `stream` */
168 SDL_PutAudioStreamData(stream, buf, buflen);
169
170```
171
172...these same migration examples apply to audio recording, just using SDL_GetAudioStreamData instead of SDL_PutAudioStreamData.
173
174SDL_AudioInit() and SDL_AudioQuit() have been removed. Instead you can call SDL_InitSubSystem() and SDL_QuitSubSystem() with SDL_INIT_AUDIO, which will properly refcount the subsystems. You can choose a specific audio driver using SDL_AUDIO_DRIVER hint.
175
176The `SDL_AUDIO_ALLOW_*` symbols have been removed; now one may request the format they desire from the audio device, but ultimately SDL_AudioStream will manage the difference. One can use SDL_GetAudioDeviceFormat() to see what the final format is, if any "allowed" changes should be accomodated by the app.
177
178SDL_AudioDeviceID now represents both an open audio device's handle (a "logical" device) and the instance ID that the hardware owns as long as it exists on the system (a "physical" device). The separation between device instances and device indexes is gone, and logical and physical devices are almost entirely interchangeable at the API level.
179
180Devices are opened by physical device instance ID, and a new logical instance ID is generated by the open operation; This allows any device to be opened multiple times, possibly by unrelated pieces of code. SDL will manage the logical devices to provide a single stream of audio to the physical device behind the scenes.
181
182Devices are not opened by an arbitrary string name anymore, but by device instance ID (or magic numbers to request a reasonable default, like a NULL string would do in SDL2). In SDL2, the string was used to open both a standard list of system devices, but also allowed for arbitrary devices, such as hostnames of network sound servers. In SDL3, many of the backends that supported arbitrary device names are obsolete and have been removed; of those that remain, arbitrary devices will be opened with a default device ID and an SDL_hint, so specific end-users can set an environment variable to fit their needs and apps don't have to concern themselves with it.
183
184Many functions that would accept a device index and an `iscapture` parameter now just take an SDL_AudioDeviceID, as they are unique across all devices, instead of separate indices into playback and recording device lists.
185
186Rather than iterating over audio devices using a device index, there are new functions, SDL_GetAudioPlaybackDevices() and SDL_GetAudioRecordingDevices(), to get the current list of devices, and new functions to get information about devices from their instance ID:
187
188```c
189{
190 if (SDL_InitSubSystem(SDL_INIT_AUDIO)) {
191 int i, num_devices;
192 SDL_AudioDeviceID *devices = SDL_GetAudioPlaybackDevices(&num_devices);
193 if (devices) {
194 for (i = 0; i < num_devices; ++i) {
195 SDL_AudioDeviceID instance_id = devices[i];
196 SDL_Log("AudioDevice %" SDL_PRIu32 ": %s", instance_id, SDL_GetAudioDeviceName(instance_id));
197 }
198 SDL_free(devices);
199 }
200 SDL_QuitSubSystem(SDL_INIT_AUDIO);
201 }
202}
203```
204
205SDL_LockAudioDevice() and SDL_UnlockAudioDevice() have been removed, since there is no callback in another thread to protect. SDL's audio subsystem and SDL_AudioStream maintain their own locks internally, so audio streams are safe to use from any thread. If the app assigns a callback to a specific stream, it can use the stream's lock through SDL_LockAudioStream() if necessary.
206
207SDL_PauseAudioDevice() no longer takes a second argument; it always pauses the device. To unpause, use SDL_ResumeAudioDevice().
208
209Audio devices, opened by SDL_OpenAudioDevice(), no longer start in a paused state, as they don't begin processing audio until a stream is bound.
210
211SDL_GetAudioDeviceStatus() has been removed; there is now SDL_AudioDevicePaused().
212
213SDL_QueueAudio(), SDL_DequeueAudio, and SDL_ClearQueuedAudio and SDL_GetQueuedAudioSize() have been removed; an SDL_AudioStream bound to a device provides the exact same functionality.
214
215APIs that use channel counts used to use a Uint8 for the channel; now they use int.
216
217SDL_AudioSpec has been reduced; now it only holds format, channel, and sample rate. SDL_GetSilenceValueForFormat() can provide the information from the SDL_AudioSpec's removed `silence` field. SDL3 now manages the removed `samples` field; apps that want more control over device latency and throughput can force a newly-opened device's sample count with the SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES hint, but most apps should not risk messing with the defaults. The other SDL2 SDL_AudioSpec fields aren't relevant anymore.
218
219SDL_GetAudioDeviceSpec() is removed; use SDL_GetAudioDeviceFormat() instead.
220
221SDL_GetDefaultAudioInfo() is removed; SDL_GetAudioDeviceFormat() with SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK or SDL_AUDIO_DEVICE_DEFAULT_RECORDING. There is no replacement for querying the default device name; the string is no longer used to open devices, and SDL3 will migrate between physical devices on the fly if the system default changes, so if you must show this to the user, a generic name like "System default" is recommended.
222
223SDL_MixAudioFormat() and SDL_MIX_MAXVOLUME have been removed in favour of SDL_MixAudio(), which now takes the audio format, and a float volume between 0.0 and 1.0.
224
225SDL_FreeWAV has been removed and calls can be replaced with SDL_free.
226
227SDL_LoadWAV() is a proper function now and no longer a macro (but offers the same functionality otherwise).
228
229SDL_LoadWAV_IO() and SDL_LoadWAV() return an bool now, like most of SDL. They no longer return a pointer to an SDL_AudioSpec.
230
231SDL_AudioCVT interface has been removed, the SDL_AudioStream interface (for audio supplied in pieces) or the new SDL_ConvertAudioSamples() function (for converting a complete audio buffer in one call) can be used instead.
232
233Code that used to look like this:
234```c
235 SDL_AudioCVT cvt;
236 SDL_BuildAudioCVT(&cvt, src_format, src_channels, src_rate, dst_format, dst_channels, dst_rate);
237 cvt.len = src_len;
238 cvt.buf = (Uint8 *) SDL_malloc(src_len * cvt.len_mult);
239 SDL_memcpy(cvt.buf, src_data, src_len);
240 SDL_ConvertAudio(&cvt);
241 do_something(cvt.buf, cvt.len_cvt);
242```
243should be changed to:
244```c
245 Uint8 *dst_data = NULL;
246 int dst_len = 0;
247 const SDL_AudioSpec src_spec = { src_format, src_channels, src_rate };
248 const SDL_AudioSpec dst_spec = { dst_format, dst_channels, dst_rate };
249 if (!SDL_ConvertAudioSamples(&src_spec, src_data, src_len, &dst_spec, &dst_data, &dst_len)) {
250 /* error */
251 }
252 do_something(dst_data, dst_len);
253 SDL_free(dst_data);
254```
255
256AUDIO_U16, AUDIO_U16LSB, AUDIO_U16MSB, and AUDIO_U16SYS have been removed. They were not heavily used, and one could not memset a buffer in this format to silence with a single byte value. Use a different audio format.
257
258If you need to convert U16 audio data to a still-supported format at runtime, the fastest, lossless conversion is to SDL_AUDIO_S16:
259
260```c
261 /* this converts the buffer in-place. The buffer size does not change. */
262 Sint16 *audio_ui16_to_si16(Uint16 *buffer, const size_t num_samples)
263 {
264 size_t i;
265 const Uint16 *src = buffer;
266 Sint16 *dst = (Sint16 *) buffer;
267
268 for (i = 0; i < num_samples; i++) {
269 dst[i] = (Sint16) (src[i] ^ 0x8000);
270 }
271
272 return dst;
273 }
274```
275
276All remaining `AUDIO_*` symbols have been renamed to `SDL_AUDIO_*` for API consistency, but othewise are identical in value and usage.
277
278In SDL2, SDL_AudioStream would convert/resample audio data during input (via SDL_AudioStreamPut). In SDL3, it does this work when requesting audio (via SDL_GetAudioStreamData, which would have been SDL_AudioStreamGet in SDL2). The way you use an AudioStream is roughly the same, just be aware that the workload moved to a different phase.
279
280In SDL2, SDL_AudioStreamAvailable() returns 0 if passed a NULL stream. In SDL3, the equivalent SDL_GetAudioStreamAvailable() call returns -1 and sets an error string, which matches other audiostream APIs' behavior.
281
282In SDL2, SDL_AUDIODEVICEREMOVED events would fire for open devices with the `which` field set to the SDL_AudioDeviceID of the lost device, and in later SDL2 releases, would also fire this event with a `which` field of zero for unopened devices, to signify that the app might want to refresh the available device list. In SDL3, this event works the same, except it won't ever fire with a zero; in this case it'll return the physical device's SDL_AudioDeviceID. Any still-open SDL_AudioDeviceIDs generated from this device with SDL_OpenAudioDevice() will also fire a separate event.
283
284The following functions have been renamed:
285* SDL_AudioStreamAvailable() => SDL_GetAudioStreamAvailable()
286* SDL_AudioStreamClear() => SDL_ClearAudioStream(), returns bool
287* SDL_AudioStreamFlush() => SDL_FlushAudioStream(), returns bool
288* SDL_AudioStreamGet() => SDL_GetAudioStreamData()
289* SDL_AudioStreamPut() => SDL_PutAudioStreamData(), returns bool
290* SDL_FreeAudioStream() => SDL_DestroyAudioStream()
291* SDL_LoadWAV_RW() => SDL_LoadWAV_IO(), returns bool
292* SDL_MixAudioFormat() => SDL_MixAudio(), returns bool
293* SDL_NewAudioStream() => SDL_CreateAudioStream()
294
295
296The following functions have been removed:
297* SDL_GetNumAudioDevices()
298* SDL_GetAudioDeviceSpec()
299* SDL_ConvertAudio()
300* SDL_BuildAudioCVT()
301* SDL_OpenAudio()
302* SDL_CloseAudio()
303* SDL_PauseAudio()
304* SDL_GetAudioStatus()
305* SDL_GetAudioDeviceStatus()
306* SDL_GetDefaultAudioInfo()
307* SDL_LockAudio()
308* SDL_LockAudioDevice()
309* SDL_UnlockAudio()
310* SDL_UnlockAudioDevice()
311* SDL_MixAudio()
312* SDL_QueueAudio()
313* SDL_DequeueAudio()
314* SDL_ClearAudioQueue()
315* SDL_GetQueuedAudioSize()
316
317The following symbols have been renamed:
318* AUDIO_F32 => SDL_AUDIO_F32LE
319* AUDIO_F32LSB => SDL_AUDIO_F32LE
320* AUDIO_F32MSB => SDL_AUDIO_F32BE
321* AUDIO_F32SYS => SDL_AUDIO_F32
322* AUDIO_S16 => SDL_AUDIO_S16LE
323* AUDIO_S16LSB => SDL_AUDIO_S16LE
324* AUDIO_S16MSB => SDL_AUDIO_S16BE
325* AUDIO_S16SYS => SDL_AUDIO_S16
326* AUDIO_S32 => SDL_AUDIO_S32LE
327* AUDIO_S32LSB => SDL_AUDIO_S32LE
328* AUDIO_S32MSB => SDL_AUDIO_S32BE
329* AUDIO_S32SYS => SDL_AUDIO_S32
330* AUDIO_S8 => SDL_AUDIO_S8
331* AUDIO_U8 => SDL_AUDIO_U8
332
333The following symbols have been removed:
334* SDL_MIX_MAXVOLUME - mixer volume is now a float between 0.0 and 1.0
335
336## SDL_cpuinfo.h
337
338The intrinsics headers (mmintrin.h, etc.) have been moved to `<SDL3/SDL_intrin.h>` and are no longer automatically included in SDL.h.
339
340SDL_Has3DNow() has been removed; there is no replacement.
341
342SDL_HasRDTSC() has been removed; there is no replacement. Don't use the RDTSC opcode in modern times, use SDL_GetPerformanceCounter and SDL_GetPerformanceFrequency instead.
343
344SDL_SIMDAlloc(), SDL_SIMDRealloc(), and SDL_SIMDFree() have been removed. You can use SDL_aligned_alloc() and SDL_aligned_free() with SDL_GetSIMDAlignment() to get the same functionality.
345
346The following functions have been renamed:
347* SDL_GetCPUCount() => SDL_GetNumLogicalCPUCores()
348* SDL_SIMDGetAlignment() => SDL_GetSIMDAlignment()
349
350## SDL_endian.h
351
352The following functions have been renamed:
353* SDL_SwapBE16() => SDL_Swap16BE()
354* SDL_SwapBE32() => SDL_Swap32BE()
355* SDL_SwapBE64() => SDL_Swap64BE()
356* SDL_SwapLE16() => SDL_Swap16LE()
357* SDL_SwapLE32() => SDL_Swap32LE()
358* SDL_SwapLE64() => SDL_Swap64LE()
359
360## SDL_error.h
361
362The following functions have been removed:
363* SDL_GetErrorMsg() - Can be implemented as `SDL_strlcpy(errstr, SDL_GetError(), maxlen);`
364
365## SDL_events.h
366
367SDL_PRESSED and SDL_RELEASED have been removed. For the most part you can replace uses of these with true and false respectively. Events which had a field `state` to represent these values have had those fields changed to bool `down`, e.g. `event.key.state` is now `event.key.down`.
368
369The timestamp member of the SDL_Event structure now represents nanoseconds, and is populated with SDL_GetTicksNS()
370
371The timestamp_us member of the sensor events has been renamed sensor_timestamp and now represents nanoseconds. This value is filled in from the hardware, if available, and may not be synchronized with values returned from SDL_GetTicksNS().
372
373You should set the event.common.timestamp field before passing an event to SDL_PushEvent(). If the timestamp is 0 it will be filled in with SDL_GetTicksNS().
374
375Event memory is now managed by SDL, so you should not free the data in SDL_EVENT_DROP_FILE, and if you want to hold onto the text in SDL_EVENT_TEXT_EDITING and SDL_EVENT_TEXT_INPUT events, you should make a copy of it. SDL_TEXTINPUTEVENT_TEXT_SIZE is no longer necessary and has been removed.
376
377Mouse events use floating point values for mouse coordinates and relative motion values. You can get sub-pixel motion depending on the platform and display scaling.
378
379The SDL_DISPLAYEVENT_* events have been moved to top level events, and SDL_DISPLAYEVENT has been removed. In general, handling this change just means checking for the individual events instead of first checking for SDL_DISPLAYEVENT and then checking for display events. You can compare the event >= SDL_EVENT_DISPLAY_FIRST and <= SDL_EVENT_DISPLAY_LAST if you need to see whether it's a display event.
380
381The SDL_WINDOWEVENT_* events have been moved to top level events, and SDL_WINDOWEVENT has been removed. In general, handling this change just means checking for the individual events instead of first checking for SDL_WINDOWEVENT and then checking for window events. You can compare the event >= SDL_EVENT_WINDOW_FIRST and <= SDL_EVENT_WINDOW_LAST if you need to see whether it's a window event.
382
383The SDL_EVENT_WINDOW_RESIZED event is always sent, even in response to SDL_SetWindowSize().
384
385The SDL_EVENT_WINDOW_SIZE_CHANGED event has been removed, and you can use SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED to detect window backbuffer size changes.
386
387The keysym field of key events has been removed to remove one level of indirection, and `sym` has been renamed `key`.
388
389Code that used to look like this:
390```c
391 SDL_Event event;
392 SDL_Keycode key = event.key.keysym.sym;
393 SDL_Keymod mod = event.key.keysym.mod;
394```
395should be changed to:
396```c
397 SDL_Event event;
398 SDL_Keycode key = event.key.key;
399 SDL_Keymod mod = event.key.mod;
400```
401
402The gamepad event structures caxis, cbutton, cdevice, ctouchpad, and csensor have been renamed gaxis, gbutton, gdevice, gtouchpad, and gsensor.
403
404The mouseX and mouseY fields of SDL_MouseWheelEvent have been renamed mouse_x and mouse_y.
405
406The touchId and fingerId fields of SDL_TouchFingerEvent have been renamed touchID and fingerID.
407
408The level field of SDL_JoyBatteryEvent has been split into state and percent.
409
410The iscapture field of SDL_AudioDeviceEvent has been renamed recording.
411
412SDL_QUERY, SDL_IGNORE, SDL_ENABLE, and SDL_DISABLE have been removed. You can use the functions SDL_SetEventEnabled() and SDL_EventEnabled() to set and query event processing state.
413
414SDL_AddEventWatch() now returns false if it fails because it ran out of memory and couldn't add the event watch callback.
415
416SDL_RegisterEvents() now returns 0 if it couldn't allocate any user events.
417
418SDL_EventFilter functions now return bool.
419
420The following symbols have been renamed:
421* SDL_APP_DIDENTERBACKGROUND => SDL_EVENT_DID_ENTER_BACKGROUND
422* SDL_APP_DIDENTERFOREGROUND => SDL_EVENT_DID_ENTER_FOREGROUND
423* SDL_APP_LOWMEMORY => SDL_EVENT_LOW_MEMORY
424* SDL_APP_TERMINATING => SDL_EVENT_TERMINATING
425* SDL_APP_WILLENTERBACKGROUND => SDL_EVENT_WILL_ENTER_BACKGROUND
426* SDL_APP_WILLENTERFOREGROUND => SDL_EVENT_WILL_ENTER_FOREGROUND
427* SDL_AUDIODEVICEADDED => SDL_EVENT_AUDIO_DEVICE_ADDED
428* SDL_AUDIODEVICEREMOVED => SDL_EVENT_AUDIO_DEVICE_REMOVED
429* SDL_CLIPBOARDUPDATE => SDL_EVENT_CLIPBOARD_UPDATE
430* SDL_CONTROLLERAXISMOTION => SDL_EVENT_GAMEPAD_AXIS_MOTION
431* SDL_CONTROLLERBUTTONDOWN => SDL_EVENT_GAMEPAD_BUTTON_DOWN
432* SDL_CONTROLLERBUTTONUP => SDL_EVENT_GAMEPAD_BUTTON_UP
433* SDL_CONTROLLERDEVICEADDED => SDL_EVENT_GAMEPAD_ADDED
434* SDL_CONTROLLERDEVICEREMAPPED => SDL_EVENT_GAMEPAD_REMAPPED
435* SDL_CONTROLLERDEVICEREMOVED => SDL_EVENT_GAMEPAD_REMOVED
436* SDL_CONTROLLERSENSORUPDATE => SDL_EVENT_GAMEPAD_SENSOR_UPDATE
437* SDL_CONTROLLERSTEAMHANDLEUPDATED => SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED
438* SDL_CONTROLLERTOUCHPADDOWN => SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN
439* SDL_CONTROLLERTOUCHPADMOTION => SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION
440* SDL_CONTROLLERTOUCHPADUP => SDL_EVENT_GAMEPAD_TOUCHPAD_UP
441* SDL_DROPBEGIN => SDL_EVENT_DROP_BEGIN
442* SDL_DROPCOMPLETE => SDL_EVENT_DROP_COMPLETE
443* SDL_DROPFILE => SDL_EVENT_DROP_FILE
444* SDL_DROPTEXT => SDL_EVENT_DROP_TEXT
445* SDL_FINGERDOWN => SDL_EVENT_FINGER_DOWN
446* SDL_FINGERMOTION => SDL_EVENT_FINGER_MOTION
447* SDL_FINGERUP => SDL_EVENT_FINGER_UP
448* SDL_FIRSTEVENT => SDL_EVENT_FIRST
449* SDL_JOYAXISMOTION => SDL_EVENT_JOYSTICK_AXIS_MOTION
450* SDL_JOYBALLMOTION => SDL_EVENT_JOYSTICK_BALL_MOTION
451* SDL_JOYBATTERYUPDATED => SDL_EVENT_JOYSTICK_BATTERY_UPDATED
452* SDL_JOYBUTTONDOWN => SDL_EVENT_JOYSTICK_BUTTON_DOWN
453* SDL_JOYBUTTONUP => SDL_EVENT_JOYSTICK_BUTTON_UP
454* SDL_JOYDEVICEADDED => SDL_EVENT_JOYSTICK_ADDED
455* SDL_JOYDEVICEREMOVED => SDL_EVENT_JOYSTICK_REMOVED
456* SDL_JOYHATMOTION => SDL_EVENT_JOYSTICK_HAT_MOTION
457* SDL_KEYDOWN => SDL_EVENT_KEY_DOWN
458* SDL_KEYMAPCHANGED => SDL_EVENT_KEYMAP_CHANGED
459* SDL_KEYUP => SDL_EVENT_KEY_UP
460* SDL_LASTEVENT => SDL_EVENT_LAST
461* SDL_LOCALECHANGED => SDL_EVENT_LOCALE_CHANGED
462* SDL_MOUSEBUTTONDOWN => SDL_EVENT_MOUSE_BUTTON_DOWN
463* SDL_MOUSEBUTTONUP => SDL_EVENT_MOUSE_BUTTON_UP
464* SDL_MOUSEMOTION => SDL_EVENT_MOUSE_MOTION
465* SDL_MOUSEWHEEL => SDL_EVENT_MOUSE_WHEEL
466* SDL_POLLSENTINEL => SDL_EVENT_POLL_SENTINEL
467* SDL_QUIT => SDL_EVENT_QUIT
468* SDL_RENDER_DEVICE_RESET => SDL_EVENT_RENDER_DEVICE_RESET
469* SDL_RENDER_TARGETS_RESET => SDL_EVENT_RENDER_TARGETS_RESET
470* SDL_SENSORUPDATE => SDL_EVENT_SENSOR_UPDATE
471* SDL_TEXTEDITING => SDL_EVENT_TEXT_EDITING
472* SDL_TEXTEDITING_EXT => SDL_EVENT_TEXT_EDITING_EXT
473* SDL_TEXTINPUT => SDL_EVENT_TEXT_INPUT
474* SDL_USEREVENT => SDL_EVENT_USER
475
476The following symbols have been removed:
477* SDL_DROPEVENT_DATA_SIZE - drop event data is dynamically allocated
478* SDL_SYSWMEVENT - you can use SDL_SetWindowsMessageHook() and SDL_SetX11EventHook() to watch and modify system events before SDL sees them.
479* SDL_TEXTEDITINGEVENT_TEXT_SIZE - text editing event data is dynamically allocated
480
481The following structures have been renamed:
482* SDL_ControllerAxisEvent => SDL_GamepadAxisEvent
483* SDL_ControllerButtonEvent => SDL_GamepadButtonEvent
484* SDL_ControllerDeviceEvent => SDL_GamepadDeviceEvent
485* SDL_ControllerSensorEvent => SDL_GamepadSensorEvent
486* SDL_ControllerTouchpadEvent => SDL_GamepadTouchpadEvent
487
488The following functions have been removed:
489* SDL_EventState() - replaced with SDL_SetEventEnabled()
490* SDL_GetEventState() - replaced with SDL_EventEnabled()
491
492The following enums have been renamed:
493* SDL_eventaction => SDL_EventAction
494
495The following functions have been renamed:
496* SDL_DelEventWatch() => SDL_RemoveEventWatch()
497
498## SDL_gamecontroller.h
499
500SDL_gamecontroller.h has been renamed SDL_gamepad.h, and all APIs have been renamed to match.
501
502The SDL_EVENT_GAMEPAD_ADDED event now provides the joystick instance ID in the which member of the cdevice event structure.
503
504The functions SDL_GetGamepads(), SDL_GetGamepadNameForID(), SDL_GetGamepadPathForID(), SDL_GetGamepadPlayerIndexForID(), SDL_GetGamepadGUIDForID(), SDL_GetGamepadVendorForID(), SDL_GetGamepadProductForID(), SDL_GetGamepadProductVersionForID(), and SDL_GetGamepadTypeForID() have been added to directly query the list of available gamepads.
505
506The gamepad face buttons have been renamed from A/B/X/Y to North/South/East/West to indicate that they are positional rather than hardware-specific. You can use SDL_GetGamepadButtonLabel() to get the labels for the face buttons, e.g. A/B/X/Y or Cross/Circle/Square/Triangle. The hint SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS is ignored, and mappings that use this hint are translated correctly into positional buttons. Applications should provide a way for users to swap between South/East as their accept/cancel buttons, as this varies based on region and muscle memory. You can use an approach similar to the following to handle this:
507
508```c
509#define CONFIRM_BUTTON SDL_GAMEPAD_BUTTON_SOUTH
510#define CANCEL_BUTTON SDL_GAMEPAD_BUTTON_EAST
511
512bool flipped_buttons;
513
514void InitMappedButtons(SDL_Gamepad *gamepad)
515{
516 if (!GetFlippedButtonSetting(&flipped_buttons)) {
517 if (SDL_GetGamepadButtonLabel(gamepad, SDL_GAMEPAD_BUTTON_SOUTH) == SDL_GAMEPAD_BUTTON_LABEL_B) {
518 flipped_buttons = true;
519 } else {
520 flipped_buttons = false;
521 }
522 }
523}
524
525SDL_GamepadButton GetMappedButton(SDL_GamepadButton button)
526{
527 if (flipped_buttons) {
528 switch (button) {
529 case SDL_GAMEPAD_BUTTON_SOUTH:
530 return SDL_GAMEPAD_BUTTON_EAST;
531 case SDL_GAMEPAD_BUTTON_EAST:
532 return SDL_GAMEPAD_BUTTON_SOUTH;
533 case SDL_GAMEPAD_BUTTON_WEST:
534 return SDL_GAMEPAD_BUTTON_NORTH;
535 case SDL_GAMEPAD_BUTTON_NORTH:
536 return SDL_GAMEPAD_BUTTON_WEST;
537 default:
538 break;
539 }
540 }
541 return button;
542}
543
544SDL_GamepadButtonLabel GetConfirmActionLabel(SDL_Gamepad *gamepad)
545{
546 return SDL_GetGamepadButtonLabel(gamepad, GetMappedButton(CONFIRM_BUTTON));
547}
548
549SDL_GamepadButtonLabel GetCancelActionLabel(SDL_Gamepad *gamepad)
550{
551 return SDL_GetGamepadButtonLabel(gamepad, GetMappedButton(CANCEL_BUTTON));
552}
553
554void HandleGamepadEvent(SDL_Event *event)
555{
556 if (event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN) {
557 switch (GetMappedButton(event->gbutton.button)) {
558 case CONFIRM_BUTTON:
559 /* Handle confirm action */
560 break;
561 case CANCEL_BUTTON:
562 /* Handle cancel action */
563 break;
564 default:
565 /* ... */
566 break;
567 }
568 }
569}
570```
571
572SDL_GameControllerGetSensorDataWithTimestamp() has been removed. If you want timestamps for the sensor data, you should use the sensor_timestamp member of SDL_EVENT_GAMEPAD_SENSOR_UPDATE events.
573
574SDL_CONTROLLER_TYPE_VIRTUAL has been removed, so virtual controllers can emulate other gamepad types. If you need to know whether a controller is virtual, you can use SDL_IsJoystickVirtual().
575
576SDL_CONTROLLER_TYPE_AMAZON_LUNA has been removed, and can be replaced with this code:
577```c
578bool SDL_IsJoystickAmazonLunaController(Uint16 vendor_id, Uint16 product_id)
579{
580 return ((vendor_id == 0x1949 && product_id == 0x0419) ||
581 (vendor_id == 0x0171 && product_id == 0x0419));
582}
583```
584
585SDL_CONTROLLER_TYPE_GOOGLE_STADIA has been removed, and can be replaced with this code:
586```c
587bool SDL_IsJoystickGoogleStadiaController(Uint16 vendor_id, Uint16 product_id)
588{
589 return (vendor_id == 0x18d1 && product_id == 0x9400);
590}
591```
592
593SDL_CONTROLLER_TYPE_NVIDIA_SHIELD has been removed, and can be replaced with this code:
594```c
595bool SDL_IsJoystickNVIDIASHIELDController(Uint16 vendor_id, Uint16 product_id)
596{
597 return (vendor_id == 0x0955 && (product_id == 0x7210 || product_id == 0x7214));
598}
599```
600
601The inputType and outputType fields of SDL_GamepadBinding have been renamed input_type and output_type.
602
603SDL_GetGamepadTouchpadFinger() takes a pointer to bool for the finger state instead of a pointer to Uint8.
604
605The following enums have been renamed:
606* SDL_GameControllerAxis => SDL_GamepadAxis
607* SDL_GameControllerBindType => SDL_GamepadBindingType
608* SDL_GameControllerButton => SDL_GamepadButton
609* SDL_GameControllerType => SDL_GamepadType
610
611The following structures have been renamed:
612* SDL_GameController => SDL_Gamepad
613
614The following functions have been renamed:
615* SDL_GameControllerAddMapping() => SDL_AddGamepadMapping()
616* SDL_GameControllerAddMappingsFromFile() => SDL_AddGamepadMappingsFromFile()
617* SDL_GameControllerAddMappingsFromRW() => SDL_AddGamepadMappingsFromIO()
618* SDL_GameControllerClose() => SDL_CloseGamepad()
619* SDL_GameControllerFromInstanceID() => SDL_GetGamepadFromID()
620* SDL_GameControllerFromPlayerIndex() => SDL_GetGamepadFromPlayerIndex()
621* SDL_GameControllerGetAppleSFSymbolsNameForAxis() => SDL_GetGamepadAppleSFSymbolsNameForAxis()
622* SDL_GameControllerGetAppleSFSymbolsNameForButton() => SDL_GetGamepadAppleSFSymbolsNameForButton()
623* SDL_GameControllerGetAttached() => SDL_GamepadConnected()
624* SDL_GameControllerGetAxis() => SDL_GetGamepadAxis()
625* SDL_GameControllerGetAxisFromString() => SDL_GetGamepadAxisFromString()
626* SDL_GameControllerGetButton() => SDL_GetGamepadButton()
627* SDL_GameControllerGetButtonFromString() => SDL_GetGamepadButtonFromString()
628* SDL_GameControllerGetFirmwareVersion() => SDL_GetGamepadFirmwareVersion()
629* SDL_GameControllerGetJoystick() => SDL_GetGamepadJoystick()
630* SDL_GameControllerGetNumTouchpadFingers() => SDL_GetNumGamepadTouchpadFingers()
631* SDL_GameControllerGetNumTouchpads() => SDL_GetNumGamepadTouchpads()
632* SDL_GameControllerGetPlayerIndex() => SDL_GetGamepadPlayerIndex()
633* SDL_GameControllerGetProduct() => SDL_GetGamepadProduct()
634* SDL_GameControllerGetProductVersion() => SDL_GetGamepadProductVersion()
635* SDL_GameControllerGetSensorData() => SDL_GetGamepadSensorData(), returns bool
636* SDL_GameControllerGetSensorDataRate() => SDL_GetGamepadSensorDataRate()
637* SDL_GameControllerGetSerial() => SDL_GetGamepadSerial()
638* SDL_GameControllerGetSteamHandle() => SDL_GetGamepadSteamHandle()
639* SDL_GameControllerGetStringForAxis() => SDL_GetGamepadStringForAxis()
640* SDL_GameControllerGetStringForButton() => SDL_GetGamepadStringForButton()
641* SDL_GameControllerGetTouchpadFinger() => SDL_GetGamepadTouchpadFinger(), returns bool
642* SDL_GameControllerGetType() => SDL_GetGamepadType()
643* SDL_GameControllerGetVendor() => SDL_GetGamepadVendor()
644* SDL_GameControllerHasAxis() => SDL_GamepadHasAxis()
645* SDL_GameControllerHasButton() => SDL_GamepadHasButton()
646* SDL_GameControllerHasSensor() => SDL_GamepadHasSensor()
647* SDL_GameControllerIsSensorEnabled() => SDL_GamepadSensorEnabled()
648* SDL_GameControllerMapping() => SDL_GetGamepadMapping()
649* SDL_GameControllerMappingForGUID() => SDL_GetGamepadMappingForGUID()
650* SDL_GameControllerName() => SDL_GetGamepadName()
651* SDL_GameControllerOpen() => SDL_OpenGamepad()
652* SDL_GameControllerPath() => SDL_GetGamepadPath()
653* SDL_GameControllerRumble() => SDL_RumbleGamepad(), returns bool
654* SDL_GameControllerRumbleTriggers() => SDL_RumbleGamepadTriggers(), returns bool
655* SDL_GameControllerSendEffect() => SDL_SendGamepadEffect(), returns bool
656* SDL_GameControllerSetLED() => SDL_SetGamepadLED(), returns bool
657* SDL_GameControllerSetPlayerIndex() => SDL_SetGamepadPlayerIndex(), returns bool
658* SDL_GameControllerSetSensorEnabled() => SDL_SetGamepadSensorEnabled(), returns bool
659* SDL_GameControllerUpdate() => SDL_UpdateGamepads()
660* SDL_IsGameController() => SDL_IsGamepad()
661
662The following functions have been removed:
663* SDL_GameControllerEventState() - replaced with SDL_SetGamepadEventsEnabled() and SDL_GamepadEventsEnabled()
664* SDL_GameControllerGetBindForAxis() - replaced with SDL_GetGamepadBindings()
665* SDL_GameControllerGetBindForButton() - replaced with SDL_GetGamepadBindings()
666* SDL_GameControllerHasLED() - replaced with SDL_PROP_GAMEPAD_CAP_RGB_LED_BOOLEAN
667* SDL_GameControllerHasRumble() - replaced with SDL_PROP_GAMEPAD_CAP_RUMBLE_BOOLEAN
668* SDL_GameControllerHasRumbleTriggers() - replaced with SDL_PROP_GAMEPAD_CAP_TRIGGER_RUMBLE_BOOLEAN
669* SDL_GameControllerMappingForDeviceIndex() - replaced with SDL_GetGamepadMappingForID()
670* SDL_GameControllerMappingForIndex() - replaced with SDL_GetGamepadMappings()
671* SDL_GameControllerNameForIndex() - replaced with SDL_GetGamepadNameForID()
672* SDL_GameControllerNumMappings() - replaced with SDL_GetGamepadMappings()
673* SDL_GameControllerPathForIndex() - replaced with SDL_GetGamepadPathForID()
674* SDL_GameControllerTypeForIndex() - replaced with SDL_GetGamepadTypeForID()
675
676The following symbols have been renamed:
677* SDL_CONTROLLER_AXIS_INVALID => SDL_GAMEPAD_AXIS_INVALID
678* SDL_CONTROLLER_AXIS_LEFTX => SDL_GAMEPAD_AXIS_LEFTX
679* SDL_CONTROLLER_AXIS_LEFTY => SDL_GAMEPAD_AXIS_LEFTY
680* SDL_CONTROLLER_AXIS_MAX => SDL_GAMEPAD_AXIS_COUNT
681* SDL_CONTROLLER_AXIS_RIGHTX => SDL_GAMEPAD_AXIS_RIGHTX
682* SDL_CONTROLLER_AXIS_RIGHTY => SDL_GAMEPAD_AXIS_RIGHTY
683* SDL_CONTROLLER_AXIS_TRIGGERLEFT => SDL_GAMEPAD_AXIS_LEFT_TRIGGER
684* SDL_CONTROLLER_AXIS_TRIGGERRIGHT => SDL_GAMEPAD_AXIS_RIGHT_TRIGGER
685* SDL_CONTROLLER_BINDTYPE_AXIS => SDL_GAMEPAD_BINDTYPE_AXIS
686* SDL_CONTROLLER_BINDTYPE_BUTTON => SDL_GAMEPAD_BINDTYPE_BUTTON
687* SDL_CONTROLLER_BINDTYPE_HAT => SDL_GAMEPAD_BINDTYPE_HAT
688* SDL_CONTROLLER_BINDTYPE_NONE => SDL_GAMEPAD_BINDTYPE_NONE
689* SDL_CONTROLLER_BUTTON_A => SDL_GAMEPAD_BUTTON_SOUTH
690* SDL_CONTROLLER_BUTTON_B => SDL_GAMEPAD_BUTTON_EAST
691* SDL_CONTROLLER_BUTTON_BACK => SDL_GAMEPAD_BUTTON_BACK
692* SDL_CONTROLLER_BUTTON_DPAD_DOWN => SDL_GAMEPAD_BUTTON_DPAD_DOWN
693* SDL_CONTROLLER_BUTTON_DPAD_LEFT => SDL_GAMEPAD_BUTTON_DPAD_LEFT
694* SDL_CONTROLLER_BUTTON_DPAD_RIGHT => SDL_GAMEPAD_BUTTON_DPAD_RIGHT
695* SDL_CONTROLLER_BUTTON_DPAD_UP => SDL_GAMEPAD_BUTTON_DPAD_UP
696* SDL_CONTROLLER_BUTTON_GUIDE => SDL_GAMEPAD_BUTTON_GUIDE
697* SDL_CONTROLLER_BUTTON_INVALID => SDL_GAMEPAD_BUTTON_INVALID
698* SDL_CONTROLLER_BUTTON_LEFTSHOULDER => SDL_GAMEPAD_BUTTON_LEFT_SHOULDER
699* SDL_CONTROLLER_BUTTON_LEFTSTICK => SDL_GAMEPAD_BUTTON_LEFT_STICK
700* SDL_CONTROLLER_BUTTON_MAX => SDL_GAMEPAD_BUTTON_COUNT
701* SDL_CONTROLLER_BUTTON_MISC1 => SDL_GAMEPAD_BUTTON_MISC1
702* SDL_CONTROLLER_BUTTON_PADDLE1 => SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1
703* SDL_CONTROLLER_BUTTON_PADDLE2 => SDL_GAMEPAD_BUTTON_LEFT_PADDLE1
704* SDL_CONTROLLER_BUTTON_PADDLE3 => SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2
705* SDL_CONTROLLER_BUTTON_PADDLE4 => SDL_GAMEPAD_BUTTON_LEFT_PADDLE2
706* SDL_CONTROLLER_BUTTON_RIGHTSHOULDER => SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER
707* SDL_CONTROLLER_BUTTON_RIGHTSTICK => SDL_GAMEPAD_BUTTON_RIGHT_STICK
708* SDL_CONTROLLER_BUTTON_START => SDL_GAMEPAD_BUTTON_START
709* SDL_CONTROLLER_BUTTON_TOUCHPAD => SDL_GAMEPAD_BUTTON_TOUCHPAD
710* SDL_CONTROLLER_BUTTON_X => SDL_GAMEPAD_BUTTON_WEST
711* SDL_CONTROLLER_BUTTON_Y => SDL_GAMEPAD_BUTTON_NORTH
712* SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT => SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT
713* SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR => SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR
714* SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT => SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT
715* SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO => SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO
716* SDL_CONTROLLER_TYPE_PS3 => SDL_GAMEPAD_TYPE_PS3
717* SDL_CONTROLLER_TYPE_PS4 => SDL_GAMEPAD_TYPE_PS4
718* SDL_CONTROLLER_TYPE_PS5 => SDL_GAMEPAD_TYPE_PS5
719* SDL_CONTROLLER_TYPE_UNKNOWN => SDL_GAMEPAD_TYPE_STANDARD
720* SDL_CONTROLLER_TYPE_VIRTUAL => SDL_GAMEPAD_TYPE_VIRTUAL
721* SDL_CONTROLLER_TYPE_XBOX360 => SDL_GAMEPAD_TYPE_XBOX360
722* SDL_CONTROLLER_TYPE_XBOXONE => SDL_GAMEPAD_TYPE_XBOXONE
723
724## SDL_gesture.h
725
726The gesture API has been removed. There is no replacement planned in SDL3.
727However, the SDL2 code has been moved to a single-header library that can
728be dropped into an SDL3 or SDL2 program, to continue to provide this
729functionality to your app and aid migration. That is located in the
730[SDL_gesture GitHub repository](https://github.com/libsdl-org/SDL_gesture).
731
732## SDL_guid.h
733
734SDL_GUIDToString() returns a const pointer to the string representation of a GUID.
735
736The following functions have been renamed:
737* SDL_GUIDFromString() => SDL_StringToGUID()
738
739## SDL_haptic.h
740
741Gamepads with simple rumble capability no longer show up in the SDL haptics interface, instead you should use SDL_RumbleGamepad().
742
743Rather than iterating over haptic devices using device index, there is a new function SDL_GetHaptics() to get the current list of haptic devices, and new functions to get information about haptic devices from their instance ID:
744```c
745{
746 if (SDL_InitSubSystem(SDL_INIT_HAPTIC)) {
747 int i, num_haptics;
748 SDL_HapticID *haptics = SDL_GetHaptics(&num_haptics);
749 if (haptics) {
750 for (i = 0; i < num_haptics; ++i) {
751 SDL_HapticID instance_id = haptics[i];
752 SDL_Log("Haptic %" SDL_PRIu32 ": %s", instance_id, SDL_GetHapticNameForID(instance_id));
753 }
754 SDL_free(haptics);
755 }
756 SDL_QuitSubSystem(SDL_INIT_HAPTIC);
757 }
758}
759```
760
761SDL_GetHapticEffectStatus() now returns bool instead of an int result. You should call SDL_GetHapticFeatures() to make sure effect status is supported before calling this function.
762
763The following functions have been renamed:
764* SDL_HapticClose() => SDL_CloseHaptic()
765* SDL_HapticDestroyEffect() => SDL_DestroyHapticEffect()
766* SDL_HapticGetEffectStatus() => SDL_GetHapticEffectStatus(), returns bool
767* SDL_HapticNewEffect() => SDL_CreateHapticEffect()
768* SDL_HapticNumAxes() => SDL_GetNumHapticAxes()
769* SDL_HapticNumEffects() => SDL_GetMaxHapticEffects()
770* SDL_HapticNumEffectsPlaying() => SDL_GetMaxHapticEffectsPlaying()
771* SDL_HapticOpen() => SDL_OpenHaptic()
772* SDL_HapticOpenFromJoystick() => SDL_OpenHapticFromJoystick()
773* SDL_HapticOpenFromMouse() => SDL_OpenHapticFromMouse()
774* SDL_HapticPause() => SDL_PauseHaptic(), returns bool
775* SDL_HapticQuery() => SDL_GetHapticFeatures()
776* SDL_HapticRumbleInit() => SDL_InitHapticRumble(), returns bool
777* SDL_HapticRumblePlay() => SDL_PlayHapticRumble(), returns bool
778* SDL_HapticRumbleStop() => SDL_StopHapticRumble(), returns bool
779* SDL_HapticRunEffect() => SDL_RunHapticEffect(), returns bool
780* SDL_HapticSetAutocenter() => SDL_SetHapticAutocenter(), returns bool
781* SDL_HapticSetGain() => SDL_SetHapticGain(), returns bool
782* SDL_HapticStopAll() => SDL_StopHapticEffects(), returns bool
783* SDL_HapticStopEffect() => SDL_StopHapticEffect(), returns bool
784* SDL_HapticUnpause() => SDL_ResumeHaptic(), returns bool
785* SDL_HapticUpdateEffect() => SDL_UpdateHapticEffect(), returns bool
786* SDL_JoystickIsHaptic() => SDL_IsJoystickHaptic()
787* SDL_MouseIsHaptic() => SDL_IsMouseHaptic()
788
789The following functions have been removed:
790* SDL_HapticIndex() - replaced with SDL_GetHapticID()
791* SDL_HapticName() - replaced with SDL_GetHapticNameForID()
792* SDL_HapticOpened() - replaced with SDL_GetHapticFromID()
793* SDL_NumHaptics() - replaced with SDL_GetHaptics()
794
795## SDL_hints.h
796
797Calling SDL_GetHint() with the name of the hint being changed from within a hint callback will now return the new value rather than the old value. The old value is still passed as a parameter to the hint callback.
798
799The environment variables SDL_VIDEODRIVER and SDL_AUDIODRIVER have been renamed to SDL_VIDEO_DRIVER and SDL_AUDIO_DRIVER, but the old names are still supported as a fallback.
800
801The environment variables SDL_VIDEO_X11_WMCLASS and SDL_VIDEO_WAYLAND_WMCLASS have been removed and replaced by either using the appindentifier param to SDL_SetAppMetadata() or setting SDL_PROP_APP_METADATA_IDENTIFIER_STRING with SDL_SetAppMetadataProperty()
802
803The environment variable AUDIODEV is used exclusively to specify the audio device for the OSS and NetBSD audio drivers. Its use in the ALSA driver has been replaced with the hint SDL_HINT_AUDIO_ALSA_DEFAULT_DEVICE and in the sndio driver with the environment variable AUDIODEVICE.
804
805The following hints have been renamed:
806* SDL_HINT_ALLOW_TOPMOST => SDL_HINT_WINDOW_ALLOW_TOPMOST
807* SDL_HINT_AUDIODRIVER => SDL_HINT_AUDIO_DRIVER
808* SDL_HINT_DIRECTINPUT_ENABLED => SDL_HINT_JOYSTICK_DIRECTINPUT
809* SDL_HINT_GDK_TEXTINPUT_DEFAULT => SDL_HINT_GDK_TEXTINPUT_DEFAULT_TEXT
810* SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE => SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE_RUMBLE_BRAKE
811* SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE => SDL_HINT_JOYSTICK_ENHANCED_REPORTS
812* SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE => SDL_HINT_JOYSTICK_ENHANCED_REPORTS
813* SDL_HINT_LINUX_DIGITAL_HATS => SDL_HINT_JOYSTICK_LINUX_DIGITAL_HATS
814* SDL_HINT_LINUX_HAT_DEADZONES => SDL_HINT_JOYSTICK_LINUX_HAT_DEADZONES
815* SDL_HINT_LINUX_JOYSTICK_CLASSIC => SDL_HINT_JOYSTICK_LINUX_CLASSIC
816* SDL_HINT_LINUX_JOYSTICK_DEADZONES => SDL_HINT_JOYSTICK_LINUX_DEADZONES
817* SDL_HINT_VIDEODRIVER => SDL_HINT_VIDEO_DRIVER
818* SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP => SDL_HINT_MOUSE_EMULATE_WARP_WITH_RELATIVE
819
820The following hints have been removed:
821* SDL_HINT_ACCELEROMETER_AS_JOYSTICK
822* SDL_HINT_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO - the audio will be paused when the application is paused, and SDL_HINT_ANDROID_BLOCK_ON_PAUSE can be used to control that
823* SDL_HINT_AUDIO_DEVICE_APP_NAME - replaced by either using the appname param to SDL_SetAppMetadata() or setting SDL_PROP_APP_METADATA_NAME_STRING with SDL_SetAppMetadataProperty()
824* SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS - gamepad buttons are always positional
825* SDL_HINT_GRAB_KEYBOARD - use SDL_SetWindowKeyboardGrab() instead
826* SDL_HINT_IDLE_TIMER_DISABLED - use SDL_DisableScreenSaver() instead
827* SDL_HINT_IME_INTERNAL_EDITING - replaced with SDL_HINT_IME_IMPLEMENTED_UI
828* SDL_HINT_IME_SHOW_UI - replaced with SDL_HINT_IME_IMPLEMENTED_UI
829* SDL_HINT_IME_SUPPORT_EXTENDED_TEXT - the normal text editing event has extended text
830* SDL_HINT_MOUSE_RELATIVE_MODE_WARP - relative mode is always implemented at the hardware level or reported as unavailable
831* SDL_HINT_MOUSE_RELATIVE_SCALING - mouse coordinates are no longer automatically scaled by the SDL renderer
832* SDL_HINT_PS2_DYNAMIC_VSYNC - use SDL_SetRenderVSync(renderer, -1) instead
833* SDL_HINT_RENDER_BATCHING - Render batching is always enabled, apps should call SDL_FlushRenderer() before calling into a lower-level graphics API.
834* SDL_HINT_RENDER_LOGICAL_SIZE_MODE - the logical size mode is explicitly set with SDL_SetRenderLogicalPresentation()
835* SDL_HINT_RENDER_OPENGL_SHADERS - shaders are always used if they are available
836* SDL_HINT_RENDER_SCALE_QUALITY - textures now default to linear filtering, use SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_NEAREST) if you want nearest pixel mode instead
837* SDL_HINT_THREAD_STACK_SIZE - the stack size can be specified using SDL_CreateThreadWithProperties()
838* SDL_HINT_VIDEO_EXTERNAL_CONTEXT - replaced with SDL_PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN in SDL_CreateWindowWithProperties()
839* SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL - replaced with SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN in SDL_CreateWindowWithProperties()
840* SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN - replaced with SDL_PROP_WINDOW_CREATE_VULKAN_BOOLEAN in SDL_CreateWindowWithProperties()
841* SDL_HINT_VIDEO_HIGHDPI_DISABLED - high DPI support is always enabled
842* SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT - replaced with SDL_PROP_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER in SDL_CreateWindowWithProperties()
843* SDL_HINT_VIDEO_X11_FORCE_EGL - use SDL_HINT_VIDEO_FORCE_EGL instead
844* SDL_HINT_VIDEO_X11_XINERAMA - Xinerama no longer supported by the X11 backend
845* SDL_HINT_VIDEO_X11_XVIDMODE - Xvidmode no longer supported by the X11 backend
846* SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING - SDL now properly handles the 0x406D1388 Exception if no debugger intercepts it, preventing its propagation.
847* SDL_HINT_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS - Slim Reader/Writer Locks are always used if available
848* SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4 - replaced with SDL_HINT_WINDOWS_CLOSE_ON_ALT_F4, defaulting to true
849* SDL_HINT_WINRT_HANDLE_BACK_BUTTON - WinRT support was removed in SDL3.
850* SDL_HINT_WINRT_PRIVACY_POLICY_LABEL - WinRT support was removed in SDL3.
851* SDL_HINT_WINRT_PRIVACY_POLICY_URL - WinRT support was removed in SDL3.
852* SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING
853
854The following environment variables have been renamed:
855* SDL_AUDIODRIVER => SDL_AUDIO_DRIVER
856* SDL_PATH_DSP => AUDIODEV
857* SDL_VIDEODRIVER => SDL_VIDEO_DRIVER
858
859The following environment variables have been removed:
860* SDL_AUDIO_ALSA_DEBUG - replaced by setting the hint SDL_HINT_LOGGING to "audio=debug"
861* SDL_DISKAUDIODELAY - replaced with the hint SDL_HINT_AUDIO_DISK_TIMESCALE which allows scaling the audio time rather than specifying an absolute delay.
862* SDL_DISKAUDIOFILE - replaced with the hint SDL_HINT_AUDIO_DISK_OUTPUT_FILE
863* SDL_DISKAUDIOFILEIN - replaced with the hint SDL_HINT_AUDIO_DISK_INPUT_FILE
864* SDL_DUMMYAUDIODELAY - replaced with the hint SDL_HINT_AUDIO_DUMMY_TIMESCALE which allows scaling the audio time rather than specifying an absolute delay.
865* SDL_HAPTIC_GAIN_MAX
866* SDL_HIDAPI_DISABLE_LIBUSB - replaced with the hint SDL_HINT_HIDAPI_LIBUSB
867* SDL_HIDAPI_JOYSTICK_DISABLE_UDEV - replaced with the hint SDL_HINT_HIDAPI_UDEV
868* SDL_INPUT_FREEBSD_KEEP_KBD - replaced with the hint SDL_HINT_MUTE_CONSOLE_KEYBOARD
869* SDL_INPUT_LINUX_KEEP_KBD - replaced with the hint SDL_HINT_MUTE_CONSOLE_KEYBOARD
870* VITA_DISABLE_TOUCH_BACK - replaced with the hint SDL_HINT_VITA_ENABLE_BACK_TOUCH
871* VITA_DISABLE_TOUCH_FRONT - replaced with the hint SDL_HINT_VITA_ENABLE_FRONT_TOUCH
872* VITA_MODULE_PATH - replaced with the hint SDL_HINT_VITA_MODULE_PATH
873* VITA_PVR_OGL - replaced with the hint SDL_HINT_VITA_PVR_OPENGL
874* VITA_PVR_SKIP_INIT - replaced with the hint SDL_HINT_VITA_PVR_INIT
875* VITA_RESOLUTION - replaced with the hint SDL_HINT_VITA_RESOLUTION
876
877The following functions have been removed:
878* SDL_ClearHints() - replaced with SDL_ResetHints()
879
880The following functions have been renamed:
881* SDL_DelHintCallback() => SDL_RemoveHintCallback()
882
883## SDL_init.h
884
885On Haiku OS, SDL no longer sets the current working directory to the executable's path during SDL_Init(). If you need this functionality, the fastest solution is to add this code directly after the call to SDL_Init:
886
887```c
888{
889 const char *path = SDL_GetBasePath();
890 if (path) {
891 chdir(path);
892 }
893}
894```
895
896The following symbols have been renamed:
897* SDL_INIT_GAMECONTROLLER => SDL_INIT_GAMEPAD
898
899The following symbols have been removed:
900* SDL_INIT_NOPARACHUTE
901* SDL_INIT_EVERYTHING - you should only initialize the subsystems you are using
902* SDL_INIT_TIMER - no longer needed before calling SDL_AddTimer()
903
904## SDL_joystick.h
905
906SDL_JoystickID has changed from Sint32 to Uint32, with an invalid ID being 0.
907
908Rather than iterating over joysticks using device index, there is a new function SDL_GetJoysticks() to get the current list of joysticks, and new functions to get information about joysticks from their instance ID:
909```c
910{
911 if (SDL_InitSubSystem(SDL_INIT_JOYSTICK)) {
912 int i, num_joysticks;
913 SDL_JoystickID *joysticks = SDL_GetJoysticks(&num_joysticks);
914 if (joysticks) {
915 for (i = 0; i < num_joysticks; ++i) {
916 SDL_JoystickID instance_id = joysticks[i];
917 const char *name = SDL_GetJoystickNameForID(instance_id);
918 const char *path = SDL_GetJoystickPathForID(instance_id);
919
920 SDL_Log("Joystick %" SDL_PRIu32 ": %s%s%s VID 0x%.4x, PID 0x%.4x",
921 instance_id, name ? name : "Unknown", path ? ", " : "", path ? path : "", SDL_GetJoystickVendorForID(instance_id), SDL_GetJoystickProductForID(instance_id));
922 }
923 SDL_free(joysticks);
924 }
925 SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
926 }
927}
928```
929
930The SDL_EVENT_JOYSTICK_ADDED event now provides the joystick instance ID in the `which` member of the jdevice event structure.
931
932The functions SDL_GetJoysticks(), SDL_GetJoystickNameForID(), SDL_GetJoystickPathForID(), SDL_GetJoystickPlayerIndexForID(), SDL_GetJoystickGUIDForID(), SDL_GetJoystickVendorForID(), SDL_GetJoystickProductForID(), SDL_GetJoystickProductVersionForID(), and SDL_GetJoystickTypeForID() have been added to directly query the list of available joysticks.
933
934SDL_AttachVirtualJoystick() now returns the joystick instance ID instead of a device index, and returns 0 if there was an error.
935
936SDL_VirtualJoystickDesc version should not be set to SDL_VIRTUAL_JOYSTICK_DESC_VERSION, instead the structure should be initialized using SDL_INIT_INTERFACE().
937
938The following functions have been renamed:
939* SDL_JoystickAttachVirtualEx() => SDL_AttachVirtualJoystick()
940* SDL_JoystickClose() => SDL_CloseJoystick()
941* SDL_JoystickDetachVirtual() => SDL_DetachVirtualJoystick(), returns bool
942* SDL_JoystickFromInstanceID() => SDL_GetJoystickFromID()
943* SDL_JoystickFromPlayerIndex() => SDL_GetJoystickFromPlayerIndex()
944* SDL_JoystickGetAttached() => SDL_JoystickConnected()
945* SDL_JoystickGetAxis() => SDL_GetJoystickAxis()
946* SDL_JoystickGetAxisInitialState() => SDL_GetJoystickAxisInitialState()
947* SDL_JoystickGetBall() => SDL_GetJoystickBall(), returns bool
948* SDL_JoystickGetButton() => SDL_GetJoystickButton()
949* SDL_JoystickGetFirmwareVersion() => SDL_GetJoystickFirmwareVersion()
950* SDL_JoystickGetGUID() => SDL_GetJoystickGUID()
951* SDL_JoystickGetGUIDFromString() => SDL_StringToGUID()
952* SDL_JoystickGetHat() => SDL_GetJoystickHat()
953* SDL_JoystickGetPlayerIndex() => SDL_GetJoystickPlayerIndex()
954* SDL_JoystickGetProduct() => SDL_GetJoystickProduct()
955* SDL_JoystickGetProductVersion() => SDL_GetJoystickProductVersion()
956* SDL_JoystickGetSerial() => SDL_GetJoystickSerial()
957* SDL_JoystickGetType() => SDL_GetJoystickType()
958* SDL_JoystickGetVendor() => SDL_GetJoystickVendor()
959* SDL_JoystickInstanceID() => SDL_GetJoystickID()
960* SDL_JoystickIsVirtual() => SDL_IsJoystickVirtual()
961* SDL_JoystickName() => SDL_GetJoystickName()
962* SDL_JoystickNumAxes() => SDL_GetNumJoystickAxes()
963* SDL_JoystickNumBalls() => SDL_GetNumJoystickBalls()
964* SDL_JoystickNumButtons() => SDL_GetNumJoystickButtons()
965* SDL_JoystickNumHats() => SDL_GetNumJoystickHats()
966* SDL_JoystickOpen() => SDL_OpenJoystick()
967* SDL_JoystickPath() => SDL_GetJoystickPath()
968* SDL_JoystickRumble() => SDL_RumbleJoystick(), returns bool
969* SDL_JoystickRumbleTriggers() => SDL_RumbleJoystickTriggers(), returns bool
970* SDL_JoystickSendEffect() => SDL_SendJoystickEffect(), returns bool
971* SDL_JoystickSetLED() => SDL_SetJoystickLED(), returns bool
972* SDL_JoystickSetPlayerIndex() => SDL_SetJoystickPlayerIndex(), returns bool
973* SDL_JoystickSetVirtualAxis() => SDL_SetJoystickVirtualAxis(), returns bool
974* SDL_JoystickSetVirtualButton() => SDL_SetJoystickVirtualButton(), returns bool
975* SDL_JoystickSetVirtualHat() => SDL_SetJoystickVirtualHat(), returns bool
976* SDL_JoystickUpdate() => SDL_UpdateJoysticks()
977
978The following symbols have been renamed:
979* SDL_JOYSTICK_TYPE_GAMECONTROLLER => SDL_JOYSTICK_TYPE_GAMEPAD
980
981The following functions have been removed:
982* SDL_JoystickAttachVirtual() - replaced with SDL_AttachVirtualJoystick()
983* SDL_JoystickCurrentPowerLevel() - replaced with SDL_GetJoystickConnectionState() and SDL_GetJoystickPowerInfo()
984* SDL_JoystickEventState() - replaced with SDL_SetJoystickEventsEnabled() and SDL_JoystickEventsEnabled()
985* SDL_JoystickGetDeviceGUID() - replaced with SDL_GetJoystickGUIDForID()
986* SDL_JoystickGetDeviceInstanceID()
987* SDL_JoystickGetDevicePlayerIndex() - replaced with SDL_GetJoystickPlayerIndexForID()
988* SDL_JoystickGetDeviceProduct() - replaced with SDL_GetJoystickProductForID()
989* SDL_JoystickGetDeviceProductVersion() - replaced with SDL_GetJoystickProductVersionForID()
990* SDL_JoystickGetDeviceType() - replaced with SDL_GetJoystickTypeForID()
991* SDL_JoystickGetDeviceVendor() - replaced with SDL_GetJoystickVendorForID()
992* SDL_JoystickGetGUIDString() - replaced with SDL_GUIDToString()
993* SDL_JoystickHasLED() - replaced with SDL_PROP_JOYSTICK_CAP_RGB_LED_BOOLEAN
994* SDL_JoystickHasRumble() - replaced with SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN
995* SDL_JoystickHasRumbleTriggers() - replaced with SDL_PROP_JOYSTICK_CAP_TRIGGER_RUMBLE_BOOLEAN
996* SDL_JoystickNameForIndex() - replaced with SDL_GetJoystickNameForID()
997* SDL_JoystickPathForIndex() - replaced with SDL_GetJoystickPathForID()
998* SDL_NumJoysticks() - replaced with SDL_GetJoysticks()
999* SDL_VIRTUAL_JOYSTICK_DESC_VERSION - no longer needed
1000
1001The following symbols have been removed:
1002* SDL_IPHONE_MAX_GFORCE
1003* SDL_JOYBALLMOTION
1004
1005
1006The following structures have been renamed:
1007* SDL_JoystickGUID => SDL_GUID
1008
1009## SDL_keyboard.h
1010
1011Text input is no longer automatically enabled when initializing video, you should call SDL_StartTextInput() when you want to receive text input and call SDL_StopTextInput() when you are done. Starting text input may shown an input method editor (IME) and cause key up/down events to be skipped, so should only be enabled when the application wants text input.
1012
1013The text input state hase been changed to be window-specific. SDL_StartTextInput(), SDL_StopTextInput(), SDL_TextInputActive(), and SDL_ClearComposition() all now take a window parameter.
1014
1015SDL_GetDefaultKeyFromScancode(), SDL_GetKeyFromScancode(), and SDL_GetScancodeFromKey() take an SDL_Keymod parameter and use that to provide the correct result based on keyboard modifier state.
1016
1017SDL_GetKeyboardState() returns a pointer to bool instead of Uint8.
1018
1019The following functions have been renamed:
1020* SDL_IsScreenKeyboardShown() => SDL_ScreenKeyboardShown()
1021* SDL_IsTextInputActive() => SDL_TextInputActive()
1022
1023The following functions have been removed:
1024* SDL_IsTextInputShown()
1025* SDL_SetTextInputRect() - replaced with SDL_SetTextInputArea()
1026
1027The following structures have been removed:
1028* SDL_Keysym
1029
1030## SDL_keycode.h
1031
1032SDL_Keycode is now Uint32 and the SDLK_* constants are now defines instead of an enum, to more clearly reflect that they are a subset of the possible values of an SDL_Keycode.
1033
1034In addition to the `SDLK_SCANCODE_MASK` bit found on key codes that directly map to scancodes, there is now the
1035`SDLK_EXTENDED_MASK` bit used to denote key codes that don't have a corresponding scancode, and aren't a unicode value.
1036
1037The following symbols have been removed:
1038
1039* KMOD_RESERVED - No replacement. A bit named "RESERVED" probably shouldn't be used in an app, but if you need it, this was equivalent to KMOD_SCROLL (0x8000) in SDL2.
1040* SDLK_WWW
1041* SDLK_MAIL
1042* SDLK_CALCULATOR
1043* SDLK_COMPUTER
1044* SDLK_BRIGHTNESSDOWN
1045* SDLK_BRIGHTNESSUP
1046* SDLK_DISPLAYSWITCH
1047* SDLK_KBDILLUMTOGGLE
1048* SDLK_KBDILLUMDOWN
1049* SDLK_KBDILLUMUP
1050* SDLK_APP1
1051* SDLK_APP2
1052
1053
1054The following symbols have been renamed:
1055* KMOD_ALT => SDL_KMOD_ALT
1056* KMOD_CAPS => SDL_KMOD_CAPS
1057* KMOD_CTRL => SDL_KMOD_CTRL
1058* KMOD_GUI => SDL_KMOD_GUI
1059* KMOD_LALT => SDL_KMOD_LALT
1060* KMOD_LCTRL => SDL_KMOD_LCTRL
1061* KMOD_LGUI => SDL_KMOD_LGUI
1062* KMOD_LSHIFT => SDL_KMOD_LSHIFT
1063* KMOD_MODE => SDL_KMOD_MODE
1064* KMOD_NONE => SDL_KMOD_NONE
1065* KMOD_NUM => SDL_KMOD_NUM
1066* KMOD_RALT => SDL_KMOD_RALT
1067* KMOD_RCTRL => SDL_KMOD_RCTRL
1068* KMOD_RGUI => SDL_KMOD_RGUI
1069* KMOD_RSHIFT => SDL_KMOD_RSHIFT
1070* KMOD_SCROLL => SDL_KMOD_SCROLL
1071* KMOD_SHIFT => SDL_KMOD_SHIFT
1072* SDLK_AUDIOFASTFORWARD => SDLK_MEDIA_FAST_FORWARD
1073* SDLK_AUDIOMUTE => SDLK_MUTE
1074* SDLK_AUDIONEXT => SDLK_MEDIA_NEXT_TRACK
1075* SDLK_AUDIOPLAY => SDLK_MEDIA_PLAY
1076* SDLK_AUDIOPREV => SDLK_MEDIA_PREVIOUS_TRACK
1077* SDLK_AUDIOREWIND => SDLK_MEDIA_REWIND
1078* SDLK_AUDIOSTOP => SDLK_MEDIA_STOP
1079* SDLK_BACKQUOTE => SDLK_GRAVE
1080* SDLK_EJECT => SDLK_MEDIA_EJECT
1081* SDLK_MEDIASELECT => SDLK_MEDIA_SELECT
1082* SDLK_QUOTE => SDLK_APOSTROPHE
1083* SDLK_QUOTEDBL => SDLK_DBLAPOSTROPHE
1084* SDLK_a => SDLK_A
1085* SDLK_b => SDLK_B
1086* SDLK_c => SDLK_C
1087* SDLK_d => SDLK_D
1088* SDLK_e => SDLK_E
1089* SDLK_f => SDLK_F
1090* SDLK_g => SDLK_G
1091* SDLK_h => SDLK_H
1092* SDLK_i => SDLK_I
1093* SDLK_j => SDLK_J
1094* SDLK_k => SDLK_K
1095* SDLK_l => SDLK_L
1096* SDLK_m => SDLK_M
1097* SDLK_n => SDLK_N
1098* SDLK_o => SDLK_O
1099* SDLK_p => SDLK_P
1100* SDLK_q => SDLK_Q
1101* SDLK_r => SDLK_R
1102* SDLK_s => SDLK_S
1103* SDLK_t => SDLK_T
1104* SDLK_u => SDLK_U
1105* SDLK_v => SDLK_V
1106* SDLK_w => SDLK_W
1107* SDLK_x => SDLK_X
1108* SDLK_y => SDLK_Y
1109* SDLK_z => SDLK_Z
1110
1111## SDL_loadso.h
1112
1113Shared object handles are now `SDL_SharedObject *`, an opaque type, instead of `void *`. This is just for type-safety and there is no functional difference.
1114
1115SDL_LoadFunction() now returns `SDL_FunctionPointer` instead of `void *`, and should be cast to the appropriate function type. You can define SDL_FUNCTION_POINTER_IS_VOID_POINTER in your project to restore the previous behavior.
1116
1117## SDL_log.h
1118
1119SDL_Log() no longer prints a log prefix by default for SDL_LOG_PRIORITY_INFO and below. The log prefixes can be customized with SDL_SetLogPriorityPrefix().
1120
1121The following macros have been removed:
1122* SDL_MAX_LOG_MESSAGE - there's no message length limit anymore. If you need an artificial limit, this used to be 4096 in SDL versions before 2.0.24.
1123
1124The following functions have been renamed:
1125* SDL_LogGetOutputFunction() => SDL_GetLogOutputFunction()
1126* SDL_LogGetPriority() => SDL_GetLogPriority()
1127* SDL_LogResetPriorities() => SDL_ResetLogPriorities()
1128* SDL_LogSetAllPriority() => SDL_SetLogPriorities()
1129* SDL_LogSetOutputFunction() => SDL_SetLogOutputFunction()
1130* SDL_LogSetPriority() => SDL_SetLogPriority()
1131
1132The following symbols have been renamed:
1133* SDL_NUM_LOG_PRIORITIES => SDL_LOG_PRIORITY_COUNT
1134
1135## SDL_main.h
1136
1137SDL3 doesn't have a static libSDLmain to link against anymore.
1138Instead SDL_main.h is now a header-only library **and not included by SDL.h anymore**.
1139
1140Using it is really simple: Just `#include <SDL3/SDL_main.h>` in the source file with your standard
1141`int main(int argc, char* argv[])` function. See docs/README-main-functions.md for details.
1142
1143Several platform-specific entry point functions have been removed as unnecessary. If for some reason you explicitly need them, here are easy replacements:
1144
1145```c
1146#define SDL_UIKitRunApp(ARGC, ARGV, MAIN_FUNC) SDL_RunApp(ARGC, ARGV, MAIN_FUNC, NULL)
1147#define SDL_GDKRunApp(MAIN_FUNC, RESERVED) SDL_RunApp(0, NULL, MAIN_FUNC, RESERVED)
1148```
1149
1150The following functions have been removed:
1151* SDL_WinRTRunApp() - WinRT support was removed in SDL3.
1152
1153
1154## SDL_messagebox.h
1155
1156The buttonid field of SDL_MessageBoxButtonData has been renamed buttonID.
1157
1158The following symbols have been renamed:
1159* SDL_MESSAGEBOX_COLOR_MAX => SDL_MESSAGEBOX_COLOR_COUNT
1160
1161## SDL_metal.h
1162
1163SDL_Metal_GetDrawableSize() has been removed. SDL_GetWindowSizeInPixels() can be used in its place.
1164
1165## SDL_mouse.h
1166
1167SDL_ShowCursor() has been split into three functions: SDL_ShowCursor(), SDL_HideCursor(), and SDL_CursorVisible()
1168
1169SDL_GetMouseState(), SDL_GetGlobalMouseState(), SDL_GetRelativeMouseState(), SDL_WarpMouseInWindow(), and SDL_WarpMouseGlobal() all use floating point mouse positions, to provide sub-pixel precision on platforms that support it.
1170
1171SDL_SystemCursor's items from SDL2 have been renamed to match CSS cursor names.
1172
1173The following functions have been renamed:
1174* SDL_FreeCursor() => SDL_DestroyCursor()
1175
1176The following functions have been removed:
1177* SDL_SetRelativeMouseMode() - replaced with SDL_SetWindowRelativeMouseMode()
1178* SDL_GetRelativeMouseMode() - replaced with SDL_GetWindowRelativeMouseMode()
1179
1180The following symbols have been renamed:
1181* SDL_BUTTON => SDL_BUTTON_MASK
1182* SDL_NUM_SYSTEM_CURSORS => SDL_SYSTEM_CURSOR_COUNT
1183* SDL_SYSTEM_CURSOR_ARROW => SDL_SYSTEM_CURSOR_DEFAULT
1184* SDL_SYSTEM_CURSOR_HAND => SDL_SYSTEM_CURSOR_POINTER
1185* SDL_SYSTEM_CURSOR_IBEAM => SDL_SYSTEM_CURSOR_TEXT
1186* SDL_SYSTEM_CURSOR_NO => SDL_SYSTEM_CURSOR_NOT_ALLOWED
1187* SDL_SYSTEM_CURSOR_SIZEALL => SDL_SYSTEM_CURSOR_MOVE
1188* SDL_SYSTEM_CURSOR_SIZENESW => SDL_SYSTEM_CURSOR_NESW_RESIZE
1189* SDL_SYSTEM_CURSOR_SIZENS => SDL_SYSTEM_CURSOR_NS_RESIZE
1190* SDL_SYSTEM_CURSOR_SIZENWSE => SDL_SYSTEM_CURSOR_NWSE_RESIZE
1191* SDL_SYSTEM_CURSOR_SIZEWE => SDL_SYSTEM_CURSOR_EW_RESIZE
1192* SDL_SYSTEM_CURSOR_WAITARROW => SDL_SYSTEM_CURSOR_PROGRESS
1193
1194## SDL_mutex.h
1195
1196SDL_MUTEX_MAXWAIT has been removed; it suggested there was a maximum timeout one could outlive, instead of an infinite wait. Instead, pass a -1 to functions that accepted this symbol.
1197
1198SDL_MUTEX_TIMEDOUT has been removed, the wait functions return true if the operation succeeded or false if they timed out.
1199
1200SDL_LockMutex(), SDL_UnlockMutex(), SDL_WaitSemaphore(), SDL_SignalSemaphore(), SDL_WaitCondition(), SDL_SignalCondition(), and SDL_BroadcastCondition() now return void; if the object is valid (including being a NULL pointer, which returns immediately), these functions never fail. If the object is invalid or the caller does something illegal, like unlock another thread's mutex, this is considered undefined behavior.
1201
1202SDL_TryWaitSemaphore(), SDL_WaitSemaphoreTimeout(), and SDL_WaitConditionTimeout() now return true if the operation succeeded or false if they timed out.
1203
1204The following functions have been renamed:
1205* SDL_CondBroadcast() => SDL_BroadcastCondition()
1206* SDL_CondSignal() => SDL_SignalCondition()
1207* SDL_CondWait() => SDL_WaitCondition()
1208* SDL_CondWaitTimeout() => SDL_WaitConditionTimeout(), returns bool
1209* SDL_CreateCond() => SDL_CreateCondition()
1210* SDL_DestroyCond() => SDL_DestroyCondition()
1211* SDL_SemPost() => SDL_SignalSemaphore()
1212* SDL_SemTryWait() => SDL_TryWaitSemaphore(), returns bool
1213* SDL_SemValue() => SDL_GetSemaphoreValue()
1214* SDL_SemWait() => SDL_WaitSemaphore()
1215* SDL_SemWaitTimeout() => SDL_WaitSemaphoreTimeout(), returns bool
1216
1217The following symbols have been renamed:
1218* SDL_cond => SDL_Condition
1219* SDL_mutex => SDL_Mutex
1220* SDL_sem => SDL_Semaphore
1221
1222## SDL_pixels.h
1223
1224SDL_PixelFormat has been renamed SDL_PixelFormatDetails and just describes the pixel format, it does not include a palette for indexed pixel types.
1225
1226SDL_PixelFormatEnum has been renamed SDL_PixelFormat and is used instead of Uint32 for API functions that refer to pixel format by enumerated value.
1227
1228SDL_MapRGB(), SDL_MapRGBA(), SDL_GetRGB(), and SDL_GetRGBA() take an optional palette parameter for indexed color lookups.
1229
1230Code that used to look like this:
1231```c
1232 SDL_GetRGBA(pixel, surface->format, &r, &g, &b, &a);
1233```
1234should be changed to:
1235```c
1236 SDL_GetRGBA(pixel, SDL_GetPixelFormatDetails(surface->format), SDL_GetSurfacePalette(surface), &r, &g, &b, &a);
1237```
1238
1239Code that used to look like this:
1240```c
1241 pixel = SDL_MapRGBA(surface->format, r, g, b, a);
1242```
1243should be changed to:
1244```c
1245 pixel = SDL_MapSurfaceRGBA(surface, r, g, b, a);
1246```
1247
1248SDL_CalculateGammaRamp has been removed, because SDL_SetWindowGammaRamp has been removed as well due to poor support in modern operating systems (see [SDL_video.h](#sdl_videoh)).
1249
1250The following functions have been renamed:
1251* SDL_AllocFormat() => SDL_GetPixelFormatDetails()
1252* SDL_AllocPalette() => SDL_CreatePalette()
1253* SDL_FreePalette() => SDL_DestroyPalette()
1254* SDL_MasksToPixelFormatEnum() => SDL_GetPixelFormatForMasks()
1255* SDL_PixelFormatEnumToMasks() => SDL_GetMasksForPixelFormat(), returns bool
1256
1257The following symbols have been renamed:
1258* SDL_PIXELFORMAT_BGR444 => SDL_PIXELFORMAT_XBGR4444
1259* SDL_PIXELFORMAT_BGR555 => SDL_PIXELFORMAT_XBGR1555
1260* SDL_PIXELFORMAT_BGR888 => SDL_PIXELFORMAT_XBGR8888
1261* SDL_PIXELFORMAT_RGB444 => SDL_PIXELFORMAT_XRGB4444
1262* SDL_PIXELFORMAT_RGB555 => SDL_PIXELFORMAT_XRGB1555
1263* SDL_PIXELFORMAT_RGB888 => SDL_PIXELFORMAT_XRGB8888
1264
1265The following functions have been removed:
1266* SDL_FreeFormat()
1267* SDL_SetPixelFormatPalette()
1268* SDL_CalculateGammaRamp()
1269
1270The following macros have been removed:
1271* SDL_Colour - use SDL_Color instead
1272
1273The following structures have been renamed:
1274* SDL_PixelFormat => SDL_PixelFormatDetails
1275
1276## SDL_platform.h
1277
1278The following platform preprocessor macros have been renamed:
1279
1280| SDL2 | SDL3 |
1281|-------------------|---------------------------|
1282| `__3DS__` | `SDL_PLATFORM_3DS` |
1283| `__AIX__` | `SDL_PLATFORM_AIX` |
1284| `__ANDROID__` | `SDL_PLATFORM_ANDROID` |
1285| `__APPLE__` | `SDL_PLATFORM_APPLE` |
1286| `__BSDI__` | `SDL_PLATFORM_BSDI` |
1287| `__CYGWIN_` | `SDL_PLATFORM_CYGWIN` |
1288| `__EMSCRIPTEN__` | `SDL_PLATFORM_EMSCRIPTEN` |
1289| `__FREEBSD__` | `SDL_PLATFORM_FREEBSD` |
1290| `__GDK__` | `SDL_PLATFORM_GDK` |
1291| `__HAIKU__` | `SDL_PLATFORM_HAIKU` |
1292| `__HPUX__` | `SDL_PLATFORM_HPUX` |
1293| `__IPHONEOS__` | `SDL_PLATFORM_IOS` |
1294| `__IRIX__` | `SDL_PLATFORM_IRIX` |
1295| `__LINUX__` | `SDL_PLATFORM_LINUX` |
1296| `__MACOSX__` | `SDL_PLATFORM_MACOS` |
1297| `__NETBSD__` | `SDL_PLATFORM_NETBSD` |
1298| `__OPENBSD__` | `SDL_PLATFORM_OPENBSD` |
1299| `__OS2__` | `SDL_PLATFORM_OS2` |
1300| `__OSF__` | `SDL_PLATFORM_OSF` |
1301| `__PS2__` | `SDL_PLATFORM_PS2` |
1302| `__PSP__` | `SDL_PLATFORM_PSP` |
1303| `__QNXNTO__` | `SDL_PLATFORM_QNXNTO` |
1304| `__RISCOS__` | `SDL_PLATFORM_RISCOS` |
1305| `__SOLARIS__` | `SDL_PLATFORM_SOLARIS` |
1306| `__TVOS__` | `SDL_PLATFORM_TVOS` |
1307| `__unix__` | `SDL_PLATFORM_UNI` |
1308| `__VITA__` | `SDL_PLATFORM_VITA` |
1309| `__WIN32__` | `SDL_PLATFORM_WIN32` |
1310| `__WINGDK__` | `SDL_PLATFORM_WINGDK` |
1311| `__XBOXONE__` | `SDL_PLATFORM_XBOXONE` |
1312| `__XBOXSERIES__` | `SDL_PLATFORM_XBOXSERIES` |
1313
1314You can use the Python script [rename_macros.py](https://github.com/libsdl-org/SDL/blob/main/build-scripts/rename_macros.py) to automatically rename these in your source code.
1315
1316A new macro `SDL_PLATFORM_WINDOWS` has been added that is true for all Windows platforms, including Xbox, GDK, etc.
1317
1318The following platform preprocessor macros have been removed:
1319* `__DREAMCAST__`
1320* `__NACL__`
1321* `__PNACL__`
1322* `__WINDOWS__`
1323* `__WINRT__`
1324
1325
1326## SDL_quit.h
1327
1328SDL_quit.h has been completely removed. It only had one symbol in it--SDL_QuitRequested--and if you want it, you can just add this to your app...
1329
1330```c
1331#define SDL_QuitRequested() (SDL_PumpEvents(), (SDL_PeepEvents(NULL,0,SDL_PEEKEVENT,SDL_EVENT_QUIT,SDL_EVENT_QUIT) > 0))
1332```
1333
1334...but this macro is sort of messy, calling two functions in sequence in an expression.
1335
1336The following macros have been removed:
1337* SDL_QuitRequested - call SDL_PumpEvents() then SDL_PeepEvents() directly, instead.
1338
1339## SDL_rect.h
1340
1341The following functions have been renamed:
1342* SDL_EncloseFPoints() => SDL_GetRectEnclosingPointsFloat()
1343* SDL_EnclosePoints() => SDL_GetRectEnclosingPoints()
1344* SDL_FRectEmpty() => SDL_RectEmptyFloat()
1345* SDL_FRectEquals() => SDL_RectsEqualFloat()
1346* SDL_FRectEqualsEpsilon() => SDL_RectsEqualEpsilon()
1347* SDL_HasIntersection() => SDL_HasRectIntersection()
1348* SDL_HasIntersectionF() => SDL_HasRectIntersectionFloat()
1349* SDL_IntersectFRect() => SDL_GetRectIntersectionFloat()
1350* SDL_IntersectFRectAndLine() => SDL_GetRectAndLineIntersectionFloat()
1351* SDL_IntersectRect() => SDL_GetRectIntersection()
1352* SDL_IntersectRectAndLine() => SDL_GetRectAndLineIntersection()
1353* SDL_PointInFRect() => SDL_PointInRectFloat()
1354* SDL_RectEquals() => SDL_RectsEqual()
1355* SDL_UnionFRect() => SDL_GetRectUnionFloat(), returns bool
1356* SDL_UnionRect() => SDL_GetRectUnion(), returns bool
1357
1358## SDL_render.h
1359
1360The 2D renderer API always uses batching in SDL3. There is no magic to turn
1361it on and off; it doesn't matter if you select a specific renderer or try to
1362use any hint. This means that all apps that use SDL3's 2D renderer and also
1363want to call directly into the platform's lower-layer graphics API _must_ call
1364SDL_FlushRenderer() before doing so. This will make sure any pending rendering
1365work from SDL is done before the app starts directly drawing.
1366
1367SDL_GetRenderDriverInfo() has been removed, since most of the information it reported were
1368estimates and could not be accurate before creating a renderer. Often times this function
1369was used to figure out the index of a driver, so one would call it in a for-loop, looking
1370for the driver named "opengl" or whatnot. SDL_GetRenderDriver() has been added for this
1371functionality, which returns only the name of the driver.
1372
1373SDL_CreateRenderer()'s second argument is no longer an integer index, but a
1374`const char *` representing a renderer's name; if you were just using a for-loop to find
1375which index is the "opengl" or whatnot driver, you can just pass that string directly
1376here, now. Passing NULL is the same as passing -1 here in SDL2, to signify you want SDL
1377to decide for you.
1378
1379SDL_CreateRenderer()'s flags parameter has been removed. See specific flags below for how to achieve the same functionality in SDL 3.0.
1380
1381SDL_CreateWindowAndRenderer() now takes the window title as the first parameter.
1382
1383SDL_GetRendererInfo() has been removed. The name of a renderer can be retrieved using SDL_GetRendererName(), and the other information is available as properties on the renderer.
1384
1385Textures are created with SDL_SCALEMODE_LINEAR by default, and use SDL_BLENDMODE_BLEND by default if they are created with a format that has an alpha channel.
1386
1387SDL_QueryTexture() has been removed. The properties of the texture can be queried using SDL_PROP_TEXTURE_FORMAT_NUMBER, SDL_PROP_TEXTURE_ACCESS_NUMBER, SDL_PROP_TEXTURE_WIDTH_NUMBER, and SDL_PROP_TEXTURE_HEIGHT_NUMBER. A function SDL_GetTextureSize() has been added to get the size of the texture as floating point values.
1388
1389Mouse and touch events are no longer filtered to change their coordinates, instead you
1390can call SDL_ConvertEventToRenderCoordinates() to explicitly map event coordinates into
1391the rendering viewport.
1392
1393SDL_RenderWindowToLogical() and SDL_RenderLogicalToWindow() have been renamed SDL_RenderCoordinatesFromWindow() and SDL_RenderCoordinatesToWindow() and take floating point coordinates in both directions.
1394
1395The viewport, clipping state, and scale for render targets are now persistent and will remain set whenever they are active.
1396
1397SDL_Vertex has been changed to use floating point colors, in the range of [0..1] for SDR content.
1398
1399SDL_RenderReadPixels() returns a surface instead of filling in preallocated memory.
1400
1401SDL_RenderSetLogicalSize() (now called SDL_SetRenderLogicalPresentation()) in SDL2 would modify the scaling and viewport state. In SDL3, logical presentation maintains its state separately, so the app can use its own viewport and scaling while also setting a logical size.
1402
1403The following functions have been renamed:
1404* SDL_GetRendererOutputSize() => SDL_GetCurrentRenderOutputSize(), returns bool
1405* SDL_RenderCopy() => SDL_RenderTexture(), returns bool
1406* SDL_RenderCopyEx() => SDL_RenderTextureRotated(), returns bool
1407* SDL_RenderCopyExF() => SDL_RenderTextureRotated(), returns bool
1408* SDL_RenderCopyF() => SDL_RenderTexture(), returns bool
1409* SDL_RenderDrawLine() => SDL_RenderLine(), returns bool
1410* SDL_RenderDrawLineF() => SDL_RenderLine(), returns bool
1411* SDL_RenderDrawLines() => SDL_RenderLines(), returns bool
1412* SDL_RenderDrawLinesF() => SDL_RenderLines(), returns bool
1413* SDL_RenderDrawPoint() => SDL_RenderPoint(), returns bool
1414* SDL_RenderDrawPointF() => SDL_RenderPoint(), returns bool
1415* SDL_RenderDrawPoints() => SDL_RenderPoints(), returns bool
1416* SDL_RenderDrawPointsF() => SDL_RenderPoints(), returns bool
1417* SDL_RenderDrawRect() => SDL_RenderRect(), returns bool
1418* SDL_RenderDrawRectF() => SDL_RenderRect(), returns bool
1419* SDL_RenderDrawRects() => SDL_RenderRects(), returns bool
1420* SDL_RenderDrawRectsF() => SDL_RenderRects(), returns bool
1421* SDL_RenderFillRectF() => SDL_RenderFillRect(), returns bool
1422* SDL_RenderFillRectsF() => SDL_RenderFillRects(), returns bool
1423* SDL_RenderFlush() => SDL_FlushRenderer(), returns bool
1424* SDL_RenderGetClipRect() => SDL_GetRenderClipRect(), returns bool
1425* SDL_RenderGetIntegerScale() => SDL_GetRenderIntegerScale()
1426* SDL_RenderGetLogicalSize() => SDL_GetRenderLogicalPresentation(), returns bool
1427* SDL_RenderGetMetalCommandEncoder() => SDL_GetRenderMetalCommandEncoder()
1428* SDL_RenderGetMetalLayer() => SDL_GetRenderMetalLayer()
1429* SDL_RenderGetScale() => SDL_GetRenderScale(), returns bool
1430* SDL_RenderGetViewport() => SDL_GetRenderViewport(), returns bool
1431* SDL_RenderGetWindow() => SDL_GetRenderWindow()
1432* SDL_RenderIsClipEnabled() => SDL_RenderClipEnabled()
1433* SDL_RenderLogicalToWindow() => SDL_RenderCoordinatesToWindow(), returns bool
1434* SDL_RenderSetClipRect() => SDL_SetRenderClipRect(), returns bool
1435* SDL_RenderSetLogicalSize() => SDL_SetRenderLogicalPresentation(), returns bool
1436* SDL_RenderSetScale() => SDL_SetRenderScale(), returns bool
1437* SDL_RenderSetVSync() => SDL_SetRenderVSync(), returns bool
1438* SDL_RenderSetViewport() => SDL_SetRenderViewport(), returns bool
1439* SDL_RenderWindowToLogical() => SDL_RenderCoordinatesFromWindow(), returns bool
1440
1441The following functions have been removed:
1442* SDL_GL_BindTexture() - use SDL_GetTextureProperties() to get the OpenGL texture ID and bind the texture directly
1443* SDL_GL_UnbindTexture() - use SDL_GetTextureProperties() to get the OpenGL texture ID and unbind the texture directly
1444* SDL_GetTextureUserData() - use SDL_GetTextureProperties() instead
1445* SDL_RenderGetIntegerScale()
1446* SDL_RenderSetIntegerScale() - this is now explicit with SDL_LOGICAL_PRESENTATION_INTEGER_SCALE
1447* SDL_RenderTargetSupported() - render targets are always supported
1448* SDL_SetTextureUserData() - use SDL_GetTextureProperties() instead
1449
1450The following enums have been renamed:
1451* SDL_RendererFlip => SDL_FlipMode - moved to SDL_surface.h
1452
1453The following symbols have been renamed:
1454* SDL_ScaleModeLinear => SDL_SCALEMODE_LINEAR
1455* SDL_ScaleModeNearest => SDL_SCALEMODE_NEAREST
1456
1457The following symbols have been removed:
1458* SDL_RENDERER_ACCELERATED - all renderers except `SDL_SOFTWARE_RENDERER` are accelerated
1459* SDL_RENDERER_PRESENTVSYNC - replaced with SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER during renderer creation and SDL_PROP_RENDERER_VSYNC_NUMBER after renderer creation
1460* SDL_RENDERER_SOFTWARE - you can check whether the name of the renderer is `SDL_SOFTWARE_RENDERER`
1461* SDL_RENDERER_TARGETTEXTURE - all renderers support target texture functionality
1462* SDL_ScaleModeBest = use SDL_SCALEMODE_LINEAR instead
1463
1464## SDL_rwops.h
1465
1466The following symbols have been renamed:
1467* RW_SEEK_CUR => SDL_IO_SEEK_CUR
1468* RW_SEEK_END => SDL_IO_SEEK_END
1469* RW_SEEK_SET => SDL_IO_SEEK_SET
1470
1471SDL_rwops.h is now named SDL_iostream.h
1472
1473SDL_RWops is now an opaque structure, and has been renamed to SDL_IOStream. The SDL3 APIs to create an SDL_IOStream (SDL_IOFromFile, etc) are renamed but otherwise still function as they did in SDL2. However, to make a custom SDL_IOStream with app-provided function pointers, call SDL_OpenIO and provide the function pointers through there. To call into an SDL_IOStream's functionality, use the standard APIs (SDL_ReadIO, etc), as the function pointers are internal.
1474
1475SDL_IOStream is not to be confused with the unrelated standard C++ iostream class!
1476
1477The RWops function pointers are now in a separate structure called SDL_IOStreamInterface, which is provided to SDL_OpenIO when creating a custom SDL_IOStream implementation. All the functions now take a `void *` userdata argument for their first parameter instead of an SDL_IOStream, since that's now an opaque structure.
1478
1479SDL_RWread and SDL_RWwrite (and the read and write function pointers) have a different function signature in SDL3, in addition to being renamed.
1480
1481Previously they looked more like stdio:
1482
1483```c
1484size_t SDL_RWread(SDL_RWops *context, void *ptr, size_t size, size_t maxnum);
1485size_t SDL_RWwrite(SDL_RWops *context, const void *ptr, size_t size, size_t maxnum);
1486```
1487
1488But now they look more like POSIX:
1489
1490```c
1491size_t SDL_ReadIO(SDL_IOStream *context, void *ptr, size_t size);
1492size_t SDL_WriteIO(SDL_IOStream *context, const void *ptr, size_t size);
1493```
1494
1495Code that used to look like this:
1496```c
1497size_t custom_read(void *ptr, size_t size, size_t nitems, SDL_RWops *stream)
1498{
1499 return SDL_RWread(stream, ptr, size, nitems);
1500}
1501```
1502should be changed to:
1503```c
1504size_t custom_read(void *ptr, size_t size, size_t nitems, SDL_IOStream *stream)
1505{
1506 if (size > 0 && nitems > 0) {
1507 return SDL_ReadIO(stream, ptr, size * nitems) / size;
1508 }
1509 return 0;
1510}
1511```
1512
1513SDL_RWops::type was removed; it wasn't meaningful for app-provided implementations at all, and wasn't much use for SDL's internal implementations, either. If you _have_ to identify the type, you can examine the SDL_IOStream's properties to detect built-in implementations.
1514
1515SDL_IOStreamInterface::close implementations should clean up their own userdata, but not call SDL_CloseIO on themselves; now the contract is always that SDL_CloseIO is called, which calls `->close` before freeing the opaque object.
1516
1517SDL_AllocRW(), SDL_FreeRW(), SDL_RWclose() and direct access to the `->close` function pointer have been removed from the API, so there's only one path to manage RWops lifetimes now: SDL_OpenIO() and SDL_CloseIO().
1518
1519SDL_RWFromFP has been removed from the API, due to issues when the SDL library uses a different C runtime from the application.
1520
1521You can implement this in your own code easily:
1522```c
1523#include <stdio.h>
1524
1525typedef struct IOStreamStdioFPData
1526{
1527 FILE *fp;
1528 bool autoclose;
1529} IOStreamStdioFPData;
1530
1531static Sint64 SDLCALL stdio_seek(void *userdata, Sint64 offset, int whence)
1532{
1533 FILE *fp = ((IOStreamStdioFPData *) userdata)->fp;
1534 int stdiowhence;
1535
1536 switch (whence) {
1537 case SDL_IO_SEEK_SET:
1538 stdiowhence = SEEK_SET;
1539 break;
1540 case SDL_IO_SEEK_CUR:
1541 stdiowhence = SEEK_CUR;
1542 break;
1543 case SDL_IO_SEEK_END:
1544 stdiowhence = SEEK_END;
1545 break;
1546 default:
1547 SDL_SetError("Unknown value for 'whence'");
1548 return -1;
1549 }
1550
1551 if (fseek(fp, (fseek_off_t)offset, stdiowhence) == 0) {
1552 const Sint64 pos = ftell(fp);
1553 if (pos < 0) {
1554 SDL_SetError("Couldn't get stream offset");
1555 return -1;
1556 }
1557 return pos;
1558 }
1559 SDL_SetError("Couldn't seek in stream");
1560 return -1;
1561}
1562
1563static size_t SDLCALL stdio_read(void *userdata, void *ptr, size_t size, SDL_IOStatus *status)
1564{
1565 FILE *fp = ((IOStreamStdioFPData *) userdata)->fp;
1566 const size_t bytes = fread(ptr, 1, size, fp);
1567 if (bytes == 0 && ferror(fp)) {
1568 SDL_SetError("Couldn't read stream");
1569 }
1570 return bytes;
1571}
1572
1573static size_t SDLCALL stdio_write(void *userdata, const void *ptr, size_t size, SDL_IOStatus *status)
1574{
1575 FILE *fp = ((IOStreamStdioFPData *) userdata)->fp;
1576 const size_t bytes = fwrite(ptr, 1, size, fp);
1577 if (bytes == 0 && ferror(fp)) {
1578 SDL_SetError("Couldn't write stream");
1579 }
1580 return bytes;
1581}
1582
1583static bool SDLCALL stdio_close(void *userdata)
1584{
1585 IOStreamStdioData *rwopsdata = (IOStreamStdioData *) userdata;
1586 bool status = true;
1587 if (rwopsdata->autoclose) {
1588 if (fclose(rwopsdata->fp) != 0) {
1589 SDL_SetError("Couldn't close stream");
1590 status = false;
1591 }
1592 }
1593 return status;
1594}
1595
1596SDL_IOStream *SDL_RWFromFP(FILE *fp, bool autoclose)
1597{
1598 SDL_IOStreamInterface iface;
1599 IOStreamStdioFPData *rwopsdata;
1600 SDL_IOStream *rwops;
1601
1602 rwopsdata = (IOStreamStdioFPData *) SDL_malloc(sizeof (*rwopsdata));
1603 if (!rwopsdata) {
1604 return NULL;
1605 }
1606
1607 SDL_INIT_INTERFACE(&iface);
1608 /* There's no stdio_size because SDL_GetIOSize emulates it the same way we'd do it for stdio anyhow. */
1609 iface.seek = stdio_seek;
1610 iface.read = stdio_read;
1611 iface.write = stdio_write;
1612 iface.close = stdio_close;
1613
1614 rwopsdata->fp = fp;
1615 rwopsdata->autoclose = autoclose;
1616
1617 rwops = SDL_OpenIO(&iface, rwopsdata);
1618 if (!rwops) {
1619 iface.close(rwopsdata);
1620 }
1621 return rwops;
1622}
1623```
1624
1625The internal `FILE *` is available through a standard SDL_IOStream property, for streams made through SDL_IOFromFile() that use stdio behind the scenes; apps use this pointer at their own risk and should make sure that SDL and the app are using the same C runtime.
1626
1627On Apple platforms, SDL_RWFromFile (now called SDL_IOFromFile) no longer tries to read from inside the app bundle's resource directory, instead now using the specified path unchanged. One can use SDL_GetBasePath() to find the resource directory on these platforms.
1628
1629
1630The functions SDL_ReadU8(), SDL_ReadU16LE(), SDL_ReadU16BE(), SDL_ReadU32LE(), SDL_ReadU32BE(), SDL_ReadU64LE(), and SDL_ReadU64BE() now return true if the read succeeded and false if it didn't, and store the data in a pointer passed in as a parameter.
1631
1632The following functions have been renamed:
1633* SDL_RWFromConstMem() => SDL_IOFromConstMem()
1634* SDL_RWFromFile() => SDL_IOFromFile()
1635* SDL_RWFromMem() => SDL_IOFromMem()
1636* SDL_RWclose() => SDL_CloseIO(), returns bool
1637* SDL_RWread() => SDL_ReadIO()
1638* SDL_RWseek() => SDL_SeekIO()
1639* SDL_RWsize() => SDL_GetIOSize()
1640* SDL_RWtell() => SDL_TellIO()
1641* SDL_RWwrite() => SDL_WriteIO()
1642* SDL_ReadBE16() => SDL_ReadU16BE()
1643* SDL_ReadBE32() => SDL_ReadU32BE()
1644* SDL_ReadBE64() => SDL_ReadU64BE()
1645* SDL_ReadLE16() => SDL_ReadU16LE()
1646* SDL_ReadLE32() => SDL_ReadU32LE()
1647* SDL_ReadLE64() => SDL_ReadU64LE()
1648* SDL_WriteBE16() => SDL_WriteU16BE()
1649* SDL_WriteBE32() => SDL_WriteU32BE()
1650* SDL_WriteBE64() => SDL_WriteU64BE()
1651* SDL_WriteLE16() => SDL_WriteU16LE()
1652* SDL_WriteLE32() => SDL_WriteU32LE()
1653* SDL_WriteLE64() => SDL_WriteU64LE()
1654
1655
1656The following structures have been renamed:
1657* SDL_RWops => SDL_IOStream
1658
1659## SDL_scancode.h
1660
1661The following symbols have been removed:
1662* SDL_SCANCODE_WWW
1663* SDL_SCANCODE_MAIL
1664* SDL_SCANCODE_CALCULATOR
1665* SDL_SCANCODE_COMPUTER
1666* SDL_SCANCODE_BRIGHTNESSDOWN
1667* SDL_SCANCODE_BRIGHTNESSUP
1668* SDL_SCANCODE_DISPLAYSWITCH
1669* SDL_SCANCODE_KBDILLUMTOGGLE
1670* SDL_SCANCODE_KBDILLUMDOWN
1671* SDL_SCANCODE_KBDILLUMUP
1672* SDL_SCANCODE_APP1
1673* SDL_SCANCODE_APP2
1674
1675The following symbols have been renamed:
1676* SDL_NUM_SCANCODES => SDL_SCANCODE_COUNT
1677* SDL_SCANCODE_AUDIOFASTFORWARD => SDL_SCANCODE_MEDIA_FAST_FORWARD
1678* SDL_SCANCODE_AUDIOMUTE => SDL_SCANCODE_MUTE
1679* SDL_SCANCODE_AUDIONEXT => SDL_SCANCODE_MEDIA_NEXT_TRACK
1680* SDL_SCANCODE_AUDIOPLAY => SDL_SCANCODE_MEDIA_PLAY
1681* SDL_SCANCODE_AUDIOPREV => SDL_SCANCODE_MEDIA_PREVIOUS_TRACK
1682* SDL_SCANCODE_AUDIOREWIND => SDL_SCANCODE_MEDIA_REWIND
1683* SDL_SCANCODE_AUDIOSTOP => SDL_SCANCODE_MEDIA_STOP
1684* SDL_SCANCODE_EJECT => SDL_SCANCODE_MEDIA_EJECT
1685* SDL_SCANCODE_MEDIASELECT => SDL_SCANCODE_MEDIA_SELECT
1686
1687## SDL_sensor.h
1688
1689SDL_SensorID has changed from Sint32 to Uint32, with an invalid ID being 0.
1690
1691Rather than iterating over sensors using device index, there is a new function SDL_GetSensors() to get the current list of sensors, and new functions to get information about sensors from their instance ID:
1692```c
1693{
1694 if (SDL_InitSubSystem(SDL_INIT_SENSOR)) {
1695 int i, num_sensors;
1696 SDL_SensorID *sensors = SDL_GetSensors(&num_sensors);
1697 if (sensors) {
1698 for (i = 0; i < num_sensors; ++i) {
1699 SDL_Log("Sensor %" SDL_PRIu32 ": %s, type %d, platform type %d",
1700 sensors[i],
1701 SDL_GetSensorNameForID(sensors[i]),
1702 SDL_GetSensorTypeForID(sensors[i]),
1703 SDL_GetSensorNonPortableTypeForID(sensors[i]));
1704 }
1705 SDL_free(sensors);
1706 }
1707 SDL_QuitSubSystem(SDL_INIT_SENSOR);
1708 }
1709}
1710```
1711
1712Removed SDL_SensorGetDataWithTimestamp(), if you want timestamps for the sensor data, you should use the sensor_timestamp member of SDL_EVENT_SENSOR_UPDATE events.
1713
1714
1715The following functions have been renamed:
1716* SDL_SensorClose() => SDL_CloseSensor()
1717* SDL_SensorFromInstanceID() => SDL_GetSensorFromID()
1718* SDL_SensorGetData() => SDL_GetSensorData(), returns bool
1719* SDL_SensorGetInstanceID() => SDL_GetSensorID()
1720* SDL_SensorGetName() => SDL_GetSensorName()
1721* SDL_SensorGetNonPortableType() => SDL_GetSensorNonPortableType()
1722* SDL_SensorGetType() => SDL_GetSensorType()
1723* SDL_SensorOpen() => SDL_OpenSensor()
1724* SDL_SensorUpdate() => SDL_UpdateSensors()
1725
1726The following functions have been removed:
1727* SDL_LockSensors()
1728* SDL_NumSensors() - replaced with SDL_GetSensors()
1729* SDL_SensorGetDeviceInstanceID()
1730* SDL_SensorGetDeviceName() - replaced with SDL_GetSensorNameForID()
1731* SDL_SensorGetDeviceNonPortableType() - replaced with SDL_GetSensorNonPortableTypeForID()
1732* SDL_SensorGetDeviceType() - replaced with SDL_GetSensorTypeForID()
1733* SDL_UnlockSensors()
1734
1735## SDL_shape.h
1736
1737This header has been removed and a simplified version of this API has been added as SDL_SetWindowShape() in SDL_video.h. See test/testshape.c for an example.
1738
1739## SDL_stdinc.h
1740
1741The standard C headers like stdio.h and stdlib.h are no longer included, you should include them directly in your project if you use non-SDL C runtime functions.
1742M_PI is no longer defined in SDL_stdinc.h, you can use the new symbols SDL_PI_D (double) and SDL_PI_F (float) instead.
1743
1744bool is now defined as bool, and is 1 byte instead of the size of an int.
1745
1746SDL3 attempts to apply consistency to case-insensitive string functions. In SDL2, things like SDL_strcasecmp() would usually only work on English letters, and depending on the user's locale, possibly not even those. In SDL3, consistency is applied:
1747
1748- Many things that don't care about case-insensitivity, like SDL_strcmp(), continue to work with any null-terminated string of bytes, even if it happens to be malformed UTF-8.
1749- SDL_strcasecmp() expects valid UTF-8 strings, and will attempt to support _most_ Unicode characters with a technique known as "case-folding," which is to say it can match 'A' and 'a', and also 'Η' and 'η', but ALSO 'ß' and "ss". This is _probably_ how most apps assumed it worked in SDL2 and won't need any changes.
1750- SDL_strncasecmp() works the same, but the third parameter takes _bytes_, as before, so SDL_strlen() can continue to be used with it. If a string hits the limit in the middle of a codepoint, the half-processed bytes of the codepoint will be treated as a collection of U+0xFFFD (REPLACEMENT CHARACTER) codepoints, which you probably don't want.
1751- SDL_wcscasecmp() and SDL_wcsncasecmp() work the same way but operate on UTF-16 or UTF-32 encoded strings, depending on what the platform considers "wchar_t" to be. SDL_wcsncasecmp's third parameter is number of wchar_t values, not bytes, but UTF-16 has the same concerns as UTF-8 for variable-length codepoints.
1752- SDL_strcasestr() expects valid UTF-8 strings, and will compare codepoints using case-folding.
1753- SDL_tolower() and SDL_toupper() continue to only work on single bytes (even though the parameter is an `int`) and _only_ converts low-ASCII English A through Z.
1754- SDL_strlwr() and SDL_strupr() operates on individual bytes (not UTF-8 codepoints) and only change low-ASCII English 'A' through 'Z'. These functions do not check the string for valid UTF-8 encoding.
1755- The ctype.h replacement SDL_is*() functions (SDL_isalpha, SDL_isdigit, etc) only work on low-ASCII characters and ignore user locale, assuming English. This makes these functions consistent in SDL3, but applications need to be careful to understand their limits.
1756
1757Please note that the case-folding technique used by SDL3 will not produce correct results for the "Turkish 'I'"; this one letter is a surprisingly hard problem in the Unicode world, and since these functions do not specify the human language in use, we have chosen to ignore this problem.
1758
1759SDL_strtoll(), SDL_strtoull(), SDL_lltoa(), and SDL_ulltoa() use long long values instead of 64-bit values, to match their C runtime counterparts.
1760
1761SDL_setenv() is not thread-safe and has been renamed SDL_setenv_unsafe().
1762
1763The following macros have been removed:
1764* SDL_TABLESIZE() - use SDL_arraysize() instead
1765
1766The following functions have been renamed:
1767* SDL_size_add_overflow() => SDL_size_add_check_overflow(), returns bool
1768* SDL_size_mul_overflow() => SDL_size_mul_check_overflow(), returns bool
1769* SDL_strtokr() => SDL_strtok_r()
1770
1771The following functions have been removed:
1772* SDL_memcpy4()
1773
1774The following symbols have been renamed:
1775* SDL_FALSE => false
1776* SDL_TRUE => true
1777* SDL_bool => bool
1778
1779## SDL_surface.h
1780
1781SDL_Surface has been simplified and internal details are no longer in the public structure.
1782
1783The `format` member of SDL_Surface is now an enumerated pixel format value. You can get the full details of the pixel format by calling `SDL_GetPixelFormatDetails(surface->format)`. You can get the palette associated with the surface by calling SDL_GetSurfacePalette(). You can get the clip rectangle by calling SDL_GetSurfaceClipRect().
1784
1785The userdata member of SDL_Surface has been replaced with a more general properties interface, which can be queried with SDL_GetSurfaceProperties()
1786
1787Indexed format surfaces no longer have a palette by default. Surfaces without a palette will copy the pixels untranslated between surfaces.
1788
1789Code that used to look like this:
1790```c
1791 SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, 32, 32, 8, SDL_PIXELFORMAT_INDEX8);
1792 SDL_Palette *palette = surface->format->palette;
1793 ...
1794```
1795should be changed to:
1796```c
1797 SDL_Surface *surface = SDL_CreateSurface(32, 32, SDL_PIXELFORMAT_INDEX8);
1798 SDL_Palette *palette = SDL_CreateSurfacePalette(surface);
1799 ...
1800```
1801
1802Removed the unused 'flags' parameter from SDL_ConvertSurface.
1803
1804SDL_CreateRGBSurface() and SDL_CreateRGBSurfaceWithFormat() have been combined into a new function SDL_CreateSurface().
1805SDL_CreateRGBSurfaceFrom() and SDL_CreateRGBSurfaceWithFormatFrom() have been combined into a new function SDL_CreateSurfaceFrom(), and the parameter order has changed for consistency with SDL_CreateSurface().
1806
1807You can implement the old functions in your own code easily:
1808```c
1809SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
1810{
1811 return SDL_CreateSurface(width, height,
1812 SDL_GetPixelFormatForMasks(depth, Rmask, Gmask, Bmask, Amask));
1813}
1814
1815SDL_Surface *SDL_CreateRGBSurfaceWithFormat(Uint32 flags, int width, int height, int depth, Uint32 format)
1816{
1817 return SDL_CreateSurface(width, height, format);
1818}
1819
1820SDL_Surface *SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
1821{
1822 return SDL_CreateSurfaceFrom(width, height,
1823 SDL_GetPixelFormatForMasks(depth, Rmask, Gmask, Bmask, Amask),
1824 pixels, pitch);
1825}
1826
1827SDL_Surface *SDL_CreateRGBSurfaceWithFormatFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 format)
1828{
1829 return SDL_CreateSurfaceFrom(width, height, format, pixels, pitch);
1830}
1831
1832```
1833
1834But if you're migrating your code which uses masks, you probably have a format in mind, possibly one of these:
1835```c
1836// Various mask (R, G, B, A) and their corresponding format:
18370xFF000000 0x00FF0000 0x0000FF00 0x000000FF => SDL_PIXELFORMAT_RGBA8888
18380x00FF0000 0x0000FF00 0x000000FF 0xFF000000 => SDL_PIXELFORMAT_ARGB8888
18390x0000FF00 0x00FF0000 0xFF000000 0x000000FF => SDL_PIXELFORMAT_BGRA8888
18400x000000FF 0x0000FF00 0x00FF0000 0xFF000000 => SDL_PIXELFORMAT_ABGR8888
18410x0000F800 0x000007E0 0x0000001F 0x00000000 => SDL_PIXELFORMAT_RGB565
1842```
1843
1844SDL_BlitSurface() and SDL_BlitSurfaceScaled() now have a const `dstrect` parameter and do not fill it in with the final destination rectangle.
1845
1846SDL_BlitSurfaceScaled() and SDL_BlitSurfaceUncheckedScaled() now take a scale parameter.
1847
1848SDL_PixelFormat is used instead of Uint32 for API functions that refer to pixel format by enumerated value.
1849
1850SDL_SetSurfaceColorKey() takes an bool to enable and disable colorkey. RLE acceleration isn't controlled by the parameter, you should use SDL_SetSurfaceRLE() to change that separately.
1851
1852SDL_SetSurfaceRLE() takes an bool to enable and disable RLE acceleration.
1853
1854The following functions have been renamed:
1855* SDL_BlitScaled() => SDL_BlitSurfaceScaled(), returns bool
1856* SDL_ConvertSurfaceFormat() => SDL_ConvertSurface()
1857* SDL_FillRect() => SDL_FillSurfaceRect(), returns bool
1858* SDL_FillRects() => SDL_FillSurfaceRects(), returns bool
1859* SDL_FreeSurface() => SDL_DestroySurface()
1860* SDL_GetClipRect() => SDL_GetSurfaceClipRect(), returns bool
1861* SDL_GetColorKey() => SDL_GetSurfaceColorKey(), returns bool
1862* SDL_HasColorKey() => SDL_SurfaceHasColorKey()
1863* SDL_HasSurfaceRLE() => SDL_SurfaceHasRLE()
1864* SDL_LoadBMP_RW() => SDL_LoadBMP_IO()
1865* SDL_LowerBlit() => SDL_BlitSurfaceUnchecked(), returns bool
1866* SDL_LowerBlitScaled() => SDL_BlitSurfaceUncheckedScaled(), returns bool
1867* SDL_SaveBMP_RW() => SDL_SaveBMP_IO(), returns bool
1868* SDL_SetClipRect() => SDL_SetSurfaceClipRect()
1869* SDL_SetColorKey() => SDL_SetSurfaceColorKey(), returns bool
1870* SDL_UpperBlit() => SDL_BlitSurface(), returns bool
1871* SDL_UpperBlitScaled() => SDL_BlitSurfaceScaled(), returns bool
1872
1873The following symbols have been removed:
1874* SDL_SWSURFACE
1875
1876The following functions have been removed:
1877* SDL_FreeFormat()
1878* SDL_GetYUVConversionMode()
1879* SDL_GetYUVConversionModeForResolution()
1880* SDL_SetYUVConversionMode() - use SDL_SetSurfaceColorspace() to set the surface colorspace and SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER with SDL_CreateTextureWithProperties() to set the texture colorspace. The default colorspace for YUV pixel formats is SDL_COLORSPACE_JPEG.
1881* SDL_SoftStretch() - use SDL_StretchSurface() with SDL_SCALEMODE_NEAREST
1882* SDL_SoftStretchLinear() - use SDL_StretchSurface() with SDL_SCALEMODE_LINEAR
1883
1884The following symbols have been renamed:
1885* SDL_PREALLOC => SDL_SURFACE_PREALLOCATED
1886* SDL_SIMD_ALIGNED => SDL_SURFACE_SIMD_ALIGNED
1887
1888## SDL_system.h
1889
1890SDL_WindowsMessageHook has changed signatures so the message may be modified and it can block further message processing.
1891
1892SDL_RequestAndroidPermission is no longer a blocking call; the caller now provides a callback function that fires when a response is available.
1893
1894SDL_iPhoneSetAnimationCallback() and SDL_iPhoneSetEventPump() have been renamed to SDL_SetiOSAnimationCallback() and SDL_SetiOSEventPump(), respectively. SDL2 has had macros to provide this new name with the old symbol since the introduction of the iPad, but now the correctly-named symbol is the only option.
1895
1896SDL_IsAndroidTV() has been renamed SDL_IsTV() and is no longer Android-specific; an app running on an Apple TV device will also return true, for example.
1897
1898The following functions have been removed:
1899* SDL_GetWinRTFSPathUNICODE() - WinRT support was removed in SDL3.
1900* SDL_GetWinRTFSPathUTF8() - WinRT support was removed in SDL3.
1901* SDL_RenderGetD3D11Device() - replaced with the "SDL.renderer.d3d11.device" property
1902* SDL_RenderGetD3D12Device() - replaced with the "SDL.renderer.d3d12.device" property
1903* SDL_RenderGetD3D9Device() - replaced with the "SDL.renderer.d3d9.device" property
1904* SDL_WinRTGetDeviceFamily() - WinRT support was removed in SDL3.
1905
1906The following functions have been renamed:
1907* SDL_AndroidBackButton() => SDL_SendAndroidBackButton()
1908* SDL_AndroidGetActivity() => SDL_GetAndroidActivity()
1909* SDL_AndroidGetExternalStoragePath() => SDL_GetAndroidExternalStoragePath()
1910* SDL_AndroidGetExternalStorageState() => SDL_GetAndroidExternalStorageState()
1911* SDL_AndroidGetInternalStoragePath() => SDL_GetAndroidInternalStoragePath()
1912* SDL_AndroidGetJNIEnv() => SDL_GetAndroidJNIEnv()
1913* SDL_AndroidRequestPermission() => SDL_RequestAndroidPermission(), returns bool
1914* SDL_AndroidRequestPermissionCallback() => SDL_RequestAndroidPermissionCallback()
1915* SDL_AndroidSendMessage() => SDL_SendAndroidMessage(), returns bool
1916* SDL_AndroidShowToast() => SDL_ShowAndroidToast(), returns bool
1917* SDL_DXGIGetOutputInfo() => SDL_GetDXGIOutputInfo(), returns bool
1918* SDL_Direct3D9GetAdapterIndex() => SDL_GetDirect3D9AdapterIndex()
1919* SDL_GDKGetDefaultUser() => SDL_GetGDKDefaultUser(), returns bool
1920* SDL_GDKGetTaskQueue() => SDL_GetGDKTaskQueue(), returns bool
1921* SDL_IsAndroidTV() => SDL_IsTV()
1922* SDL_LinuxSetThreadPriority() => SDL_SetLinuxThreadPriority(), returns bool
1923* SDL_LinuxSetThreadPriorityAndPolicy() => SDL_SetLinuxThreadPriorityAndPolicy(), returns bool
1924* SDL_OnApplicationDidBecomeActive() => SDL_OnApplicationDidEnterForeground()
1925* SDL_OnApplicationWillResignActive() => SDL_OnApplicationWillEnterBackground()
1926* SDL_iOSSetAnimationCallback() => SDL_SetiOSAnimationCallback(), returns bool
1927* SDL_iOSSetEventPump() => SDL_SetiOSEventPump()
1928* SDL_iPhoneSetAnimationCallback() => SDL_SetiOSAnimationCallback(), returns bool
1929* SDL_iPhoneSetEventPump() => SDL_SetiOSEventPump()
1930
1931## SDL_syswm.h
1932
1933This header has been removed.
1934
1935The Windows and X11 events are now available via callbacks which you can set with SDL_SetWindowsMessageHook() and SDL_SetX11EventHook().
1936
1937The information previously available in SDL_GetWindowWMInfo() is now available as window properties, e.g.
1938```c
1939 SDL_SysWMinfo info;
1940 SDL_VERSION(&info.version);
1941
1942#if defined(__WIN32__)
1943 HWND hwnd = NULL;
1944 if (SDL_GetWindowWMInfo(window, &info) && info.subsystem == SDL_SYSWM_WINDOWS) {
1945 hwnd = info.info.win.window;
1946 }
1947 if (hwnd) {
1948 ...
1949 }
1950#elif defined(__MACOSX__)
1951 NSWindow *nswindow = NULL;
1952 if (SDL_GetWindowWMInfo(window, &info) && info.subsystem == SDL_SYSWM_COCOA) {
1953 nswindow = (__bridge NSWindow *)info.info.cocoa.window;
1954 }
1955 if (nswindow) {
1956 ...
1957 }
1958#elif defined(__LINUX__)
1959 if (SDL_GetWindowWMInfo(window, &info)) {
1960 if (info.subsystem == SDL_SYSWM_X11) {
1961 Display *xdisplay = info.info.x11.display;
1962 Window xwindow = info.info.x11.window;
1963 if (xdisplay && xwindow) {
1964 ...
1965 }
1966 } else if (info.subsystem == SDL_SYSWM_WAYLAND) {
1967 struct wl_display *display = info.info.wl.display;
1968 struct wl_surface *surface = info.info.wl.surface;
1969 if (display && surface) {
1970 ...
1971 }
1972 }
1973 }
1974#elif defined(__IPHONEOS__)
1975 UIWindow *uiwindow = NULL;
1976 if (SDL_GetWindowWMInfo(window, &info) && info.subsystem == SDL_SYSWM_UIKIT) {
1977 uiwindow = (__bridge UIWindow *)info.info.uikit.window;
1978 }
1979 if (uiwindow) {
1980 GLuint framebuffer = info.info.uikit.framebuffer;
1981 GLuint colorbuffer = info.info.uikit.colorbuffer;
1982 GLuint resolveFramebuffer = info.info.uikit.resolveFramebuffer;
1983 ...
1984 }
1985#endif
1986```
1987becomes:
1988```c
1989#if defined(SDL_PLATFORM_WIN32)
1990 HWND hwnd = (HWND)SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL);
1991 if (hwnd) {
1992 ...
1993 }
1994#elif defined(SDL_PLATFORM_MACOS)
1995 NSWindow *nswindow = (__bridge NSWindow *)SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, NULL);
1996 if (nswindow) {
1997 ...
1998 }
1999#elif defined(SDL_PLATFORM_LINUX)
2000 if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) {
2001 Display *xdisplay = (Display *)SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_X11_DISPLAY_POINTER, NULL);
2002 Window xwindow = (Window)SDL_GetNumberProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0);
2003 if (xdisplay && xwindow) {
2004 ...
2005 }
2006 } else if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0) {
2007 struct wl_display *display = (struct wl_display *)SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER, NULL);
2008 struct wl_surface *surface = (struct wl_surface *)SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, NULL);
2009 if (display && surface) {
2010 ...
2011 }
2012 }
2013#elif defined(SDL_PLATFORM_IOS)
2014 SDL_PropertiesID props = SDL_GetWindowProperties(window);
2015 UIWindow *uiwindow = (__bridge UIWindow *)SDL_GetPointerProperty(props, SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER, NULL);
2016 if (uiwindow) {
2017 GLuint framebuffer = (GLuint)SDL_GetNumberProperty(props, SDL_PROP_WINDOW_UIKIT_OPENGL_FRAMEBUFFER_NUMBER, 0);
2018 GLuint colorbuffer = (GLuint)SDL_GetNumberProperty(props, SDL_PROP_WINDOW_UIKIT_OPENGL_RENDERBUFFER_NUMBER, 0);
2019 GLuint resolveFramebuffer = (GLuint)SDL_GetNumberProperty(props, SDL_PROP_WINDOW_UIKIT_OPENGL_RESOLVE_FRAMEBUFFER_NUMBER, 0);
2020 ...
2021 }
2022#endif
2023```
2024
2025## SDL_thread.h
2026
2027SDL_CreateThreadWithStackSize has been replaced with SDL_CreateThreadWithProperties.
2028
2029SDL_CreateThread and SDL_CreateThreadWithProperties now take beginthread/endthread function pointers on all platforms (ignoring them on most), and have been replaced with macros that hide this detail on all platforms. This works the same as before at the source code level, but the actual function signature that is called in SDL has changed. The library's exported symbol is SDL_CreateThreadRuntime, and looking for "SDL_CreateThread" in the DLL/Shared Library/Dylib will fail. You should not call this directly, but instead always use the macro!
2030
2031SDL_GetTLS() and SDL_SetTLS() take a pointer to a TLS ID, and will automatically initialize it in a thread-safe way as needed.
2032
2033The following functions have been renamed:
2034* SDL_SetThreadPriority() => SDL_SetCurrentThreadPriority()
2035* SDL_TLSCleanup() => SDL_CleanupTLS()
2036* SDL_TLSGet() => SDL_GetTLS()
2037* SDL_TLSSet() => SDL_SetTLS(), returns bool
2038* SDL_ThreadID() => SDL_GetCurrentThreadID()
2039
2040The following functions have been removed:
2041* SDL_TLSCreate() - TLS IDs are automatically allocated as needed.
2042
2043The following symbols have been renamed:
2044* SDL_threadID => SDL_ThreadID
2045
2046## SDL_timer.h
2047
2048SDL_GetTicks() now returns a 64-bit value. Instead of using the SDL_TICKS_PASSED macro, you can directly compare tick values, e.g.
2049```c
2050Uint32 deadline = SDL_GetTicks() + 1000;
2051...
2052if (SDL_TICKS_PASSED(SDL_GetTicks(), deadline)) {
2053 ...
2054}
2055```
2056becomes:
2057```c
2058Uint64 deadline = SDL_GetTicks() + 1000
2059...
2060if (SDL_GetTicks() >= deadline) {
2061 ...
2062}
2063```
2064
2065If you were using this macro for other things besides SDL ticks values, you can define it in your own code as:
2066```c
2067#define SDL_TICKS_PASSED(A, B) ((Sint32)((B) - (A)) <= 0)
2068```
2069
2070The callback passed to SDL_AddTimer() has changed parameters to:
2071```c
2072Uint32 SDLCALL TimerCallback(void *userdata, SDL_TimerID timerID, Uint32 interval);
2073````
2074
2075## SDL_touch.h
2076
2077SDL_GetTouchName is replaced with SDL_GetTouchDeviceName(), which takes an SDL_TouchID instead of an index.
2078
2079SDL_TouchID and SDL_FingerID are now Uint64 with 0 being an invalid value.
2080
2081Rather than iterating over touch devices using an index, there is a new function SDL_GetTouchDevices() to get the available devices.
2082
2083Rather than iterating over touch fingers using an index, there is a new function SDL_GetTouchFingers() to get the current set of active fingers.
2084
2085The following functions have been removed:
2086* SDL_GetNumTouchDevices() - replaced with SDL_GetTouchDevices()
2087* SDL_GetNumTouchFingers() - replaced with SDL_GetTouchFingers()
2088* SDL_GetTouchDevice() - replaced with SDL_GetTouchDevices()
2089* SDL_GetTouchFinger() - replaced with SDL_GetTouchFingers()
2090
2091
2092## SDL_version.h
2093
2094SDL_GetRevisionNumber() has been removed from the API, it always returned 0 in SDL 2.0.
2095
2096SDL_GetVersion() returns the version number, which can be directly compared with another version wrapped with SDL_VERSIONNUM().
2097
2098The following structures have been removed:
2099* SDL_version
2100
2101The following symbols have been renamed:
2102* SDL_COMPILEDVERSION => SDL_VERSION
2103* SDL_PATCHLEVEL => SDL_MICRO_VERSION
2104
2105## SDL_video.h
2106
2107Several video backends have had their names lower-cased ("kmsdrm", "rpi", "android", "psp", "ps2", "vita"). SDL already does a case-insensitive compare for SDL_HINT_VIDEO_DRIVER tests, but if your app is calling SDL_GetVideoDriver() or SDL_GetCurrentVideoDriver() and doing case-sensitive compares on those strings, please update your code.
2108
2109SDL_VideoInit() and SDL_VideoQuit() have been removed. Instead you can call SDL_InitSubSystem() and SDL_QuitSubSystem() with SDL_INIT_VIDEO, which will properly refcount the subsystems. You can choose a specific video driver using SDL_HINT_VIDEO_DRIVER.
2110
2111Rather than iterating over displays using display index, there is a new function SDL_GetDisplays() to get the current list of displays, and functions which used to take a display index now take SDL_DisplayID, with an invalid ID being 0.
2112```c
2113{
2114 if (SDL_InitSubSystem(SDL_INIT_VIDEO)) {
2115 int i, num_displays = 0;
2116 SDL_DisplayID *displays = SDL_GetDisplays(&num_displays);
2117 if (displays) {
2118 for (i = 0; i < num_displays; ++i) {
2119 SDL_DisplayID instance_id = displays[i];
2120 const char *name = SDL_GetDisplayName(instance_id);
2121
2122 SDL_Log("Display %" SDL_PRIu32 ": %s", instance_id, name ? name : "Unknown");
2123 }
2124 SDL_free(displays);
2125 }
2126 SDL_QuitSubSystem(SDL_INIT_VIDEO);
2127 }
2128}
2129```
2130
2131SDL_CreateWindow() has been simplified and no longer takes a window position. You can use SDL_CreateWindowWithProperties() if you need to set the window position when creating it, e.g.
2132```c
2133 SDL_PropertiesID props = SDL_CreateProperties();
2134 SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, title);
2135 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, x);
2136 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, y);
2137 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, width);
2138 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, height);
2139 // For window flags you should use separate window creation properties,
2140 // but for easier migration from SDL2 you can use the following:
2141 SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_FLAGS_NUMBER, flags);
2142 pWindow = SDL_CreateWindowWithProperties(props);
2143 SDL_DestroyProperties(props);
2144 if (window) {
2145 ...
2146 }
2147```
2148
2149The SDL_WINDOWPOS_UNDEFINED_DISPLAY() and SDL_WINDOWPOS_CENTERED_DISPLAY() macros take a display ID instead of display index. The display ID 0 has a special meaning in this case, and is used to indicate the primary display.
2150
2151The SDL_WINDOW_SHOWN flag has been removed. Windows are shown by default and can be created hidden by using the SDL_WINDOW_HIDDEN flag.
2152
2153The SDL_WINDOW_SKIP_TASKBAR flag has been replaced by the SDL_WINDOW_UTILITY flag, which has the same functionality.
2154
2155SDL_DisplayMode now includes the pixel density which can be greater than 1.0 for display modes that have a higher pixel size than the mode size. You should use SDL_GetWindowSizeInPixels() to get the actual pixel size of the window back buffer.
2156
2157The refresh rate in SDL_DisplayMode is now a float, as well as being represented as a precise fraction with numerator and denominator.
2158
2159Rather than iterating over display modes using an index, there is a new function SDL_GetFullscreenDisplayModes() to get the list of available fullscreen modes on a display.
2160```c
2161{
2162 SDL_DisplayID display = SDL_GetPrimaryDisplay();
2163 int num_modes = 0;
2164 SDL_DisplayMode **modes = SDL_GetFullscreenDisplayModes(display, &num_modes);
2165 if (modes) {
2166 for (i = 0; i < num_modes; ++i) {
2167 SDL_DisplayMode *mode = modes[i];
2168 SDL_Log("Display %" SDL_PRIu32 " mode %d: %dx%d@%gx %gHz",
2169 display, i, mode->w, mode->h, mode->pixel_density, mode->refresh_rate);
2170 }
2171 SDL_free(modes);
2172 }
2173}
2174```
2175
2176SDL_GetDesktopDisplayMode() and SDL_GetCurrentDisplayMode() return pointers to display modes rather than filling in application memory.
2177
2178Windows now have an explicit fullscreen mode that is set, using SDL_SetWindowFullscreenMode(). The fullscreen mode for a window can be queried with SDL_GetWindowFullscreenMode(), which returns a pointer to the mode, or NULL if the window will be fullscreen desktop. SDL_SetWindowFullscreen() just takes a boolean value, setting the correct fullscreen state based on the selected mode.
2179
2180SDL_WINDOW_FULLSCREEN_DESKTOP has been removed, and you can call SDL_GetWindowFullscreenMode() to see whether an exclusive fullscreen mode will be used or the borderless fullscreen desktop mode will be used when the window is fullscreen.
2181
2182SDL_SetWindowBrightness(), SDL_GetWindowBrightness, SDL_SetWindowGammaRamp(), and SDL_GetWindowGammaRamp have been removed from the API, because they interact poorly with modern operating systems and aren't able to limit their effects to the SDL window.
2183
2184Programs which have access to shaders can implement more robust versions of those functions using custom shader code rendered as a post-process effect.
2185
2186Removed SDL_GL_CONTEXT_EGL from OpenGL configuration attributes. You can instead use `SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);`
2187
2188SDL_GL_GetProcAddress() and SDL_EGL_GetProcAddress() now return `SDL_FunctionPointer` instead of `void *`, and should be cast to the appropriate function type. You can define SDL_FUNCTION_POINTER_IS_VOID_POINTER in your project to restore the previous behavior.
2189
2190SDL_GL_DeleteContext() has been renamed to SDL_GL_DestroyContext to match SDL naming conventions (and glX/EGL!).
2191
2192SDL_GL_GetSwapInterval() takes the interval as an output parameter and returns true if the function succeeds or false if there was an error.
2193
2194SDL_GL_GetDrawableSize() has been removed. SDL_GetWindowSizeInPixels() can be used in its place.
2195
2196The SDL_WINDOW_TOOLTIP and SDL_WINDOW_POPUP_MENU window flags are now supported on Windows, Mac (Cocoa), X11, and Wayland. Creating windows with these flags must happen via the `SDL_CreatePopupWindow()` function. This function requires passing in the handle to a valid parent window for the popup, and the popup window is positioned relative to the parent.
2197
2198SDL_WindowFlags is used instead of Uint32 for API functions that refer to window flags, and has been extended to 64 bits.
2199
2200SDL_GetWindowOpacity() directly returns the opacity instead of using an out parameter.
2201
2202The following functions have been renamed:
2203* SDL_GL_DeleteContext() => SDL_GL_DestroyContext(), returns bool
2204* SDL_GetClosestDisplayMode() => SDL_GetClosestFullscreenDisplayMode(), returns bool
2205* SDL_GetDisplayOrientation() => SDL_GetCurrentDisplayOrientation()
2206* SDL_GetPointDisplayIndex() => SDL_GetDisplayForPoint()
2207* SDL_GetRectDisplayIndex() => SDL_GetDisplayForRect()
2208* SDL_GetWindowDisplayIndex() => SDL_GetDisplayForWindow()
2209* SDL_GetWindowDisplayMode() => SDL_GetWindowFullscreenMode()
2210* SDL_HasWindowSurface() => SDL_WindowHasSurface()
2211* SDL_IsScreenSaverEnabled() => SDL_ScreenSaverEnabled()
2212* SDL_SetWindowDisplayMode() => SDL_SetWindowFullscreenMode(), returns bool
2213
2214The following functions have been removed:
2215* SDL_GetDisplayDPI() - not reliable across platforms, approximately replaced by multiplying SDL_GetWindowDisplayScale() times 160 on iPhone and Android, and 96 on other platforms.
2216* SDL_GetDisplayMode()
2217* SDL_GetNumDisplayModes() - replaced with SDL_GetFullscreenDisplayModes()
2218* SDL_GetNumVideoDisplays() - replaced with SDL_GetDisplays()
2219* SDL_SetWindowGrab() - use SDL_SetWindowMouseGrab() instead, along with SDL_SetWindowKeyboardGrab() if you also set SDL_HINT_GRAB_KEYBOARD.
2220* SDL_GetWindowGrab() - use SDL_GetWindowMouseGrab() instead, along with SDL_GetWindowKeyboardGrab() if you also set SDL_HINT_GRAB_KEYBOARD.
2221* SDL_GetWindowData() - use SDL_GetPointerProperty() instead, along with SDL_GetWindowProperties()
2222* SDL_SetWindowData() - use SDL_SetPointerProperty() instead, along with SDL_GetWindowProperties()
2223* SDL_CreateWindowFrom() - use SDL_CreateWindowWithProperties() with the properties that allow you to wrap an existing window
2224* SDL_SetWindowInputFocus() - use SDL_RaiseWindow() instead
2225* SDL_SetWindowModalFor() - use SDL_SetWindowParent() with SDL_SetWindowModal() instead
2226* SDL_SetWindowBrightness() - use a shader or other in-game effect.
2227* SDL_GetWindowBrightness() - use a shader or other in-game effect.
2228* SDL_SetWindowGammaRamp() - use a shader or other in-game effect.
2229* SDL_GetWindowGammaRamp() - use a shader or other in-game effect.
2230
2231The SDL_Window id type is named SDL_WindowID
2232
2233The following environment variables have been removed:
2234* SDL_VIDEO_GL_DRIVER - replaced with the hint SDL_HINT_OPENGL_LIBRARY
2235* SDL_VIDEO_EGL_DRIVER - replaced with the hint SDL_HINT_EGL_LIBRARY
2236
2237The following symbols have been renamed:
2238* SDL_DISPLAYEVENT_DISCONNECTED => SDL_EVENT_DISPLAY_REMOVED
2239* SDL_DISPLAYEVENT_MOVED => SDL_EVENT_DISPLAY_MOVED
2240* SDL_DISPLAYEVENT_ORIENTATION => SDL_EVENT_DISPLAY_ORIENTATION
2241* SDL_GLattr => SDL_GLAttr
2242* SDL_GLcontextFlag => SDL_GLContextFlag
2243* SDL_GLcontextReleaseFlag => SDL_GLContextReleaseFlag
2244* SDL_GLprofile => SDL_GLProfile
2245* SDL_WINDOWEVENT_CLOSE => SDL_EVENT_WINDOW_CLOSE_REQUESTED
2246* SDL_WINDOWEVENT_DISPLAY_CHANGED => SDL_EVENT_WINDOW_DISPLAY_CHANGED
2247* SDL_WINDOWEVENT_ENTER => SDL_EVENT_WINDOW_MOUSE_ENTER
2248* SDL_WINDOWEVENT_EXPOSED => SDL_EVENT_WINDOW_EXPOSED
2249* SDL_WINDOWEVENT_FOCUS_GAINED => SDL_EVENT_WINDOW_FOCUS_GAINED
2250* SDL_WINDOWEVENT_FOCUS_LOST => SDL_EVENT_WINDOW_FOCUS_LOST
2251* SDL_WINDOWEVENT_HIDDEN => SDL_EVENT_WINDOW_HIDDEN
2252* SDL_WINDOWEVENT_HIT_TEST => SDL_EVENT_WINDOW_HIT_TEST
2253* SDL_WINDOWEVENT_ICCPROF_CHANGED => SDL_EVENT_WINDOW_ICCPROF_CHANGED
2254* SDL_WINDOWEVENT_LEAVE => SDL_EVENT_WINDOW_MOUSE_LEAVE
2255* SDL_WINDOWEVENT_MAXIMIZED => SDL_EVENT_WINDOW_MAXIMIZED
2256* SDL_WINDOWEVENT_MINIMIZED => SDL_EVENT_WINDOW_MINIMIZED
2257* SDL_WINDOWEVENT_MOVED => SDL_EVENT_WINDOW_MOVED
2258* SDL_WINDOWEVENT_RESIZED => SDL_EVENT_WINDOW_RESIZED
2259* SDL_WINDOWEVENT_RESTORED => SDL_EVENT_WINDOW_RESTORED
2260* SDL_WINDOWEVENT_SHOWN => SDL_EVENT_WINDOW_SHOWN
2261* SDL_WINDOW_ALLOW_HIGHDPI => SDL_WINDOW_HIGH_PIXEL_DENSITY
2262* SDL_WINDOW_INPUT_GRABBED => SDL_WINDOW_MOUSE_GRABBED
2263
2264The following symbols have been removed:
2265* SDL_WINDOWEVENT_SIZE_CHANGED - handle the SDL_EVENT_WINDOW_RESIZED and SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED events instead
2266* SDL_WINDOWEVENT_TAKE_FOCUS
2267
2268The following window operations are now considered to be asynchronous requests and should not be assumed to succeed unless
2269a corresponding event has been received:
2270* SDL_SetWindowSize() (SDL_EVENT_WINDOW_RESIZED)
2271* SDL_SetWindowPosition() (SDL_EVENT_WINDOW_MOVED)
2272* SDL_MinimizeWindow() (SDL_EVENT_WINDOW_MINIMIZED)
2273* SDL_MaximizeWindow() (SDL_EVENT_WINDOW_MAXIMIZED)
2274* SDL_RestoreWindow() (SDL_EVENT_WINDOW_RESTORED)
2275* SDL_SetWindowFullscreen() (SDL_EVENT_WINDOW_ENTER_FULLSCREEN / SDL_EVENT_WINDOW_LEAVE_FULLSCREEN)
2276
2277If it is required that operations be applied immediately after one of the preceding calls, the `SDL_SyncWindow()` function
2278will attempt to wait until all pending window operations have completed. The `SDL_HINT_VIDEO_SYNC_WINDOW_OPERATIONS` hint
2279can also be set to automatically synchronize after all calls to an asynchronous window operation, mimicking the behavior
2280of SDL 2. Be aware that synchronizing can potentially block for long periods of time, as it may have to wait for window
2281animations to complete. Also note that windowing systems can deny or not precisely obey these requests (e.g. windows may
2282not be allowed to be larger than the usable desktop space or placed offscreen), so a corresponding event may never arrive
2283or not contain the expected values.
2284
2285## SDL_vulkan.h
2286
2287SDL_Vulkan_GetInstanceExtensions() no longer takes a window parameter, and no longer makes the app allocate query/allocate space for the result, instead returning a static const internal string.
2288
2289SDL_Vulkan_GetVkGetInstanceProcAddr() now returns `SDL_FunctionPointer` instead of `void *`, and should be cast to PFN_vkGetInstanceProcAddr.
2290
2291SDL_Vulkan_CreateSurface() now takes a VkAllocationCallbacks pointer as its third parameter. If you don't have an allocator to supply, pass a NULL here to use the system default allocator (SDL2 always used the system default allocator here).
2292
2293SDL_Vulkan_GetDrawableSize() has been removed. SDL_GetWindowSizeInPixels() can be used in its place.
2294
2295SDL_vulkanInstance and SDL_vulkanSurface have been removed. They were for compatibility with Tizen, who had built their own Vulkan interface into SDL2, but these apps will need changes for the SDL3 API if they are upgraded anyhow.