Compare commits

...
Author SHA1 Message Date
Sam Lantinga 96292a5b46 Updated to version 3.2.20 for release 2025-08-04 09:58:55 -07:00
Petar Popovic ffa618c00b SDL_LoadWAV_IO(): On error, set *audio_buf to NULL and *audio_len to 0
(cherry picked from commit 23e08f7807)
2025-08-03 13:44:37 -04:00
Petar Popovic 291b9b3c82 SDL_enabled_assert(): Use NULL istead of 0 to explicity initialize the pointer members of SDL_AssertData
(cherry picked from commit faf3bd9991)
2025-08-03 13:36:14 -04:00
Frank Praznik ec45117f0f x11: Filter mouse wheel events from "Master" devices
Discard wheel events from "Master" devices to avoid duplicates, as wheel events are stateless and can't be deduplicated.

(cherry picked from commit 51ce3f8c8d)
2025-08-02 18:57:44 -04:00
Frank Praznik 0d7aff9c56 GPU: Vulkan backend flags command buffer for cleanup when swapchain is requested
When skipping presentation due to the window being hidden, presentDataCount is not incremented on the command buffer, and subsequently the submitted command buffers will not be cleaned up as long as the window is hidden. This results in a lag spike when showing the window due to all previously submitted command buffers suddenly being cleaned up at once, and lag at shutdown due to an equivalent number of fences needing to be destroyed.

Instead of relying on presentDataCount to determine whether a command buffer should be cleaned up, use a flag, which is set under the appropriate circumstances.

(cherry picked from commit 42463569d5)
2025-08-02 09:24:21 -07:00
Petar Popovic d31b239288 Fix double-free warning in src/hidapi/linux/hid.c
(cherry picked from commit ae5ce258cf)
2025-08-02 07:09:12 -07:00
capehill b1cadf0e99 Fix SDL_BlitSurfaceScaled crash
SDL_BlitSurfaceScaled could crash when passed large coordinates, due
to final_dst.w or final_dst.h getting negative values.

(cherry picked from commit 1c5c3b1479)
2025-08-01 09:22:38 -07:00
Frank Praznik c1f67585e6 wayland: Cleanup an outdated conditional and comment
There may have been a reason for not attaching a null buffer when destroying a popup at some point in the past, but that is unnecessary now, as is the comment about ShowWindow crashing, as ShowWindow assures that a null buffer is attached before (re)creating the window.

(cherry picked from commit 550d95e04f)
2025-08-01 10:40:32 -04:00
A1029384756 93988e28c0 wayland: reorder surface destruction to avoid premature blanking
(cherry picked from commit 9034375d2f)
2025-08-01 10:40:32 -04:00
Matthew Zavislak edef6e66e9 Support Google Play 16 KB Page Size Requirement (#13470)
- See: https://developer.android.com/guide/practices/page-sizes#update-packaging
- Also, make min API uniform at 21 (from 16 and 23 in a few places)

(cherry picked from commit dc2c83c383)
2025-07-31 16:21:02 -07:00
Petar Popovic e3f47809c4 Fix potential memory leak in SDL_render_gles2.c
(cherry picked from commit 09221820f6)
2025-07-31 16:19:10 -07:00
cosmonaut f759e7ac59 GPU: Bail out of aquiring Vulkan swapchain if window is hidden
(cherry picked from commit c5edf4bd5b)
2025-07-31 16:03:19 -07:00
Frank Praznik 544eb2c5a9 wayland: Adjust popup adjoining check
The previous calculation could result in a window whose original position was positioned exactly corner-to-corner with the parent not being adjusted to be adjoining, and thus subject to spurious closure.

(cherry picked from commit b0cdb7143f)
2025-07-31 12:13:54 -04:00
Cheney Wang 30e3eba20a GPU: Fix wrong Vulkan swapchain size when retrying acquire
(cherry picked from commit d8ac51859e)
2025-07-30 15:35:23 -07:00
Wouter Wijsman f0e85a2a9c psp: fix audio not playing
(cherry picked from commit 3d1a28ccf2)
2025-07-30 13:11:23 -07:00
Thaddeus Crews 106af5b46a Define relevant macros when LACKS_ERRNO_H is true
(cherry picked from commit 3195980b49)
2025-07-30 09:11:22 -07:00
Stefan Schlosser 522716ed90 SDL_getenv.c: fix dynamic loading of environ symbol on FreeBSD
The current implementation uses the returned address of the `dlsym` function
directly to load the `environ` symbol. But this function doesn't return the
address to the symbol itself, instead it returns the address to the location
where the actual address is stored, i.e. it's an additional indirection.
Consequently, the implementation fails to load and process the environment
variables successfully.

One example where this error shows up is in the `Dialog API`: in an `X11`
environment, the `zenity` driver requires access to the user's `DISPLAY` and
`XAUTHORITY` environment variables. Because these variables aren't transfered
to the `zenity` process, no dialogs are shown. This can be exercised in the
`test/testdialog.c` testprogram.

The fix changes the indirection level of the `dlsym` call from `char **` to
`char ***`, does a `NULL`-check in case the call failed, and returns the
dereferenced actual adress to the `environ` symbol.

(cherry picked from commit 10458f2cac)
2025-07-30 07:06:54 -07:00
Evan Hemsley a65fbb0211 GPU: Fix incorrect block size when D3D12 uniform buffer is rotated (#13469)
(cherry picked from commit 07af4b237b)
2025-07-29 15:51:58 -07:00
Petar Popovic 46ec859bd1 Fix two use-after-free warnings
(cherry picked from commit f27dbb22f0)
2025-07-29 12:29:34 -07:00
Xen 2a7aa4eae4 Update SDL_clipboard.h
Typo fixes and a small addition to SDL_SetClipboardData about mime_type list usage clarity.

(cherry picked from commit b3ba1c159e)
2025-07-28 11:59:34 -07:00
Dan Andrus c31ddf021e Check NSWindow::isVisible before sending SDL_WINDOWEVENT_RESTORED during Cocoa_WindowListener::windowDidResize
(cherry picked from commit 30f0aeb26a)
2025-07-28 14:47:45 -04:00
Shootfast eaa2a8239f Fixed typo in SDL_scancode.h
The backslash/vertical line key is between the left shift and "Z" key on ISO keyboards

(cherry picked from commit 507ee033cc)
2025-07-27 19:58:45 -07:00
Brenton Bostick d313ecb737 Fix warning on Android arm-v7
Building SDL for armeabi-v7a gives this warning:
```
SDL/src/audio/SDL_audiotypecvt.c:541:14: warning: '#pragma FENV_ACCESS' is not supported on this target - ignored [-Wignored-pragmas]
  541 | #pragma STDC FENV_ACCESS ON
```

(cherry picked from commit ed4de7aeed)
2025-07-27 08:16:21 -07:00
Petar Popovic 64b2af0340 SDL_gpu.c: Fixed deref-before-check warning
(cherry picked from commit 6a5af95364)
2025-07-26 12:08:57 -07:00
Anonymous Maarten 58d0702948 ci+n3ds: avoid apt-get package manager
- use Unix Makefiles (with parallelization) CMake generator
- use binutils strings binary from devkitpro

(cherry picked from commit e6d200e51c)
2025-07-26 16:06:36 +02:00
Sam Lantinga 707717e94b Reverted: Added Steam Virtual Gamepad support to the GameInput driver
This version of SDL doesn't support newer GameInput versions required for this feature.
2025-07-24 14:00:20 -07:00
Sam Lantinga a140bba55a Fixed building with GameInput v1.0
(cherry picked from commit e5d57d8ad6)
2025-07-24 10:52:28 -07:00
Sam Lantinga f4ddacacd0 Fixed building with GameInput v1.0
(cherry picked from commit 0ee0fe1572)
2025-07-24 10:43:05 -07:00
Sam Lantinga ebba656bdb Added Steam Virtual Gamepad support to the GameInput driver
(cherry picked from commit 66dad9c21f)
2025-07-24 10:38:02 -07:00
Sam Lantinga b78c61d67a Fixed double SDL_EVENT_GAMEPAD_ADDED for controllers with automatic gamepad mappings
(cherry picked from commit 6babade758)
2025-07-24 10:38:02 -07:00
L zard 4210aa61e1 build_config_windows: define HAVE_STDARG/STDDEF_H outside of
condition.
They are defined in both `#if HAVE_LIBC` and its `#else` anyway.
[sdl-ci-filter msvc-*]

(cherry picked from commit ea995b1694)
2025-07-21 14:45:19 -07:00
L zard d8a345d924 build_config_windows: fix HAVE_VSSCANF defined regardless of MSVC version.
[sdl-ci-filter msvc-*]

(cherry picked from commit a977a11fa6)
2025-07-21 14:45:19 -07:00
Acclution b8dc9767da GPU: Fix Vulkan compute uniform descriptor not being marked as set (#13389)
(cherry picked from commit 8bd29f7ca3)
2025-07-18 15:30:05 -07:00
BurntRanch 1ab01b9367 Clarify SDL_GPUVertexBufferDescription.pitch comment (#13381)
(cherry picked from commit ee6d8f78f4)
2025-07-17 08:55:04 -07:00
Sam Lantinga ee371ff740 Fixed crash if a clipboard event was sent with video uninitialized
This can happen if you're using SDL on Android without using the video subsystem.

(cherry picked from commit 855d28e97a)
2025-07-17 08:48:00 -07:00
Evan Hemsley ef58dd77ca GPU: Clean up properties in SDL_ReleaseGPUTexture (#13378) 2025-07-17 00:23:52 -07:00
Ryan C. Gordon e6a7121904 audio: Binding an SDL_AudioStream will set missing formats.
It _must_ have the format set for the opposite side from the device (so
playback needs the src format set, and recording needs the dst format set),
since the stream gets mangled by the device thread if not. So if it has never
been set (stream created with NULL audiospec), just set it to match the device.
If the stream is just meant to buffer and not convert, this is desired
behavior, even if it didn't also fix a bug.

Binding the audio stream will always set the device side's format, as usual;
this does not need to be set by the caller at all.

Fixes #13363.

(cherry picked from commit f2ae6503c0)
2025-07-15 06:44:12 -04:00
Sam Lantinga a6ed8ab59d Updated to version 3.2.19 for development 2025-07-14 11:44:22 -07:00
Sam Lantinga bd40d0ded1 Removed the Mayflash GameCube adapter from the PS3 controller list
(cherry picked from commit 277f91c317)
2025-07-14 11:30:46 -07:00
Andon M. Coleman 68bfcb6c54 Allow 1 kHz sample rate for DualSense Edge over USB
DualSense Edge natively reports at 1 kHz for all connection types, but gyro sample rate was limited to 250 Hz for USB.

(cherry picked from commit a07cf3ecdc)
2025-07-14 10:02:46 -07:00
Josh Dowell 0d01efca52 windows: Fix crash when using a system that reports itself as Windows 17763 or newer, but is missing many of the newer dark mode window functions (Linux Mint Cinnamon w/ Proton 7.0.6)
(cherry picked from commit 0a50b798bf)
2025-07-13 20:10:26 -07:00
Kyle Sylvestre 0e65e04ce1 remove spoofed SDL_HelperWindow when SDL_VIDEO is off
(cherry picked from commit 0f061ff154)
2025-07-12 07:48:56 -07:00
Kyle Sylvestre 58d351fe98 check SDL_PLATFORM_WINDOWS instead of SDL_VIDEO_DRIVER_WINDOWS when using SDL_HelperWindow
(cherry picked from commit d42217ba26)
2025-07-12 07:48:56 -07:00
Kyle Sylvestre 9b71f18141 move SDL_HelperWindow outside of video
move to SDL_window.c to prevent relying on SDL_VIDEO

(cherry picked from commit a190e3b514)
2025-07-12 07:48:56 -07:00
Anonymous Maarten 554f08bac3 ci: build MSVC release binary on windows-2025 2025-07-12 01:25:08 +02:00
Sam Lantinga 913813a933 Updated to version 3.2.18 for release 2025-07-11 15:56:55 -07:00
Ryan C. Gordon 4e34c771e4 Revert "windows: Use wglSwapLayerBuffers if available."
This reverts commit b8ee44ca6a.

This is reverting a cherry-pick. It's probably too risky for a 3.2.x release,
but we'll let it marinate on main, for 3.4.0.
2025-07-11 18:25:14 -04:00
Ryan C. Gordon 9995174e68 gpu: Fixed uninitialized variable in SDL_AcquireGPUCommandBuffer().
Fixes #13191.

(cherry picked from commit 190afc0f4f)
2025-07-11 18:23:15 -04:00
Ryan C. Gordon 5a0197d430 wasapi: Force enumerated audio devices to report themselves as float32 format.
This is what they'll end up being when used through WASAPI in shared mode,
regardless of what the hardware actually expects.

Reference Issue #12914.

(cherry picked from commit a81cf566f4)
2025-07-11 18:23:01 -04:00
Sam Lantinga 4a55143e15 Fixed build
(cherry picked from commit 92e8224d32)
2025-07-11 14:12:27 -07:00
Sam Lantinga 87c9bc1b1f Fixed long delay when enumerating the Razer Huntsman keyboard
Fixes https://github.com/libsdl-org/SDL/issues/13236

(cherry picked from commit 0b2e389ee3)
2025-07-11 14:12:27 -07:00
Sam Lantinga 16a57b70f7 Set hwndTarget to NULL when unregistering raw input
Fixes https://github.com/libsdl-org/SDL/issues/13335

(cherry picked from commit 937e8d55a4)
2025-07-11 12:14:50 -07:00
Aleksey Sakovets 69564cd0b1 README-macos.md: replace old API calls
(cherry picked from commit 6386781351)
2025-07-11 12:08:58 -07:00
Ryan C. Gordon da648b00e7 cocoa: Don't minimize fullscreen windows for a modal file dialog.
macOS sends a focus loss event when the dialog is created, which causes SDL
to try to minimize the window, which confuses the entire system. So in this
special case, don't do the minimization.

Fixes #13168.

(cherry picked from commit 9af93abd4f)
2025-07-11 15:06:10 -04:00
Sam Lantinga 5886d90308 Fixed long delay when enumerating the Razer Huntsman keyboard
Fixes https://github.com/libsdl-org/SDL/issues/13236

(cherry picked from commit f199aafaeb)
2025-07-11 11:56:06 -07:00
Ryan C. Gordon e84df0cad1 x11: Avoid duplicate mouse events when using a pen device.
Fixes #12968.

(cherry picked from commit 72f4dd17be)
2025-07-11 14:31:07 -04:00
Frank Praznik e482904111 Add support for non-constrained and non-grabbing popups
By default, popups are automatically constrained to be completely within display bounds, so as not to cut off information and result in an unusable menu, or unreadable tooltip. In some cases, however, this is not wanted, so a property to toggle this behavior is added.

There are also cases where the client may not want a popup menu to implicitly grab the keyboard focus, as is the default behavior, so popup menus now respect the focusable flag/property, as well as being able to toggle focus grabbing via SDL_SetWindowFocusable().

(cherry picked from commit b871ac0d97)
2025-07-11 14:26:51 -04:00
Ryan C. Gordon b8ee44ca6a windows: Use wglSwapLayerBuffers if available.
It apparently works better (or can work better?) on multimonitor setups
than SwapBuffers.

This should be available back to Windows 95, but just in case, it falls
back to standard SwapBuffers if not available.

Fixes #13269.

(cherry picked from commit f286558bae)
2025-07-11 13:25:18 -04:00
Anonymous Maarten 4a4abe4240 cmake: remove /RTC1 from CXX flags when building with SDL_LIBC=OFF
(cherry picked from commit cfb8e591cb)
2025-07-11 10:00:22 -07:00
Wouter Wijsman fe47f5cc30 PSP: Truncate thread name when passing to sceKernelCreateThread
(cherry picked from commit c64518f300)
2025-07-11 10:00:07 -07:00
Ryan C. Gordon 5b64be0810 docs: Documentation for SDL_Swap64 was reporting the wrong return type.
Fixes #13309.

(cherry picked from commit 530639aa4a)
2025-07-11 09:59:13 -07:00
Ryan C. Gordon 17656d051b cocoa: Don't use trick of briefly focusing the Dock on newer macOS releases.
On newer systems, the trick isn't necessary, and if you do it, if the user is
moving the mouse when launching the app, it'll show a hidden Dock.

Fixes #10340.

(cherry picked from commit 279dabfc96)
2025-07-10 15:54:25 -04:00
Ozkan Sezer 233fce456a fix ARM64 linkage with Visual Studio >= 17.14 when SDL_LIBC is disabled
Reference issue:  https://github.com/libsdl-org/SDL/issues/13254

(cherry picked from commit 2fb6abb9ad)
(cherry picked from commit fb0e03f262)
2025-07-09 01:32:00 +03:00
Frank Praznik 5290bb036c wayland: Ensure that the xdg_surface is always configured after creation
The spec states that xdg_surface must have seen an initial configure event before attaching a buffer, however, this was only being done when initially showing the window, and not after show->hide->show cycle.

Always wait for the initial configure event when (re)creating an xdg_surface as part of the show window sequence.

(cherry picked from commit ecdc6f2adb)
2025-07-05 12:10:28 -04:00
WillyJL 2bff72b4f6 SDL3 GPU: Fix -Wbool-conversion warnings
(cherry picked from commit 4eff36ef53)
2025-06-29 13:33:56 -04:00
Anonymous Maarten 08ebeaee5c cmake: Android always needs a native HIDAPI implementation
(cherry picked from commit 89eef1bd34)
2025-06-26 15:43:29 -07:00
Caleb Heuer 12b56f5447 Allow overriding SDL_FORK_MESSAGEBOX in build environment
(cherry picked from commit cd98b66114)
2025-06-26 10:49:48 -07:00
Frank Praznik 165b86e7b7 x11: Always update the borders on frame extent events
Always update the border sizes on frame extent events, or they can incorrectly still be zero if followed by a PropertyNotify event when leaving fullscreen.

Fixes sending the correct restored window size when leaving fullscreen in fvwm.

(cherry picked from commit 0ac1241b7a)
2025-06-26 11:53:32 -04:00
Sam Lantinga 608101a185 Update the viewport when logical presentation changes
Fixes https://github.com/libsdl-org/SDL/issues/13256

(cherry picked from commit 727b4924c8)
2025-06-25 09:59:13 -07:00
Paul Vick 554bee6aae Fix #13276: Crash in SDL_GetAudioDeviceChannelMap
(cherry picked from commit de6a23028a)
2025-06-25 09:59:07 -07:00
Rémi Verschelde 3e0ce51067 joystick: Fix MSVC errors C2099 with /fp:strict
(cherry picked from commit db3a35e9bc)
2025-06-24 07:32:26 -07:00
Ozkan Sezer 7261c43342 alsa: change an SDL_LogError into SDL_LogDebug.
it is informational only and seeing ERROR on the terminal was confusing

(cherry picked from commit af8bee2dd1)
2025-06-22 21:05:10 -07:00
Marcin Serwin ad57c6ea37 test: Fix resource paths in testtray
Signed-off-by: Marcin Serwin <marcin@serwin.dev>
(cherry picked from commit bbc674b9e7)
2025-06-22 21:03:55 -07:00
mitchellcairns caecff650d Resolve bug for calibration Nintendo Switch Pro Controller (#13260)
Resolves a bug which prevents the stored calibration data from loading, only allowing loading of factory-installed calibration data

(cherry picked from commit 796961acec)
2025-06-22 21:00:01 -07:00
Mitch Cairns f6300be4b2 Fixed Nintendo Switch thumbstick calibration
(cherry picked from commit 3a6f9e01f8)
2025-06-22 15:27:30 -07:00
Sam Lantinga bde5687a3c Fixed Nintendo Switch Pro thumbstick calibration
Fixes https://github.com/libsdl-org/SDL/issues/13246

(cherry picked from commit 038a3806eb)
2025-06-21 19:57:04 -07:00
Sam Lantinga 0f3504f78d Updated testffmpeg for ffmpeg 7.1
(cherry picked from commit e6c2649afc)
2025-06-21 08:49:43 -07:00
Sam Lantinga 0aaa0321cc Fixed warning C5286: implicit conversion from enum type 'VkFilter' to enum type 'SDL_ScaleMode' 2025-06-21 07:41:20 -07:00
Josh Dowell caaaf52583 win32: Invalidate window message mouse button flags when reading buttons from raw input or GameInput
SDL2 would set a high bit in the mouse button flags to indicate when raw input had been read from, without this, if you hold down a mouse button and left raw input mode (leaving relative mode) the button would remain partially stuck, and would require two clicks to start producing mouse down events again.
SDL3's raw input code was refactored to not use the mouse button flags, but forgot to invalidate the flags, causing this bug to manifest.

(cherry picked from commit 6aedc488d3)
2025-06-21 07:29:05 -07:00
Ozkan Sezer 56449f167d hidapi/libusb: disable C5287 warning in MSVC builds
A quick search implies that it is a bogus warning:
https://www.google.com/search?q=visual+studio+C5287

(cherry picked from commit 81e3066303)
2025-06-21 07:16:36 -07:00
Ryan C. Gordon c7325228dc audio: Enumerating audio devices will skip zombie devices still in the hash.
(cherry picked from commit eb04219efe)
2025-06-20 14:49:32 -07:00
Sam Lantinga 079967afa5 Clarify that SDL_GetAudioStreamDevice() returns the logical device.
(cherry picked from commit c19ad189dc)
2025-06-20 14:01:32 -07:00
Lilian Gimenez 2ed55b614c Fix support for F21 to F24 scancodes on Linux
(cherry picked from commit e4e29b8601)
2025-06-20 09:07:27 -07:00
Frank Praznik 28721e3cd2 test: Fix a window parenting bug in testmodal
(cherry picked from commit 390fe65323)
2025-06-18 09:27:03 -04:00
Frank Praznik 9d9845d063 video: Explicitly disallow setting the parent of a window to itself
Doing so causes a cycle in the window hierarchy tree graph, which leads to infinite recursion when destroying the windows.

(cherry picked from commit ca9b7c8ea3)
2025-06-18 09:27:03 -04:00
ceski a96dc76831 Read Switch controller gyro/accel sensitivity coeffs (SDL3)
These vary by controller, so using the stored values should improve the accuracy of the sensor data.

(cherry picked from commit 558a89fdb6)
2025-06-13 12:18:43 -07:00
e4m2 ad8e517227 Tweak Vulkan include guard check and 64-bit platform defines (#13210)
(cherry picked from commit c5b1341757)
2025-06-12 09:32:32 -07:00
Sam Lantinga 8d578d590f Fixed replacing existing specific gamepad mappings
If the first mapping we see doesn't have a CRC, continue looking for another exact CRC match.

Fixes testautomation --filter TestVirtualJoystick

(cherry picked from commit 5826966873)
2025-06-06 09:55:04 -07:00
Sam Lantinga 6b4a211374 Added support for the ZEROPLUS P4 Wired Gamepad
(cherry picked from commit f90a21483c)
2025-06-06 09:27:17 -07:00
Sam Lantinga 55b023c961 Remove the CRC from automatically generated gamepad mappings
Fixes https://github.com/libsdl-org/SDL/issues/13127

(cherry picked from commit 638acdc02a)
2025-06-06 09:25:19 -07:00
Frank Praznik e2d0fe3e2f x11: Resize fixed-size windows after mapping on xmonad
XMonad ignores size hints and shrinks the client area to overlay borders on fixed-size windows, even if no borders were requested, resulting in the window client area being smaller than requested. Calling XResizeWindow after mapping seems to fix it, even though resizing fixed-size windows in this manner doesn't work on any other window manager.

(cherry picked from commit 45eb6310a8)
2025-06-06 11:35:56 -04:00
Frank Praznik 6b56ff7a97 win32: Ensure that text input is initially disabled when creating a window
Windows seems to implicitly enable IME text input on windows created while an IME is active, which causes the IME suggestion window to pop up when keys are pressed, even if a client never explicitly enabled it. Ensure that IME support is initially disabled on new windows; SDL will enable it at a later time, if required.

(cherry picked from commit 22fa45b3c1)
2025-06-05 12:21:49 -04:00
Ethan Lee 67f796ebde gdk: Ignore focus loss events caused by text input showing the OSK 2025-06-04 09:41:06 -04:00
Sam Lantinga 06da7490fc Added support for the NACON Revolution X Unlimited controller on macOS
This adds support for the controller in Bluetooth mode.

Fixes https://github.com/libsdl-org/SDL/issues/13143

(cherry picked from commit 6622f4e1ea)
2025-06-03 15:08:11 -07:00
Sam Lantinga af83c442d3 Fixed input from the MayFlash GameCube adapter with version 7 firmware
(cherry picked from commit 7457857304)
2025-06-03 11:14:09 -07:00
Sam Lantinga d726e98596 Updated to version 3.2.17 for development 2025-06-02 15:57:36 -07:00
96 changed files with 1091 additions and 589 deletions

No files matched your search

+9 -2
View File
@@ -174,6 +174,7 @@ class JobDetails:
brew_packages: list[str] = dataclasses.field(default_factory=list)
cmake_toolchain_file: str = ""
cmake_arguments: list[str] = dataclasses.field(default_factory=list)
cmake_generator: str = "Ninja"
cmake_build_arguments: list[str] = dataclasses.field(default_factory=list)
clang_tidy: bool = True
cppflags: list[str] = dataclasses.field(default_factory=list)
@@ -222,6 +223,7 @@ class JobDetails:
check_sources: bool = False
setup_python: bool = False
pypi_packages: list[str] = dataclasses.field(default_factory=list)
binutils_strings: str = "strings"
def to_workflow(self, enable_artifacts: bool) -> dict[str, str|bool]:
data = {
@@ -255,6 +257,7 @@ class JobDetails:
"cflags": my_shlex_join(self.cppflags + self.cflags),
"cxxflags": my_shlex_join(self.cppflags + self.cxxflags),
"ldflags": my_shlex_join(self.ldflags),
"cmake-generator": self.cmake_generator,
"cmake-toolchain-file": self.cmake_toolchain_file,
"clang-tidy": self.clang_tidy,
"cmake-arguments": my_shlex_join(self.cmake_arguments),
@@ -289,6 +292,7 @@ class JobDetails:
"check-sources": self.check_sources,
"setup-python": self.setup_python,
"pypi-packages": my_shlex_join(self.pypi_packages),
"binutils-strings": self.binutils_strings,
}
return {k: v for k, v in data.items() if v != ""}
@@ -675,13 +679,16 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
job.shared_lib = SharedLibType.SO_0
job.static_lib = StaticLibType.A
case SdlPlatform.N3ds:
job.ccache = True
job.cmake_generator = "Unix Makefiles"
job.cmake_build_arguments.append("-j$(nproc)")
job.ccache = False
job.shared = False
job.apt_packages = ["ccache", "ninja-build", "binutils"]
job.apt_packages = []
job.clang_tidy = False
job.run_tests = False
job.cc_from_cmake = True
job.cmake_toolchain_file = "${DEVKITPRO}/cmake/3DS.cmake"
job.binutils_strings = "/opt/devkitpro/devkitARM/bin/arm-none-eabi-strings"
job.static_lib = StaticLibType.A
case SdlPlatform.Msys2:
job.ccache = True
+3 -3
View File
@@ -201,7 +201,7 @@ jobs:
#shell: ${{ matrix.platform.shell }}
run: |
${{ matrix.platform.source-cmd }}
${{ matrix.platform.cmake-config-emulator }} cmake -S . -B build -GNinja \
${{ matrix.platform.cmake-config-emulator }} cmake -S . -B build -G "${{ matrix.platform.cmake-generator }}" \
-Wdeprecated -Wdev -Werror \
${{ matrix.platform.cmake-toolchain-file != '' && format('-DCMAKE_TOOLCHAIN_FILE={0}', matrix.platform.cmake-toolchain-file) || '' }} \
-DSDL_WERROR=${{ matrix.platform.werror }} \
@@ -232,9 +232,9 @@ jobs:
run: |
echo "This should show us the SDL_REVISION"
echo "Shared library:"
${{ (matrix.platform.shared-lib && format('strings build/{0} | grep "Github Workflow"', matrix.platform.shared-lib)) || 'echo "<Shared library not supported by platform>"' }}
${{ (matrix.platform.shared-lib && format('{0} build/{1} | grep "Github Workflow"', matrix.platform.binutils-strings, matrix.platform.shared-lib)) || 'echo "<Shared library not supported by platform>"' }}
echo "Static library:"
${{ (matrix.platform.static-lib && format('strings build/{0} | grep "Github Workflow"', matrix.platform.static-lib)) || 'echo "<Static library not supported by platform>"' }}
${{ (matrix.platform.static-lib && format('{0} build/{1} | grep "Github Workflow"', matrix.platform.binutils-strings, matrix.platform.static-lib)) || 'echo "<Static library not supported by platform>"' }}
- name: 'Run build-time tests (CMake)'
id: tests
if: ${{ !matrix.platform.no-cmake && matrix.platform.run-tests }}
+1 -1
View File
@@ -256,7 +256,7 @@ jobs:
msvc:
needs: [src]
runs-on: windows-2019
runs-on: windows-2025
outputs:
VC-x86: ${{ steps.releaser.outputs.VC-x86 }}
VC-x64: ${{ steps.releaser.outputs.VC-x64 }}
+4
View File
@@ -107,6 +107,10 @@ LOCAL_LDLIBS := -ldl -lGLESv1_CM -lGLESv2 -lOpenSLES -llog -landroid
LOCAL_LDFLAGS := -Wl,--no-undefined -Wl,--no-undefined-version -Wl,--version-script=$(LOCAL_PATH)/src/dynapi/SDL_dynapi.sym
# https://developer.android.com/guide/practices/page-sizes
LOCAL_LDFLAGS += "-Wl,-z,max-page-size=16384"
LOCAL_LDFLAGS += "-Wl,-z,common-page-size=16384"
ifeq ($(NDK_DEBUG),1)
cmd-strip :=
endif
+16 -5
View File
@@ -5,7 +5,7 @@ if(NOT DEFINED CMAKE_BUILD_TYPE)
endif()
# See docs/release_checklist.md
project(SDL3 LANGUAGES C VERSION "3.2.16")
project(SDL3 LANGUAGES C VERSION "3.2.20")
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
set(SDL3_MAINPROJECT ON)
@@ -188,9 +188,12 @@ if(MSVC)
# Make sure /RTC1 is disabled, otherwise it will use functions from the CRT
foreach(flag_var
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO)
CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
string(REGEX REPLACE "/RTC(su|[1su])" "" ${flag_var} "${${flag_var}}")
endforeach(flag_var)
set(CMAKE_MSVC_RUNTIME_CHECKS "")
endif()
if(MSVC_CLANG)
@@ -634,6 +637,11 @@ if(MSVC)
# Mark SDL3.dll as compatible with Control-flow Enforcement Technology (CET)
sdl_shared_link_options("-CETCOMPAT")
endif()
# for VS >= 17.14 targeting ARM64: inline the Interlocked funcs
if(MSVC_VERSION GREATER 1943 AND SDL_CPU_ARM64 AND NOT SDL_LIBC)
sdl_compile_options(PRIVATE "/forceInterlockedFunctions-")
endif()
endif()
if(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
@@ -1336,9 +1344,7 @@ if(ANDROID)
set(HAVE_SDL_HAPTIC TRUE)
endif()
if(SDL_HIDAPI)
CheckHIDAPI()
endif()
CheckHIDAPI()
if(SDL_JOYSTICK)
set(SDL_JOYSTICK_ANDROID 1)
@@ -1481,6 +1487,11 @@ if(ANDROID)
endif()
endif()
if(TARGET SDL3-shared)
target_link_options(SDL3-shared PRIVATE "-Wl,-z,max-page-size=16384")
target_link_options(SDL3-shared PRIVATE "-Wl,-z,common-page-size=16384")
endif()
elseif(EMSCRIPTEN)
# Hide noisy warnings that intend to aid mostly during initial stages of porting a new
# project. Uncomment at will for verbose cross-compiling -I/../ path info.
+2 -2
View File
@@ -19,10 +19,10 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>3.2.16</string>
<string>3.2.20</string>
<key>CFBundleSignature</key>
<string>SDLX</string>
<key>CFBundleVersion</key>
<string>3.2.16</string>
<string>3.2.20</string>
</dict>
</plist>
+4 -4
View File
@@ -3086,7 +3086,7 @@
CLANG_ENABLE_OBJC_ARC = YES;
DEPLOYMENT_POSTPROCESSING = YES;
DYLIB_COMPATIBILITY_VERSION = 201.0.0;
DYLIB_CURRENT_VERSION = 201.16.0;
DYLIB_CURRENT_VERSION = 201.20.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_ALTIVEC_EXTENSIONS = YES;
@@ -3121,7 +3121,7 @@
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 3.2.16;
MARKETING_VERSION = 3.2.20;
OTHER_LDFLAGS = "$(CONFIG_FRAMEWORK_LDFLAGS)";
PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3;
PRODUCT_NAME = SDL3;
@@ -3150,7 +3150,7 @@
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
DYLIB_COMPATIBILITY_VERSION = 201.0.0;
DYLIB_CURRENT_VERSION = 201.16.0;
DYLIB_CURRENT_VERSION = 201.20.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@@ -3182,7 +3182,7 @@
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 3.2.16;
MARKETING_VERSION = 3.2.20;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "$(CONFIG_FRAMEWORK_LDFLAGS)";
PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3;
+1 -1
View File
@@ -1,4 +1,4 @@
Title SDL 3.2.16
Title SDL 3.2.20
Version 1
Description SDL Library for macOS (http://www.libsdl.org)
DefaultLocation /Library/Frameworks
+1 -1
View File
@@ -19,7 +19,7 @@ android {
abiFilters 'arm64-v8a'
}
cmake {
arguments "-DANDROID_PLATFORM=android-21", "-DANDROID_STL=c++_static"
arguments "-DANDROID_PLATFORM=android-21", "-DANDROID_STL=c++_static", "-DAPP_SUPPORT_FLEXIBLE_PAGE_SIZES=true"
// abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
abiFilters 'arm64-v8a'
}
+4 -1
View File
@@ -7,4 +7,7 @@
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
# Min runtime API level
APP_PLATFORM=android-16
APP_PLATFORM=android-21
# https://developer.android.com/guide/practices/page-sizes#update-packaging
APP_SUPPORT_FLEXIBLE_PAGE_SIZES := true
@@ -26,4 +26,9 @@ endif()
add_library(main SHARED
YourSourceHere.c
)
#https://developer.android.com/guide/practices/page-sizes#update-packaging
target_link_options(main PRIVATE "-Wl,-z,max-page-size=16384")
target_link_options(main PRIVATE "-Wl,-z,common-page-size=16384")
target_link_libraries(main PRIVATE SDL3::SDL3)
@@ -61,7 +61,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
private static final String TAG = "SDL";
private static final int SDL_MAJOR_VERSION = 3;
private static final int SDL_MINOR_VERSION = 2;
private static final int SDL_MICRO_VERSION = 16;
private static final int SDL_MICRO_VERSION = 20;
/*
// Display InputType.SOURCE/CLASS of events and devices
//
+7
View File
@@ -30,6 +30,7 @@ abi="arm64-v8a" # "armeabi-v7a arm64-v8a x86 x86_64"
obj=
lib=
ndk_args=
flexpage=true
# Allow an external caller to specify locations and platform.
while [ $# -gt 0 ]; do
@@ -42,6 +43,8 @@ while [ $# -gt 0 ]; do
platform=${arg#APP_PLATFORM=}
elif [ "${arg:0:8}" == "APP_ABI=" ]; then
abi=${arg#APP_ABI=}
elif [ "${arg:0:32}" == "APP_SUPPORT_FLEXIBLE_PAGE_SIZES=" ]; then
flexpage=${arg#APP_SUPPORT_FLEXIBLE_PAGE_SIZES=}
else
ndk_args="$ndk_args $arg"
fi
@@ -67,6 +70,9 @@ done
# APP_* variables set in the environment here will not be seen by the
# ndk-build makefile segments that use them, e.g., default-application.mk.
# For consistency, pass all values on the command line.
#
# Add support for Google Play 16 KB Page size requirement:
# https://developer.android.com/guide/practices/page-sizes#ndk-build
ndk-build \
NDK_PROJECT_PATH=null \
NDK_OUT=$obj \
@@ -75,4 +81,5 @@ ndk-build \
APP_ABI="$abi" \
APP_PLATFORM="$platform" \
APP_MODULES="SDL3" \
APP_SUPPORT_FLEXIBLE_PAGE_SIZES="$flexpage" \
$ndk_args
+8 -8
View File
@@ -1077,6 +1077,14 @@ endmacro()
# Check for HIDAPI support
macro(CheckHIDAPI)
if(ANDROID)
enable_language(CXX)
sdl_sources("${SDL3_SOURCE_DIR}/src/hidapi/android/hid.cpp")
endif()
if(IOS OR TVOS)
sdl_sources("${SDL3_SOURCE_DIR}/src/hidapi/ios/hid.m")
set(SDL_FRAMEWORK_COREBLUETOOTH 1)
endif()
if(SDL_HIDAPI)
set(HAVE_HIDAPI ON)
if(SDL_HIDAPI_LIBUSB)
@@ -1109,14 +1117,6 @@ macro(CheckHIDAPI)
endif()
if(HAVE_HIDAPI)
if(ANDROID)
enable_language(CXX)
sdl_sources("${SDL3_SOURCE_DIR}/src/hidapi/android/hid.cpp")
endif()
if(IOS OR TVOS)
sdl_sources("${SDL3_SOURCE_DIR}/src/hidapi/ios/hid.m")
set(SDL_FRAMEWORK_COREBLUETOOTH 1)
endif()
set(HAVE_SDL_HIDAPI TRUE)
if(SDL_JOYSTICK AND SDL_HIDAPI_JOYSTICK)
+2 -2
View File
@@ -49,7 +49,7 @@ NSApplicationDelegate implementation:
```objc
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
if (SDL_GetEventState(SDL_EVENT_QUIT) == SDL_ENABLE) {
if (SDL_EventEnabled(SDL_EVENT_QUIT)) {
SDL_Event event;
SDL_zero(event);
event.type = SDL_EVENT_QUIT;
@@ -61,7 +61,7 @@ NSApplicationDelegate implementation:
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
{
if (SDL_GetEventState(SDL_EVENT_DROP_FILE) == SDL_ENABLE) {
if (SDL_EventEnabled(SDL_EVENT_DROP_FILE)) {
SDL_Event event;
SDL_zero(event);
event.type = SDL_EVENT_DROP_FILE;
+1 -1
View File
@@ -20,7 +20,7 @@
*/
/**
* Main include header for the SDL library, version 3.2.16
* Main include header for the SDL library, version 3.2.20
*
* It is almost always best to include just this one header instead of
* picking out individual headers included here. There are exceptions to
+1 -1
View File
@@ -362,7 +362,7 @@ extern SDL_DECLSPEC SDL_AssertState SDLCALL SDL_ReportAssertion(SDL_AssertData *
#define SDL_enabled_assert(condition) \
do { \
while ( !(condition) ) { \
static struct SDL_AssertData sdl_assert_data = { 0, 0, #condition, 0, 0, 0, 0 }; \
static struct SDL_AssertData sdl_assert_data = { false, 0, #condition, NULL, 0, NULL, NULL }; \
const SDL_AssertState sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \
if (sdl_assert_state == SDL_ASSERTION_RETRY) { \
continue; /* go again. */ \
+5 -2
View File
@@ -942,7 +942,10 @@ extern SDL_DECLSPEC void SDLCALL SDL_CloseAudioDevice(SDL_AudioDeviceID devid);
* Binding a stream to a device will set its output format for playback
* devices, and its input format for recording devices, so they match the
* device's settings. The caller is welcome to change the other end of the
* stream's format at any time with SDL_SetAudioStreamFormat().
* stream's format at any time with SDL_SetAudioStreamFormat(). If the other
* end of the stream's format has never been set (the audio stream was created
* with a NULL audio spec), this function will set it to match the device
* end's format.
*
* \param devid an audio device to bind a stream to.
* \param streams an array of audio streams to bind.
@@ -1021,7 +1024,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_UnbindAudioStream(SDL_AudioStream *stream);
/**
* Query an audio stream for its currently-bound device.
*
* This reports the audio device that an audio stream is currently bound to.
* This reports the logical audio device that an audio stream is currently bound to.
*
* If not bound, or invalid, this returns zero, which is not a valid device
* ID.
+14 -14
View File
@@ -106,7 +106,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetClipboardText(const char *text);
/**
* Get UTF-8 text from the clipboard.
*
* This functions returns an empty string if there was not enough memory left
* This function returns an empty string if there is not enough memory left
* for a copy of the clipboard's content.
*
* \returns the clipboard text on success or an empty string on failure; call
@@ -155,7 +155,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetPrimarySelectionText(const char *text);
/**
* Get UTF-8 text from the primary selection.
*
* This functions returns an empty string if there was not enough memory left
* This function returns an empty string if there is not enough memory left
* for a copy of the primary selection's content.
*
* \returns the primary selection text on success or an empty string on
@@ -194,15 +194,15 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HasPrimarySelectionText(void);
* clipboard is cleared or new data is set. The clipboard is automatically
* cleared in SDL_Quit().
*
* \param userdata a pointer to provided user data.
* \param userdata a pointer to the provided user data.
* \param mime_type the requested mime-type.
* \param size a pointer filled in with the length of the returned data.
* \returns a pointer to the data for the provided mime-type. Returning NULL
* or setting length to 0 will cause no data to be sent to the
* or setting the length to 0 will cause no data to be sent to the
* "receiver". It is up to the receiver to handle this. Essentially
* returning no data is more or less undefined behavior and may cause
* breakage in receiving applications. The returned data will not be
* freed so it needs to be retained and dealt with internally.
* freed, so it needs to be retained and dealt with internally.
*
* \since This function is available since SDL 3.2.0.
*
@@ -211,10 +211,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HasPrimarySelectionText(void);
typedef const void *(SDLCALL *SDL_ClipboardDataCallback)(void *userdata, const char *mime_type, size_t *size);
/**
* Callback function that will be called when the clipboard is cleared, or new
* Callback function that will be called when the clipboard is cleared, or when new
* data is set.
*
* \param userdata a pointer to provided user data.
* \param userdata a pointer to the provided user data.
*
* \since This function is available since SDL 3.2.0.
*
@@ -231,7 +231,7 @@ typedef void (SDLCALL *SDL_ClipboardCleanupCallback)(void *userdata);
* respond with the data for the requested mime-type.
*
* The size of text data does not include any terminator, and the text does
* not need to be null terminated (e.g. you can directly copy a portion of a
* not need to be null-terminated (e.g., you can directly copy a portion of a
* document).
*
* \param callback a function pointer to the function that provides the
@@ -239,7 +239,7 @@ typedef void (SDLCALL *SDL_ClipboardCleanupCallback)(void *userdata);
* \param cleanup a function pointer to the function that cleans up the
* clipboard data.
* \param userdata an opaque pointer that will be forwarded to the callbacks.
* \param mime_types a list of mime-types that are being offered.
* \param mime_types a list of mime-types that are being offered. SDL copies the given list.
* \param num_mime_types the number of mime-types in the mime_types list.
* \returns true on success or false on failure; call SDL_GetError() for more
* information.
@@ -269,10 +269,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_SetClipboardData(SDL_ClipboardDataCallback
extern SDL_DECLSPEC bool SDLCALL SDL_ClearClipboardData(void);
/**
* Get the data from clipboard for a given mime type.
* Get the data from the clipboard for a given mime type.
*
* The size of text data does not include the terminator, but the text is
* guaranteed to be null terminated.
* guaranteed to be null-terminated.
*
* \param mime_type the mime type to read from the clipboard.
* \param size a pointer filled in with the length of the returned data.
@@ -292,8 +292,8 @@ extern SDL_DECLSPEC void * SDLCALL SDL_GetClipboardData(const char *mime_type, s
/**
* Query whether there is data in the clipboard for the provided mime type.
*
* \param mime_type the mime type to check for data for.
* \returns true if there exists data in clipboard for the provided mime type,
* \param mime_type the mime type to check for data.
* \returns true if data exists in the clipboard for the provided mime type,
* false if it does not.
*
* \threadsafety This function should only be called on the main thread.
@@ -310,7 +310,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_HasClipboardData(const char *mime_type);
*
* \param num_mime_types a pointer filled with the number of mime types, may
* be NULL.
* \returns a null terminated array of strings with mime types, or NULL on
* \returns a null-terminated array of strings with mime types, or NULL on
* failure; call SDL_GetError() for more information. This should be
* freed with SDL_free() when it is no longer needed.
*
+1 -1
View File
@@ -486,7 +486,7 @@ SDL_FORCE_INLINE Uint32 SDL_Swap32(Uint32 x) { return x_but_byteswapped; }
*
* \since This function is available since SDL 3.2.0.
*/
SDL_FORCE_INLINE Uint32 SDL_Swap64(Uint64 x) { return x_but_byteswapped; }
SDL_FORCE_INLINE Uint64 SDL_Swap64(Uint64 x) { return x_but_byteswapped; }
/**
* Swap a 16-bit value from littleendian to native byte order.
+1 -1
View File
@@ -1549,7 +1549,7 @@ typedef struct SDL_GPUSamplerCreateInfo
typedef struct SDL_GPUVertexBufferDescription
{
Uint32 slot; /**< The binding slot of the vertex buffer. */
Uint32 pitch; /**< The byte pitch between consecutive elements of the vertex buffer. */
Uint32 pitch; /**< The size of a single element + the offset between elements. */
SDL_GPUVertexInputRate input_rate; /**< Whether attribute addressing is a function of the vertex index or instance index. */
Uint32 instance_step_rate; /**< Reserved for future use. Must be set to 0. */
} SDL_GPUVertexBufferDescription;
+1 -1
View File
@@ -208,7 +208,7 @@ typedef enum SDL_Scancode
SDL_SCANCODE_NONUSBACKSLASH = 100, /**< This is the additional key that ISO
* keyboards have over ANSI ones,
* located between left shift and Y.
* located between left shift and Z.
* Produces GRAVE ACCENT and TILDE in a
* US or UK Mac layout, REVERSE SOLIDUS
* (backslash) and VERTICAL LINE in a
+1 -1
View File
@@ -62,7 +62,7 @@ extern "C" {
*
* \since This macro is available since SDL 3.2.0.
*/
#define SDL_MICRO_VERSION 16
#define SDL_MICRO_VERSION 20
/**
* This macro turns the version numbers into a numeric value.
+13
View File
@@ -1167,6 +1167,15 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreateWindow(const char *title, int
* Popup windows implicitly do not have a border/decorations and do not appear
* on the taskbar/dock or in lists of windows such as alt-tab menus.
*
* By default, popup window positions will automatically be constrained to keep
* the entire window within display bounds. This can be overridden with the
* `SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN` property.
*
* By default, popup menus will automatically grab keyboard focus from the parent
* when shown. This behavior can be overridden by setting the `SDL_WINDOW_NOT_FOCUSABLE`
* flag, setting the `SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN` property to false, or
* toggling it after creation via the `SDL_SetWindowFocusable()` function.
*
* If a parent window is hidden or destroyed, any child popup windows will be
* recursively hidden or destroyed as well. Child popup windows not explicitly
* hidden will be restored when the parent is shown.
@@ -1207,6 +1216,9 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreatePopupWindow(SDL_Window *paren
* be always on top
* - `SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN`: true if the window has no
* window decoration
* - `SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN`: true if the "tooltip" and
* "menu" window types should be automatically constrained to be entirely within
* display bounds (default), false if no constraints on the position are desired.
* - `SDL_PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN`: true if the
* window will be used with an externally managed graphics context.
* - `SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN`: true if the window should
@@ -1321,6 +1333,7 @@ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreateWindowWithProperties(SDL_Prop
#define SDL_PROP_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN "SDL.window.create.always_on_top"
#define SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN "SDL.window.create.borderless"
#define SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN "SDL.window.create.constrain_popup"
#define SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN "SDL.window.create.focusable"
#define SDL_PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN "SDL.window.create.external_graphics_context"
#define SDL_PROP_WINDOW_CREATE_FLAGS_NUMBER "SDL.window.create.flags"
+3 -3
View File
@@ -51,14 +51,14 @@
extern "C" {
#endif
/* Avoid including vulkan.h, don't define VkInstance if it's already included */
#ifdef VULKAN_H_
/* Avoid including vulkan_core.h, don't define VkInstance if it's already included */
#ifdef VULKAN_CORE_H_
#define NO_SDL_VULKAN_TYPEDEFS
#endif
#ifndef NO_SDL_VULKAN_TYPEDEFS
#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
#if defined(__LP64__) || defined(_WIN64) || defined(__x86_64__) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__) || (defined(__riscv) && __riscv_xlen == 64)
#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;
#else
#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
@@ -111,6 +111,9 @@ typedef unsigned int uintptr_t;
# define SDL_DISABLE_AVX 1
#endif
#define HAVE_STDARG_H 1
#define HAVE_STDDEF_H 1
/* This can be disabled to avoid C runtime dependencies and manifest requirements */
#ifndef HAVE_LIBC
#define HAVE_LIBC 1
@@ -122,8 +125,6 @@ typedef unsigned int uintptr_t;
#define HAVE_LIMITS_H 1
#define HAVE_MATH_H 1
#define HAVE_SIGNAL_H 1
#define HAVE_STDARG_H 1
#define HAVE_STDDEF_H 1
#define HAVE_STDIO_H 1
#define HAVE_STDLIB_H 1
#define HAVE_STRING_H 1
@@ -153,7 +154,6 @@ typedef unsigned int uintptr_t;
#define HAVE_STRCMP 1
#define HAVE_STRNCMP 1
#define HAVE_STRPBRK 1
#define HAVE_VSSCANF 1
#define HAVE_VSNPRINTF 1
#define HAVE_ACOS 1
#define HAVE_ASIN 1
@@ -211,10 +211,7 @@ typedef unsigned int uintptr_t;
#if _MSC_VER >= 1400
#define HAVE__FSEEKI64 1
#endif
#endif /* _MSC_VER */
#else
#define HAVE_STDARG_H 1
#define HAVE_STDDEF_H 1
#endif /* _MSC_VER */
#endif
/* Enable various audio drivers */
+3 -3
View File
@@ -65,7 +65,7 @@
// Initialization/Cleanup routines
#include "timer/SDL_timer_c.h"
#ifdef SDL_VIDEO_DRIVER_WINDOWS
#ifdef SDL_PLATFORM_WINDOWS
extern bool SDL_HelperWindowCreate(void);
extern void SDL_HelperWindowDestroy(void);
#endif
@@ -317,7 +317,7 @@ bool SDL_InitSubSystem(SDL_InitFlags flags)
SDL_DBus_Init();
#endif
#ifdef SDL_VIDEO_DRIVER_WINDOWS
#ifdef SDL_PLATFORM_WINDOWS
if (flags & (SDL_INIT_HAPTIC | SDL_INIT_JOYSTICK)) {
if (!SDL_HelperWindowCreate()) {
goto quit_and_error;
@@ -653,7 +653,7 @@ void SDL_Quit(void)
SDL_bInMainQuit = true;
// Quit all subsystems
#ifdef SDL_VIDEO_DRIVER_WINDOWS
#ifdef SDL_PLATFORM_WINDOWS
SDL_HelperWindowDestroy();
#endif
SDL_QuitSubSystem(SDL_INIT_EVERYTHING);
+29 -9
View File
@@ -1153,7 +1153,10 @@ bool SDL_PlaybackAudioThreadIterate(SDL_AudioDevice *device)
// We should have updated this elsewhere if the format changed!
SDL_assert(SDL_AudioSpecsEqual(&stream->dst_spec, &device->spec, NULL, NULL));
SDL_assert(stream->src_spec.format != SDL_AUDIO_UNKNOWN);
const int br = SDL_GetAtomicInt(&logdev->paused) ? 0 : SDL_GetAudioStreamDataAdjustGain(stream, device_buffer, buffer_size, logdev->gain);
if (br < 0) { // Probably OOM. Kill the audio device; the whole thing is likely dying soon anyhow.
failed = true;
SDL_memset(device_buffer, device->silence_value, buffer_size); // just supply silence to the device before we die.
@@ -1195,6 +1198,8 @@ bool SDL_PlaybackAudioThreadIterate(SDL_AudioDevice *device)
// We should have updated this elsewhere if the format changed!
SDL_assert(SDL_AudioSpecsEqual(&stream->dst_spec, &outspec, NULL, NULL));
SDL_assert(stream->src_spec.format != SDL_AUDIO_UNKNOWN);
/* this will hold a lock on `stream` while getting. We don't explicitly lock the streams
for iterating here because the binding linked list can only change while the device lock is held.
(we _do_ lock the stream during binding/unbinding to make sure that two threads can't try to bind
@@ -1330,6 +1335,7 @@ bool SDL_RecordingAudioThreadIterate(SDL_AudioDevice *device)
SDL_assert(stream->src_spec.format == ((logdev->postmix || (logdev->gain != 1.0f)) ? SDL_AUDIO_F32 : device->spec.format));
SDL_assert(stream->src_spec.channels == device->spec.channels);
SDL_assert(stream->src_spec.freq == device->spec.freq);
SDL_assert(stream->dst_spec.format != SDL_AUDIO_UNKNOWN);
void *final_buf = output_buffer;
@@ -1391,6 +1397,7 @@ static int SDLCALL RecordingAudioThread(void *devicep) // thread entry point
typedef struct CountAudioDevicesData
{
int devs_seen;
int devs_skipped;
const int num_devices;
SDL_AudioDeviceID *result;
const bool recording;
@@ -1406,7 +1413,13 @@ static bool SDLCALL CountAudioDevices(void *userdata, const SDL_HashTable *table
const bool isphysical = !!(devid & (1<<1));
if (isphysical && (devid_recording == data->recording)) {
SDL_assert(data->devs_seen < data->num_devices);
data->result[data->devs_seen++] = devid;
SDL_AudioDevice *device = (SDL_AudioDevice *) value; // this is normally risky, but we hold the device_hash_lock here.
const bool zombie = SDL_GetAtomicInt(&device->zombie) != 0;
if (zombie) {
data->devs_skipped++;
} else {
data->result[data->devs_seen++] = devid;
}
}
return true; // keep iterating.
}
@@ -1422,10 +1435,11 @@ static SDL_AudioDeviceID *GetAudioDevices(int *count, bool recording)
num_devices = SDL_GetAtomicInt(recording ? &current_audio.recording_device_count : &current_audio.playback_device_count);
result = (SDL_AudioDeviceID *) SDL_malloc((num_devices + 1) * sizeof (SDL_AudioDeviceID));
if (result) {
CountAudioDevicesData data = { 0, num_devices, result, recording };
CountAudioDevicesData data = { 0, 0, num_devices, result, recording };
SDL_IterateHashTable(current_audio.device_hash, CountAudioDevices, &data);
SDL_assert(data.devs_seen == num_devices);
result[data.devs_seen] = 0; // null-terminated.
SDL_assert((data.devs_seen + data.devs_skipped) == num_devices);
num_devices = data.devs_seen; // might be less if we skipped any.
result[num_devices] = 0; // null-terminated.
}
}
SDL_UnlockRWLock(current_audio.device_hash_lock);
@@ -1567,7 +1581,9 @@ int *SDL_GetAudioDeviceChannelMap(SDL_AudioDeviceID devid, int *count)
SDL_AudioDevice *device = ObtainPhysicalAudioDeviceDefaultAllowed(devid);
if (device) {
channels = device->spec.channels;
result = SDL_ChannelMapDup(device->chmap, channels);
if (channels > 0 && device->chmap) {
result = SDL_ChannelMapDup(device->chmap, channels);
}
}
ReleaseAudioDevice(device);
@@ -1965,10 +1981,6 @@ bool SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream * const *stre
} else if (logdev->simplified) {
result = SDL_SetError("Cannot change stream bindings on device opened with SDL_OpenAudioDeviceStream");
} else {
// !!! FIXME: We'll set the device's side's format below, but maybe we should refuse to bind a stream if the app's side doesn't have a format set yet.
// !!! FIXME: Actually, why do we allow there to be an invalid format, again?
// make sure start of list is sane.
SDL_assert(!logdev->bound_streams || (logdev->bound_streams->prev_binding == NULL));
@@ -2003,9 +2015,17 @@ bool SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream * const *stre
if (result) {
// Now that everything is verified, chain everything together.
const bool recording = device->recording;
for (int i = 0; i < num_streams; i++) {
SDL_AudioStream *stream = streams[i];
if (stream) { // shouldn't be NULL, but just in case...
// if the stream never had its non-device-end format set, just set it to the device end's format.
if (recording && (stream->dst_spec.format == SDL_AUDIO_UNKNOWN)) {
SDL_copyp(&stream->dst_spec, &device->spec);
} else if (!recording && (stream->src_spec.format == SDL_AUDIO_UNKNOWN)) {
SDL_copyp(&stream->src_spec, &device->spec);
}
stream->bound_device = logdev;
stream->prev_binding = NULL;
stream->next_binding = logdev->bound_streams;
+4
View File
@@ -537,8 +537,10 @@ static void SDL_TARGETING("ssse3") SDL_Convert_Swap32_SSSE3(Uint32* dst, const U
// behavior. However, the compiler support for this pragma is bad.
#if defined(__clang__)
#if __clang_major__ >= 12
#if defined(__aarch64__)
#pragma STDC FENV_ACCESS ON
#endif
#endif
#elif defined(_MSC_VER)
#pragma fenv_access (on)
#elif defined(__GNUC__)
@@ -814,8 +816,10 @@ static void SDL_Convert_Swap32_NEON(Uint32* dst, const Uint32* src, int num_samp
#if defined(__clang__)
#if __clang_major__ >= 12
#if defined(__aarch64__)
#pragma STDC FENV_ACCESS DEFAULT
#endif
#endif
#elif defined(_MSC_VER)
#pragma fenv_access (off)
#elif defined(__GNUC__)
+2 -2
View File
@@ -2114,8 +2114,8 @@ bool SDL_LoadWAV_IO(SDL_IOStream *src, bool closeio, SDL_AudioSpec *spec, Uint8
result = WaveLoad(src, &file, spec, audio_buf, audio_len);
if (!result) {
SDL_free(*audio_buf);
audio_buf = NULL;
audio_len = 0;
*audio_buf = NULL;
*audio_len = 0;
}
// Cleanup
+1 -1
View File
@@ -1156,7 +1156,7 @@ static bool ALSA_OpenDevice(SDL_AudioDevice *device)
#if SDL_ALSA_DEBUG
snd_pcm_uframes_t bufsize;
ALSA_snd_pcm_hw_params_get_buffer_size(cfg_ctx.hwparams, &bufsize);
SDL_LogError(SDL_LOG_CATEGORY_AUDIO,
SDL_LogDebug(SDL_LOG_CATEGORY_AUDIO,
"ALSA: period size = %ld, periods = %u, buffer size = %lu",
cfg_ctx.persize, cfg_ctx.periods, bufsize);
#endif
+1 -1
View File
@@ -206,7 +206,7 @@ static void DSOUND_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDe
{
#ifdef HAVE_MMDEVICEAPI_H
if (SupportsIMMDevice) {
SDL_IMMDevice_EnumerateEndpoints(default_playback, default_recording);
SDL_IMMDevice_EnumerateEndpoints(default_playback, default_recording, SDL_AUDIO_UNKNOWN);
} else
#endif
{
+1 -1
View File
@@ -114,7 +114,7 @@ static bool PSPAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, in
} else {
rc = sceAudioOutputPannedBlocking(device->hidden->channel, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, (void *) buffer);
}
return (rc == 0);
return (rc >= 0);
}
static bool PSPAUDIO_WaitDevice(SDL_AudioDevice *device)
+1 -1
View File
@@ -337,7 +337,7 @@ typedef struct
static bool mgmtthrtask_DetectDevices(void *userdata)
{
mgmtthrtask_DetectDevicesData *data = (mgmtthrtask_DetectDevicesData *)userdata;
SDL_IMMDevice_EnumerateEndpoints(data->default_playback, data->default_recording);
SDL_IMMDevice_EnumerateEndpoints(data->default_playback, data->default_recording, SDL_AUDIO_F32);
return true;
}
+1 -1
View File
@@ -814,7 +814,7 @@ static void ANDROIDCAMERA_Deinitialize(void)
static bool ANDROIDCAMERA_Init(SDL_CameraDriverImpl *impl)
{
// !!! FIXME: slide this off into a subroutine
// system libraries are in android-24 and later; we currently target android-16 and later, so check if they exist at runtime.
// system libraries are in android-24 and later; we currently target android-21 and later, so check if they exist at runtime.
void *libcamera2 = dlopen("libcamera2ndk.so", RTLD_NOW | RTLD_LOCAL);
if (!libcamera2) {
SDL_Log("CAMERA: libcamera2ndk.so can't be loaded: %s", dlerror());
+1 -1
View File
@@ -105,7 +105,7 @@ bool GDK_RegisterChangeNotifications(void)
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[GDK] in RegisterAppConstrainedChangeNotification handler");
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (_this) {
if (constrained) {
if (constrained && !((_this->windows) && _this->windows->text_input_active)) {
SDL_SetKeyboardFocus(NULL);
} else {
SDL_SetKeyboardFocus(_this->windows);
+13 -9
View File
@@ -120,7 +120,7 @@ void SDL_IMMDevice_FreeDeviceHandle(SDL_AudioDevice *device)
}
}
static SDL_AudioDevice *SDL_IMMDevice_Add(const bool recording, const char *devname, WAVEFORMATEXTENSIBLE *fmt, LPCWSTR devid, GUID *dsoundguid)
static SDL_AudioDevice *SDL_IMMDevice_Add(const bool recording, const char *devname, WAVEFORMATEXTENSIBLE *fmt, LPCWSTR devid, GUID *dsoundguid, SDL_AudioFormat force_format)
{
/* You can have multiple endpoints on a device that are mutually exclusive ("Speakers" vs "Line Out" or whatever).
In a perfect world, things that are unplugged won't be in this collection. The only gotcha is probably for
@@ -162,7 +162,7 @@ static SDL_AudioDevice *SDL_IMMDevice_Add(const bool recording, const char *devn
SDL_zero(spec);
spec.channels = (Uint8)fmt->Format.nChannels;
spec.freq = fmt->Format.nSamplesPerSec;
spec.format = SDL_WaveFormatExToSDLFormat((WAVEFORMATEX *)fmt);
spec.format = (force_format != SDL_AUDIO_UNKNOWN) ? force_format : SDL_WaveFormatExToSDLFormat((WAVEFORMATEX *)fmt);
device = SDL_AddAudioDevice(recording, devname, &spec, handle);
if (!device) {
@@ -183,6 +183,7 @@ typedef struct SDLMMNotificationClient
{
const IMMNotificationClientVtbl *lpVtbl;
SDL_AtomicInt refcount;
SDL_AudioFormat force_format;
} SDLMMNotificationClient;
static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_QueryInterface(IMMNotificationClient *client, REFIID iid, void **ppv)
@@ -241,6 +242,7 @@ static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_OnDeviceRemoved(IMMNoti
static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_OnDeviceStateChanged(IMMNotificationClient *iclient, LPCWSTR pwstrDeviceId, DWORD dwNewState)
{
SDLMMNotificationClient *client = (SDLMMNotificationClient *)iclient;
IMMDevice *device = NULL;
if (SUCCEEDED(IMMDeviceEnumerator_GetDevice(enumerator, pwstrDeviceId, &device))) {
@@ -255,7 +257,7 @@ static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_OnDeviceStateChanged(IM
GUID dsoundguid;
GetMMDeviceInfo(device, &utf8dev, &fmt, &dsoundguid);
if (utf8dev) {
SDL_IMMDevice_Add(recording, utf8dev, &fmt, pwstrDeviceId, &dsoundguid);
SDL_IMMDevice_Add(recording, utf8dev, &fmt, pwstrDeviceId, &dsoundguid, client->force_format);
SDL_free(utf8dev);
}
} else {
@@ -286,7 +288,7 @@ static const IMMNotificationClientVtbl notification_client_vtbl = {
SDLMMNotificationClient_OnPropertyValueChanged
};
static SDLMMNotificationClient notification_client = { &notification_client_vtbl, { 1 } };
static SDLMMNotificationClient notification_client = { &notification_client_vtbl, { 1 }, SDL_AUDIO_UNKNOWN };
bool SDL_IMMDevice_Init(const SDL_IMMDevice_callbacks *callbacks)
{
@@ -363,7 +365,7 @@ bool SDL_IMMDevice_Get(SDL_AudioDevice *device, IMMDevice **immdevice, bool reco
return true;
}
static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **default_device)
static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **default_device, SDL_AudioFormat force_format)
{
/* Note that WASAPI separates "adapter devices" from "audio endpoint devices"
...one adapter device ("SoundBlaster Pro") might have multiple endpoint devices ("Speakers", "Line-Out"). */
@@ -405,7 +407,7 @@ static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **de
SDL_zero(dsoundguid);
GetMMDeviceInfo(immdevice, &devname, &fmt, &dsoundguid);
if (devname) {
SDL_AudioDevice *sdldevice = SDL_IMMDevice_Add(recording, devname, &fmt, devid, &dsoundguid);
SDL_AudioDevice *sdldevice = SDL_IMMDevice_Add(recording, devname, &fmt, devid, &dsoundguid, force_format);
if (default_device && default_devid && SDL_wcscmp(default_devid, devid) == 0) {
*default_device = sdldevice;
}
@@ -422,10 +424,12 @@ static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **de
IMMDeviceCollection_Release(collection);
}
void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording, SDL_AudioFormat force_format)
{
EnumerateEndpointsForFlow(false, default_playback);
EnumerateEndpointsForFlow(true, default_recording);
EnumerateEndpointsForFlow(false, default_playback, force_format);
EnumerateEndpointsForFlow(true, default_recording, force_format);
notification_client.force_format = force_format;
// if this fails, we just won't get hotplug events. Carry on anyhow.
IMMDeviceEnumerator_RegisterEndpointNotificationCallback(enumerator, (IMMNotificationClient *)&notification_client);
+1 -1
View File
@@ -37,7 +37,7 @@ typedef struct SDL_IMMDevice_callbacks
bool SDL_IMMDevice_Init(const SDL_IMMDevice_callbacks *callbacks);
void SDL_IMMDevice_Quit(void);
bool SDL_IMMDevice_Get(struct SDL_AudioDevice *device, IMMDevice **immdevice, bool recording);
void SDL_IMMDevice_EnumerateEndpoints(struct SDL_AudioDevice **default_playback, struct SDL_AudioDevice **default_recording);
void SDL_IMMDevice_EnumerateEndpoints(struct SDL_AudioDevice **default_playback, struct SDL_AudioDevice **default_recording, SDL_AudioFormat force_format);
LPGUID SDL_IMMDevice_GetDirectSoundGUID(struct SDL_AudioDevice *device);
LPCWSTR SDL_IMMDevice_GetDevID(struct SDL_AudioDevice *device);
void SDL_IMMDevice_FreeDeviceHandle(struct SDL_AudioDevice *device);
+72
View File
@@ -53,6 +53,78 @@ typedef enum RO_INIT_TYPE
#define WC_ERR_INVALID_CHARS 0x00000080
#endif
// Fake window to help with DirectInput events.
HWND SDL_HelperWindow = NULL;
static const TCHAR *SDL_HelperWindowClassName = TEXT("SDLHelperWindowInputCatcher");
static const TCHAR *SDL_HelperWindowName = TEXT("SDLHelperWindowInputMsgWindow");
static ATOM SDL_HelperWindowClass = 0;
/*
* Creates a HelperWindow used for DirectInput.
*/
bool SDL_HelperWindowCreate(void)
{
HINSTANCE hInstance = GetModuleHandle(NULL);
WNDCLASS wce;
// Make sure window isn't created twice.
if (SDL_HelperWindow != NULL) {
return true;
}
// Create the class.
SDL_zero(wce);
wce.lpfnWndProc = DefWindowProc;
wce.lpszClassName = SDL_HelperWindowClassName;
wce.hInstance = hInstance;
// Register the class.
SDL_HelperWindowClass = RegisterClass(&wce);
if (SDL_HelperWindowClass == 0 && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) {
return WIN_SetError("Unable to create Helper Window Class");
}
// Create the window.
SDL_HelperWindow = CreateWindowEx(0, SDL_HelperWindowClassName,
SDL_HelperWindowName,
WS_OVERLAPPED, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, HWND_MESSAGE, NULL,
hInstance, NULL);
if (!SDL_HelperWindow) {
UnregisterClass(SDL_HelperWindowClassName, hInstance);
return WIN_SetError("Unable to create Helper Window");
}
return true;
}
/*
* Destroys the HelperWindow previously created with SDL_HelperWindowCreate.
*/
void SDL_HelperWindowDestroy(void)
{
HINSTANCE hInstance = GetModuleHandle(NULL);
// Destroy the window.
if (SDL_HelperWindow != NULL) {
if (DestroyWindow(SDL_HelperWindow) == 0) {
WIN_SetError("Unable to destroy Helper Window");
return;
}
SDL_HelperWindow = NULL;
}
// Unregister the class.
if (SDL_HelperWindowClass != 0) {
if ((UnregisterClass(SDL_HelperWindowClassName, hInstance)) == 0) {
WIN_SetError("Unable to destroy Helper Window Class");
return;
}
SDL_HelperWindowClass = 0;
}
}
// Sets an error message based on an HRESULT
bool WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr)
{
+4 -4
View File
@@ -9,8 +9,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,2,16,0
PRODUCTVERSION 3,2,16,0
FILEVERSION 3,2,20,0
PRODUCTVERSION 3,2,20,0
FILEFLAGSMASK 0x3fL
FILEFLAGS 0x0L
FILEOS 0x40004L
@@ -23,12 +23,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "\0"
VALUE "FileDescription", "SDL\0"
VALUE "FileVersion", "3, 2, 16, 0\0"
VALUE "FileVersion", "3, 2, 20, 0\0"
VALUE "InternalName", "SDL\0"
VALUE "LegalCopyright", "Copyright (C) 2025 Sam Lantinga\0"
VALUE "OriginalFilename", "SDL3.dll\0"
VALUE "ProductName", "Simple DirectMedia Layer\0"
VALUE "ProductVersion", "3, 2, 16, 0\0"
VALUE "ProductVersion", "3, 2, 20, 0\0"
END
END
BLOCK "VarFileInfo"
+7
View File
@@ -27,6 +27,8 @@
#import <Cocoa/Cocoa.h>
#import <UniformTypeIdentifiers/UTType.h>
extern void Cocoa_SetWindowHasModalDialog(SDL_Window *window, bool has_modal);
static void AddFileExtensionType(NSMutableArray *types, const char *pattern_ptr)
{
if (!*pattern_ptr) {
@@ -163,6 +165,9 @@ void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFil
if (window) {
w = (__bridge NSWindow *)SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, NULL);
if (w) {
Cocoa_SetWindowHasModalDialog(window, true);
}
}
if (w) {
@@ -186,6 +191,7 @@ void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFil
callback(userdata, files, -1);
}
Cocoa_SetWindowHasModalDialog(window, false);
ReactivateAfterDialog();
}];
} else {
@@ -206,6 +212,7 @@ void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFil
const char *files[1] = { NULL };
callback(userdata, files, -1);
}
ReactivateAfterDialog();
}
}
+4 -4
View File
@@ -371,10 +371,10 @@ static const SDL_Scancode xfree86_scancode_table2[] = {
/* 188, 0x0bc */ SDL_SCANCODE_F18, // XF86Launch9
/* 189, 0x0bd */ SDL_SCANCODE_F19, // NoSymbol
/* 190, 0x0be */ SDL_SCANCODE_F20, // XF86AudioMicMute
/* 191, 0x0bf */ SDL_SCANCODE_UNKNOWN, // XF86TouchpadToggle
/* 192, 0x0c0 */ SDL_SCANCODE_UNKNOWN, // XF86TouchpadOn
/* 193, 0x0c1 */ SDL_SCANCODE_UNKNOWN, // XF86TouchpadOff
/* 194, 0x0c2 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
/* 191, 0x0bf */ SDL_SCANCODE_F21, // XF86TouchpadToggle
/* 192, 0x0c0 */ SDL_SCANCODE_F22, // XF86TouchpadOn
/* 193, 0x0c1 */ SDL_SCANCODE_F23, // XF86TouchpadOff
/* 194, 0x0c2 */ SDL_SCANCODE_F24, // NoSymbol
/* 195, 0x0c3 */ SDL_SCANCODE_MODE, // Mode_switch
/* 196, 0x0c4 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
/* 197, 0x0c5 */ SDL_SCANCODE_UNKNOWN, // NoSymbol
+5 -4
View File
@@ -1573,6 +1573,7 @@ SDL_GPUCommandBuffer *SDL_AcquireGPUCommandBuffer(
commandBufferHeader->copy_pass.in_progress = false;
commandBufferHeader->swapchain_texture_acquired = false;
commandBufferHeader->submitted = false;
commandBufferHeader->ignore_render_pass_texture_validation = false;
SDL_zeroa(commandBufferHeader->render_pass.vertex_sampler_bound);
SDL_zeroa(commandBufferHeader->render_pass.vertex_storage_texture_bound);
SDL_zeroa(commandBufferHeader->render_pass.vertex_storage_buffer_bound);
@@ -2247,14 +2248,14 @@ void SDL_DrawGPUIndexedPrimitivesIndirect(
void SDL_EndGPURenderPass(
SDL_GPURenderPass *render_pass)
{
CommandBufferCommonHeader *commandBufferCommonHeader;
commandBufferCommonHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER;
if (render_pass == NULL) {
SDL_InvalidParamError("render_pass");
return;
}
CommandBufferCommonHeader *commandBufferCommonHeader;
commandBufferCommonHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER;
if (RENDERPASS_DEVICE->debug_mode) {
CHECK_RENDERPASS
}
@@ -2543,7 +2544,7 @@ void SDL_EndGPUComputePass(
if (COMPUTEPASS_DEVICE->debug_mode) {
commandBufferCommonHeader = (CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER;
commandBufferCommonHeader->compute_pass.in_progress = false;
commandBufferCommonHeader->compute_pass.compute_pipeline = false;
commandBufferCommonHeader->compute_pass.compute_pipeline = NULL;
SDL_zeroa(commandBufferCommonHeader->compute_pass.sampler_bound);
SDL_zeroa(commandBufferCommonHeader->compute_pass.read_only_storage_texture_bound);
SDL_zeroa(commandBufferCommonHeader->compute_pass.read_only_storage_buffer_bound);
+6 -5
View File
@@ -1194,7 +1194,6 @@ struct D3D12UniformBuffer
D3D12Buffer *buffer;
Uint32 writeOffset;
Uint32 drawOffset;
Uint32 currentBlockSize;
};
// Forward function declarations
@@ -1441,6 +1440,8 @@ static void D3D12_INTERNAL_ReleaseTextureContainer(
container->textures[i]);
}
SDL_DestroyProperties(container->header.info.props);
// Containers are just client handles, so we can destroy immediately
if (container->debugName) {
SDL_free(container->debugName);
@@ -4496,7 +4497,6 @@ static D3D12UniformBuffer *D3D12_INTERNAL_AcquireUniformBufferFromPool(
SDL_UnlockMutex(renderer->acquireUniformBufferLock);
uniformBuffer->currentBlockSize = 0;
uniformBuffer->drawOffset = 0;
uniformBuffer->writeOffset = 0;
@@ -4535,6 +4535,7 @@ static void D3D12_INTERNAL_PushUniformData(
Uint32 length)
{
D3D12UniformBuffer *uniformBuffer;
Uint32 blockSize;
if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
if (commandBuffer->vertexUniformBuffers[slotIndex] == NULL) {
@@ -4559,13 +4560,13 @@ static void D3D12_INTERNAL_PushUniformData(
return;
}
uniformBuffer->currentBlockSize =
blockSize =
D3D12_INTERNAL_Align(
length,
256);
// If there is no more room, acquire a new uniform buffer
if (uniformBuffer->writeOffset + uniformBuffer->currentBlockSize >= UNIFORM_BUFFER_SIZE) {
if (uniformBuffer->writeOffset + blockSize >= UNIFORM_BUFFER_SIZE) {
ID3D12Resource_Unmap(
uniformBuffer->buffer->handle,
0,
@@ -4595,7 +4596,7 @@ static void D3D12_INTERNAL_PushUniformData(
data,
length);
uniformBuffer->writeOffset += uniformBuffer->currentBlockSize;
uniformBuffer->writeOffset += blockSize;
if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
commandBuffer->needVertexUniformBufferBind[slotIndex] = true;
+1
View File
@@ -888,6 +888,7 @@ static void METAL_INTERNAL_DestroyTextureContainer(
container->textures[i]->handle = nil;
SDL_free(container->textures[i]);
}
SDL_DestroyProperties(container->header.info.props);
if (container->debugName != NULL) {
SDL_free(container->debugName);
}
+36 -14
View File
@@ -1108,6 +1108,7 @@ typedef struct VulkanCommandBuffer
VulkanFenceHandle *inFlightFence;
bool autoReleaseFence;
bool swapchainRequested;
bool isDefrag; // Whether this CB was created for defragging
} VulkanCommandBuffer;
@@ -1277,13 +1278,20 @@ static inline const char *VkErrorMessages(VkResult code)
#undef ERR_TO_STR
}
#define SET_ERROR_AND_RETURN(fmt, msg, ret) \
#define SET_ERROR(fmt, msg) \
do { \
if (renderer->debugMode) { \
SDL_LogError(SDL_LOG_CATEGORY_GPU, fmt, msg); \
} \
SDL_SetError((fmt), (msg)); \
return ret; \
} while (0)
#define SET_STRING_ERROR(msg) SET_ERROR("%s", msg)
#define SET_ERROR_AND_RETURN(fmt, msg, ret) \
do { \
SET_ERROR(fmt, msg); \
return ret; \
} while (0)
#define SET_STRING_ERROR_AND_RETURN(msg, ret) SET_ERROR_AND_RETURN("%s", msg, ret)
@@ -6951,6 +6959,8 @@ static void VULKAN_ReleaseTexture(
VULKAN_INTERNAL_ReleaseTexture(renderer, vulkanTextureContainer->textures[i]);
}
SDL_DestroyProperties(vulkanTextureContainer->header.info.props);
// Containers are just client handles, so we can destroy immediately
if (vulkanTextureContainer->debugName != NULL) {
SDL_free(vulkanTextureContainer->debugName);
@@ -8592,7 +8602,7 @@ static void VULKAN_INTERNAL_BindComputeDescriptorSets(
dynamicOffsetCount,
dynamicOffsets);
commandBuffer->needNewVertexUniformOffsets = false;
commandBuffer->needNewComputeUniformOffsets = false;
}
static void VULKAN_DispatchCompute(
@@ -9925,6 +9935,14 @@ static bool VULKAN_INTERNAL_AcquireSwapchainTexture(
SET_STRING_ERROR_AND_RETURN("Cannot acquire a swapchain texture from an unclaimed window!", false);
}
// The command buffer is flagged for cleanup when the swapchain is requested as a cleanup timing mechanism
vulkanCommandBuffer->swapchainRequested = true;
if (window->flags & SDL_WINDOW_HIDDEN) {
// Edge case, texture is filled in with NULL but not an error
return true;
}
// If window data marked as needing swapchain recreate, try to recreate
if (windowData->needsSwapchainRecreate) {
Uint32 recreateSwapchainResult = VULKAN_INTERNAL_RecreateSwapchain(renderer, windowData);
@@ -9942,13 +9960,6 @@ static bool VULKAN_INTERNAL_AcquireSwapchainTexture(
}
}
if (swapchainTextureWidth) {
*swapchainTextureWidth = windowData->width;
}
if (swapchainTextureHeight) {
*swapchainTextureHeight = windowData->height;
}
if (windowData->inFlightFences[windowData->frameCounter] != NULL) {
if (block) {
// If we are blocking, just wait for the fence!
@@ -10000,6 +10011,14 @@ static bool VULKAN_INTERNAL_AcquireSwapchainTexture(
}
}
if (swapchainTextureWidth) {
*swapchainTextureWidth = windowData->width;
}
if (swapchainTextureHeight) {
*swapchainTextureHeight = windowData->height;
}
swapchainTextureContainer = &windowData->textureContainers[swapchainImageIndex];
// We need a special execution dependency with pWaitDstStageMask or image transition can start before acquire finishes
@@ -10377,6 +10396,7 @@ static void VULKAN_INTERNAL_CleanCommandBuffer(
commandBuffer->presentDataCount = 0;
commandBuffer->waitSemaphoreCount = 0;
commandBuffer->signalSemaphoreCount = 0;
commandBuffer->swapchainRequested = false;
// Reset defrag state
@@ -10533,7 +10553,7 @@ static bool VULKAN_Submit(
VulkanTextureSubresource *swapchainTextureSubresource;
VulkanMemorySubAllocator *allocator;
bool performCleanups =
(renderer->claimedWindowCount > 0 && vulkanCommandBuffer->presentDataCount > 0) ||
(renderer->claimedWindowCount > 0 && vulkanCommandBuffer->swapchainRequested) ||
renderer->claimedWindowCount == 0;
SDL_LockMutex(renderer->submitLock);
@@ -11686,7 +11706,7 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
renderer = (VulkanRenderer *)SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
SDL_Vulkan_UnloadLibrary();
return false;
return NULL;
}
renderer->debugMode = debugMode;
@@ -11694,9 +11714,10 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
renderer->allowedFramesInFlight = 2;
if (!VULKAN_INTERNAL_PrepareVulkan(renderer)) {
SET_STRING_ERROR("Failed to initialize Vulkan!");
SDL_free(renderer);
SDL_Vulkan_UnloadLibrary();
SET_STRING_ERROR_AND_RETURN("Failed to initialize Vulkan!", NULL);
return NULL;
}
SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "SDL_GPU Driver: Vulkan");
@@ -11722,9 +11743,10 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
if (!VULKAN_INTERNAL_CreateLogicalDevice(
renderer)) {
SET_STRING_ERROR("Failed to create logical device!");
SDL_free(renderer);
SDL_Vulkan_UnloadLibrary();
SET_STRING_ERROR_AND_RETURN("Failed to create logical device!", NULL);
return NULL;
}
// FIXME: just move this into this function
-4
View File
@@ -31,11 +31,7 @@
/*
* External stuff.
*/
#ifdef SDL_VIDEO_DRIVER_WINDOWS
extern HWND SDL_HelperWindow;
#else
static const HWND SDL_HelperWindow = NULL;
#endif
/*
* Internal stuff.
+27 -1
View File
@@ -71,6 +71,11 @@ extern "C" {
#define DETACH_KERNEL_DRIVER
#endif
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:5287) /* operands are different enum types */
#endif
/* Uncomment to enable the retrieval of Usage and Usage Page in
hid_enumerate(). Warning, on platforms different from FreeBSD
this is very invasive as it requires the detach
@@ -918,6 +923,22 @@ static int should_enumerate_interface(unsigned short vendor_id, const struct lib
return 0;
}
static int libusb_blacklist(unsigned short vendor_id, unsigned short product_id)
{
size_t i;
static const struct { unsigned short vid; unsigned short pid; } known_bad[] = {
{ 0x1532, 0x0227 } /* Razer Huntsman Gaming keyboard - long delay asking for device details */
};
for (i = 0; i < (sizeof(known_bad)/sizeof(known_bad[0])); i++) {
if ((vendor_id == known_bad[i].vid) && (product_id == known_bad[i].pid || known_bad[i].pid == 0x0000)) {
return 1;
}
}
return 0;
}
struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
{
libusb_device **devs;
@@ -948,7 +969,8 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id,
unsigned short dev_pid = desc.idProduct;
if ((vendor_id != 0x0 && vendor_id != dev_vid) ||
(product_id != 0x0 && product_id != dev_pid)) {
(product_id != 0x0 && product_id != dev_pid) ||
libusb_blacklist(dev_vid, dev_pid)) {
continue;
}
@@ -2140,6 +2162,10 @@ uint16_t get_usb_code_for_current_locale(void)
return 0x0;
}
#if defined(_MSC_VER)
#pragma warning (pop)
#endif
#ifdef __cplusplus
}
#endif
+1 -1
View File
@@ -134,7 +134,6 @@ static wchar_t *utf8_to_wchar_t(const char *utf8)
* Use register_error_str(NULL) to free the error message completely. */
static void register_error_str(wchar_t **error_str, const char *msg)
{
free(*error_str);
#ifdef HIDAPI_USING_SDL_RUNTIME
/* Thread-safe error handling */
if (msg) {
@@ -143,6 +142,7 @@ static void register_error_str(wchar_t **error_str, const char *msg)
SDL_ClearError();
}
#else
free(*error_str);
*error_str = utf8_to_wchar_t(msg);
#endif
}
+1
View File
@@ -949,6 +949,7 @@ static int hid_blacklist(unsigned short vendor_id, unsigned short product_id)
{ 0x0D8C, 0x0014 }, /* Sharkoon Skiller SGH2 headset - causes deadlock asking for device details */
{ 0x1532, 0x0109 }, /* Razer Lycosa Gaming keyboard - causes deadlock asking for device details */
{ 0x1532, 0x010B }, /* Razer Arctosa Gaming keyboard - causes deadlock asking for device details */
{ 0x1532, 0x0227 }, /* Razer Huntsman Gaming keyboard - long delay asking for device details */
{ 0x1B1C, 0x1B3D }, /* Corsair Gaming keyboard - causes deadlock asking for device details */
{ 0x1CCF, 0x0000 } /* All Konami Amusement Devices - causes deadlock asking for device details */
};
+7 -2
View File
@@ -311,7 +311,7 @@ void SDL_PrivateGamepadAdded(SDL_JoystickID instance_id)
{
SDL_Event event;
if (!SDL_gamepads_initialized) {
if (!SDL_gamepads_initialized || SDL_IsJoystickBeingAdded()) {
return;
}
@@ -913,7 +913,7 @@ static GamepadMapping_t *SDL_PrivateMatchGamepadMappingForGUID(SDL_GUID guid, bo
// An exact match, including CRC
return mapping;
} else if (crc && exact_match_crc) {
return NULL;
continue;
}
if (!best_match) {
@@ -1786,6 +1786,11 @@ static GamepadMapping_t *SDL_PrivateGenerateAutomaticGamepadMapping(const char *
char name_string[128];
char mapping[1024];
// Remove the CRC from the GUID
// We already know that this GUID doesn't have a mapping without the CRC, and we want newly
// added mappings without a CRC to override this mapping.
SDL_SetJoystickGUIDCRC(&guid, 0);
// Remove any commas in the name
SDL_strlcpy(name_string, name, sizeof(name_string));
{
+4 -2
View File
@@ -215,7 +215,7 @@ static const char *s_GamepadMappings[] = {
"03000000362800000100000000000000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,",
"03000000782300000a10000000000000,Onlive Wireless Controller,a:b15,b:b14,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b11,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b13,y:b12,",
"030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,",
"0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,rightx:a3,righty:a4,righttrigger:-a5,start:b11,x:b3,y:b4,",
"0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,righttrigger:-a5,rightx:a3,righty:a4,start:b11,x:b3,y:b4,",
"03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,",
"030000006f0e00000901000000000000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
"03000000632500002306000000000000,PS Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
@@ -416,12 +416,13 @@ static const char *s_GamepadMappings[] = {
"03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,",
"0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,",
"03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,",
"03000000853200008906000000010000,NACON Revolution X Unlimited,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,",
"030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,",
"03000000550900001472000025050000,NVIDIA Controller v01.04,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,",
"030000004b120000014d000000010000,NYKO AIRFLO EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,",
"030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
"050000007e05000009200000ff070000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"0300000009120000072f000000010000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a2,leftx:a0,lefty:a1,rightx:a3,righty:a4,righttrigger:a5,start:b11,x:b3,y:b4,",
"0300000009120000072f000000010000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a2,leftx:a0,lefty:a1,righttrigger:a5,rightx:a3,righty:a4,start:b11,x:b3,y:b4,",
"030000006f0e00000901000002010000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
"030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
"030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
@@ -796,6 +797,7 @@ static const char *s_GamepadMappings[] = {
"03000000c0160000e105000010010000,Xin-Mo Dual Arcade,crc:82d5,a:b1,b:b2,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b8,x:b0,y:b3,", /* Ultimate Atari Fight Stick */
"03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"03000000120c0000182e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,",
"03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
"050000006964726f69643a636f6e0000,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
+5 -1
View File
@@ -2143,6 +2143,7 @@ void SDL_PrivateJoystickAdded(SDL_JoystickID instance_id)
SDL_JoystickDriver *driver;
int device_index;
int player_index = -1;
bool is_gamepad;
SDL_AssertJoysticksLocked();
@@ -2177,9 +2178,12 @@ void SDL_PrivateJoystickAdded(SDL_JoystickID instance_id)
}
}
// This might create an automatic gamepad mapping, so wait to send the event
is_gamepad = SDL_IsGamepad(instance_id);
SDL_joystick_being_added = false;
if (SDL_IsGamepad(instance_id)) {
if (is_gamepad) {
SDL_PrivateGamepadAdded(instance_id);
}
}
+1 -1
View File
@@ -21,7 +21,6 @@
static const ControllerDescription_t arrControllers[] = {
{ MAKE_CONTROLLER_ID( 0x0079, 0x181a ), k_eControllerType_PS3Controller, NULL }, // Venom Arcade Stick
{ MAKE_CONTROLLER_ID( 0x0079, 0x1844 ), k_eControllerType_PS3Controller, NULL }, // From SDL
{ MAKE_CONTROLLER_ID( 0x044f, 0xb315 ), k_eControllerType_PS3Controller, NULL }, // Firestorm Dual Analog 3
{ MAKE_CONTROLLER_ID( 0x044f, 0xd007 ), k_eControllerType_PS3Controller, NULL }, // Thrustmaster wireless 3-1
{ MAKE_CONTROLLER_ID( 0x046d, 0xcad1 ), k_eControllerType_PS3Controller, NULL }, // Logitech Chillstream
@@ -96,6 +95,7 @@ static const ControllerDescription_t arrControllers[] = {
{ MAKE_CONTROLLER_ID( 0x0c12, 0x0ef6 ), k_eControllerType_PS4Controller, NULL }, // Hitbox Arcade Stick
{ MAKE_CONTROLLER_ID( 0x0c12, 0x1cf6 ), k_eControllerType_PS4Controller, NULL }, // EMIO PS4 Elite Controller
{ MAKE_CONTROLLER_ID( 0x0c12, 0x1e10 ), k_eControllerType_PS4Controller, NULL }, // P4 Wired Gamepad generic knock off - lightbar but not trackpad or gyro
{ MAKE_CONTROLLER_ID( 0x0c12, 0x2e18 ), k_eControllerType_PS4Controller, NULL }, // ZEROPLUS P4 Wired Gamepad
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0203 ), k_eControllerType_PS4Controller, NULL }, // Victrix Pro FS (PS4 peripheral but no trackpad/lightbar)
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x0207 ), k_eControllerType_PS4Controller, NULL }, // Victrix Pro FS V2 w/ Touchpad for PS4
{ MAKE_CONTROLLER_ID( 0x0e6f, 0x020a ), k_eControllerType_PS4Controller, NULL }, // Victrix Pro FS PS4/PS5 (PS4 mode)
+34 -1
View File
@@ -27,6 +27,7 @@
#include "SDL_iokitjoystick_c.h"
#include "../hidapi/SDL_hidapijoystick_c.h"
#include "../../haptic/darwin/SDL_syshaptic_c.h" // For haptic hot plugging
#include "../usb_ids.h"
#define SDL_JOYSTICK_RUNLOOP_MODE CFSTR("SDLJoystick")
@@ -213,6 +214,29 @@ static bool GetHIDScaledCalibratedState(recDevice *pDevice, recElement *pElement
return result;
}
static bool GetHIDScaledCalibratedState_NACON_Revolution_X_Unlimited(recDevice *pDevice, recElement *pElement, SInt32 min, SInt32 max, SInt32 *pValue)
{
if (pElement->minReport == 0 && pElement->maxReport == 255) {
return GetHIDScaledCalibratedState(pDevice, pElement, min, max, pValue);
}
// This device thumbstick axes have an unusual axis range that
// doesn't work with GetHIDScaledCalibratedState() above.
//
// See https://github.com/libsdl-org/SDL/issues/13143 for details
if (GetHIDElementState(pDevice, pElement, pValue)) {
if (*pValue >= 0) {
// Negative axis values range from 32767 (at rest) to 0 (minimum)
*pValue = -32767 + *pValue;
} else if (*pValue < 0) {
// Positive axis values range from -32768 (at rest) to 0 (maximum)
*pValue = 32768 + *pValue;
}
return true;
}
return false;
}
static void JoystickDeviceWasRemovedCallback(void *ctx, IOReturn result, void *sender)
{
recDevice *device = (recDevice *)ctx;
@@ -506,6 +530,11 @@ static bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
pDevice->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, (Uint16)vendor, (Uint16)product, (Uint16)version, manufacturer_string, product_string, 0, 0);
pDevice->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot((Uint16)vendor, (Uint16)product, product_string);
if (vendor == USB_VENDOR_NACON_ALT &&
product == USB_PRODUCT_NACON_REVOLUTION_X_UNLIMITED_BT) {
pDevice->nacon_revolution_x_unlimited = true;
}
array = IOHIDDeviceCopyMatchingElements(hidDevice, NULL, kIOHIDOptionsTypeNone);
if (array) {
AddHIDElements(array, pDevice);
@@ -957,7 +986,11 @@ static void DARWIN_JoystickUpdate(SDL_Joystick *joystick)
i = 0;
while (element) {
goodRead = GetHIDScaledCalibratedState(device, element, -32768, 32767, &value);
if (device->nacon_revolution_x_unlimited) {
goodRead = GetHIDScaledCalibratedState_NACON_Revolution_X_Unlimited(device, element, -32768, 32767, &value);
} else {
goodRead = GetHIDScaledCalibratedState(device, element, -32768, 32767, &value);
}
if (goodRead) {
SDL_SendJoystickAxis(timestamp, joystick, i, value);
}
@@ -72,6 +72,7 @@ struct joystick_hwdata
int instance_id;
SDL_GUID guid;
int steam_virtual_gamepad_slot;
bool nacon_revolution_x_unlimited;
struct joystick_hwdata *pNext; // next device
};
+52 -54
View File
@@ -31,7 +31,9 @@
#ifdef SDL_JOYSTICK_HIDAPI_GAMECUBE
// Define this if you want to log all packets from the controller
// #define DEBUG_GAMECUBE_PROTOCOL
#if 0
#define DEBUG_GAMECUBE_PROTOCOL
#endif
#define MAX_CONTROLLERS 4
@@ -119,22 +121,15 @@ static bool HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
}
device->context = ctx;
ctx->joysticks[0] = 0;
ctx->joysticks[1] = 0;
ctx->joysticks[2] = 0;
ctx->joysticks[3] = 0;
ctx->rumble[0] = rumbleMagic;
ctx->useRumbleBrake = false;
if (device->vendor_id != USB_VENDOR_NINTENDO) {
ctx->pc_mode = true;
}
if (ctx->pc_mode) {
for (i = 0; i < MAX_CONTROLLERS; ++i) {
ResetAxisRange(ctx, i);
HIDAPI_JoystickConnected(device, &ctx->joysticks[i]);
}
ResetAxisRange(ctx, 0);
HIDAPI_JoystickConnected(device, &ctx->joysticks[0]);
} else {
// This is all that's needed to initialize the device. Really!
if (SDL_hid_write(device->dev, &initMagic, sizeof(initMagic)) != sizeof(initMagic)) {
@@ -204,69 +199,61 @@ static void HIDAPI_DriverGameCube_SetDevicePlayerIndex(SDL_HIDAPI_Device *device
{
}
static void HIDAPI_DriverGameCube_HandleJoystickPacket(SDL_HIDAPI_Device *device, SDL_DriverGameCube_Context *ctx, const Uint8 *packet, int size)
static void HIDAPI_DriverGameCube_HandleJoystickPacket(SDL_HIDAPI_Device *device, SDL_DriverGameCube_Context *ctx, const Uint8 *packet, bool invert_c_stick)
{
SDL_Joystick *joystick;
Uint8 i, v;
const Uint8 i = 0; // We have a separate context for each connected controller in PC mode, just use the first index
Uint8 v;
Sint16 axis_value;
Uint64 timestamp = SDL_GetTicksNS();
if (size != 10) {
return; // How do we handle this packet?
}
i = packet[0] - 1;
if (i >= MAX_CONTROLLERS) {
return; // How do we handle this packet?
}
joystick = SDL_GetJoystickFromID(ctx->joysticks[i]);
if (!joystick) {
// Hasn't been opened yet, skip
return;
}
#define READ_BUTTON(off, flag, button) \
SDL_SendJoystickButton( \
timestamp, \
joystick, \
button, \
#define READ_BUTTON(off, flag, button) \
SDL_SendJoystickButton( \
timestamp, \
joystick, \
button, \
((packet[off] & flag) != 0));
READ_BUTTON(1, 0x02, 0) // A
READ_BUTTON(1, 0x04, 1) // B
READ_BUTTON(1, 0x08, 3) // Y
READ_BUTTON(1, 0x01, 2) // X
READ_BUTTON(2, 0x80, 4) // DPAD_LEFT
READ_BUTTON(2, 0x20, 5) // DPAD_RIGHT
READ_BUTTON(2, 0x40, 6) // DPAD_DOWN
READ_BUTTON(2, 0x10, 7) // DPAD_UP
READ_BUTTON(2, 0x02, 8) // START
READ_BUTTON(1, 0x80, 9) // RIGHTSHOULDER
READ_BUTTON(0, 0x02, 0) // A
READ_BUTTON(0, 0x04, 1) // B
READ_BUTTON(0, 0x08, 3) // Y
READ_BUTTON(0, 0x01, 2) // X
READ_BUTTON(1, 0x80, 4) // DPAD_LEFT
READ_BUTTON(1, 0x20, 5) // DPAD_RIGHT
READ_BUTTON(1, 0x40, 6) // DPAD_DOWN
READ_BUTTON(1, 0x10, 7) // DPAD_UP
READ_BUTTON(1, 0x02, 8) // START
READ_BUTTON(0, 0x80, 9) // RIGHTSHOULDER
/* These two buttons are for the bottoms of the analog triggers.
* More than likely, you're going to want to read the axes instead!
* -flibit
*/
READ_BUTTON(1, 0x20, 10) // TRIGGERRIGHT
READ_BUTTON(1, 0x10, 11) // TRIGGERLEFT
READ_BUTTON(0, 0x20, 10) // TRIGGERRIGHT
READ_BUTTON(0, 0x10, 11) // TRIGGERLEFT
#undef READ_BUTTON
#define READ_AXIS(off, axis, invert) \
v = invert ? (0xff - packet[off]) : packet[off]; \
if (v < ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \
ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \
if (v > ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \
ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \
#define READ_AXIS(off, axis, invert) \
v = (invert) ? (0xff - packet[off]) : packet[off]; \
if (v < ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \
ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \
if (v > ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \
ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \
axis_value = (Sint16)HIDAPI_RemapVal(v, ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis], ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis], SDL_MIN_SINT16, SDL_MAX_SINT16); \
SDL_SendJoystickAxis( \
timestamp, \
joystick, \
SDL_SendJoystickAxis( \
timestamp, \
joystick, \
axis, axis_value);
READ_AXIS(3, SDL_GAMEPAD_AXIS_LEFTX, 0)
READ_AXIS(4, SDL_GAMEPAD_AXIS_LEFTY, 1)
READ_AXIS(6, SDL_GAMEPAD_AXIS_RIGHTX, 0)
READ_AXIS(5, SDL_GAMEPAD_AXIS_RIGHTY, 1)
READ_AXIS(7, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0)
READ_AXIS(8, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0)
READ_AXIS(2, SDL_GAMEPAD_AXIS_LEFTX, 0)
READ_AXIS(3, SDL_GAMEPAD_AXIS_LEFTY, 1)
READ_AXIS(5, SDL_GAMEPAD_AXIS_RIGHTX, invert_c_stick ? 1 : 0)
READ_AXIS(4, SDL_GAMEPAD_AXIS_RIGHTY, invert_c_stick ? 0 : 1)
READ_AXIS(6, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0)
READ_AXIS(7, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0)
#undef READ_AXIS
}
@@ -365,7 +352,18 @@ static bool HIDAPI_DriverGameCube_UpdateDevice(SDL_HIDAPI_Device *device)
HIDAPI_DumpPacket("Nintendo GameCube packet: size = %d", packet, size);
#endif
if (ctx->pc_mode) {
HIDAPI_DriverGameCube_HandleJoystickPacket(device, ctx, packet, size);
if (size == 10) {
// This is the older firmware
// The first byte is the index of the connected controller
// The C stick has an inverted value range compared to the left stick
HIDAPI_DriverGameCube_HandleJoystickPacket(device, ctx, &packet[1], true);
} else if (size == 9) {
// This is the newer firmware (version 0x7)
// The C stick has the same value range compared to the left stick
HIDAPI_DriverGameCube_HandleJoystickPacket(device, ctx, packet, false);
} else {
// How do we handle this packet?
}
} else {
HIDAPI_DriverGameCube_HandleNintendoPacket(device, ctx, packet, size);
}
+2 -2
View File
@@ -1003,8 +1003,8 @@ static bool HIDAPI_DriverPS4_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device
static void HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverPS4_Context *ctx, PS4StatePacket_t *packet, int size)
{
static const float TOUCHPAD_SCALEX = 1.0f / 1920;
static const float TOUCHPAD_SCALEY = 1.0f / 920; // This is noted as being 944 resolution, but 920 feels better
static const float TOUCHPAD_SCALEX = 5.20833333e-4f; // 1.0f / 1920
static const float TOUCHPAD_SCALEY = 1.08695652e-3f; // 1.0f / 920 // This is noted as being 944 resolution, but 920 feels better
Sint16 axis;
bool touchpad_down;
int touchpad_x, touchpad_y;
+14 -9
View File
@@ -812,14 +812,19 @@ static void HIDAPI_DriverPS5_SetEnhancedModeAvailable(SDL_DriverPS5_Context *ctx
}
if (ctx->sensors_supported) {
// Standard DualSense sensor update rate is 250 Hz over USB
float update_rate = 250.0f;
if (ctx->device->is_bluetooth) {
// Bluetooth sensor update rate appears to be 1000 Hz
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_GYRO, 1000.0f);
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL, 1000.0f);
} else {
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_GYRO, 250.0f);
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL, 250.0f);
update_rate = 1000.0f;
} else if (SDL_IsJoystickDualSenseEdge(ctx->device->vendor_id, ctx->device->product_id)) {
// DualSense Edge sensor update rate is 1000 Hz over USB
update_rate = 1000.0f;
}
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_GYRO, update_rate);
SDL_PrivateJoystickAddSensor(ctx->joystick, SDL_SENSOR_ACCEL, update_rate);
}
ctx->report_battery = true;
@@ -1355,8 +1360,8 @@ static void HIDAPI_DriverPS5_HandleStatePacketCommon(SDL_Joystick *joystick, SDL
static void HIDAPI_DriverPS5_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverPS5_Context *ctx, PS5StatePacket_t *packet, Uint64 timestamp)
{
static const float TOUCHPAD_SCALEX = 1.0f / 1920;
static const float TOUCHPAD_SCALEY = 1.0f / 1070;
static const float TOUCHPAD_SCALEX = 5.20833333e-4f; // 1.0f / 1920
static const float TOUCHPAD_SCALEY = 9.34579439e-4f; // 1.0f / 1070
bool touchpad_down;
int touchpad_x, touchpad_y;
@@ -1406,8 +1411,8 @@ static void HIDAPI_DriverPS5_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_d
static void HIDAPI_DriverPS5_HandleStatePacketAlt(SDL_Joystick *joystick, SDL_hid_device *dev, SDL_DriverPS5_Context *ctx, PS5StatePacketAlt_t *packet, Uint64 timestamp)
{
static const float TOUCHPAD_SCALEX = 1.0f / 1920;
static const float TOUCHPAD_SCALEY = 1.0f / 1070;
static const float TOUCHPAD_SCALEX = 5.20833333e-4f; // 1.0f / 1920
static const float TOUCHPAD_SCALEY = 9.34579439e-4f; // 1.0f / 1070
bool touchpad_down;
int touchpad_x, touchpad_y;
+72 -44
View File
@@ -58,9 +58,7 @@
#define SWITCH_GYRO_SCALE 14.2842f
#define SWITCH_ACCEL_SCALE 4096.f
#define SWITCH_GYRO_SCALE_OFFSET 13371.0f
#define SWITCH_GYRO_SCALE_MULT 936.0f
#define SWITCH_ACCEL_SCALE_OFFSET 16384.0f
#define SWITCH_ACCEL_SCALE_MULT 4.0f
enum
@@ -930,13 +928,14 @@ static bool SetIMUEnabled(SDL_DriverSwitch_Context *ctx, bool enabled)
static bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx)
{
Uint8 *pLeftStickCal;
Uint8 *pRightStickCal;
Uint8 *pLeftStickCal = NULL;
Uint8 *pRightStickCal = NULL;
size_t stick, axis;
SwitchSubcommandInputPacket_t *user_reply = NULL;
SwitchSubcommandInputPacket_t *factory_reply = NULL;
SwitchSPIOpData_t readUserParams;
SwitchSPIOpData_t readFactoryParams;
Uint8 userParamsReadSuccessCount = 0;
// Read User Calibration Info
readUserParams.unAddress = k_unSPIStickUserCalibrationStartOffset;
@@ -949,33 +948,46 @@ static bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx)
readFactoryParams.unAddress = k_unSPIStickFactoryCalibrationStartOffset;
readFactoryParams.ucLength = k_unSPIStickFactoryCalibrationLength;
const int MAX_ATTEMPTS = 3;
for (int attempt = 0; ; ++attempt) {
if (!WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t *)&readFactoryParams, sizeof(readFactoryParams), &factory_reply)) {
return false;
}
if (factory_reply->stickFactoryCalibration.opData.unAddress == k_unSPIStickFactoryCalibrationStartOffset) {
// We successfully read the calibration data
break;
}
if (attempt == MAX_ATTEMPTS) {
return false;
}
}
// Automatically select the user calibration if magic bytes are set
if (user_reply && user_reply->stickUserCalibration.rgucLeftMagic[0] == 0xB2 && user_reply->stickUserCalibration.rgucLeftMagic[1] == 0xA1) {
userParamsReadSuccessCount += 1;
pLeftStickCal = user_reply->stickUserCalibration.rgucLeftCalibration;
} else {
pLeftStickCal = factory_reply->stickFactoryCalibration.rgucLeftCalibration;
}
if (user_reply && user_reply->stickUserCalibration.rgucRightMagic[0] == 0xB2 && user_reply->stickUserCalibration.rgucRightMagic[1] == 0xA1) {
userParamsReadSuccessCount += 1;
pRightStickCal = user_reply->stickUserCalibration.rgucRightCalibration;
} else {
pRightStickCal = factory_reply->stickFactoryCalibration.rgucRightCalibration;
}
// Only read the factory calibration info if we failed to receive the correct magic bytes
if (userParamsReadSuccessCount < 2) {
// Read Factory Calibration Info
readFactoryParams.unAddress = k_unSPIStickFactoryCalibrationStartOffset;
readFactoryParams.ucLength = k_unSPIStickFactoryCalibrationLength;
const int MAX_ATTEMPTS = 3;
for (int attempt = 0;; ++attempt) {
if (!WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t *)&readFactoryParams, sizeof(readFactoryParams), &factory_reply)) {
return false;
}
if (factory_reply->stickFactoryCalibration.opData.unAddress == k_unSPIStickFactoryCalibrationStartOffset) {
// We successfully read the calibration data
pLeftStickCal = factory_reply->stickFactoryCalibration.rgucLeftCalibration;
pRightStickCal = factory_reply->stickFactoryCalibration.rgucRightCalibration;
break;
}
if (attempt == MAX_ATTEMPTS) {
return false;
}
}
}
// If we still don't have calibration data, return false
if (pLeftStickCal == NULL || pRightStickCal == NULL)
{
return false;
}
/* Stick calibration values are 12-bits each and are packed by bit
@@ -1044,6 +1056,8 @@ static bool LoadIMUCalibration(SDL_DriverSwitch_Context *ctx)
if (WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t *)&readParams, sizeof(readParams), &reply)) {
Uint8 *pIMUScale;
Sint16 sAccelRawX, sAccelRawY, sAccelRawZ, sGyroRawX, sGyroRawY, sGyroRawZ;
Sint16 sAccelSensCoeffX, sAccelSensCoeffY, sAccelSensCoeffZ;
Sint16 sGyroSensCoeffX, sGyroSensCoeffY, sGyroSensCoeffZ;
// IMU scale gives us multipliers for converting raw values to real world values
pIMUScale = reply->spiReadData.rgucReadData;
@@ -1052,10 +1066,18 @@ static bool LoadIMUCalibration(SDL_DriverSwitch_Context *ctx)
sAccelRawY = (pIMUScale[3] << 8) | pIMUScale[2];
sAccelRawZ = (pIMUScale[5] << 8) | pIMUScale[4];
sAccelSensCoeffX = (pIMUScale[7] << 8) | pIMUScale[6];
sAccelSensCoeffY = (pIMUScale[9] << 8) | pIMUScale[8];
sAccelSensCoeffZ = (pIMUScale[11] << 8) | pIMUScale[10];
sGyroRawX = (pIMUScale[13] << 8) | pIMUScale[12];
sGyroRawY = (pIMUScale[15] << 8) | pIMUScale[14];
sGyroRawZ = (pIMUScale[17] << 8) | pIMUScale[16];
sGyroSensCoeffX = (pIMUScale[19] << 8) | pIMUScale[18];
sGyroSensCoeffY = (pIMUScale[21] << 8) | pIMUScale[20];
sGyroSensCoeffZ = (pIMUScale[23] << 8) | pIMUScale[22];
// Check for user calibration data. If it's present and set, it'll override the factory settings
readParams.unAddress = k_unSPIIMUUserScaleStartOffset;
readParams.ucLength = k_unSPIIMUUserScaleLength;
@@ -1072,14 +1094,14 @@ static bool LoadIMUCalibration(SDL_DriverSwitch_Context *ctx)
}
// Accelerometer scale
ctx->m_IMUScaleData.fAccelScaleX = SWITCH_ACCEL_SCALE_MULT / (SWITCH_ACCEL_SCALE_OFFSET - (float)sAccelRawX) * SDL_STANDARD_GRAVITY;
ctx->m_IMUScaleData.fAccelScaleY = SWITCH_ACCEL_SCALE_MULT / (SWITCH_ACCEL_SCALE_OFFSET - (float)sAccelRawY) * SDL_STANDARD_GRAVITY;
ctx->m_IMUScaleData.fAccelScaleZ = SWITCH_ACCEL_SCALE_MULT / (SWITCH_ACCEL_SCALE_OFFSET - (float)sAccelRawZ) * SDL_STANDARD_GRAVITY;
ctx->m_IMUScaleData.fAccelScaleX = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffX - (float)sAccelRawX) * SDL_STANDARD_GRAVITY;
ctx->m_IMUScaleData.fAccelScaleY = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffY - (float)sAccelRawY) * SDL_STANDARD_GRAVITY;
ctx->m_IMUScaleData.fAccelScaleZ = SWITCH_ACCEL_SCALE_MULT / ((float)sAccelSensCoeffZ - (float)sAccelRawZ) * SDL_STANDARD_GRAVITY;
// Gyro scale
ctx->m_IMUScaleData.fGyroScaleX = SWITCH_GYRO_SCALE_MULT / (SWITCH_GYRO_SCALE_OFFSET - (float)sGyroRawX) * SDL_PI_F / 180.0f;
ctx->m_IMUScaleData.fGyroScaleY = SWITCH_GYRO_SCALE_MULT / (SWITCH_GYRO_SCALE_OFFSET - (float)sGyroRawY) * SDL_PI_F / 180.0f;
ctx->m_IMUScaleData.fGyroScaleZ = SWITCH_GYRO_SCALE_MULT / (SWITCH_GYRO_SCALE_OFFSET - (float)sGyroRawZ) * SDL_PI_F / 180.0f;
ctx->m_IMUScaleData.fGyroScaleX = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffX - (float)sGyroRawX) * SDL_PI_F / 180.0f;
ctx->m_IMUScaleData.fGyroScaleY = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffY - (float)sGyroRawY) * SDL_PI_F / 180.0f;
ctx->m_IMUScaleData.fGyroScaleZ = SWITCH_GYRO_SCALE_MULT / ((float)sGyroSensCoeffZ - (float)sGyroRawZ) * SDL_PI_F / 180.0f;
} else {
// Use default values
@@ -1101,14 +1123,17 @@ static Sint16 ApplyStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, i
{
sRawValue -= ctx->m_StickCalData[nStick].axis[nAxis].sCenter;
if (sRawValue > ctx->m_StickExtents[nStick].axis[nAxis].sMax) {
ctx->m_StickExtents[nStick].axis[nAxis].sMax = sRawValue;
if (sRawValue >= 0) {
if (sRawValue > ctx->m_StickExtents[nStick].axis[nAxis].sMax) {
ctx->m_StickExtents[nStick].axis[nAxis].sMax = sRawValue;
}
return (Sint16)HIDAPI_RemapVal(sRawValue, 0, ctx->m_StickExtents[nStick].axis[nAxis].sMax, 0, SDL_MAX_SINT16);
} else {
if (sRawValue < ctx->m_StickExtents[nStick].axis[nAxis].sMin) {
ctx->m_StickExtents[nStick].axis[nAxis].sMin = sRawValue;
}
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, 0, SDL_MIN_SINT16, 0);
}
if (sRawValue < ctx->m_StickExtents[nStick].axis[nAxis].sMin) {
ctx->m_StickExtents[nStick].axis[nAxis].sMin = sRawValue;
}
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, ctx->m_StickExtents[nStick].axis[nAxis].sMax, SDL_MIN_SINT16, SDL_MAX_SINT16);
}
static Sint16 ApplySimpleStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, int nAxis, Sint16 sRawValue)
@@ -1118,14 +1143,17 @@ static Sint16 ApplySimpleStickCalibration(SDL_DriverSwitch_Context *ctx, int nSt
sRawValue -= usJoystickCenter;
if (sRawValue > ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax) {
ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax = sRawValue;
if (sRawValue >= 0) {
if (sRawValue > ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax) {
ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax = sRawValue;
}
return (Sint16)HIDAPI_RemapVal(sRawValue, 0, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax, 0, SDL_MAX_SINT16);
} else {
if (sRawValue < ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin) {
ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin = sRawValue;
}
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin, 0, SDL_MIN_SINT16, 0);
}
if (sRawValue < ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin) {
ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin = sRawValue;
}
return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMin, ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax, SDL_MIN_SINT16, SDL_MAX_SINT16);
}
static Uint8 RemapButton(SDL_DriverSwitch_Context *ctx, Uint8 button)
+1
View File
@@ -84,6 +84,7 @@
#define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS4_WIRED 0x0d17
#define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS5_WIRELESS 0x0d18
#define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS5_WIRED 0x0d19
#define USB_PRODUCT_NACON_REVOLUTION_X_UNLIMITED_BT 0x0689
#define USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER 0x0337
#define USB_PRODUCT_NINTENDO_N64_CONTROLLER 0x2019
#define USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER 0x201e
@@ -40,11 +40,7 @@
#define CONVERT_MAGNITUDE(x) (((x)*10000) / 0x7FFF)
// external variables referenced.
#ifdef SDL_VIDEO_DRIVER_WINDOWS
extern HWND SDL_HelperWindow;
#else
static const HWND SDL_HelperWindow = NULL;
#endif
// local variables
static bool coinitialized = false;
+5 -3
View File
@@ -2685,6 +2685,8 @@ static void UpdateLogicalPresentation(SDL_Renderer *renderer)
view->pixel_h = (int) view->logical_dst_rect.h;
UpdatePixelViewport(renderer, view);
UpdatePixelClipRect(renderer, view);
QueueCmdSetViewport(renderer);
QueueCmdSetClipRect(renderer);
}
bool SDL_SetRenderLogicalPresentation(SDL_Renderer *renderer, int w, int h, SDL_RendererLogicalPresentation mode)
@@ -3605,7 +3607,7 @@ bool SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count
#endif
SDL_RenderViewState *view = renderer->view;
const bool islogical = ((view == &renderer->main_view) && (view->logical_presentation_mode != SDL_LOGICAL_PRESENTATION_DISABLED));
const bool islogical = (view->logical_presentation_mode != SDL_LOGICAL_PRESENTATION_DISABLED);
if (islogical || (renderer->line_method == SDL_RENDERLINEMETHOD_GEOMETRY)) {
const float scale_x = view->current_scale.x;
@@ -3624,7 +3626,7 @@ bool SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count
int num_indices = 0;
const int size_indices = 4;
int cur_index = -4;
const int is_looping = (points[0].x == points[count - 1].x && points[0].y == points[count - 1].y);
const bool is_looping = (points[0].x == points[count - 1].x && points[0].y == points[count - 1].y);
SDL_FPoint p; // previous point
p.x = p.y = 0.0f;
/* p q
@@ -3656,7 +3658,7 @@ bool SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count
num_indices += 3;
// closed polyline, don´t draw twice the point
if (i || is_looping == 0) {
if (i || !is_looping) {
ADD_TRIANGLE(4, 5, 6)
ADD_TRIANGLE(4, 6, 7)
}
+16
View File
@@ -1651,6 +1651,8 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
} else {
renderdata->glGenTextures(1, &data->texture_v);
if (!GL_CheckError("glGenTexures()", renderer)) {
SDL_free(data->pixel_data);
SDL_free(data);
return false;
}
}
@@ -1665,6 +1667,8 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
} else {
renderdata->glGenTextures(1, &data->texture_u);
if (!GL_CheckError("glGenTexures()", renderer)) {
SDL_free(data->pixel_data);
SDL_free(data);
return false;
}
}
@@ -1672,11 +1676,15 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
renderdata->glBindTexture(data->texture_type, data->texture_u);
renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
if (!GL_CheckError("glTexImage2D()", renderer)) {
SDL_free(data->pixel_data);
SDL_free(data);
return false;
}
SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER, data->texture_u);
if (!SDL_GetYCbCRtoRGBConversionMatrix(texture->colorspace, texture->w, texture->h, 8)) {
SDL_free(data->pixel_data);
SDL_free(data);
return SDL_SetError("Unsupported YUV colorspace");
}
} else if (data->nv12) {
@@ -1686,6 +1694,8 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
} else {
renderdata->glGenTextures(1, &data->texture_u);
if (!GL_CheckError("glGenTexures()", renderer)) {
SDL_free(data->pixel_data);
SDL_free(data);
return false;
}
}
@@ -1693,11 +1703,15 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
renderdata->glBindTexture(data->texture_type, data->texture_u);
renderdata->glTexImage2D(data->texture_type, 0, GL_LUMINANCE_ALPHA, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
if (!GL_CheckError("glTexImage2D()", renderer)) {
SDL_free(data->pixel_data);
SDL_free(data);
return false;
}
SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER, data->texture_u);
if (!SDL_GetYCbCRtoRGBConversionMatrix(texture->colorspace, texture->w, texture->h, 8)) {
SDL_free(data->pixel_data);
SDL_free(data);
return SDL_SetError("Unsupported YUV colorspace");
}
}
@@ -1709,6 +1723,8 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
} else {
renderdata->glGenTextures(1, &data->texture);
if (!GL_CheckError("glGenTexures()", renderer)) {
SDL_free(data->pixel_data);
SDL_free(data);
return false;
}
}
+2 -2
View File
@@ -3763,7 +3763,7 @@ static bool VULKAN_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand
VULKAN_SetupShaderConstants(renderer, cmd, texture, &constants);
switch (cmd->data.draw.texture_scale_mode) {
case VK_FILTER_NEAREST:
case SDL_SCALEMODE_NEAREST:
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
textureSampler = rendererData->samplers[VULKAN_SAMPLER_NEAREST_CLAMP];
@@ -3775,7 +3775,7 @@ static bool VULKAN_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand
return SDL_SetError("Unknown texture address mode: %d", cmd->data.draw.texture_address_mode);
}
break;
case VK_FILTER_LINEAR:
case SDL_SCALEMODE_LINEAR:
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
textureSampler = rendererData->samplers[VULKAN_SAMPLER_LINEAR_CLAMP];
+6 -1
View File
@@ -41,7 +41,12 @@
#define environ (*_NSGetEnviron())
#elif defined(SDL_PLATFORM_FREEBSD)
#include <dlfcn.h>
#define environ ((char **)dlsym(RTLD_DEFAULT, "environ"))
static char **get_environ_rtld(void)
{
char ***environ_rtld = (char ***)dlsym(RTLD_DEFAULT, "environ");
return environ_rtld ? *environ_rtld : NULL;
}
#define environ (get_environ_rtld())
#else
extern char **environ;
#endif
+7
View File
@@ -1478,6 +1478,13 @@ DLMALLOC_EXPORT int mspace_mallopt(int, int);
#endif /* NO_MALLOC_STATS */
#ifndef LACKS_ERRNO_H
#include <errno.h> /* for MALLOC_FAILURE_ACTION */
#else /* LACKS_ERRNO_H */
#ifndef EINVAL
#define EINVAL 22
#endif
#ifndef ENOMEM
#define ENOMEM 12
#endif
#endif /* LACKS_ERRNO_H */
#ifdef DEBUG
#if ABORT_ON_ASSERT_FAILURE
+9 -1
View File
@@ -32,6 +32,8 @@
#include <pspkerneltypes.h>
#include <pspthreadman.h>
#define PSP_THREAD_NAME_MAX 32
static int ThreadEntry(SceSize args, void *argp)
{
SDL_RunThread(*(SDL_Thread **)argp);
@@ -44,6 +46,7 @@ bool SDL_SYS_CreateThread(SDL_Thread *thread,
{
SceKernelThreadInfo status;
int priority = 32;
char thread_name[PSP_THREAD_NAME_MAX];
// Set priority of new thread to the same as the current thread
status.size = sizeof(SceKernelThreadInfo);
@@ -51,7 +54,12 @@ bool SDL_SYS_CreateThread(SDL_Thread *thread,
priority = status.currentPriority;
}
thread->handle = sceKernelCreateThread(thread->name, ThreadEntry,
SDL_strlcpy(thread_name, "SDL thread", PSP_THREAD_NAME_MAX);
if (thread->name) {
SDL_strlcpy(thread_name, thread->name, PSP_THREAD_NAME_MAX);
}
thread->handle = sceKernelCreateThread(thread_name, ThreadEntry,
priority, thread->stacksize ? ((int)thread->stacksize) : 0x8000,
PSP_THREAD_ATTR_VFPU, NULL);
if (thread->handle < 0) {
+10 -4
View File
@@ -42,6 +42,10 @@ void SDL_CancelClipboardData(Uint32 sequence)
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (!_this) {
return;
}
if (sequence && sequence != _this->clipboard_sequence) {
// This clipboard data was already canceled
return;
@@ -62,6 +66,10 @@ bool SDL_SaveClipboardMimeTypes(const char **mime_types, size_t num_mime_types)
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (!_this) {
return SDL_UninitializedVideo();
}
SDL_FreeClipboardMimeTypes(_this);
if (mime_types && num_mime_types > 0) {
@@ -234,13 +242,11 @@ bool SDL_HasClipboardData(const char *mime_type)
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (!_this) {
SDL_UninitializedVideo();
return false;
return SDL_UninitializedVideo();
}
if (!mime_type) {
SDL_InvalidParamError("mime_type");
return false;
return SDL_InvalidParamError("mime_type");
}
if (_this->HasClipboardData) {
+1 -1
View File
@@ -1247,7 +1247,7 @@ bool SDL_BlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surfac
// Clip again
SDL_GetRectIntersection(clip_rect, &final_dst, &final_dst);
if (final_dst.w == 0 || final_dst.h == 0 ||
if (final_dst.w <= 0 || final_dst.h <= 0 ||
final_src.w < 0 || final_src.h < 0) {
// No-op.
return true;
+6
View File
@@ -103,6 +103,7 @@ struct SDL_Window
bool restore_on_show; // Child was hidden recursively by the parent, restore when shown.
bool last_position_pending; // This should NOT be cleared by the backend, as it is used for fullscreen positioning.
bool last_size_pending; // This should be cleared by the backend if the new size cannot be applied.
bool constrain_popup;
bool is_destroying;
bool is_dropping; // drag/drop in progress, expecting SDL_SendDropComplete().
@@ -129,6 +130,9 @@ struct SDL_Window
SDL_WindowData *internal;
// If a toplevel window, holds the current keyboard focus for grabbing popups.
SDL_Window *keyboard_focus;
SDL_Window *prev;
SDL_Window *next;
@@ -565,6 +569,8 @@ extern bool SDL_RecreateWindow(SDL_Window *window, SDL_WindowFlags flags);
extern bool SDL_HasWindows(void);
extern void SDL_RelativeToGlobalForWindow(SDL_Window *window, int rel_x, int rel_y, int *abs_x, int *abs_y);
extern void SDL_GlobalToRelativeForWindow(SDL_Window *window, int abs_x, int abs_y, int *rel_x, int *rel_y);
extern bool SDL_ShouldFocusPopup(SDL_Window *window);
extern bool SDL_ShouldRelinquishPopupFocus(SDL_Window *window, SDL_Window **new_focus);
extern void SDL_OnDisplayAdded(SDL_VideoDisplay *display);
extern void SDL_OnDisplayMoved(SDL_VideoDisplay *display);
+52 -2
View File
@@ -171,9 +171,10 @@ static VideoBootStrap *bootstrap[] = {
}
#if defined(SDL_PLATFORM_MACOS) && defined(SDL_VIDEO_DRIVER_COCOA)
// Support for macOS fullscreen spaces
// Support for macOS fullscreen spaces, etc.
extern bool Cocoa_IsWindowInFullscreenSpace(SDL_Window *window);
extern bool Cocoa_SetWindowFullscreenSpace(SDL_Window *window, bool state, bool blocking);
extern bool Cocoa_IsShowingModalDialog(SDL_Window *window);
#endif
#ifdef SDL_VIDEO_DRIVER_UIKIT
@@ -2503,6 +2504,7 @@ SDL_Window *SDL_CreateWindowWithProperties(SDL_PropertiesID props)
window->is_destroying = false;
window->last_displayID = SDL_GetDisplayForWindow(window);
window->external_graphics_context = external_graphics_context;
window->constrain_popup = SDL_GetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN, true);
if (_this->windows) {
_this->windows->prev = window;
@@ -3661,6 +3663,10 @@ bool SDL_SetWindowParent(SDL_Window *window, SDL_Window *parent)
CHECK_WINDOW_NOT_POPUP(parent, false);
}
if (window == parent) {
return SDL_SetError("Cannot set the parent of a window to itself.");
}
if (!_this->SetWindowParent) {
return SDL_Unsupported();
}
@@ -3706,6 +3712,48 @@ bool SDL_SetWindowModal(SDL_Window *window, bool modal)
return _this->SetWindowModal(_this, window, modal);
}
bool SDL_ShouldRelinquishPopupFocus(SDL_Window *window, SDL_Window **new_focus)
{
SDL_Window *focus = window->parent;
bool set_focus = !!(window->flags & SDL_WINDOW_INPUT_FOCUS);
// Find the highest level window, up to the toplevel parent, that isn't being hidden or destroyed, and can grab the keyboard focus.
while (SDL_WINDOW_IS_POPUP(focus) && ((focus->flags & SDL_WINDOW_NOT_FOCUSABLE) || focus->is_hiding || focus->is_destroying)) {
focus = focus->parent;
// If some window in the chain currently had focus, set it to the new lowest-level window.
if (!set_focus) {
set_focus = !!(focus->flags & SDL_WINDOW_INPUT_FOCUS);
}
}
*new_focus = focus;
return set_focus;
}
bool SDL_ShouldFocusPopup(SDL_Window *window)
{
SDL_Window *toplevel_parent;
for (toplevel_parent = window->parent; SDL_WINDOW_IS_POPUP(toplevel_parent); toplevel_parent = toplevel_parent->parent) {
}
SDL_Window *current_focus = toplevel_parent->keyboard_focus;
bool found_higher_focus = false;
/* Traverse the window tree from the currently focused window to the toplevel parent and see if we encounter
* the new focus request. If the new window is found, a higher-level window already has focus.
*/
SDL_Window *w;
for (w = current_focus; w != toplevel_parent; w = w->parent) {
if (w == window) {
found_higher_focus = true;
break;
}
}
return !found_higher_focus || w == toplevel_parent;
}
bool SDL_SetWindowFocusable(SDL_Window *window, bool focusable)
{
CHECK_WINDOW_MAGIC(window, false);
@@ -4124,7 +4172,9 @@ static bool SDL_ShouldMinimizeOnFocusLoss(SDL_Window *window)
#if defined(SDL_PLATFORM_MACOS) && defined(SDL_VIDEO_DRIVER_COCOA)
if (SDL_strcmp(_this->name, "cocoa") == 0) { // don't do this for X11, etc
if (Cocoa_IsWindowInFullscreenSpace(window)) {
if (Cocoa_IsShowingModalDialog(window)) {
return false; // modal system dialogs can live over fullscreen windows, don't minimize.
} else if (Cocoa_IsWindowInFullscreenSpace(window)) {
return false;
}
}
+14 -3
View File
@@ -311,15 +311,26 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
- (void)applicationDidFinishLaunching:(NSNotification *)notification
{
if (!SDL_GetHintBoolean("SDL_MAC_REGISTER_ACTIVATION_HANDLERS", true))
if (!SDL_GetHintBoolean("SDL_MAC_REGISTER_ACTIVATION_HANDLERS", true)) {
return;
}
/* The menu bar of SDL apps which don't have the typical .app bundle
* structure fails to work the first time a window is created (until it's
* de-focused and re-focused), if this call is in Cocoa_RegisterApp instead
* of here. https://bugzilla.libsdl.org/show_bug.cgi?id=3051
* of here. https://github.com/libsdl-org/SDL/issues/1913
*/
if (!SDL_GetHintBoolean(SDL_HINT_MAC_BACKGROUND_APP, false)) {
/* this apparently became unnecessary on macOS 14.0, and will addition pop up a
hidden dock if you're moving the mouse during launch, so change the default
behaviour there. https://github.com/libsdl-org/SDL/issues/10340
(13.6 still needs it, presumably 13.7 does, too.) */
bool background_app_default = false;
if (@available(macOS 14.0, *)) {
background_app_default = true; /* by default, don't explicitly activate the dock and then us again to force to foreground */
}
if (!SDL_GetHintBoolean(SDL_HINT_MAC_BACKGROUND_APP, background_app_default)) {
// Get more aggressive for Catalina: activate the Dock first so we definitely reset all activation state.
for (NSRunningApplication *i in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.dock"]) {
[i activateWithOptions:NSApplicationActivateIgnoringOtherApps];
+1 -1
View File
@@ -146,13 +146,13 @@ typedef enum
@property(nonatomic) BOOL was_zoomed;
@property(nonatomic) NSInteger window_number;
@property(nonatomic) NSInteger flash_request;
@property(nonatomic) SDL_Window *keyboard_focus;
@property(nonatomic) SDL3Cocoa_WindowListener *listener;
@property(nonatomic) NSModalSession modal_session;
@property(nonatomic) SDL_CocoaVideoData *videodata;
@property(nonatomic) bool pending_size;
@property(nonatomic) bool pending_position;
@property(nonatomic) bool border_toggled;
@property(nonatomic) bool has_modal_dialog;
#ifdef SDL_VIDEO_OPENGL_EGL
@property(nonatomic) EGLSurface egl_surface;
+61 -40
View File
@@ -432,6 +432,18 @@ bool Cocoa_IsWindowZoomed(SDL_Window *window)
return zoomed;
}
bool Cocoa_IsShowingModalDialog(SDL_Window *window)
{
SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->internal;
return data.has_modal_dialog;
}
void Cocoa_SetWindowHasModalDialog(SDL_Window *window, bool has_modal)
{
SDL_CocoaWindowData *data = (__bridge SDL_CocoaWindowData *)window->internal;
data.has_modal_dialog = has_modal;
}
typedef enum CocoaMenuVisibility
{
COCOA_MENU_VISIBILITY_AUTO = 0,
@@ -707,10 +719,7 @@ static SDL_Window *GetParentToplevelWindow(SDL_Window *window)
static void Cocoa_SetKeyboardFocus(SDL_Window *window, bool set_active_focus)
{
SDL_Window *toplevel = GetParentToplevelWindow(window);
SDL_CocoaWindowData *toplevel_data;
toplevel_data = (__bridge SDL_CocoaWindowData *)toplevel->internal;
toplevel_data.keyboard_focus = window;
toplevel->keyboard_focus = window;
if (set_active_focus && !window->is_hiding && !window->is_destroying) {
SDL_SetKeyboardFocus(window);
@@ -1190,21 +1199,27 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
ScheduleContextUpdates(_data);
/* isZoomed always returns true if the window is not resizable
* and fullscreen windows are considered zoomed.
/* The OS can resize the window automatically if the display density
* changes while the window is miniaturized or hidden.
*/
if ((window->flags & SDL_WINDOW_RESIZABLE) && [nswindow isZoomed] &&
!(window->flags & SDL_WINDOW_FULLSCREEN) && ![self isInFullscreenSpace]) {
zoomed = YES;
} else {
zoomed = NO;
}
if (!zoomed) {
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESTORED, 0, 0);
} else {
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MAXIMIZED, 0, 0);
if ([self windowOperationIsPending:PENDING_OPERATION_MINIMIZE]) {
[nswindow miniaturize:nil];
if ([nswindow isVisible])
{
/* isZoomed always returns true if the window is not resizable
* and fullscreen windows are considered zoomed.
*/
if ((window->flags & SDL_WINDOW_RESIZABLE) && [nswindow isZoomed] &&
!(window->flags & SDL_WINDOW_FULLSCREEN) && ![self isInFullscreenSpace]) {
zoomed = YES;
} else {
zoomed = NO;
}
if (!zoomed) {
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESTORED, 0, 0);
} else {
SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MAXIMIZED, 0, 0);
if ([self windowOperationIsPending:PENDING_OPERATION_MINIMIZE]) {
[nswindow miniaturize:nil];
}
}
}
@@ -1252,7 +1267,7 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
// We're going to get keyboard events, since we're key.
// This needs to be done before restoring the relative mouse mode.
Cocoa_SetKeyboardFocus(_data.keyboard_focus ? _data.keyboard_focus : window, true);
Cocoa_SetKeyboardFocus(window->keyboard_focus ? window->keyboard_focus : window, true);
// If we just gained focus we need the updated mouse position
if (!(window->flags & SDL_WINDOW_MOUSE_RELATIVE_MODE)) {
@@ -2261,7 +2276,9 @@ static bool SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, NSWindow
[nswindow setIgnoresMouseEvents:YES];
[nswindow setAcceptsMouseMovedEvents:NO];
} else if ((window->flags & SDL_WINDOW_POPUP_MENU) && !(window->flags & SDL_WINDOW_HIDDEN)) {
Cocoa_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus());
if (!(window->flags & SDL_WINDOW_NOT_FOCUSABLE)) {
Cocoa_SetKeyboardFocus(window, true);
}
Cocoa_UpdateMouseFocus();
}
}
@@ -2351,7 +2368,7 @@ bool Cocoa_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properti
rect.origin.y -= screenRect.origin.y;
// Constrain the popup
if (SDL_WINDOW_IS_POPUP(window)) {
if (SDL_WINDOW_IS_POPUP(window) && window->constrain_popup) {
if (rect.origin.x + rect.size.width > screenRect.origin.x + screenRect.size.width) {
rect.origin.x -= (rect.origin.x + rect.size.width) - (screenRect.origin.x + screenRect.size.width);
}
@@ -2507,7 +2524,7 @@ bool Cocoa_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window)
ConvertNSRect(&rect);
// Position and constrain the popup
if (SDL_WINDOW_IS_POPUP(window)) {
if (SDL_WINDOW_IS_POPUP(window) && window->constrain_popup) {
NSRect screenRect = [ScreenForRect(&rect) frame];
if (rect.origin.x + rect.size.width > screenRect.origin.x + screenRect.size.width) {
@@ -2648,7 +2665,9 @@ void Cocoa_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
}
}
} else if (window->flags & SDL_WINDOW_POPUP_MENU) {
Cocoa_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus());
if (!(window->flags & SDL_WINDOW_NOT_FOCUSABLE)) {
Cocoa_SetKeyboardFocus(window, true);
}
Cocoa_UpdateMouseFocus();
}
}
@@ -2682,20 +2701,9 @@ void Cocoa_HideWindow(SDL_VideoDevice *_this, SDL_Window *window)
Cocoa_SetWindowModal(_this, window, false);
// Transfer keyboard focus back to the parent when closing a popup menu
if (window->flags & SDL_WINDOW_POPUP_MENU) {
SDL_Window *new_focus = window->parent;
bool set_focus = window == SDL_GetKeyboardFocus();
// Find the highest level window, up to the toplevel parent, that isn't being hidden or destroyed.
while (SDL_WINDOW_IS_POPUP(new_focus) && (new_focus->is_hiding || new_focus->is_destroying)) {
new_focus = new_focus->parent;
// If some window in the chain currently had focus, set it to the new lowest-level window.
if (!set_focus) {
set_focus = new_focus == SDL_GetKeyboardFocus();
}
}
if ((window->flags & SDL_WINDOW_POPUP_MENU) && !(window->flags & SDL_WINDOW_NOT_FOCUSABLE)) {
SDL_Window *new_focus;
const bool set_focus = SDL_ShouldRelinquishPopupFocus(window, &new_focus);
Cocoa_SetKeyboardFocus(new_focus, set_focus);
Cocoa_UpdateMouseFocus();
} else if (window->parent && waskey) {
@@ -3122,20 +3130,19 @@ void Cocoa_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
#endif // SDL_VIDEO_OPENGL
SDL_Window *topmost = GetParentToplevelWindow(window);
SDL_CocoaWindowData *topmost_data = (__bridge SDL_CocoaWindowData *)topmost->internal;
/* Reset the input focus of the root window if this window is still set as keyboard focus.
* SDL_DestroyWindow will have already taken care of reassigning focus if this is the SDL
* keyboard focus, this ensures that an inactive window with this window set as input focus
* does not try to reference it the next time it gains focus.
*/
if (topmost_data.keyboard_focus == window) {
if (topmost->keyboard_focus == window) {
SDL_Window *new_focus = window;
while (SDL_WINDOW_IS_POPUP(new_focus) && (new_focus->is_hiding || new_focus->is_destroying)) {
new_focus = new_focus->parent;
}
topmost_data.keyboard_focus = new_focus;
topmost->keyboard_focus = new_focus;
}
if ([data.listener isInFullscreenSpace]) {
@@ -3300,6 +3307,20 @@ bool Cocoa_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOper
bool Cocoa_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, bool focusable)
{
if (window->flags & SDL_WINDOW_POPUP_MENU) {
if (!(window->flags & SDL_WINDOW_HIDDEN)) {
if (!focusable && (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
SDL_Window *new_focus;
const bool set_focus = SDL_ShouldRelinquishPopupFocus(window, &new_focus);
Cocoa_SetKeyboardFocus(new_focus, set_focus);
} else if (focusable) {
if (SDL_ShouldFocusPopup(window)) {
Cocoa_SetKeyboardFocus(window, true);
}
}
}
}
return true; // just succeed, the real work is done elsewhere.
}
+1 -1
View File
@@ -1717,7 +1717,7 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
window->keyboard_device = input;
// Restore the keyboard focus to the child popup that was holding it
SDL_SetKeyboardFocus(window->keyboard_focus ? window->keyboard_focus : window->sdlwindow);
SDL_SetKeyboardFocus(window->sdlwindow->keyboard_focus ? window->sdlwindow->keyboard_focus : window->sdlwindow);
#ifdef SDL_USE_IME
if (!input->text_input) {
+1
View File
@@ -642,6 +642,7 @@ static SDL_VideoDevice *Wayland_CreateDevice(bool require_preferred_protocols)
device->HasScreenKeyboardSupport = Wayland_HasScreenKeyboardSupport;
device->ShowWindowSystemMenu = Wayland_ShowWindowSystemMenu;
device->SyncWindow = Wayland_SyncWindow;
device->SetWindowFocusable = Wayland_SetWindowFocusable;
#ifdef SDL_USE_LIBDBUS
if (SDL_SystemTheme_Init())
+66 -65
View File
@@ -181,7 +181,7 @@ static void SetMinMaxDimensions(SDL_Window *window)
#ifdef HAVE_LIBDECOR_H
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
if (!wind->shell_surface.libdecor.initial_configure_seen || !wind->shell_surface.libdecor.frame) {
if (!wind->shell_surface.libdecor.frame) {
return; // Can't do anything yet, wait for ShowWindow
}
/* No need to change these values if the window is non-resizable,
@@ -198,7 +198,7 @@ static void SetMinMaxDimensions(SDL_Window *window)
} else
#endif
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL) {
if (wind->shell_surface.xdg.toplevel.xdg_toplevel == NULL) {
if (!wind->shell_surface.xdg.toplevel.xdg_toplevel) {
return; // Can't do anything yet, wait for ShowWindow
}
xdg_toplevel_set_min_size(wind->shell_surface.xdg.toplevel.xdg_toplevel,
@@ -215,32 +215,32 @@ static void EnsurePopupPositionIsValid(SDL_Window *window, int *x, int *y)
int adj_count = 0;
/* Per the xdg-positioner spec, child popup windows must intersect or at
* least be partially adjacent to the parent window.
* least be partially adjoining the parent window.
*
* Failure to ensure this on a compositor that enforces this restriction
* can result in behavior ranging from the window being spuriously closed
* to a protocol violation.
*/
if (*x + window->w < 0) {
if (*x + window->w <= 0) {
*x = -window->w;
++adj_count;
}
if (*y + window->h < 0) {
if (*y + window->h <= 0) {
*y = -window->h;
++adj_count;
}
if (*x > window->parent->w) {
if (*x >= window->parent->w) {
*x = window->parent->w;
++adj_count;
}
if (*y > window->parent->h) {
if (*y >= window->parent->h) {
*y = window->parent->h;
++adj_count;
}
/* If adjustment was required on the x and y axes, the popup is aligned with
* the parent corner-to-corner and is neither overlapping nor adjacent, so it
* must be nudged by 1 to be considered adjacent.
* the parent corner-to-corner and is neither overlapping nor adjoining, so it
* must be nudged by 1 to be considered adjoining.
*/
if (adj_count > 1) {
*x += *x < 0 ? 1 : -1;
@@ -753,7 +753,9 @@ static void handle_configure_xdg_shell_surface(void *data, struct xdg_surface *x
xdg_surface_ack_configure(xdg, serial);
}
wind->shell_surface.xdg.initial_configure_seen = true;
if (wind->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_CONFIGURE) {
wind->shell_surface_status = WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_FRAME;
}
}
static const struct xdg_surface_listener shell_surface_listener_xdg = {
@@ -970,10 +972,6 @@ static void handle_configure_xdg_toplevel(void *data,
wind->active = active;
window->tiled = tiled;
wind->resizing = resizing;
if (wind->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_CONFIGURE) {
wind->shell_surface_status = WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_FRAME;
}
}
static void handle_close_xdg_toplevel(void *data, struct xdg_toplevel *xdg_toplevel)
@@ -1122,9 +1120,7 @@ static void handle_configure_zxdg_decoration(void *data,
WAYLAND_wl_display_roundtrip(internal->waylandData->display);
Wayland_HideWindow(device, window);
SDL_zero(internal->shell_surface);
internal->shell_surface_type = WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR;
Wayland_ShowWindow(device, window);
}
}
@@ -1406,11 +1402,8 @@ static void decoration_frame_configure(struct libdecor_frame *frame,
libdecor_state_free(state);
}
if (!wind->shell_surface.libdecor.initial_configure_seen) {
LibdecorGetMinContentSize(frame, &wind->system_limits.min_width, &wind->system_limits.min_height);
wind->shell_surface.libdecor.initial_configure_seen = true;
}
if (wind->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_CONFIGURE) {
LibdecorGetMinContentSize(frame, &wind->system_limits.min_width, &wind->system_limits.min_height);
wind->shell_surface_status = WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_FRAME;
}
@@ -1666,7 +1659,7 @@ static const struct wp_color_management_surface_feedback_v1_listener color_manag
feedback_surface_preferred_changed
};
static void SetKeyboardFocus(SDL_Window *window, bool set_focus)
static void Wayland_SetKeyboardFocus(SDL_Window *window, bool set_focus)
{
SDL_Window *toplevel = window;
@@ -1675,7 +1668,7 @@ static void SetKeyboardFocus(SDL_Window *window, bool set_focus)
toplevel = toplevel->parent;
}
toplevel->internal->keyboard_focus = window;
toplevel->keyboard_focus = window;
if (set_focus && !window->is_hiding && !window->is_destroying) {
SDL_SetKeyboardFocus(window);
@@ -1819,12 +1812,10 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
}
}
/* The window was hidden, but the sync point hasn't yet been reached.
* Pump events to avoid a possible protocol violation.
*/
if (data->show_hide_sync_required) {
// Always roundtrip to ensure there are no pending buffer attachments.
do {
WAYLAND_wl_display_roundtrip(c->display);
}
} while (data->show_hide_sync_required);
data->shell_surface_status = WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_CONFIGURE;
@@ -1905,8 +1896,9 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
data->shell_surface.xdg.popup.xdg_positioner = xdg_wm_base_create_positioner(c->shell.xdg);
xdg_positioner_set_anchor(data->shell_surface.xdg.popup.xdg_positioner, XDG_POSITIONER_ANCHOR_TOP_LEFT);
xdg_positioner_set_anchor_rect(data->shell_surface.xdg.popup.xdg_positioner, 0, 0, parent->internal->current.logical_width, parent->internal->current.logical_width);
xdg_positioner_set_constraint_adjustment(data->shell_surface.xdg.popup.xdg_positioner,
XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y);
const Uint32 constraint = window->constrain_popup ? (XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y) : XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_NONE;
xdg_positioner_set_constraint_adjustment(data->shell_surface.xdg.popup.xdg_positioner, constraint);
xdg_positioner_set_gravity(data->shell_surface.xdg.popup.xdg_positioner, XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT);
xdg_positioner_set_size(data->shell_surface.xdg.popup.xdg_positioner, data->current.logical_width, data->current.logical_height);
@@ -1935,8 +1927,8 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
wl_region_add(region, 0, 0, 0, 0);
wl_surface_set_input_region(data->surface, region);
wl_region_destroy(region);
} else if (window->flags & SDL_WINDOW_POPUP_MENU) {
SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus());
} else if ((window->flags & SDL_WINDOW_POPUP_MENU) && !(window->flags & SDL_WINDOW_NOT_FOCUSABLE)) {
Wayland_SetKeyboardFocus(window, true);
}
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_POPUP_POINTER, data->shell_surface.xdg.popup.xdg_popup);
@@ -1984,7 +1976,7 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
#ifdef HAVE_LIBDECOR_H
if (data->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
if (data->shell_surface.libdecor.frame) {
while (!data->shell_surface.libdecor.initial_configure_seen) {
while (data->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_CONFIGURE) {
WAYLAND_wl_display_flush(c->display);
WAYLAND_wl_display_dispatch(c->display);
}
@@ -1998,7 +1990,7 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
*/
wl_surface_commit(data->surface);
if (data->shell_surface.xdg.surface) {
while (!data->shell_surface.xdg.initial_configure_seen) {
while (data->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_CONFIGURE) {
WAYLAND_wl_display_flush(c->display);
WAYLAND_wl_display_dispatch(c->display);
}
@@ -2083,21 +2075,10 @@ static void Wayland_ReleasePopup(SDL_VideoDevice *_this, SDL_Window *popup)
return;
}
if (popup->flags & SDL_WINDOW_POPUP_MENU) {
SDL_Window *new_focus = popup->parent;
bool set_focus = popup == SDL_GetKeyboardFocus();
// Find the highest level window, up to the toplevel parent, that isn't being hidden or destroyed.
while (SDL_WINDOW_IS_POPUP(new_focus) && (new_focus->is_hiding || new_focus->is_destroying)) {
new_focus = new_focus->parent;
// If some window in the chain currently had focus, set it to the new lowest-level window.
if (!set_focus) {
set_focus = new_focus == SDL_GetKeyboardFocus();
}
}
SetKeyboardFocus(new_focus, set_focus);
if ((popup->flags & SDL_WINDOW_POPUP_MENU) && !(popup->flags & SDL_WINDOW_NOT_FOCUSABLE)) {
SDL_Window *new_focus;
const bool set_focus = SDL_ShouldRelinquishPopupFocus(popup, &new_focus);
Wayland_SetKeyboardFocus(new_focus, set_focus);
}
xdg_popup_destroy(popupdata->shell_surface.xdg.popup.xdg_popup);
@@ -2135,12 +2116,6 @@ void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window)
wind->server_decoration = NULL;
}
// Be sure to detach after this is done, otherwise ShowWindow crashes!
if (wind->shell_surface_type != WAYLAND_SHELL_SURFACE_TYPE_XDG_POPUP) {
wl_surface_attach(wind->surface, NULL, 0, 0);
wl_surface_commit(wind->surface);
}
// Clean up the export handle.
if (wind->exported) {
zxdg_exported_v2_destroy(wind->exported);
@@ -2158,26 +2133,31 @@ void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window)
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
if (wind->shell_surface.libdecor.frame) {
libdecor_frame_unref(wind->shell_surface.libdecor.frame);
wind->shell_surface.libdecor.frame = NULL;
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_SURFACE_POINTER, NULL);
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, NULL);
}
} else
#endif
{
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_POPUP) {
Wayland_ReleasePopup(_this, window);
} else if (wind->shell_surface.xdg.toplevel.xdg_toplevel) {
xdg_toplevel_destroy(wind->shell_surface.xdg.toplevel.xdg_toplevel);
wind->shell_surface.xdg.toplevel.xdg_toplevel = NULL;
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, NULL);
}
if (wind->shell_surface.xdg.surface) {
xdg_surface_destroy(wind->shell_surface.xdg.surface);
wind->shell_surface.xdg.surface = NULL;
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_SURFACE_POINTER, NULL);
Wayland_ReleasePopup(_this, window);
} else if (wind->shell_surface.xdg.toplevel.xdg_toplevel) {
xdg_toplevel_destroy(wind->shell_surface.xdg.toplevel.xdg_toplevel);
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, NULL);
}
if (wind->shell_surface.xdg.surface) {
xdg_surface_destroy(wind->shell_surface.xdg.surface);
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_SURFACE_POINTER, NULL);
}
}
// Attach a null buffer to unmap the surface.
wl_surface_attach(wind->surface, NULL, 0, 0);
wl_surface_commit(wind->surface);
SDL_zero(wind->shell_surface);
wind->show_hide_sync_required = true;
struct wl_callback *cb = wl_display_sync(_this->internal->display);
wl_callback_add_listener(cb, &show_hide_sync_listener, (void*)((uintptr_t)window->id));
@@ -2991,6 +2971,27 @@ bool Wayland_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window)
return true;
}
bool Wayland_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, bool focusable)
{
if (window->flags & SDL_WINDOW_POPUP_MENU) {
if (!(window->flags & SDL_WINDOW_HIDDEN)) {
if (!focusable && (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
SDL_Window *new_focus;
const bool set_focus = SDL_ShouldRelinquishPopupFocus(window, &new_focus);
Wayland_SetKeyboardFocus(new_focus, set_focus);
} else if (focusable) {
if (SDL_ShouldFocusPopup(window)) {
Wayland_SetKeyboardFocus(window, true);
}
}
}
return true;
}
return SDL_SetError("wayland: focus can only be toggled on popup menu windows");
}
void Wayland_ShowWindowSystemMenu(SDL_Window *window, int x, int y)
{
SDL_WindowData *wind = window->internal;
+1 -4
View File
@@ -48,7 +48,6 @@ struct SDL_WindowData
struct
{
struct libdecor_frame *frame;
bool initial_configure_seen;
} libdecor;
#endif
struct
@@ -66,7 +65,6 @@ struct SDL_WindowData
struct xdg_positioner *xdg_positioner;
} popup;
};
bool initial_configure_seen;
} xdg;
} shell_surface;
enum
@@ -125,8 +123,6 @@ struct SDL_WindowData
SDL_DisplayData **outputs;
int num_outputs;
SDL_Window *keyboard_focus;
char *app_id;
double scale_factor;
@@ -237,6 +233,7 @@ extern void Wayland_ShowWindowSystemMenu(SDL_Window *window, int x, int y);
extern void Wayland_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern bool Wayland_SuspendScreenSaver(SDL_VideoDevice *_this);
extern bool Wayland_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon);
extern bool Wayland_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, bool focusable);
extern float Wayland_GetWindowContentScale(SDL_VideoDevice *_this, SDL_Window *window);
extern void *Wayland_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, size_t *size);
+5 -1
View File
@@ -385,7 +385,7 @@ static void WIN_UpdateFocus(SDL_Window *window, bool expect_focus, DWORD pos)
}
}
SDL_SetKeyboardFocus(data->keyboard_focus ? data->keyboard_focus : window);
SDL_SetKeyboardFocus(window->keyboard_focus ? window->keyboard_focus : window);
// In relative mode we are guaranteed to have mouse focus if we have keyboard focus
if (!SDL_GetMouse()->relative_mode) {
@@ -732,6 +732,10 @@ static void WIN_HandleRawMouseInput(Uint64 timestamp, SDL_VideoData *data, HANDL
float fAmount = (float)amount / WHEEL_DELTA;
SDL_SendMouseWheel(WIN_GetEventTimestamp(), window, mouseID, fAmount, 0.0f, SDL_MOUSEWHEEL_NORMAL);
}
/* Invalidate the mouse button flags. If we don't do this then disabling raw input
will cause held down mouse buttons to persist when released. */
windowdata->mouse_button_flags = (WPARAM)-1;
}
}
+6
View File
@@ -277,6 +277,9 @@ static void GAMEINPUT_InitialMouseReading(WIN_GameInputData *data, SDL_Window *w
bool down = ((state.buttons & mask) != 0);
SDL_SendMouseButton(timestamp, window, mouseID, GAMEINPUT_button_map[i], down);
}
// Invalidate mouse button flags
window->internal->mouse_button_flags = (WPARAM)-1;
}
}
@@ -307,6 +310,9 @@ static void GAMEINPUT_HandleMouseDelta(WIN_GameInputData *data, SDL_Window *wind
SDL_SendMouseButton(timestamp, window, mouseID, GAMEINPUT_button_map[i], down);
}
}
// Invalidate mouse button flags
window->internal->mouse_button_flags = (WPARAM)-1;
}
if (delta.wheelX || delta.wheelY) {
float fAmountX = (float)delta.wheelX / WHEEL_DELTA;
+2
View File
@@ -112,7 +112,9 @@ static DWORD WINAPI WIN_RawInputThread(LPVOID param)
}
devices[0].dwFlags |= RIDEV_REMOVE;
devices[0].hwndTarget = NULL;
devices[1].dwFlags |= RIDEV_REMOVE;
devices[1].hwndTarget = NULL;
RegisterRawInputDevices(devices, count, sizeof(devices[0]));
DestroyWindow(window);
+71 -132
View File
@@ -33,6 +33,7 @@
#include "../SDL_sysvideo.h"
#include "SDL_windowsvideo.h"
#include "SDL_windowskeyboard.h"
#include "SDL_windowswindow.h"
// Dropfile support
@@ -91,12 +92,6 @@ typedef void (NTAPI *RtlGetVersion_t)(NT_OSVERSIONINFOW *);
// #define HIGHDPI_DEBUG
// Fake window to help with DirectInput events.
HWND SDL_HelperWindow = NULL;
static const TCHAR *SDL_HelperWindowClassName = TEXT("SDLHelperWindowInputCatcher");
static const TCHAR *SDL_HelperWindowName = TEXT("SDLHelperWindowInputMsgWindow");
static ATOM SDL_HelperWindowClass = 0;
/* For borderless Windows, still want the following flag:
- WS_MINIMIZEBOX: window will respond to Windows minimize commands sent to all windows, such as windows key + m, shaking title bar, etc.
Additionally, non-fullscreen windows can add:
@@ -638,7 +633,7 @@ static void CleanupWindowData(SDL_VideoDevice *_this, SDL_Window *window)
static void WIN_ConstrainPopup(SDL_Window *window, bool output_to_pending)
{
// Clamp popup windows to the output borders
// Possibly clamp popup windows to the output borders
if (SDL_WINDOW_IS_POPUP(window)) {
SDL_Window *w;
SDL_DisplayID displayID;
@@ -649,28 +644,30 @@ static void WIN_ConstrainPopup(SDL_Window *window, bool output_to_pending)
const int height = window->last_size_pending ? window->pending.h : window->floating.h;
int offset_x = 0, offset_y = 0;
// Calculate the total offset from the parents
for (w = window->parent; SDL_WINDOW_IS_POPUP(w); w = w->parent) {
if (window->constrain_popup) {
// Calculate the total offset from the parents
for (w = window->parent; SDL_WINDOW_IS_POPUP(w); w = w->parent) {
offset_x += w->x;
offset_y += w->y;
}
offset_x += w->x;
offset_y += w->y;
}
abs_x += offset_x;
abs_y += offset_y;
offset_x += w->x;
offset_y += w->y;
abs_x += offset_x;
abs_y += offset_y;
// Constrain the popup window to the display of the toplevel parent
displayID = SDL_GetDisplayForWindow(w);
SDL_GetDisplayBounds(displayID, &rect);
if (abs_x + width > rect.x + rect.w) {
abs_x -= (abs_x + width) - (rect.x + rect.w);
// Constrain the popup window to the display of the toplevel parent
displayID = SDL_GetDisplayForWindow(w);
SDL_GetDisplayBounds(displayID, &rect);
if (abs_x + width > rect.x + rect.w) {
abs_x -= (abs_x + width) - (rect.x + rect.w);
}
if (abs_y + height > rect.y + rect.h) {
abs_y -= (abs_y + height) - (rect.y + rect.h);
}
abs_x = SDL_max(abs_x, rect.x);
abs_y = SDL_max(abs_y, rect.y);
}
if (abs_y + height > rect.y + rect.h) {
abs_y -= (abs_y + height) - (rect.y + rect.h);
}
abs_x = SDL_max(abs_x, rect.x);
abs_y = SDL_max(abs_y, rect.y);
if (output_to_pending) {
window->pending.x = abs_x - offset_x;
@@ -695,7 +692,7 @@ static void WIN_SetKeyboardFocus(SDL_Window *window, bool set_active_focus)
toplevel = toplevel->parent;
}
toplevel->internal->keyboard_focus = window;
toplevel->keyboard_focus = window;
if (set_active_focus && !window->is_hiding && !window->is_destroying) {
SDL_SetKeyboardFocus(window);
@@ -750,6 +747,9 @@ bool WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properties
return false;
}
// Ensure that the IME isn't active on the new window until explicitly requested.
WIN_StopTextInput(_this, window);
// Inform Windows of the frame change so we can respond to WM_NCCALCSIZE
SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE);
@@ -1068,8 +1068,8 @@ void WIN_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
}
data->showing_window = false;
if (window->flags & SDL_WINDOW_POPUP_MENU && bActivate) {
WIN_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus());
if ((window->flags & SDL_WINDOW_POPUP_MENU) && !(window->flags & SDL_WINDOW_NOT_FOCUSABLE) && bActivate) {
WIN_SetKeyboardFocus(window, true);
}
if (window->flags & SDL_WINDOW_MODAL) {
WIN_SetWindowModal(_this, window, true);
@@ -1086,21 +1086,10 @@ void WIN_HideWindow(SDL_VideoDevice *_this, SDL_Window *window)
ShowWindow(hwnd, SW_HIDE);
// Transfer keyboard focus back to the parent
if (window->flags & SDL_WINDOW_POPUP_MENU) {
SDL_Window *new_focus = window->parent;
bool set_focus = window == SDL_GetKeyboardFocus();
// Find the highest level window, up to the toplevel parent, that isn't being hidden or destroyed.
while (SDL_WINDOW_IS_POPUP(new_focus) && (new_focus->is_hiding || new_focus->is_destroying)) {
new_focus = new_focus->parent;
// If some window in the chain currently had keyboard focus, set it to the new lowest-level window.
if (!set_focus) {
set_focus = new_focus == SDL_GetKeyboardFocus();
}
}
// Transfer keyboard focus back to the parent from a grabbing popup.
if ((window->flags & SDL_WINDOW_POPUP_MENU) && !(window->flags & SDL_WINDOW_NOT_FOCUSABLE)) {
SDL_Window *new_focus;
const bool set_focus = SDL_ShouldRelinquishPopupFocus(window, &new_focus);
WIN_SetKeyboardFocus(new_focus, set_focus);
}
}
@@ -1138,7 +1127,7 @@ void WIN_RaiseWindow(SDL_VideoDevice *_this, SDL_Window *window)
}
if (bActivate) {
SetForegroundWindow(hwnd);
if (window->flags & SDL_WINDOW_POPUP_MENU) {
if ((window->flags & SDL_WINDOW_POPUP_MENU) && !(window->flags & SDL_WINDOW_NOT_FOCUSABLE)) {
WIN_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus());
}
} else {
@@ -1515,72 +1504,6 @@ void WIN_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
CleanupWindowData(_this, window);
}
/*
* Creates a HelperWindow used for DirectInput.
*/
bool SDL_HelperWindowCreate(void)
{
HINSTANCE hInstance = GetModuleHandle(NULL);
WNDCLASS wce;
// Make sure window isn't created twice.
if (SDL_HelperWindow != NULL) {
return true;
}
// Create the class.
SDL_zero(wce);
wce.lpfnWndProc = DefWindowProc;
wce.lpszClassName = SDL_HelperWindowClassName;
wce.hInstance = hInstance;
// Register the class.
SDL_HelperWindowClass = RegisterClass(&wce);
if (SDL_HelperWindowClass == 0 && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) {
return WIN_SetError("Unable to create Helper Window Class");
}
// Create the window.
SDL_HelperWindow = CreateWindowEx(0, SDL_HelperWindowClassName,
SDL_HelperWindowName,
WS_OVERLAPPED, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, HWND_MESSAGE, NULL,
hInstance, NULL);
if (!SDL_HelperWindow) {
UnregisterClass(SDL_HelperWindowClassName, hInstance);
return WIN_SetError("Unable to create Helper Window");
}
return true;
}
/*
* Destroys the HelperWindow previously created with SDL_HelperWindowCreate.
*/
void SDL_HelperWindowDestroy(void)
{
HINSTANCE hInstance = GetModuleHandle(NULL);
// Destroy the window.
if (SDL_HelperWindow != NULL) {
if (DestroyWindow(SDL_HelperWindow) == 0) {
WIN_SetError("Unable to destroy Helper Window");
return;
}
SDL_HelperWindow = NULL;
}
// Unregister the class.
if (SDL_HelperWindowClass != 0) {
if ((UnregisterClass(SDL_HelperWindowClassName, hInstance)) == 0) {
WIN_SetError("Unable to destroy Helper Window Class");
return;
}
SDL_HelperWindowClass = 0;
}
}
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
void WIN_OnWindowEnter(SDL_VideoDevice *_this, SDL_Window *window)
{
@@ -2254,24 +2177,40 @@ void WIN_ShowWindowSystemMenu(SDL_Window *window, int x, int y)
bool WIN_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, bool focusable)
{
SDL_WindowData *data = window->internal;
HWND hwnd = data->hwnd;
const LONG style = GetWindowLong(hwnd, GWL_EXSTYLE);
if (!SDL_WINDOW_IS_POPUP(window)) {
SDL_WindowData *data = window->internal;
HWND hwnd = data->hwnd;
const LONG style = GetWindowLong(hwnd, GWL_EXSTYLE);
SDL_assert(style != 0);
SDL_assert(style != 0);
if (focusable) {
if (style & WS_EX_NOACTIVATE) {
if (SetWindowLong(hwnd, GWL_EXSTYLE, style & ~WS_EX_NOACTIVATE) == 0) {
return WIN_SetError("SetWindowLong()");
if (focusable) {
if (style & WS_EX_NOACTIVATE) {
if (SetWindowLong(hwnd, GWL_EXSTYLE, style & ~WS_EX_NOACTIVATE) == 0) {
return WIN_SetError("SetWindowLong()");
}
}
} else {
if (!(style & WS_EX_NOACTIVATE)) {
if (SetWindowLong(hwnd, GWL_EXSTYLE, style | WS_EX_NOACTIVATE) == 0) {
return WIN_SetError("SetWindowLong()");
}
}
}
} else {
if (!(style & WS_EX_NOACTIVATE)) {
if (SetWindowLong(hwnd, GWL_EXSTYLE, style | WS_EX_NOACTIVATE) == 0) {
return WIN_SetError("SetWindowLong()");
} else if (window->flags & SDL_WINDOW_POPUP_MENU) {
if (!(window->flags & SDL_WINDOW_HIDDEN)) {
if (!focusable && (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
SDL_Window *new_focus;
const bool set_focus = SDL_ShouldRelinquishPopupFocus(window, &new_focus);
WIN_SetKeyboardFocus(new_focus, set_focus);
} else if (focusable) {
if (SDL_ShouldFocusPopup(window)) {
WIN_SetKeyboardFocus(window, true);
}
}
}
return true;
}
return true;
@@ -2281,38 +2220,38 @@ bool WIN_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, bool foc
void WIN_UpdateDarkModeForHWND(HWND hwnd)
{
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
SDL_SharedObject *ntdll = SDL_LoadObject("ntdll.dll");
HMODULE ntdll = LoadLibrary(TEXT("ntdll.dll"));
if (!ntdll) {
return;
}
// There is no function to get Windows build number, so let's get it here via RtlGetVersion
RtlGetVersion_t RtlGetVersionFunc = (RtlGetVersion_t)SDL_LoadFunction(ntdll, "RtlGetVersion");
RtlGetVersion_t RtlGetVersionFunc = (RtlGetVersion_t)GetProcAddress(ntdll, "RtlGetVersion");
NT_OSVERSIONINFOW os_info;
os_info.dwOSVersionInfoSize = sizeof(NT_OSVERSIONINFOW);
os_info.dwBuildNumber = 0;
if (RtlGetVersionFunc) {
RtlGetVersionFunc(&os_info);
}
SDL_UnloadObject(ntdll);
FreeLibrary(ntdll);
os_info.dwBuildNumber &= ~0xF0000000;
if (os_info.dwBuildNumber < 17763) {
// Too old to support dark mode
return;
}
SDL_SharedObject *uxtheme = SDL_LoadObject("uxtheme.dll");
HMODULE uxtheme = LoadLibrary(TEXT("uxtheme.dll"));
if (!uxtheme) {
return;
}
RefreshImmersiveColorPolicyState_t RefreshImmersiveColorPolicyStateFunc = (RefreshImmersiveColorPolicyState_t)SDL_LoadFunction(uxtheme, MAKEINTRESOURCEA(104));
ShouldAppsUseDarkMode_t ShouldAppsUseDarkModeFunc = (ShouldAppsUseDarkMode_t)SDL_LoadFunction(uxtheme, MAKEINTRESOURCEA(132));
AllowDarkModeForWindow_t AllowDarkModeForWindowFunc = (AllowDarkModeForWindow_t)SDL_LoadFunction(uxtheme, MAKEINTRESOURCEA(133));
RefreshImmersiveColorPolicyState_t RefreshImmersiveColorPolicyStateFunc = (RefreshImmersiveColorPolicyState_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(104));
ShouldAppsUseDarkMode_t ShouldAppsUseDarkModeFunc = (ShouldAppsUseDarkMode_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(132));
AllowDarkModeForWindow_t AllowDarkModeForWindowFunc = (AllowDarkModeForWindow_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(133));
if (os_info.dwBuildNumber < 18362) {
AllowDarkModeForApp_t AllowDarkModeForAppFunc = (AllowDarkModeForApp_t)SDL_LoadFunction(uxtheme, MAKEINTRESOURCEA(135));
AllowDarkModeForApp_t AllowDarkModeForAppFunc = (AllowDarkModeForApp_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(135));
if (AllowDarkModeForAppFunc) {
AllowDarkModeForAppFunc(true);
}
} else {
SetPreferredAppMode_t SetPreferredAppModeFunc = (SetPreferredAppMode_t)SDL_LoadFunction(uxtheme, MAKEINTRESOURCEA(135));
SetPreferredAppMode_t SetPreferredAppModeFunc = (SetPreferredAppMode_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(135));
if (SetPreferredAppModeFunc) {
SetPreferredAppModeFunc(UXTHEME_APPMODE_ALLOW_DARK);
}
@@ -2330,7 +2269,7 @@ void WIN_UpdateDarkModeForHWND(HWND hwnd)
} else {
value = (SDL_GetSystemTheme() == SDL_SYSTEM_THEME_DARK) ? TRUE : FALSE;
}
SDL_UnloadObject(uxtheme);
FreeLibrary(uxtheme);
if (os_info.dwBuildNumber < 18362) {
SetProp(hwnd, TEXT("UseImmersiveDarkModeColors"), SDL_reinterpret_cast(HANDLE, SDL_static_cast(INT_PTR, value)));
} else {
-1
View File
@@ -93,7 +93,6 @@ struct SDL_WindowData
bool destroy_parent_with_window;
SDL_DisplayID last_displayID;
WCHAR *ICMFileName;
SDL_Window *keyboard_focus;
SDL_WindowEraseBackgroundMode hint_erase_background_mode;
struct SDL_VideoData *videodata;
#ifdef SDL_VIDEO_OPENGL_EGL
+11 -15
View File
@@ -194,7 +194,7 @@ static bool X11_KeyRepeat(Display *display, XEvent *event)
return d.found;
}
static bool X11_IsWheelEvent(Display *display, int button, int *xticks, int *yticks)
bool X11_IsWheelEvent(int button, int *xticks, int *yticks)
{
/* according to the xlib docs, no specific mouse wheel events exist.
However, the defacto standard is that the vertical wheel is X buttons
@@ -1016,8 +1016,6 @@ void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_
void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_MouseID mouseID, int button, float x, float y, unsigned long time)
{
SDL_Window *window = windowdata->window;
const SDL_VideoData *videodata = _this->internal;
Display *display = videodata->display;
int xticks = 0, yticks = 0;
Uint64 timestamp = X11_GetEventTimestamp(time);
@@ -1031,7 +1029,7 @@ void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, S
SDL_SendMouseMotion(timestamp, window, mouseID, false, x, y);
}
if (X11_IsWheelEvent(display, button, &xticks, &yticks)) {
if (X11_IsWheelEvent(button, &xticks, &yticks)) {
SDL_SendMouseWheel(timestamp, window, mouseID, (float)-xticks, (float)yticks, SDL_MOUSEWHEEL_NORMAL);
} else {
bool ignore_click = false;
@@ -1063,8 +1061,6 @@ void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, S
void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_MouseID mouseID, int button, unsigned long time)
{
SDL_Window *window = windowdata->window;
const SDL_VideoData *videodata = _this->internal;
Display *display = videodata->display;
// The X server sends a Release event for each Press for wheels. Ignore them.
int xticks = 0, yticks = 0;
Uint64 timestamp = X11_GetEventTimestamp(time);
@@ -1072,7 +1068,7 @@ void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *windowdata,
#ifdef DEBUG_XEVENTS
SDL_Log("window 0x%lx: ButtonRelease (X11 button = %d)", windowdata->xwindow, button);
#endif
if (!X11_IsWheelEvent(display, button, &xticks, &yticks)) {
if (!X11_IsWheelEvent(button, &xticks, &yticks)) {
if (button > 7) {
// see explanation at case ButtonPress
button -= (8 - SDL_BUTTON_X1);
@@ -1513,9 +1509,10 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
&ChildReturn);
}
/* Xfce sends ConfigureNotify before PropertyNotify when toggling fullscreen and maximized, which
* is backwards from every other window manager, as well as what is expected by SDL and its clients.
* Defer emitting the size/move events until the corresponding PropertyNotify arrives.
/* Some window managers send ConfigureNotify before PropertyNotify when changing state (Xfce and
* fvwm are known to do this), which is backwards from other window managers, as well as what is
* expected by SDL and its clients. Defer emitting the size/move events until the corresponding
* PropertyNotify arrives for consistency.
*/
const Uint32 changed = X11_GetNetWMState(_this, data->window, xevent->xproperty.window) ^ data->window->flags;
if (changed & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_MAXIMIZED)) {
@@ -1950,13 +1947,12 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
right approach, but it seems to work. */
X11_UpdateKeymap(_this, true);
} else if (xevent->xproperty.atom == videodata->atoms._NET_FRAME_EXTENTS) {
/* Events are disabled when leaving fullscreen until the borders appear to avoid
* incorrect size/position events.
*/
X11_GetBorderValues(data);
if (data->size_move_event_flags) {
/* Events are disabled when leaving fullscreen until the borders appear to avoid
* incorrect size/position events on compositing window managers.
*/
data->size_move_event_flags &= ~X11_SIZE_MOVE_EVENTS_WAIT_FOR_BORDERS;
X11_GetBorderValues(data);
}
if (!(data->window->flags & SDL_WINDOW_FULLSCREEN) && data->toggle_borders) {
data->toggle_borders = false;
+1
View File
@@ -36,5 +36,6 @@ extern void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *wind
extern SDL_WindowData *X11_FindWindow(SDL_VideoDevice *_this, Window window);
extern bool X11_ProcessHitTest(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y, bool force_new_result);
extern bool X11_TriggerHitTestAction(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y);
extern bool X11_IsWheelEvent(int button, int *xticks, int *yticks);
#endif // SDL_x11events_h_
+3
View File
@@ -30,7 +30,10 @@
#include <X11/keysym.h>
#include <locale.h>
#ifndef SDL_FORK_MESSAGEBOX
#define SDL_FORK_MESSAGEBOX 1
#endif
#define SDL_SET_LOCALE 1
#if SDL_FORK_MESSAGEBOX
+80 -47
View File
@@ -86,6 +86,23 @@ static Bool X11_XIfEventTimeout(Display *display, XEvent *event_return, Bool (*p
}
*/
static bool X11_CheckCurrentDesktop(const char *name)
{
SDL_Environment *env = SDL_GetEnvironment();
const char *desktopVar = SDL_GetEnvironmentVariable(env, "DESKTOP_SESSION");
if (desktopVar && SDL_strcasecmp(desktopVar, name) == 0) {
return true;
}
desktopVar = SDL_GetEnvironmentVariable(env, "XDG_CURRENT_DESKTOP");
if (desktopVar && SDL_strcasestr(desktopVar, name)) {
return true;
}
return false;
}
static bool X11_IsWindowMapped(SDL_VideoDevice *_this, SDL_Window *window)
{
SDL_WindowData *data = window->internal;
@@ -215,28 +232,30 @@ static void X11_ConstrainPopup(SDL_Window *window, bool output_to_pending)
int abs_y = window->last_position_pending ? window->pending.y : window->floating.y;
int offset_x = 0, offset_y = 0;
// Calculate the total offset from the parents
for (w = window->parent; SDL_WINDOW_IS_POPUP(w); w = w->parent) {
if (window->constrain_popup) {
// Calculate the total offset from the parents
for (w = window->parent; SDL_WINDOW_IS_POPUP(w); w = w->parent) {
offset_x += w->x;
offset_y += w->y;
}
offset_x += w->x;
offset_y += w->y;
}
abs_x += offset_x;
abs_y += offset_y;
offset_x += w->x;
offset_y += w->y;
abs_x += offset_x;
abs_y += offset_y;
displayID = SDL_GetDisplayForWindow(w);
displayID = SDL_GetDisplayForWindow(w);
SDL_GetDisplayBounds(displayID, &rect);
if (abs_x + window->w > rect.x + rect.w) {
abs_x -= (abs_x + window->w) - (rect.x + rect.w);
SDL_GetDisplayBounds(displayID, &rect);
if (abs_x + window->w > rect.x + rect.w) {
abs_x -= (abs_x + window->w) - (rect.x + rect.w);
}
if (abs_y + window->h > rect.y + rect.h) {
abs_y -= (abs_y + window->h) - (rect.y + rect.h);
}
abs_x = SDL_max(abs_x, rect.x);
abs_y = SDL_max(abs_y, rect.y);
}
if (abs_y + window->h > rect.y + rect.h) {
abs_y -= (abs_y + window->h) - (rect.y + rect.h);
}
abs_x = SDL_max(abs_x, rect.x);
abs_y = SDL_max(abs_y, rect.y);
if (output_to_pending) {
window->pending.x = abs_x - offset_x;
@@ -257,7 +276,7 @@ static void X11_SetKeyboardFocus(SDL_Window *window, bool set_active_focus)
toplevel = toplevel->parent;
}
toplevel->internal->keyboard_focus = window;
toplevel->keyboard_focus = window;
if (set_active_focus && !window->is_hiding && !window->is_destroying) {
SDL_SetKeyboardFocus(window);
@@ -1542,9 +1561,9 @@ void X11_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
X11_XFlush(display);
}
// Popup menus grab the keyboard
if (window->flags & SDL_WINDOW_POPUP_MENU) {
X11_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus());
// Grabbing popup menus get keyboard focus.
if ((window->flags & SDL_WINDOW_POPUP_MENU) && !(window->flags & SDL_WINDOW_NOT_FOCUSABLE)) {
X11_SetKeyboardFocus(window, true);
}
// Get some valid border values, if we haven't received them yet
@@ -1566,6 +1585,15 @@ void X11_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
X11_XMoveWindow(display, data->xwindow, x, y);
}
/* XMonad ignores size hints and shrinks the client area to overlay borders on fixed-size windows,
* even if no borders were requested, resulting in the window client area being smaller than
* requested. Calling XResizeWindow after mapping seems to fix it, even though resizing fixed-size
* windows in this manner doesn't work on any other window manager.
*/
if (!(window->flags & SDL_WINDOW_RESIZABLE) && X11_CheckCurrentDesktop("xmonad")) {
X11_XResizeWindow(display, data->xwindow, window->w, window->h);
}
/* Some window managers can send garbage coordinates while mapping the window, so don't emit size and position
* events during the initial configure events.
*/
@@ -1607,20 +1635,9 @@ void X11_HideWindow(SDL_VideoDevice *_this, SDL_Window *window)
}
// Transfer keyboard focus back to the parent
if (window->flags & SDL_WINDOW_POPUP_MENU) {
SDL_Window *new_focus = window->parent;
bool set_focus = window == SDL_GetKeyboardFocus();
// Find the highest level window, up to the toplevel parent, that isn't being hidden or destroyed.
while (SDL_WINDOW_IS_POPUP(new_focus) && (new_focus->is_hiding || new_focus->is_destroying)) {
new_focus = new_focus->parent;
// If some window in the chain currently had focus, set it to the new lowest-level window.
if (!set_focus) {
set_focus = new_focus == SDL_GetKeyboardFocus();
}
}
if ((window->flags & SDL_WINDOW_POPUP_MENU) && !(window->flags & SDL_WINDOW_NOT_FOCUSABLE)) {
SDL_Window *new_focus;
const bool set_focus = SDL_ShouldRelinquishPopupFocus(window, &new_focus);
X11_SetKeyboardFocus(new_focus, set_focus);
}
@@ -2338,21 +2355,37 @@ bool X11_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window)
bool X11_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, bool focusable)
{
SDL_WindowData *data = window->internal;
Display *display = data->videodata->display;
XWMHints *wmhints;
if (!SDL_WINDOW_IS_POPUP(window)) {
SDL_WindowData *data = window->internal;
Display *display = data->videodata->display;
XWMHints *wmhints;
wmhints = X11_XGetWMHints(display, data->xwindow);
if (!wmhints) {
return SDL_SetError("Couldn't get WM hints");
wmhints = X11_XGetWMHints(display, data->xwindow);
if (!wmhints) {
return SDL_SetError("Couldn't get WM hints");
}
wmhints->input = focusable ? True : False;
wmhints->flags |= InputHint;
X11_XSetWMHints(display, data->xwindow, wmhints);
X11_XFree(wmhints);
} else if (window->flags & SDL_WINDOW_POPUP_MENU) {
if (!(window->flags & SDL_WINDOW_HIDDEN)) {
if (!focusable && (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
SDL_Window *new_focus;
const bool set_focus = SDL_ShouldRelinquishPopupFocus(window, &new_focus);
X11_SetKeyboardFocus(new_focus, set_focus);
} else if (focusable) {
if (SDL_ShouldFocusPopup(window)) {
X11_SetKeyboardFocus(window, true);
}
}
}
return true;
}
wmhints->input = focusable ? True : False;
wmhints->flags |= InputHint;
X11_XSetWMHints(display, data->xwindow, wmhints);
X11_XFree(wmhints);
return true;
}
-1
View File
@@ -75,7 +75,6 @@ struct SDL_WindowData
Window xdnd_source;
bool flashing_window;
Uint64 flash_cancel_time;
SDL_Window *keyboard_focus;
#ifdef SDL_VIDEO_OPENGL_EGL
EGLSurface egl_surface;
#endif
+12 -4
View File
@@ -406,11 +406,15 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
case XI_ButtonRelease:
{
const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data;
X11_PenHandle *pen = X11_FindPenByDeviceID(xev->deviceid);
X11_PenHandle *pen = X11_FindPenByDeviceID(xev->sourceid);
const int button = xev->detail;
const bool down = (cookie->evtype == XI_ButtonPress);
if (pen) {
if (xev->deviceid != xev->sourceid) {
// Discard events from "Master" devices to avoid duplicates.
break;
}
// Only report button event; if there was also pen movement / pressure changes, we expect an XI_Motion event first anyway.
SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event);
if (button == 1) { // button 1 is the pen tip
@@ -421,9 +425,12 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
} else {
// Otherwise assume a regular mouse
SDL_WindowData *windowdata = xinput2_get_sdlwindowdata(videodata, xev->event);
int x_ticks = 0, y_ticks = 0;
if (xev->deviceid != xev->sourceid) {
// Discard events from "Master" devices to avoid duplicates.
/* Discard wheel events from "Master" devices to avoid duplicates,
* as coarse wheel events are stateless and can't be deduplicated.
*/
if (xev->deviceid != xev->sourceid && X11_IsWheelEvent(button, &x_ticks, &y_ticks)) {
break;
}
@@ -449,7 +456,8 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
videodata->global_mouse_changed = true;
X11_PenHandle *pen = X11_FindPenByDeviceID(xev->deviceid);
X11_PenHandle *pen = X11_FindPenByDeviceID(xev->sourceid);
if (pen) {
if (xev->deviceid != xev->sourceid) {
// Discard events from "Master" devices to avoid duplicates.
+1 -1
View File
@@ -411,7 +411,7 @@ add_sdl_test_executable(testdialog SOURCES testdialog.c)
add_sdl_test_executable(testtime SOURCES testtime.c)
add_sdl_test_executable(testmanymouse SOURCES testmanymouse.c)
add_sdl_test_executable(testmodal SOURCES testmodal.c)
add_sdl_test_executable(testtray SOURCES testtray.c)
add_sdl_test_executable(testtray NEEDS_RESOURCES TESTUTILS SOURCES testtray.c)
add_sdl_test_executable(testprocess
+44
View File
@@ -989,6 +989,45 @@ static int SDLCALL surface_testBlitInvalid(void *arg)
return TEST_COMPLETED;
}
static int SDLCALL surface_testBlitsWithBadCoordinates(void *arg)
{
const SDL_Rect rect[8] = {
{ SDL_MAX_SINT32, 0, 2, 2 },
{ 0, SDL_MAX_SINT32, 2, 2 },
{ 0, 0, SDL_MAX_SINT32, 2 },
{ 0, 0, 2, SDL_MAX_SINT32 },
{ SDL_MIN_SINT32, 0, 2, 2 },
{ 0, SDL_MIN_SINT32, 2, 2 },
{ 0, 0, SDL_MIN_SINT32, 2 },
{ 0, 0, 2, SDL_MIN_SINT32 }
};
SDL_Surface *s;
bool result;
int i;
s = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_RGBA8888);
SDLTest_AssertCheck(s != NULL, "Check surface creation");
for (i = 0; i < 8; i++) {
result = SDL_BlitSurface(s, NULL, s, &rect[i]);
SDLTest_AssertCheck(result == true, "SDL_BlitSurface(valid, NULL, valid, &rect), result = %s", result ? "true" : "false");
result = SDL_BlitSurface(s, &rect[i], s, NULL);
SDLTest_AssertCheck(result == true, "SDL_BlitSurface(valid, &rect, valid, NULL), result = %s", result ? "true" : "false");
result = SDL_BlitSurfaceScaled(s, NULL, s, &rect[i], SDL_SCALEMODE_NEAREST);
SDLTest_AssertCheck(result == true, "SDL_BlitSurfaceScaled(valid, NULL, valid, &rect, SDL_SCALEMODE_NEAREST), result = %s", result ? "true" : "false");
result = SDL_BlitSurfaceScaled(s, &rect[i], s, NULL, SDL_SCALEMODE_NEAREST);
SDLTest_AssertCheck(result == true, "SDL_BlitSurfaceScaled(valid, &rect, valid, NULL, SDL_SCALEMODE_NEAREST), result = %s", result ? "true" : "false");
}
SDL_DestroySurface(s);
return TEST_COMPLETED;
}
static int SDLCALL surface_testOverflow(void *arg)
{
char buf[1024];
@@ -1664,6 +1703,10 @@ static const SDLTest_TestCaseReference surfaceTestBlitInvalid = {
surface_testBlitInvalid, "surface_testBlitInvalid", "Tests blitting routines with invalid surfaces.", TEST_ENABLED
};
static const SDLTest_TestCaseReference surfaceTestBlitsWithBadCoordinates = {
surface_testBlitsWithBadCoordinates, "surface_testBlitsWithBadCoordinates", "Test blitting routines with bad coordinates.", TEST_ENABLED
};
static const SDLTest_TestCaseReference surfaceTestOverflow = {
surface_testOverflow, "surface_testOverflow", "Test overflow detection.", TEST_ENABLED
};
@@ -1713,6 +1756,7 @@ static const SDLTest_TestCaseReference *surfaceTests[] = {
&surfaceTestBlitBlendMod,
&surfaceTestBlitBlendMul,
&surfaceTestBlitInvalid,
&surfaceTestBlitsWithBadCoordinates,
&surfaceTestOverflow,
&surfaceTestFlip,
&surfaceTestPalette,
+17
View File
@@ -679,6 +679,16 @@ void SetupVulkanRenderProperties(VulkanVideoContext *context, SDL_PropertiesID p
SDL_SetNumberProperty(props, SDL_PROP_RENDERER_CREATE_VULKAN_GRAPHICS_QUEUE_FAMILY_INDEX_NUMBER, context->graphicsQueueFamilyIndex);
}
#if LIBAVUTIL_VERSION_MAJOR >= 59
static void AddQueueFamily(AVVulkanDeviceContext *ctx, int idx, int num, VkQueueFlagBits flags)
{
AVVulkanDeviceQueueFamily *entry = &ctx->qf[ctx->nb_qf++];
entry->idx = idx;
entry->num = num;
entry->flags = flags;
}
#endif /* LIBAVUTIL_VERSION_MAJOR */
void SetupVulkanDeviceContextData(VulkanVideoContext *context, AVVulkanDeviceContext *ctx)
{
ctx->get_proc_addr = context->vkGetInstanceProcAddr;
@@ -690,6 +700,12 @@ void SetupVulkanDeviceContextData(VulkanVideoContext *context, AVVulkanDeviceCon
ctx->nb_enabled_inst_extensions = context->instanceExtensionsCount;
ctx->enabled_dev_extensions = context->deviceExtensions;
ctx->nb_enabled_dev_extensions = context->deviceExtensionsCount;
#if LIBAVUTIL_VERSION_MAJOR >= 59
AddQueueFamily(ctx, context->graphicsQueueFamilyIndex, context->graphicsQueueCount, VK_QUEUE_GRAPHICS_BIT);
AddQueueFamily(ctx, context->transferQueueFamilyIndex, context->transferQueueCount, VK_QUEUE_TRANSFER_BIT);
AddQueueFamily(ctx, context->computeQueueFamilyIndex, context->computeQueueCount, VK_QUEUE_COMPUTE_BIT);
AddQueueFamily(ctx, context->decodeQueueFamilyIndex, context->decodeQueueCount, VK_QUEUE_VIDEO_DECODE_BIT_KHR);
#else
ctx->queue_family_index = context->graphicsQueueFamilyIndex;
ctx->nb_graphics_queues = context->graphicsQueueCount;
ctx->queue_family_tx_index = context->transferQueueFamilyIndex;
@@ -700,6 +716,7 @@ void SetupVulkanDeviceContextData(VulkanVideoContext *context, AVVulkanDeviceCon
ctx->nb_encode_queues = 0;
ctx->queue_family_decode_index = context->decodeQueueFamilyIndex;
ctx->nb_decode_queues = context->decodeQueueCount;
#endif /* LIBAVUTIL_VERSION_MAJOR */
}
static int CreateCommandBuffers(VulkanVideoContext *context, SDL_Renderer *renderer)
+1 -1
View File
@@ -97,7 +97,7 @@ int main(int argc, char *argv[])
}
if (e.key.key == SDLK_M) {
if (SDL_SetWindowParent(w2, w2)) {
if (SDL_SetWindowParent(w2, w1)) {
if (SDL_SetWindowModal(w2, true)) {
SDL_SetWindowTitle(w2, "Modal Window");
}
+43 -5
View File
@@ -49,6 +49,9 @@ struct PopupWindow
static struct PopupWindow *menus;
static struct PopupWindow tooltip;
static bool no_constraints;
static bool no_grab;
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
static void quit(int rc)
{
@@ -95,14 +98,27 @@ static bool create_popup(struct PopupWindow *new_popup, bool is_menu)
const int w = is_menu ? MENU_WIDTH : TOOLTIP_WIDTH;
const int h = is_menu ? MENU_HEIGHT : TOOLTIP_HEIGHT;
const int v_off = is_menu ? 0 : 32;
const SDL_WindowFlags flags = is_menu ? SDL_WINDOW_POPUP_MENU : SDL_WINDOW_TOOLTIP;
float x, y;
focus = SDL_GetMouseFocus();
SDL_GetMouseState(&x, &y);
new_win = SDL_CreatePopupWindow(focus,
(int)x, (int)y + v_off, w, h, flags);
SDL_PropertiesID props = SDL_CreateProperties();
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_CREATE_PARENT_POINTER, focus);
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_CONSTRAIN_POPUP_BOOLEAN, !no_constraints);
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN, !no_grab);
if (is_menu) {
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_MENU_BOOLEAN, true);
} else {
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_TOOLTIP_BOOLEAN, true);
}
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, w);
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, h);
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, (int)x);
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, (int)y + v_off);
new_win = SDL_CreateWindowWithProperties(props);
SDL_DestroyProperties(props);
if (new_win) {
new_renderer = SDL_CreateRenderer(new_win, state->renderdriver);
@@ -249,8 +265,30 @@ int main(int argc, char *argv[])
}
/* Parse commandline */
if (!SDLTest_CommonDefaultArgs(state, argc, argv)) {
return 1;
for (i = 1; i < argc;) {
int consumed;
consumed = SDLTest_CommonArg(state, i);
if (consumed == 0) {
consumed = -1;
if (SDL_strcasecmp(argv[i], "--no-constraints") == 0) {
no_constraints = true;
consumed = 1;
} else if (SDL_strcasecmp(argv[i], "--no-grab") == 0) {
no_grab = true;
consumed = 1;
}
}
if (consumed < 0) {
static const char *options[] = {
"[--no-constraints]",
"[--no-grab]",
NULL
};
SDLTest_CommonLogUsage(state, argv[0], options);
return 1;
}
i += consumed;
}
if (!SDLTest_CommonInit(state)) {
+7 -3
View File
@@ -1,3 +1,4 @@
#include "testutils.h"
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <SDL3/SDL_test.h>
@@ -520,14 +521,17 @@ int main(int argc, char **argv)
goto quit;
}
/* TODO: Resource paths? */
SDL_Surface *icon = SDL_LoadBMP("../test/sdl-test_round.bmp");
char *icon1filename = GetResourceFilename(NULL, "sdl-test_round.bmp");
SDL_Surface *icon = SDL_LoadBMP(icon1filename);
SDL_free(icon1filename);
if (!icon) {
SDL_Log("Couldn't load icon 1, proceeding without: %s", SDL_GetError());
}
SDL_Surface *icon2 = SDL_LoadBMP("../test/speaker.bmp");
char *icon2filename = GetResourceFilename(NULL, "speaker.bmp");
SDL_Surface *icon2 = SDL_LoadBMP(icon2filename);
SDL_free(icon2filename);
if (!icon2) {
SDL_Log("Couldn't load icon 2, proceeding without: %s", SDL_GetError());