Compare commits

...

9 Commits

Author SHA1 Message Date
Jordan Woyak
b1bf7dcfc5
Merge 6da3f5f26a into 24b0bf01d5 2025-06-08 17:37:26 +12:00
JMC47
24b0bf01d5
Merge pull request #12836 from JosJuice/opensles-buffer-size
Android: Ask system for optimal audio buffer size and sample rate
2025-06-07 23:07:37 -04:00
Tilka
19fbbf0dba
Merge pull request #13727 from JoshuaVandaele/fmt-11.2.0-localtime-deprec
fmt: Replace deprecated `fmt::localtime` usage with `Common::LocalTime`
2025-06-08 04:04:37 +01:00
Jordan Woyak
1786e34bd3
Merge pull request #13665 from jordan-woyak/dark-mode-filter
DolphinQt: Replace widespread SetQWidgetWindowDecorations calls with an event filter.
2025-06-07 18:19:13 -05:00
Jordan Woyak
6da3f5f26a InputCommon: Update to use SDL3 and bump the SDL submodule in Externals to release-3.2.16. 2025-06-07 16:27:54 -05:00
Jordan Woyak
5906512847 DolphinQt: Replace widespread SetQWidgetWindowDecorations calls with an event filter. 2025-06-07 16:15:34 -05:00
Joshua Vandaële
4b65cc9a4c
fmt: Replace deprecated fmt::localtime usage with Common::LocalTime 2025-06-04 13:32:12 +02:00
JosJuice
f99d3dbd5c Android: Ask system for optimal audio buffer size and sample rate
This can reduce audio latency according to
https://developer.android.com/ndk/guides/audio/opensl/opensl-prog-notes#perform.

Previously we were using the hardcoded values of 48000 Hz and 256 frames
per buffer. The sample rate we use with this change is 48000 Hz on all
devices I'm aware of, but the buffer size does vary across devices.

Terminology note: The old code used the term "sample" to refer to what
Android refers to as a "frame". "Frame" is a clearer term to use for
this, so I've changed OpenSLESStream's terminology. One frame consists
of one sample per channel.
2025-05-25 11:59:33 +02:00
JosJuice
34e8fb068f Android: Get rid of OpenSLESStream's global state
Not sure if we're ever going to want to have more than one of these at
the same time, but these global variables are a code smell nonetheless.

I'm also deleting the existing member variables because they were
unused.
2025-05-25 11:55:22 +02:00
76 changed files with 695 additions and 655 deletions

View File

@ -137,6 +137,8 @@ else()
endif()
if(APPLE)
enable_language(OBJC)
enable_language(OBJCXX)
option(MACOS_USE_DEFAULT_SEARCH_PATH "Don't prioritize system library paths" OFF)
option(SKIP_POSTPROCESS_BUNDLE "Skip postprocessing bundle for redistributability" OFF)
# Enable adhoc code signing by default (otherwise makefile builds on ARM will not work)
@ -602,7 +604,7 @@ if(UNIX)
endif()
if(ENABLE_SDL)
dolphin_find_optional_system_library(SDL2 Externals/SDL 2.30.9)
dolphin_find_optional_system_library(SDL3 Externals/SDL 3.2.0)
endif()
if(ENABLE_ANALYTICS)

View File

@ -1,34 +1,16 @@
option(SDL2_DISABLE_SDL2MAIN "" ON)
option(SDL2_DISABLE_INSTALL "" ON)
option(SDL2_DISABLE_UNINSTALL "" ON)
option(SDL_SHARED "Build a shared version of the library" OFF)
option(SDL_SHARED_ENABLED_BY_DEFAULT "" OFF)
option(SDL_STATIC "Build a static version of the library" ON)
option(SDL_STATIC_ENABLED_BY_DEFAULT "" ON)
option(SDL_TEST "Build the SDL2_test library" OFF)
option(SDL_TEST_ENABLED_BY_DEFAULT "" OFF)
# SDL fails to clean up old headers after version upgrades, so do that manually
set(EXPECTED_SDL_REVISION "SDL-release-2.30.9-0")
if (EXISTS "${CMAKE_CURRENT_BINARY_DIR}/SDL/include/SDL2/SDL_revision.h")
file(READ "${CMAKE_CURRENT_BINARY_DIR}/SDL/include/SDL2/SDL_revision.h" ACTUAL_SDL_REVISION)
if (NOT "${ACTUAL_SDL_REVISION}" MATCHES "${EXPECTED_SDL_REVISION}")
message(STATUS "Found unexpected SDL2/SDL_revision.h, removing generated includes.")
file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/SDL/include/")
endif()
endif()
if (EXISTS "${CMAKE_CURRENT_BINARY_DIR}/SDL/include/SDL_revision.h")
file(READ "${CMAKE_CURRENT_BINARY_DIR}/SDL/include/SDL_revision.h" ACTUAL_SDL_REVISION)
if (NOT "${ACTUAL_SDL_REVISION}" MATCHES "${EXPECTED_SDL_REVISION}")
message(STATUS "Found unexpected SDL_revision.h, removing generated includes.")
file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/SDL/include/")
endif()
endif()
set(SDL_SHARED OFF)
set(SDL_STATIC ON)
set(SDL_TEST_LIBRARY OFF)
set(SDL_TESTS OFF)
set(SDL_DISABLE_INSTALL ON)
set(SDL_DISABLE_INSTALL_DOCS ON)
set(SDL_INSTALL_TESTS OFF)
add_subdirectory(SDL)
if (TARGET SDL2)
dolphin_disable_warnings(SDL2)
if (TARGET SDL3)
dolphin_disable_warnings(SDL3)
endif()
if (TARGET SDL2-static)
dolphin_disable_warnings(SDL2-static)
if (TARGET SDL3-static)
dolphin_disable_warnings(SDL3-static)
endif()

2
Externals/SDL/SDL vendored

@ -1 +1 @@
Subproject commit c98c4fbff6d8f3016a3ce6685bf8f43433c3efcc
Subproject commit c9a6709bd21750f1ad9597be21abace78c6378c9

View File

@ -17,147 +17,165 @@
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>SDL\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>SDL\src;SDL\include;SDL\include\build_config;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>HAVE_LIBC=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="SDL\include\begin_code.h" />
<ClInclude Include="SDL\include\close_code.h" />
<ClInclude Include="SDL\include\SDL_assert.h" />
<ClInclude Include="SDL\include\SDL_atomic.h" />
<ClInclude Include="SDL\include\SDL_audio.h" />
<ClInclude Include="SDL\include\SDL_bits.h" />
<ClInclude Include="SDL\include\SDL_blendmode.h" />
<ClInclude Include="SDL\include\SDL_clipboard.h" />
<ClInclude Include="SDL\include\SDL_config_windows.h" />
<ClInclude Include="SDL\include\SDL_config.h" />
<ClInclude Include="SDL\include\SDL_copying.h" />
<ClInclude Include="SDL\include\SDL_cpuinfo.h" />
<ClInclude Include="SDL\include\SDL_egl.h" />
<ClInclude Include="SDL\include\SDL_endian.h" />
<ClInclude Include="SDL\include\SDL_error.h" />
<ClInclude Include="SDL\include\SDL_events.h" />
<ClInclude Include="SDL\include\SDL_filesystem.h" />
<ClInclude Include="SDL\include\SDL_gamecontroller.h" />
<ClInclude Include="SDL\include\SDL_gesture.h" />
<ClInclude Include="SDL\include\SDL_guid.h" />
<ClInclude Include="SDL\include\SDL_haptic.h" />
<ClInclude Include="SDL\include\SDL_hidapi.h" />
<ClInclude Include="SDL\include\SDL_hints.h" />
<ClInclude Include="SDL\include\SDL_joystick.h" />
<ClInclude Include="SDL\include\SDL_keyboard.h" />
<ClInclude Include="SDL\include\SDL_keycode.h" />
<ClInclude Include="SDL\include\SDL_loadso.h" />
<ClInclude Include="SDL\include\SDL_locale.h" />
<ClInclude Include="SDL\include\SDL_log.h" />
<ClInclude Include="SDL\include\SDL_main.h" />
<ClInclude Include="SDL\include\SDL_messagebox.h" />
<ClInclude Include="SDL\include\SDL_metal.h" />
<ClInclude Include="SDL\include\SDL_misc.h" />
<ClInclude Include="SDL\include\SDL_mouse.h" />
<ClInclude Include="SDL\include\SDL_mutex.h" />
<ClInclude Include="SDL\include\SDL_name.h" />
<ClInclude Include="SDL\include\SDL_opengl_glext.h" />
<ClInclude Include="SDL\include\SDL_opengl.h" />
<ClInclude Include="SDL\include\SDL_opengles.h" />
<ClInclude Include="SDL\include\SDL_opengles2_gl2.h" />
<ClInclude Include="SDL\include\SDL_opengles2_gl2ext.h" />
<ClInclude Include="SDL\include\SDL_opengles2_gl2platform.h" />
<ClInclude Include="SDL\include\SDL_opengles2_khrplatform.h" />
<ClInclude Include="SDL\include\SDL_opengles2.h" />
<ClInclude Include="SDL\include\SDL_pixels.h" />
<ClInclude Include="SDL\include\SDL_platform.h" />
<ClInclude Include="SDL\include\SDL_power.h" />
<ClInclude Include="SDL\include\SDL_quit.h" />
<ClInclude Include="SDL\include\SDL_rect.h" />
<ClInclude Include="SDL\include\SDL_render.h" />
<ClInclude Include="SDL\include\SDL_revision.h" />
<ClInclude Include="SDL\include\SDL_rwops.h" />
<ClInclude Include="SDL\include\SDL_scancode.h" />
<ClInclude Include="SDL\include\SDL_sensor.h" />
<ClInclude Include="SDL\include\SDL_shape.h" />
<ClInclude Include="SDL\include\SDL_stdinc.h" />
<ClInclude Include="SDL\include\SDL_surface.h" />
<ClInclude Include="SDL\include\SDL_system.h" />
<ClInclude Include="SDL\include\SDL_syswm.h" />
<ClInclude Include="SDL\include\SDL_thread.h" />
<ClInclude Include="SDL\include\SDL_timer.h" />
<ClInclude Include="SDL\include\SDL_touch.h" />
<ClInclude Include="SDL\include\SDL_types.h" />
<ClInclude Include="SDL\include\SDL_version.h" />
<ClInclude Include="SDL\include\SDL_video.h" />
<ClInclude Include="SDL\include\SDL_vulkan.h" />
<ClInclude Include="SDL\include\SDL.h" />
<ClInclude Include="SDL\include\SDL3\SDL_begin_code.h" />
<ClInclude Include="SDL\include\SDL3\SDL_camera.h" />
<ClInclude Include="SDL\include\SDL3\SDL_close_code.h" />
<ClInclude Include="SDL\include\SDL3\SDL.h" />
<ClInclude Include="SDL\include\SDL3\SDL_assert.h" />
<ClInclude Include="SDL\include\SDL3\SDL_atomic.h" />
<ClInclude Include="SDL\include\SDL3\SDL_audio.h" />
<ClInclude Include="SDL\include\SDL3\SDL_bits.h" />
<ClInclude Include="SDL\include\SDL3\SDL_blendmode.h" />
<ClInclude Include="SDL\include\SDL3\SDL_clipboard.h" />
<ClInclude Include="SDL\include\SDL3\SDL_copying.h" />
<ClInclude Include="SDL\include\SDL3\SDL_cpuinfo.h" />
<ClInclude Include="SDL\include\SDL3\SDL_egl.h" />
<ClInclude Include="SDL\include\SDL3\SDL_endian.h" />
<ClInclude Include="SDL\include\SDL3\SDL_error.h" />
<ClInclude Include="SDL\include\SDL3\SDL_events.h" />
<ClInclude Include="SDL\include\SDL3\SDL_filesystem.h" />
<ClInclude Include="SDL\include\SDL3\SDL_gamepad.h" />
<ClInclude Include="SDL\include\SDL3\SDL_gpu.h" />
<ClInclude Include="SDL\include\SDL3\SDL_guid.h" />
<ClInclude Include="SDL\include\SDL3\SDL_haptic.h" />
<ClInclude Include="SDL\include\SDL3\SDL_hints.h" />
<ClInclude Include="SDL\include\SDL3\SDL_hidapi.h" />
<ClInclude Include="SDL\include\SDL3\SDL_asyncio.h" />
<ClInclude Include="SDL\include\SDL3\SDL_joystick.h" />
<ClInclude Include="SDL\include\SDL3\SDL_keyboard.h" />
<ClInclude Include="SDL\include\SDL3\SDL_keycode.h" />
<ClInclude Include="SDL\include\SDL3\SDL_loadso.h" />
<ClInclude Include="SDL\include\SDL3\SDL_locale.h" />
<ClInclude Include="SDL\include\SDL3\SDL_log.h" />
<ClInclude Include="SDL\include\SDL3\SDL_main.h" />
<ClInclude Include="SDL\include\SDL3\SDL_messagebox.h" />
<ClInclude Include="SDL\include\SDL3\SDL_metal.h" />
<ClInclude Include="SDL\include\SDL3\SDL_misc.h" />
<ClInclude Include="SDL\include\SDL3\SDL_mouse.h" />
<ClInclude Include="SDL\include\SDL3\SDL_mutex.h" />
<ClInclude Include="SDL\include\SDL3\SDL_opengl.h" />
<ClInclude Include="SDL\include\SDL3\SDL_opengl_glext.h" />
<ClInclude Include="SDL\include\SDL3\SDL_opengles.h" />
<ClInclude Include="SDL\include\SDL3\SDL_opengles2.h" />
<ClInclude Include="SDL\include\SDL3\SDL_opengles2_gl2.h" />
<ClInclude Include="SDL\include\SDL3\SDL_opengles2_gl2ext.h" />
<ClInclude Include="SDL\include\SDL3\SDL_opengles2_gl2platform.h" />
<ClInclude Include="SDL\include\SDL3\SDL_opengles2_khrplatform.h" />
<ClInclude Include="SDL\include\SDL3\SDL_pen.h" />
<ClInclude Include="SDL\include\SDL3\SDL_pixels.h" />
<ClInclude Include="SDL\include\SDL3\SDL_platform.h" />
<ClInclude Include="SDL\include\SDL3\SDL_platform_defines.h" />
<ClInclude Include="SDL\include\SDL3\SDL_power.h" />
<ClInclude Include="SDL\include\SDL3\SDL_process.h" />
<ClInclude Include="SDL\include\SDL3\SDL_properties.h" />
<ClInclude Include="SDL\include\SDL3\SDL_rect.h" />
<ClInclude Include="SDL\include\SDL3\SDL_render.h" />
<ClInclude Include="SDL\include\SDL3\SDL_revision.h" />
<ClInclude Include="SDL\include\SDL3\SDL_iostream.h" />
<ClInclude Include="SDL\include\SDL3\SDL_scancode.h" />
<ClInclude Include="SDL\include\SDL3\SDL_sensor.h" />
<ClInclude Include="SDL\include\SDL3\SDL_stdinc.h" />
<ClInclude Include="SDL\include\SDL3\SDL_storage.h" />
<ClInclude Include="SDL\include\SDL3\SDL_surface.h" />
<ClInclude Include="SDL\include\SDL3\SDL_system.h" />
<ClInclude Include="SDL\include\SDL3\SDL_test.h" />
<ClInclude Include="SDL\include\SDL3\SDL_test_assert.h" />
<ClInclude Include="SDL\include\SDL3\SDL_test_common.h" />
<ClInclude Include="SDL\include\SDL3\SDL_test_compare.h" />
<ClInclude Include="SDL\include\SDL3\SDL_test_crc32.h" />
<ClInclude Include="SDL\include\SDL3\SDL_test_font.h" />
<ClInclude Include="SDL\include\SDL3\SDL_test_fuzzer.h" />
<ClInclude Include="SDL\include\SDL3\SDL_test_harness.h" />
<ClInclude Include="SDL\include\SDL3\SDL_test_log.h" />
<ClInclude Include="SDL\include\SDL3\SDL_test_md5.h" />
<ClInclude Include="SDL\include\SDL3\SDL_test_memory.h" />
<ClInclude Include="SDL\include\SDL3\SDL_thread.h" />
<ClInclude Include="SDL\include\SDL3\SDL_time.h" />
<ClInclude Include="SDL\include\SDL3\SDL_timer.h" />
<ClInclude Include="SDL\include\SDL3\SDL_touch.h" />
<ClInclude Include="SDL\include\SDL3\SDL_version.h" />
<ClInclude Include="SDL\include\SDL3\SDL_video.h" />
<ClInclude Include="SDL\include\SDL3\SDL_vulkan.h" />
<ClInclude Include="SDL\src\audio\directsound\SDL_directsound.h" />
<ClInclude Include="SDL\src\audio\disk\SDL_diskaudio.h" />
<ClInclude Include="SDL\src\audio\dummy\SDL_dummyaudio.h" />
<ClInclude Include="SDL\src\audio\SDL_audio_c.h" />
<ClInclude Include="SDL\src\audio\SDL_audio_channel_converters.h" />
<ClInclude Include="SDL\src\audio\SDL_audio_resampler_filter.h" />
<ClInclude Include="SDL\src\audio\SDL_audiodev_c.h" />
<ClInclude Include="SDL\src\audio\SDL_sysaudio.h" />
<ClInclude Include="SDL\src\audio\SDL_audioqueue.h" />
<ClInclude Include="SDL\src\audio\SDL_audioresample.h" />
<ClInclude Include="SDL\src\audio\SDL_wave.h" />
<ClInclude Include="SDL\src\audio\wasapi\SDL_wasapi.h" />
<ClInclude Include="SDL\src\audio\winmm\SDL_winmm.h" />
<ClInclude Include="SDL\src\camera\SDL_camera_c.h" />
<ClInclude Include="SDL\src\camera\SDL_syscamera.h" />
<ClInclude Include="SDL\src\core\windows\SDL_directx.h" />
<ClInclude Include="SDL\src\core\windows\SDL_gameinput.h" />
<ClInclude Include="SDL\src\core\windows\SDL_hid.h" />
<ClInclude Include="SDL\src\core\windows\SDL_immdevice.h" />
<ClInclude Include="SDL\src\core\windows\SDL_windows.h" />
<ClInclude Include="SDL\src\core\windows\SDL_xinput.h" />
<ClInclude Include="SDL\src\cpuinfo\SDL_cpuinfo_c.h" />
<ClInclude Include="SDL\src\dynapi\SDL_dynapi.h" />
<ClInclude Include="SDL\src\dynapi\SDL_dynapi_overrides.h" />
<ClInclude Include="SDL\src\dynapi\SDL_dynapi_procs.h" />
<ClInclude Include="SDL\src\dynapi\SDL_dynapi.h" />
<ClInclude Include="SDL\src\dynapi\SDL_dynapi_unsupported.h" />
<ClInclude Include="SDL\src\events\blank_cursor.h" />
<ClInclude Include="SDL\src\events\default_cursor.h" />
<ClInclude Include="SDL\src\events\scancodes_ascii.h" />
<ClInclude Include="SDL\src\events\scancodes_windows.h" />
<ClInclude Include="SDL\src\events\SDL_categories_c.h" />
<ClInclude Include="SDL\src\events\SDL_clipboardevents_c.h" />
<ClInclude Include="SDL\src\events\SDL_displayevents_c.h" />
<ClInclude Include="SDL\src\events\SDL_dropevents_c.h" />
<ClInclude Include="SDL\src\events\SDL_events_c.h" />
<ClInclude Include="SDL\src\events\SDL_gesture_c.h" />
<ClInclude Include="SDL\src\events\SDL_eventwatch_c.h" />
<ClInclude Include="SDL\src\events\SDL_keyboard_c.h" />
<ClInclude Include="SDL\src\events\SDL_log.h" />
<ClInclude Include="SDL\src\events\SDL_keymap_c.h" />
<ClInclude Include="SDL\src\events\SDL_mouse_c.h" />
<ClInclude Include="SDL\src\events\SDL_touch_c.h" />
<ClInclude Include="SDL\src\events\SDL_windowevents_c.h" />
<ClInclude Include="SDL\src\filesystem\SDL_sysfilesystem.h" />
<ClInclude Include="SDL\src\gpu\SDL_sysgpu.h" />
<ClInclude Include="SDL\src\gpu\vulkan\SDL_gpu_vulkan_vkfuncs.h" />
<ClInclude Include="SDL\src\io\SDL_asyncio_c.h" />
<ClInclude Include="SDL\src\io\SDL_sysasyncio.h" />
<ClInclude Include="SDL\src\haptic\SDL_haptic_c.h" />
<ClInclude Include="SDL\src\haptic\SDL_syshaptic.h" />
<ClInclude Include="SDL\src\haptic\windows\SDL_dinputhaptic_c.h" />
<ClInclude Include="SDL\src\haptic\windows\SDL_windowshaptic_c.h" />
<ClInclude Include="SDL\src\haptic\windows\SDL_xinputhaptic_c.h" />
<ClInclude Include="SDL\src\hidapi\hidapi\hidapi.h" />
<ClInclude Include="SDL\src\hidapi\SDL_hidapi_c.h" />
<ClInclude Include="SDL\src\joystick\controller_type.h" />
<ClInclude Include="SDL\src\joystick\hidapi\steam\controller_constants.h" />
<ClInclude Include="SDL\src\joystick\hidapi\steam\controller_structs.h" />
<ClInclude Include="SDL\src\joystick\hidapi\SDL_hidapi_nintendo.h" />
<ClInclude Include="SDL\src\joystick\hidapi\SDL_hidapi_rumble.h" />
<ClInclude Include="SDL\src\joystick\hidapi\SDL_hidapijoystick_c.h" />
<ClInclude Include="SDL\src\joystick\steam\SDL_steamcontroller.h" />
<ClInclude Include="SDL\src\joystick\SDL_gamecontrollerdb.h" />
<ClInclude Include="SDL\src\joystick\hidapi\SDL_hidapi_rumble.h" />
<ClInclude Include="SDL\src\joystick\SDL_gamepad_c.h" />
<ClInclude Include="SDL\src\joystick\SDL_gamepad_db.h" />
<ClInclude Include="SDL\src\joystick\SDL_joystick_c.h" />
<ClInclude Include="SDL\src\joystick\SDL_steam_virtual_gamepad.h" />
<ClInclude Include="SDL\src\joystick\SDL_sysjoystick.h" />
<ClInclude Include="SDL\src\joystick\controller_list.h" />
<ClInclude Include="SDL\src\joystick\usb_ids.h" />
<ClInclude Include="SDL\src\joystick\virtual\SDL_virtualjoystick_c.h" />
<ClInclude Include="SDL\src\joystick\windows\SDL_dinputjoystick_c.h" />
<ClInclude Include="SDL\src\joystick\windows\SDL_rawinputjoystick_c.h" />
<ClInclude Include="SDL\src\joystick\windows\SDL_windowsjoystick_c.h" />
<ClInclude Include="SDL\src\joystick\windows\SDL_xinputjoystick_c.h" />
<ClInclude Include="SDL\src\libm\math_libm.h" />
<ClInclude Include="SDL\src\libm\math_private.h" />
<ClInclude Include="SDL\src\locale\SDL_syslocale.h" />
<ClInclude Include="SDL\src\main\SDL_main_callbacks.h" />
<ClInclude Include="SDL\src\misc\SDL_sysurl.h" />
<ClInclude Include="SDL\src\power\SDL_syspower.h" />
<ClInclude Include="SDL\src\render\direct3d\SDL_shaders_d3d.h" />
<ClInclude Include="SDL\src\render\direct3d11\SDL_shaders_d3d11.h" />
<ClInclude Include="SDL\src\render\direct3d12\SDL_render_d3d12_xbox.h" />
<ClInclude Include="SDL\src\render\direct3d12\SDL_shaders_d3d12.h" />
<ClInclude Include="SDL\src\render\opengl\SDL_glfuncs.h" />
<ClInclude Include="SDL\src\render\opengl\SDL_shaders_gl.h" />
<ClInclude Include="SDL\src\render\direct3d\SDL_shaders_d3d.h" />
<ClInclude Include="SDL\src\render\opengles2\SDL_gles2funcs.h" />
<ClInclude Include="SDL\src\render\opengles2\SDL_shaders_gles2.h" />
<ClInclude Include="SDL\src\render\opengl\SDL_glfuncs.h" />
<ClInclude Include="SDL\src\render\opengl\SDL_shaders_gl.h" />
<ClInclude Include="SDL\src\render\SDL_d3dmath.h" />
<ClInclude Include="SDL\src\render\SDL_sysrender.h" />
<ClInclude Include="SDL\src\render\SDL_yuv_sw_c.h" />
@ -170,38 +188,54 @@
<ClInclude Include="SDL\src\render\software\SDL_render_sw_c.h" />
<ClInclude Include="SDL\src\render\software\SDL_rotate.h" />
<ClInclude Include="SDL\src\render\software\SDL_triangle.h" />
<ClInclude Include="SDL\src\render\vulkan\SDL_shaders_vulkan.h" />
<ClInclude Include="SDL\src\SDL_assert_c.h" />
<ClInclude Include="SDL\src\SDL_dataqueue.h" />
<ClInclude Include="SDL\src\SDL_error_c.h" />
<ClCompile Include="SDL\src\camera\dummy\SDL_camera_dummy.c" />
<ClCompile Include="SDL\src\camera\mediafoundation\SDL_camera_mediafoundation.c" />
<ClCompile Include="SDL\src\camera\SDL_camera.c" />
<ClCompile Include="SDL\src\dialog\SDL_dialog.c" />
<ClCompile Include="SDL\src\dialog\SDL_dialog_utils.c" />
<ClCompile Include="SDL\src\filesystem\SDL_filesystem.c" />
<ClCompile Include="SDL\src\filesystem\windows\SDL_sysfsops.c" />
<ClCompile Include="SDL\src\io\windows\SDL_asyncio_windows_ioring.c" />
<ClCompile Include="SDL\src\gpu\SDL_gpu.c" />
<ClCompile Include="SDL\src\gpu\d3d12\SDL_gpu_d3d12.c" />
<ClCompile Include="SDL\src\gpu\vulkan\SDL_gpu_vulkan.c" />
<ClCompile Include="SDL\src\io\generic\SDL_asyncio_generic.c" />
<ClCompile Include="SDL\src\io\SDL_asyncio.c" />
<ClCompile Include="SDL\src\main\generic\SDL_sysmain_callbacks.c" />
<ClCompile Include="SDL\src\main\SDL_main_callbacks.c" />
<ClCompile Include="SDL\src\main\SDL_runapp.c" />
<ClCompile Include="SDL\src\main\windows\SDL_sysmain_runapp.c" />
<ClCompile Include="SDL\src\render\vulkan\SDL_render_vulkan.c" />
<ClCompile Include="SDL\src\render\vulkan\SDL_shaders_vulkan.c" />
<ClCompile Include="SDL\src\SDL_guid.c" />
<ClInclude Include="SDL\src\SDL_hashtable.h" />
<ClInclude Include="SDL\src\SDL_hints_c.h" />
<ClInclude Include="SDL\src\SDL_internal.h" />
<ClInclude Include="SDL\src\SDL_list.h" />
<ClInclude Include="SDL\src\SDL_utils_c.h" />
<ClInclude Include="SDL\src\SDL_log_c.h" />
<ClInclude Include="SDL\src\SDL_properties_c.h" />
<ClInclude Include="SDL\src\sensor\dummy\SDL_dummysensor.h" />
<ClInclude Include="SDL\src\sensor\SDL_sensor_c.h" />
<ClInclude Include="SDL\src\sensor\SDL_syssensor.h" />
<ClInclude Include="SDL\src\sensor\windows\SDL_windowssensor.h" />
<ClInclude Include="SDL\src\stdlib\SDL_vacopy.h" />
<ClInclude Include="SDL\src\thread\generic\SDL_syscond_c.h" />
<ClInclude Include="SDL\src\thread\SDL_systhread.h" />
<ClInclude Include="SDL\src\thread\SDL_thread_c.h" />
<ClInclude Include="SDL\src\thread\generic\SDL_syscond_c.h" />
<ClInclude Include="SDL\src\thread\windows\SDL_sysmutex_c.h" />
<ClInclude Include="SDL\src\thread\generic\SDL_sysrwlock_c.h" />
<ClInclude Include="SDL\src\thread\windows\SDL_systhread_c.h" />
<ClInclude Include="SDL\src\timer\SDL_timer_c.h" />
<ClInclude Include="SDL\src\video\dummy\SDL_nullevents_c.h" />
<ClInclude Include="SDL\src\video\dummy\SDL_nullframebuffer_c.h" />
<ClInclude Include="SDL\src\video\dummy\SDL_nullvideo.h" />
<ClInclude Include="SDL\src\video\khronos\vk_video\vulkan_video_codec_h264std.h" />
<ClInclude Include="SDL\src\video\khronos\vk_video\vulkan_video_codec_h264std_decode.h" />
<ClInclude Include="SDL\src\video\khronos\vk_video\vulkan_video_codec_h264std_encode.h" />
<ClInclude Include="SDL\src\video\khronos\vk_video\vulkan_video_codec_h265std.h" />
<ClInclude Include="SDL\src\video\khronos\vk_video\vulkan_video_codec_h265std_decode.h" />
<ClInclude Include="SDL\src\video\khronos\vk_video\vulkan_video_codec_h265std_encode.h" />
<ClInclude Include="SDL\src\video\khronos\vk_video\vulkan_video_codecs_common.h" />
<ClInclude Include="SDL\src\video\khronos\vulkan\vk_icd.h" />
<ClInclude Include="SDL\src\video\khronos\vulkan\vk_layer.h" />
<ClInclude Include="SDL\src\video\khronos\vulkan\vk_platform.h" />
<ClInclude Include="SDL\src\video\khronos\vulkan\vk_sdk_platform.h" />
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan.h" />
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_android.h" />
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_beta.h" />
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_core.h" />
@ -211,38 +245,45 @@
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_ios.h" />
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_macos.h" />
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_metal.h" />
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_screen.h" />
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_vi.h" />
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_wayland.h" />
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_win32.h" />
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_xcb.h" />
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_xlib_xrandr.h" />
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_xlib.h" />
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan.h" />
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan.hpp" />
<ClInclude Include="SDL\src\video\khronos\vulkan\vulkan_xlib_xrandr.h" />
<ClInclude Include="SDL\src\video\offscreen\SDL_offscreenevents_c.h" />
<ClInclude Include="SDL\src\video\offscreen\SDL_offscreenframebuffer_c.h" />
<ClInclude Include="SDL\src\video\offscreen\SDL_offscreenopengles.h" />
<ClInclude Include="SDL\src\video\offscreen\SDL_offscreenvideo.h" />
<ClInclude Include="SDL\src\video\offscreen\SDL_offscreenvulkan.h" />
<ClInclude Include="SDL\src\video\offscreen\SDL_offscreenwindow.h" />
<ClInclude Include="SDL\src\video\SDL_blit.h" />
<ClInclude Include="SDL\src\video\SDL_blit_auto.h" />
<ClInclude Include="SDL\src\video\SDL_blit_copy.h" />
<ClInclude Include="SDL\src\video\SDL_blit_slow.h" />
<ClInclude Include="SDL\src\video\SDL_blit.h" />
<ClInclude Include="SDL\src\video\SDL_clipboard_c.h" />
<ClInclude Include="SDL\src\video\SDL_egl_c.h" />
<ClInclude Include="SDL\src\video\SDL_pixels_c.h" />
<ClInclude Include="SDL\src\video\SDL_rect_c.h" />
<ClInclude Include="SDL\src\video\SDL_RLEaccel_c.h" />
<ClInclude Include="SDL\src\video\SDL_shape_internals.h" />
<ClInclude Include="SDL\src\video\SDL_stb_c.h" />
<ClInclude Include="SDL\src\video\SDL_surface_c.h" />
<ClInclude Include="SDL\src\video\SDL_sysvideo.h" />
<ClInclude Include="SDL\src\video\SDL_vulkan_internal.h" />
<ClInclude Include="SDL\src\video\SDL_yuv_c.h" />
<ClInclude Include="SDL\src\video\windows\SDL_msctf.h" />
<ClInclude Include="SDL\src\video\windows\SDL_vkeys.h" />
<ClInclude Include="SDL\src\video\windows\SDL_surface_utils.h" />
<ClInclude Include="SDL\src\video\windows\SDL_windowsclipboard.h" />
<ClInclude Include="SDL\src\video\windows\SDL_windowsevents.h" />
<ClInclude Include="SDL\src\video\windows\SDL_windowsframebuffer.h" />
<ClInclude Include="SDL\src\video\windows\SDL_windowskeyboard.h" />
<ClInclude Include="SDL\src\video\windows\SDL_windowsgameinput.h" />
<ClInclude Include="SDL\src\video\windows\SDL_windowsmessagebox.h" />
<ClInclude Include="SDL\src\video\windows\SDL_windowsmodes.h" />
<ClInclude Include="SDL\src\video\windows\SDL_windowsmouse.h" />
<ClInclude Include="SDL\src\video\windows\SDL_windowsopengl.h" />
<ClInclude Include="SDL\src\video\windows\SDL_windowsopengles.h" />
<ClInclude Include="SDL\src\video\windows\SDL_windowsrawinput.h" />
<ClInclude Include="SDL\src\video\windows\SDL_windowsshape.h" />
<ClInclude Include="SDL\src\video\windows\SDL_windowsvideo.h" />
<ClInclude Include="SDL\src\video\windows\SDL_windowsvulkan.h" />
@ -257,8 +298,6 @@
<ClInclude Include="SDL\src\video\yuv2rgb\yuv_rgb_sse_func.h" />
<ClInclude Include="SDL\src\video\yuv2rgb\yuv_rgb_std.h" />
<ClInclude Include="SDL\src\video\yuv2rgb\yuv_rgb_std_func.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="SDL\src\atomic\SDL_atomic.c" />
<ClCompile Include="SDL\src\atomic\SDL_spinlock.c" />
<ClCompile Include="SDL\src\audio\directsound\SDL_directsound.c" />
@ -268,37 +307,49 @@
<ClCompile Include="SDL\src\audio\SDL_audiocvt.c" />
<ClCompile Include="SDL\src\audio\SDL_audiodev.c" />
<ClCompile Include="SDL\src\audio\SDL_audiotypecvt.c" />
<ClCompile Include="SDL\src\audio\SDL_audioqueue.c" />
<ClCompile Include="SDL\src\audio\SDL_audioresample.c" />
<ClCompile Include="SDL\src\audio\SDL_mixer.c" />
<ClCompile Include="SDL\src\audio\SDL_wave.c" />
<ClCompile Include="SDL\src\audio\wasapi\SDL_wasapi_win32.c" />
<ClCompile Include="SDL\src\audio\wasapi\SDL_wasapi.c" />
<ClCompile Include="SDL\src\audio\winmm\SDL_winmm.c" />
<ClCompile Include="SDL\src\core\SDL_core_unsupported.c" />
<ClCompile Include="SDL\src\core\windows\SDL_gameinput.c" />
<ClCompile Include="SDL\src\core\windows\SDL_hid.c" />
<ClCompile Include="SDL\src\core\windows\SDL_immdevice.c" />
<ClCompile Include="SDL\src\core\windows\SDL_windows.c" />
<ClCompile Include="SDL\src\core\windows\SDL_xinput.c" />
<ClCompile Include="SDL\src\cpuinfo\SDL_cpuinfo.c" />
<ClCompile Include="SDL\src\dynapi\SDL_dynapi.c" />
<ClCompile Include="SDL\src\dialog\windows\SDL_windowsdialog.c" />
<ClCompile Include="SDL\src\dynapi\SDL_dynapi.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="SDL\src\events\SDL_categories.c" />
<ClCompile Include="SDL\src\events\SDL_clipboardevents.c" />
<ClCompile Include="SDL\src\events\SDL_displayevents.c" />
<ClCompile Include="SDL\src\events\SDL_dropevents.c" />
<ClCompile Include="SDL\src\events\SDL_events.c" />
<ClCompile Include="SDL\src\events\SDL_gesture.c" />
<ClCompile Include="SDL\src\events\SDL_eventwatch.c" />
<ClCompile Include="SDL\src\events\SDL_keyboard.c" />
<ClCompile Include="SDL\src\events\SDL_keymap.c" />
<ClCompile Include="SDL\src\events\SDL_mouse.c" />
<ClCompile Include="SDL\src\events\SDL_pen.c" />
<ClCompile Include="SDL\src\events\SDL_quit.c" />
<ClCompile Include="SDL\src\events\SDL_touch.c" />
<ClCompile Include="SDL\src\events\SDL_windowevents.c" />
<ClCompile Include="SDL\src\file\SDL_rwops.c" />
<ClCompile Include="SDL\src\io\SDL_iostream.c" />
<ClCompile Include="SDL\src\filesystem\windows\SDL_sysfilesystem.c" />
<ClCompile Include="SDL\src\haptic\dummy\SDL_syshaptic.c" />
<ClCompile Include="SDL\src\haptic\SDL_haptic.c" />
<ClCompile Include="SDL\src\haptic\windows\SDL_dinputhaptic.c" />
<ClCompile Include="SDL\src\haptic\windows\SDL_windowshaptic.c" />
<ClCompile Include="SDL\src\haptic\windows\SDL_xinputhaptic.c" />
<ClCompile Include="SDL\src\hidapi\SDL_hidapi.c" />
<ClCompile Include="SDL\src\joystick\controller_type.c" />
<ClCompile Include="SDL\src\joystick\dummy\SDL_sysjoystick.c" />
<ClCompile Include="SDL\src\joystick\gdk\SDL_gameinputjoystick.c" />
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapijoystick.c" />
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_combined.c" />
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_gamecube.c" />
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_luna.c" />
@ -309,23 +360,23 @@
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_shield.c" />
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_stadia.c" />
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_steam.c" />
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_steam_hori.c" />
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_steamdeck.c" />
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_switch.c" />
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_wii.c" />
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_xbox360.c" />
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_xbox360w.c" />
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapi_xboxone.c" />
<ClCompile Include="SDL\src\joystick\hidapi\SDL_hidapijoystick.c" />
<ClCompile Include="SDL\src\joystick\steam\SDL_steamcontroller.c" />
<ClCompile Include="SDL\src\joystick\SDL_gamecontroller.c" />
<ClCompile Include="SDL\src\joystick\SDL_gamepad.c" />
<ClCompile Include="SDL\src\joystick\SDL_joystick.c" />
<ClCompile Include="SDL\src\joystick\SDL_steam_virtual_gamepad.c" />
<ClCompile Include="SDL\src\joystick\virtual\SDL_virtualjoystick.c" />
<ClCompile Include="SDL\src\joystick\windows\SDL_dinputjoystick.c" />
<ClCompile Include="SDL\src\joystick\windows\SDL_rawinputjoystick.c" />
<ClCompile Include="SDL\src\joystick\windows\SDL_windows_gaming_input.c" />
<ClCompile Include="SDL\src\joystick\windows\SDL_windowsjoystick.c" />
<ClCompile Include="SDL\src\joystick\windows\SDL_windows_gaming_input.c" />
<ClCompile Include="SDL\src\joystick\windows\SDL_xinputjoystick.c" />
<ClCompile Include="SDL\src\libm\s_modf.c" />
<ClCompile Include="SDL\src\loadso\windows\SDL_sysloadso.c" />
<ClCompile Include="SDL\src\locale\SDL_locale.c" />
<ClCompile Include="SDL\src\locale\windows\SDL_syslocale.c" />
@ -333,18 +384,24 @@
<ClCompile Include="SDL\src\misc\windows\SDL_sysurl.c" />
<ClCompile Include="SDL\src\power\SDL_power.c" />
<ClCompile Include="SDL\src\power\windows\SDL_syspower.c" />
<ClCompile Include="SDL\src\render\direct3d\SDL_render_d3d.c" />
<ClCompile Include="SDL\src\render\direct3d\SDL_shaders_d3d.c" />
<ClCompile Include="SDL\src\render\direct3d11\SDL_render_d3d11.c" />
<ClCompile Include="SDL\src\process\SDL_process.c" />
<ClCompile Include="SDL\src\process\windows\SDL_windowsprocess.c" />
<ClCompile Include="SDL\src\render\direct3d11\SDL_shaders_d3d11.c" />
<ClCompile Include="SDL\src\render\direct3d12\SDL_render_d3d12.c" />
<ClCompile Include="SDL\src\render\direct3d12\SDL_shaders_d3d12.c" />
<ClCompile Include="SDL\src\render\direct3d\SDL_render_d3d.c" />
<ClCompile Include="SDL\src\render\direct3d11\SDL_render_d3d11.c" />
<ClCompile Include="SDL\src\render\direct3d\SDL_shaders_d3d.c" />
<ClCompile Include="SDL\src\render\gpu\SDL_pipeline_gpu.c" />
<ClCompile Include="SDL\src\render\gpu\SDL_render_gpu.c" />
<ClCompile Include="SDL\src\render\gpu\SDL_shaders_gpu.c" />
<ClCompile Include="SDL\src\render\opengl\SDL_render_gl.c" />
<ClCompile Include="SDL\src\render\opengl\SDL_shaders_gl.c" />
<ClCompile Include="SDL\src\render\opengles2\SDL_render_gles2.c" />
<ClCompile Include="SDL\src\render\opengles2\SDL_shaders_gles2.c" />
<ClCompile Include="SDL\src\render\SDL_d3dmath.c" />
<ClCompile Include="SDL\src\render\SDL_render.c" />
<ClCompile Include="SDL\src\render\SDL_render_unsupported.c" />
<ClCompile Include="SDL\src\render\SDL_yuv_sw.c" />
<ClCompile Include="SDL\src\render\software\SDL_blendfillrect.c" />
<ClCompile Include="SDL\src\render\software\SDL_blendline.c" />
@ -354,15 +411,15 @@
<ClCompile Include="SDL\src\render\software\SDL_render_sw.c" />
<ClCompile Include="SDL\src\render\software\SDL_rotate.c" />
<ClCompile Include="SDL\src\render\software\SDL_triangle.c" />
<ClCompile Include="SDL\src\SDL.c" />
<ClCompile Include="SDL\src\SDL_assert.c" />
<ClCompile Include="SDL\src\SDL_dataqueue.c" />
<ClCompile Include="SDL\src\SDL_error.c" />
<ClCompile Include="SDL\src\SDL_guid.c" />
<ClCompile Include="SDL\src\SDL_hashtable.c" />
<ClCompile Include="SDL\src\SDL_hints.c" />
<ClCompile Include="SDL\src\SDL_list.c" />
<ClCompile Include="SDL\src\SDL_log.c" />
<ClCompile Include="SDL\src\SDL_properties.c" />
<ClCompile Include="SDL\src\SDL_utils.c" />
<ClCompile Include="SDL\src\SDL.c" />
<ClCompile Include="SDL\src\sensor\dummy\SDL_dummysensor.c" />
<ClCompile Include="SDL\src\sensor\SDL_sensor.c" />
<ClCompile Include="SDL\src\sensor\windows\SDL_windowssensor.c" />
@ -371,23 +428,44 @@
<ClCompile Include="SDL\src\stdlib\SDL_getenv.c" />
<ClCompile Include="SDL\src\stdlib\SDL_iconv.c" />
<ClCompile Include="SDL\src\stdlib\SDL_malloc.c" />
<ClCompile Include="SDL\src\stdlib\SDL_memcpy.c" />
<ClCompile Include="SDL\src\stdlib\SDL_memmove.c" />
<ClCompile Include="SDL\src\stdlib\SDL_memset.c" />
<ClCompile Include="SDL\src\stdlib\SDL_mslibc.c" />
<ClCompile Include="SDL\src\stdlib\SDL_murmur3.c" />
<ClCompile Include="SDL\src\stdlib\SDL_qsort.c" />
<ClCompile Include="SDL\src\stdlib\SDL_random.c" />
<ClCompile Include="SDL\src\stdlib\SDL_stdlib.c" />
<ClCompile Include="SDL\src\stdlib\SDL_string.c" />
<ClCompile Include="SDL\src\stdlib\SDL_strtokr.c" />
<ClCompile Include="SDL\src\storage\generic\SDL_genericstorage.c" />
<ClCompile Include="SDL\src\storage\steam\SDL_steamstorage.c" />
<ClCompile Include="SDL\src\storage\SDL_storage.c" />
<ClCompile Include="SDL\src\thread\generic\SDL_syscond.c" />
<ClCompile Include="SDL\src\thread\generic\SDL_sysrwlock.c" />
<ClCompile Include="SDL\src\thread\SDL_thread.c" />
<ClCompile Include="SDL\src\thread\windows\SDL_syscond_cv.c" />
<ClCompile Include="SDL\src\thread\windows\SDL_sysmutex.c" />
<ClCompile Include="SDL\src\thread\windows\SDL_sysrwlock_srw.c" />
<ClCompile Include="SDL\src\thread\windows\SDL_syssem.c" />
<ClCompile Include="SDL\src\thread\windows\SDL_systhread.c" />
<ClCompile Include="SDL\src\thread\windows\SDL_systls.c" />
<ClCompile Include="SDL\src\timer\SDL_timer.c" />
<ClCompile Include="SDL\src\timer\windows\SDL_systimer.c" />
<ClCompile Include="SDL\src\time\SDL_time.c" />
<ClCompile Include="SDL\src\time\windows\SDL_systime.c" />
<ClCompile Include="SDL\src\tray\windows\SDL_tray.c" />
<ClCompile Include="SDL\src\tray\SDL_tray_utils.c" />
<ClCompile Include="SDL\src\video\dummy\SDL_nullevents.c" />
<ClCompile Include="SDL\src\video\dummy\SDL_nullframebuffer.c" />
<ClCompile Include="SDL\src\video\dummy\SDL_nullvideo.c" />
<ClCompile Include="SDL\src\video\offscreen\SDL_offscreenevents.c" />
<ClCompile Include="SDL\src\video\offscreen\SDL_offscreenframebuffer.c" />
<ClCompile Include="SDL\src\video\offscreen\SDL_offscreenopengles.c" />
<ClCompile Include="SDL\src\video\offscreen\SDL_offscreenvideo.c" />
<ClCompile Include="SDL\src\video\offscreen\SDL_offscreenvulkan.c" />
<ClCompile Include="SDL\src\video\offscreen\SDL_offscreenwindow.c" />
<ClCompile Include="SDL\src\video\SDL_blit.c" />
<ClCompile Include="SDL\src\video\SDL_blit_0.c" />
<ClCompile Include="SDL\src\video\SDL_blit_1.c" />
<ClCompile Include="SDL\src\video\SDL_blit_A.c" />
@ -395,7 +473,6 @@
<ClCompile Include="SDL\src\video\SDL_blit_copy.c" />
<ClCompile Include="SDL\src\video\SDL_blit_N.c" />
<ClCompile Include="SDL\src\video\SDL_blit_slow.c" />
<ClCompile Include="SDL\src\video\SDL_blit.c" />
<ClCompile Include="SDL\src\video\SDL_bmp.c" />
<ClCompile Include="SDL\src\video\SDL_clipboard.c" />
<ClCompile Include="SDL\src\video\SDL_egl.c" />
@ -403,21 +480,25 @@
<ClCompile Include="SDL\src\video\SDL_pixels.c" />
<ClCompile Include="SDL\src\video\SDL_rect.c" />
<ClCompile Include="SDL\src\video\SDL_RLEaccel.c" />
<ClCompile Include="SDL\src\video\SDL_shape.c" />
<ClCompile Include="SDL\src\video\SDL_stb.c" />
<ClCompile Include="SDL\src\video\SDL_stretch.c" />
<ClCompile Include="SDL\src\video\SDL_surface.c" />
<ClCompile Include="SDL\src\video\SDL_video.c" />
<ClCompile Include="SDL\src\video\SDL_video_unsupported.c" />
<ClCompile Include="SDL\src\video\SDL_vulkan_utils.c" />
<ClCompile Include="SDL\src\video\SDL_yuv.c" />
<ClCompile Include="SDL\src\video\windows\SDL_surface_utils.c" />
<ClCompile Include="SDL\src\video\windows\SDL_windowsclipboard.c" />
<ClCompile Include="SDL\src\video\windows\SDL_windowsevents.c" />
<ClCompile Include="SDL\src\video\windows\SDL_windowsframebuffer.c" />
<ClCompile Include="SDL\src\video\windows\SDL_windowskeyboard.c" />
<ClCompile Include="SDL\src\video\windows\SDL_windowsgameinput.c" />
<ClCompile Include="SDL\src\video\windows\SDL_windowsmessagebox.c" />
<ClCompile Include="SDL\src\video\windows\SDL_windowsmodes.c" />
<ClCompile Include="SDL\src\video\windows\SDL_windowsmouse.c" />
<ClCompile Include="SDL\src\video\windows\SDL_windowsopengl.c" />
<ClCompile Include="SDL\src\video\windows\SDL_windowsopengles.c" />
<ClCompile Include="SDL\src\video\windows\SDL_windowsrawinput.c" />
<ClCompile Include="SDL\src\video\windows\SDL_windowsshape.c" />
<ClCompile Include="SDL\src\video\windows\SDL_windowsvideo.c" />
<ClCompile Include="SDL\src\video\windows\SDL_windowsvulkan.c" />
@ -426,7 +507,10 @@
<ClCompile Include="SDL\src\video\yuv2rgb\yuv_rgb_sse.c" />
<ClCompile Include="SDL\src\video\yuv2rgb\yuv_rgb_std.c" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="SDL\src\core\windows\version.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -6,7 +6,7 @@
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="$(ExternalsDir)SDL\SDL2.vcxproj">
<ProjectReference Include="$(ExternalsDir)SDL\SDL3.vcxproj">
<Project>{8DC244EE-A0BD-4038-BAF7-CFAFA5EB2BAA}</Project>
</ProjectReference>
</ItemGroup>

View File

@ -1,21 +0,0 @@
{
"name": "SDL2",
"buildsystem": "autotools",
"config-opts": ["--disable-static"],
"sources": [
{
"type": "dir",
"path": "../../Externals/SDL/SDL"
}
],
"cleanup": [ "/bin/sdl2-config",
"/include",
"/lib/libSDL2.la",
"/lib/libSDL2main.a",
"/lib/libSDL2main.la",
"/lib/libSDL2_test.a",
"/lib/libSDL2_test.la",
"/lib/cmake",
"/share/aclocal",
"/lib/pkgconfig"]
}

View File

@ -37,10 +37,6 @@ modules:
project-id: 20540
stable-only: true
url-template: https://www.freedesktop.org/software/libevdev/libevdev-$version.tar.xz
# build the vendored SDL2 from Externals until the runtime gets 2.30.9
- SDL2/SDL2.json
- name: dolphin-emu
buildsystem: cmake-ninja
builddir: true

View File

@ -0,0 +1,28 @@
package org.dolphinemu.dolphinemu.utils
import android.content.Context
import android.media.AudioManager
import androidx.annotation.Keep
import org.dolphinemu.dolphinemu.DolphinApplication
object AudioUtils {
@JvmStatic @Keep
fun getSampleRate(): Int =
getAudioServiceProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE, 48000)
@JvmStatic @Keep
fun getFramesPerBuffer(): Int =
getAudioServiceProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER, 256)
private fun getAudioServiceProperty(property: String, fallback: Int): Int {
return try {
val context = DolphinApplication.getAppContext()
val am = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
Integer.parseUnsignedInt(am.getProperty(property))
} catch (e: NullPointerException) {
fallback
} catch (e: NumberFormatException) {
fallback
}
}
}

View File

@ -122,6 +122,10 @@ static jmethodID s_permission_handler_request_record_audio_permission;
static jmethodID s_runnable_run;
static jclass s_audio_utils_class;
static jmethodID s_audio_utils_get_sample_rate;
static jmethodID s_audio_utils_get_frames_per_buffer;
namespace IDCache
{
JNIEnv* GetEnvForThread()
@ -562,6 +566,21 @@ jmethodID GetRunnableRun()
return s_runnable_run;
}
jclass GetAudioUtilsClass()
{
return s_audio_utils_class;
}
jmethodID GetAudioUtilsGetSampleRate()
{
return s_audio_utils_get_sample_rate;
}
jmethodID GetAudioUtilsGetFramesPerBuffer()
{
return s_audio_utils_get_frames_per_buffer;
}
} // namespace IDCache
extern "C" {
@ -798,6 +817,13 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
s_runnable_run = env->GetMethodID(runnable_class, "run", "()V");
env->DeleteLocalRef(runnable_class);
const jclass audio_utils_class = env->FindClass("org/dolphinemu/dolphinemu/utils/AudioUtils");
s_audio_utils_class = reinterpret_cast<jclass>(env->NewGlobalRef(audio_utils_class));
s_audio_utils_get_sample_rate = env->GetStaticMethodID(audio_utils_class, "getSampleRate", "()I");
s_audio_utils_get_frames_per_buffer =
env->GetStaticMethodID(audio_utils_class, "getFramesPerBuffer", "()I");
env->DeleteLocalRef(audio_utils_class);
return JNI_VERSION;
}
@ -834,5 +860,6 @@ JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved)
env->DeleteGlobalRef(s_core_device_control_class);
env->DeleteGlobalRef(s_input_detector_class);
env->DeleteGlobalRef(s_permission_handler_class);
env->DeleteGlobalRef(s_audio_utils_class);
}
}

View File

@ -121,4 +121,8 @@ jmethodID GetPermissionHandlerRequestRecordAudioPermission();
jmethodID GetRunnableRun();
jclass GetAudioUtilsClass();
jmethodID GetAudioUtilsGetSampleRate();
jmethodID GetAudioUtilsGetFramesPerBuffer();
} // namespace IDCache

View File

@ -16,6 +16,7 @@
#include "AudioCommon/WASAPIStream.h"
#include "Common/FileUtil.h"
#include "Common/Logging/Log.h"
#include "Common/TimeUtil.h"
#include "Core/Config/MainSettings.h"
#include "Core/ConfigManager.h"
#include "Core/System.h"
@ -219,8 +220,11 @@ void StartAudioDump(Core::System& system)
std::string path_prefix = File::GetUserPath(D_DUMPAUDIO_IDX) + SConfig::GetInstance().GetGameID();
std::string base_name =
fmt::format("{}_{:%Y-%m-%d_%H-%M-%S}", path_prefix, fmt::localtime(start_time));
const auto local_time = Common::LocalTime(start_time);
if (!local_time)
return;
std::string base_name = fmt::format("{}_{:%Y-%m-%d_%H-%M-%S}", path_prefix, *local_time);
const std::string audio_file_name_dtk = fmt::format("{}_dtkdump.wav", base_name);
const std::string audio_file_name_dsp = fmt::format("{}_dspdump.wav", base_name);

View File

@ -8,40 +8,27 @@
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#include <jni.h>
#include "Common/Assert.h"
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "Core/ConfigManager.h"
#include "jni/AndroidCommon/IDCache.h"
// engine interfaces
static SLObjectItf engineObject;
static SLEngineItf engineEngine;
static SLObjectItf outputMixObject;
// buffer queue player interfaces
static SLObjectItf bqPlayerObject = nullptr;
static SLPlayItf bqPlayerPlay;
static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
static SLVolumeItf bqPlayerVolume;
static Mixer* g_mixer;
#define BUFFER_SIZE 512
#define BUFFER_SIZE_IN_SAMPLES (BUFFER_SIZE / 2)
// Double buffering.
static short buffer[2][BUFFER_SIZE];
static int curBuffer = 0;
static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context)
void OpenSLESStream::BQPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context)
{
ASSERT(bq == bqPlayerBufferQueue);
ASSERT(nullptr == context);
reinterpret_cast<OpenSLESStream*>(context)->PushSamples(bq);
}
void OpenSLESStream::PushSamples(SLAndroidSimpleBufferQueueItf bq)
{
ASSERT(bq == m_bq_player_buffer_queue);
// Render to the fresh buffer
g_mixer->Mix(reinterpret_cast<short*>(buffer[curBuffer]), BUFFER_SIZE_IN_SAMPLES);
SLresult result =
(*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[curBuffer], sizeof(buffer[0]));
curBuffer ^= 1; // Switch buffer
m_mixer->Mix(m_buffer[m_current_buffer].data(), m_frames_per_buffer);
SLresult result = (*bq)->Enqueue(bq, m_buffer[m_current_buffer].data(), m_bytes_per_buffer);
m_current_buffer ^= 1; // Switch buffer
// Comment from sample code:
// the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT,
@ -51,61 +38,78 @@ static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context)
bool OpenSLESStream::Init()
{
JNIEnv* env = IDCache::GetEnvForThread();
jclass audio_utils = IDCache::GetAudioUtilsClass();
const SLuint32 sample_rate =
env->CallStaticIntMethod(audio_utils, IDCache::GetAudioUtilsGetSampleRate());
m_frames_per_buffer =
env->CallStaticIntMethod(audio_utils, IDCache::GetAudioUtilsGetFramesPerBuffer());
INFO_LOG_FMT(AUDIO, "OpenSLES configuration: {} Hz, {} frames per buffer", sample_rate,
m_frames_per_buffer);
constexpr SLuint32 channels = 2;
const SLuint32 samples_per_buffer = m_frames_per_buffer * channels;
m_bytes_per_buffer = m_frames_per_buffer * channels * sizeof(m_buffer[0][0]);
for (std::vector<short>& buffer : m_buffer)
buffer.resize(samples_per_buffer);
SLresult result;
// create engine
result = slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
result = slCreateEngine(&m_engine_object, 0, nullptr, 0, nullptr, nullptr);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
result = (*m_engine_object)->Realize(m_engine_object, SL_BOOLEAN_FALSE);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
result = (*m_engine_object)->GetInterface(m_engine_object, SL_IID_ENGINE, &m_engine_engine);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, 0, 0);
result = (*m_engine_engine)->CreateOutputMix(m_engine_engine, &m_output_mix_object, 0, 0, 0);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
result = (*m_output_mix_object)->Realize(m_output_mix_object, SL_BOOLEAN_FALSE);
ASSERT(SL_RESULT_SUCCESS == result);
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM,
2,
m_mixer->GetSampleRate() * 1000,
SL_PCMSAMPLEFORMAT_FIXED_16,
SL_PCMSAMPLEFORMAT_FIXED_16,
SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,
SL_BYTEORDER_LITTLEENDIAN};
SLDataFormat_PCM format_pcm = {
SL_DATAFORMAT_PCM, channels,
sample_rate * 1000, SL_PCMSAMPLEFORMAT_FIXED_16,
SL_PCMSAMPLEFORMAT_FIXED_16, SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,
SL_BYTEORDER_LITTLEENDIAN};
SLDataSource audioSrc = {&loc_bufq, &format_pcm};
// configure audio sink
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, m_output_mix_object};
SLDataSink audioSnk = {&loc_outmix, nullptr};
// create audio player
const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME};
const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
result =
(*engineEngine)
->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req);
result = (*m_engine_engine)
->CreateAudioPlayer(m_engine_engine, &m_bq_player_object, &audioSrc, &audioSnk, 2,
ids, req);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
result = (*m_bq_player_object)->Realize(m_bq_player_object, SL_BOOLEAN_FALSE);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
result = (*m_bq_player_object)->GetInterface(m_bq_player_object, SL_IID_PLAY, &m_bq_player_play);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*m_bq_player_object)
->GetInterface(m_bq_player_object, SL_IID_BUFFERQUEUE, &m_bq_player_buffer_queue);
ASSERT(SL_RESULT_SUCCESS == result);
result =
(*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, &bqPlayerBufferQueue);
(*m_bq_player_object)->GetInterface(m_bq_player_object, SL_IID_VOLUME, &m_bq_player_volume);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume);
result = (*m_bq_player_buffer_queue)
->RegisterCallback(m_bq_player_buffer_queue, BQPlayerCallback, this);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, nullptr);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
result = (*m_bq_player_play)->SetPlayState(m_bq_player_play, SL_PLAYSTATE_PLAYING);
ASSERT(SL_RESULT_SUCCESS == result);
// Render and enqueue a first buffer.
curBuffer ^= 1;
g_mixer = m_mixer.get();
m_current_buffer ^= 1;
result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[0], sizeof(buffer[0]));
result = (*m_bq_player_buffer_queue)
->Enqueue(m_bq_player_buffer_queue, m_buffer[0].data(), m_bytes_per_buffer);
if (SL_RESULT_SUCCESS != result)
return false;
@ -114,39 +118,39 @@ bool OpenSLESStream::Init()
OpenSLESStream::~OpenSLESStream()
{
if (bqPlayerObject != nullptr)
if (m_bq_player_object != nullptr)
{
(*bqPlayerObject)->Destroy(bqPlayerObject);
bqPlayerObject = nullptr;
bqPlayerPlay = nullptr;
bqPlayerBufferQueue = nullptr;
bqPlayerVolume = nullptr;
(*m_bq_player_object)->Destroy(m_bq_player_object);
m_bq_player_object = nullptr;
m_bq_player_play = nullptr;
m_bq_player_buffer_queue = nullptr;
m_bq_player_volume = nullptr;
}
if (outputMixObject != nullptr)
if (m_output_mix_object != nullptr)
{
(*outputMixObject)->Destroy(outputMixObject);
outputMixObject = nullptr;
(*m_output_mix_object)->Destroy(m_output_mix_object);
m_output_mix_object = nullptr;
}
if (engineObject != nullptr)
if (m_engine_object != nullptr)
{
(*engineObject)->Destroy(engineObject);
engineObject = nullptr;
engineEngine = nullptr;
(*m_engine_object)->Destroy(m_engine_object);
m_engine_object = nullptr;
m_engine_engine = nullptr;
}
}
bool OpenSLESStream::SetRunning(bool running)
{
SLuint32 new_state = running ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_PAUSED;
return (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, new_state) == SL_RESULT_SUCCESS;
return (*m_bq_player_play)->SetPlayState(m_bq_player_play, new_state) == SL_RESULT_SUCCESS;
}
void OpenSLESStream::SetVolume(int volume)
{
const SLmillibel attenuation =
volume <= 0 ? SL_MILLIBEL_MIN : static_cast<SLmillibel>(2000 * std::log10(volume / 100.0f));
(*bqPlayerVolume)->SetVolumeLevel(bqPlayerVolume, attenuation);
(*m_bq_player_volume)->SetVolumeLevel(m_bq_player_volume, attenuation);
}
#endif // HAVE_OPENSL_ES

View File

@ -3,10 +3,15 @@
#pragma once
#include <thread>
#ifdef HAVE_OPENSL_ES
#include <array>
#include <vector>
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#endif // HAVE_OPENSL_ES
#include "AudioCommon/SoundStream.h"
#include "Common/Event.h"
class OpenSLESStream final : public SoundStream
{
@ -19,7 +24,25 @@ public:
static bool IsValid() { return true; }
private:
std::thread thread;
Common::Event soundSyncEvent;
static void BQPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context);
void PushSamples(SLAndroidSimpleBufferQueueItf bq);
// engine interfaces
SLObjectItf m_engine_object;
SLEngineItf m_engine_engine;
SLObjectItf m_output_mix_object;
// buffer queue player interfaces
SLObjectItf m_bq_player_object = nullptr;
SLPlayItf m_bq_player_play;
SLAndroidSimpleBufferQueueItf m_bq_player_buffer_queue;
SLVolumeItf m_bq_player_volume;
SLuint32 m_frames_per_buffer;
SLuint32 m_bytes_per_buffer;
// Double buffering.
std::array<std::vector<short>, 2> m_buffer;
int m_current_buffer = 0;
#endif // HAVE_OPENSL_ES
};

View File

@ -25,6 +25,7 @@
#include "Common/Logging/Log.h"
#include "Common/ScopeGuard.h"
#include "Common/StringUtil.h"
#include "Common/TimeUtil.h"
#include "Core/Config/MainSettings.h"
@ -95,12 +96,7 @@ int SDCardDiskIOCtl(File::IOFile* image, u8 pdrv, u8 cmd, void* buff)
u32 GetSystemTimeFAT()
{
const std::time_t time = std::time(nullptr);
std::tm tm;
#ifdef _WIN32
localtime_s(&tm, &time);
#else
localtime_r(&time, &tm);
#endif
std::tm tm = *Common::LocalTime(time);
DWORD fattime = 0;
fattime |= (tm.tm_year - 80) << 25;

View File

@ -122,7 +122,6 @@ std::string SettingsWriter::GenerateSerialNumber()
// Must be 9 characters at most; otherwise the serial number will be rejected by SDK libraries,
// as there is a check to ensure the string length is strictly lower than 10.
// 3 for %j, 2 for %H, 2 for %M, 2 for %S.
return fmt::format("{:%j%H%M%S}", fmt::localtime(t));
return fmt::format("{:09}", t % 1000000000);
}
} // namespace Common

View File

@ -2,23 +2,25 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "Common/TimeUtil.h"
#include "Common/Logging/Log.h"
#include <ctime>
#include <optional>
namespace Common
{
std::optional<std::tm> Localtime(std::time_t time)
std::optional<std::tm> LocalTime(std::time_t time)
{
std::tm local_time;
#ifdef _MSC_VER
if (localtime_s(&local_time, &time) != 0)
return std::nullopt;
#else
std::tm* result = localtime_r(&time, &local_time);
if (result != &local_time)
return std::nullopt;
if (localtime_r(&time, &local_time) == NULL)
#endif
{
ERROR_LOG_FMT(COMMON, "Failed to convert time to local time: {}", std::strerror(errno));
return std::nullopt;
}
return local_time;
}
} // Namespace Common

View File

@ -9,5 +9,5 @@
namespace Common
{
// Threadsafe and error-checking variant of std::localtime()
std::optional<std::tm> Localtime(std::time_t time);
std::optional<std::tm> LocalTime(std::time_t time);
} // Namespace Common

View File

@ -8,6 +8,7 @@
#include <cstring>
#include <functional>
#include <mutex>
#include <optional>
#include <queue>
#include <utility>
#include <variant>
@ -34,6 +35,7 @@
#include "Common/ScopeGuard.h"
#include "Common/StringUtil.h"
#include "Common/Thread.h"
#include "Common/TimeUtil.h"
#include "Common/Version.h"
#include "Core/AchievementManager.h"
@ -733,15 +735,17 @@ static std::string GenerateScreenshotFolderPath()
return path;
}
static std::string GenerateScreenshotName()
static std::optional<std::string> GenerateScreenshotName()
{
// append gameId, path only contains the folder here.
const std::string path_prefix =
GenerateScreenshotFolderPath() + SConfig::GetInstance().GetGameID();
const std::time_t cur_time = std::time(nullptr);
const std::string base_name =
fmt::format("{}_{:%Y-%m-%d_%H-%M-%S}", path_prefix, fmt::localtime(cur_time));
const auto local_time = Common::LocalTime(cur_time);
if (!local_time)
return std::nullopt;
const std::string base_name = fmt::format("{}_{:%Y-%m-%d_%H-%M-%S}", path_prefix, *local_time);
// First try a filename without any suffixes, if already exists then append increasing numbers
std::string name = fmt::format("{}.png", base_name);
@ -757,7 +761,9 @@ static std::string GenerateScreenshotName()
void SaveScreenShot()
{
const Core::CPUThreadGuard guard(Core::System::GetInstance());
g_frame_dumper->SaveScreenshot(GenerateScreenshotName());
std::optional<std::string> name = GenerateScreenshotName();
if (name)
g_frame_dumper->SaveScreenshot(*name);
}
void SaveScreenShot(std::string_view name)

View File

@ -16,6 +16,7 @@
#include "Common/Network.h"
#include "Common/PcapFile.h"
#include "Common/ScopeGuard.h"
#include "Common/TimeUtil.h"
#include "Core/Config/MainSettings.h"
#include "Core/ConfigManager.h"
@ -82,7 +83,7 @@ PCAPSSLCaptureLogger::PCAPSSLCaptureLogger()
{
const std::string filepath =
fmt::format("{}{} {:%Y-%m-%d %Hh%Mm%Ss}.pcap", File::GetUserPath(D_DUMPSSL_IDX),
SConfig::GetInstance().GetGameID(), fmt::localtime(std::time(nullptr)));
SConfig::GetInstance().GetGameID(), *Common::LocalTime(std::time(nullptr)));
m_file = std::make_unique<Common::PCAP>(
new File::IOFile(filepath, "wb", File::SharedAccess::Read), Common::PCAP::LinkType::Ethernet);
}

View File

@ -281,7 +281,7 @@ static std::string SystemTimeAsDoubleToString(double time)
{
// revert adjustments from GetSystemTimeAsDouble() to get a normal Unix timestamp again
const time_t seconds = static_cast<time_t>(time) + DOUBLE_TIME_OFFSET;
const auto local_time = Common::Localtime(seconds);
const auto local_time = Common::LocalTime(seconds);
if (!local_time)
return "";

View File

@ -23,7 +23,6 @@
#include "DolphinQt/Config/CheatWarningWidget.h"
#include "DolphinQt/Config/HardcoreWarningWidget.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
ARCodeWidget::ARCodeWidget(std::string game_id, u16 game_revision, bool restart_required)
: m_game_id(std::move(game_id)), m_game_revision(game_revision),
@ -257,7 +256,6 @@ void ARCodeWidget::OnCodeAddClicked()
ar.enabled = true;
m_cheat_code_editor->SetARCode(&ar);
SetQWidgetWindowDecorations(m_cheat_code_editor);
if (m_cheat_code_editor->exec() == QDialog::Rejected)
return;
@ -275,7 +273,6 @@ void ARCodeWidget::OnCodeEditClicked()
const auto* const selected = items[0];
auto& current_ar = m_ar_codes[m_code_list->row(selected)];
SetQWidgetWindowDecorations(m_cheat_code_editor);
if (current_ar.user_defined)
{

View File

@ -13,7 +13,6 @@
#include "DolphinQt/Config/ControllerInterface/ControllerInterfaceWindow.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/QtUtils/SignalBlocking.h"
#include "DolphinQt/Settings.h"
@ -60,7 +59,6 @@ void CommonControllersWidget::OnControllerInterfaceConfigure()
ControllerInterfaceWindow* window = new ControllerInterfaceWindow(this);
window->setAttribute(Qt::WA_DeleteOnClose, true);
window->setWindowModality(Qt::WindowModality::WindowModal);
SetQWidgetWindowDecorations(window);
window->show();
}

View File

@ -14,7 +14,6 @@
#include "Common/Config/Config.h"
#include "DolphinQt/Config/ControllerInterface/DualShockUDPClientAddServerDialog.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPClient.h"
DualShockUDPClientWidget::DualShockUDPClientWidget()
@ -112,7 +111,6 @@ void DualShockUDPClientWidget::OnServerAdded()
DualShockUDPClientAddServerDialog add_server_dialog(this);
connect(&add_server_dialog, &DualShockUDPClientAddServerDialog::accepted, this,
&DualShockUDPClientWidget::RefreshServerList);
SetQWidgetWindowDecorations(&add_server_dialog);
add_server_dialog.exec();
}

View File

@ -25,7 +25,6 @@
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/ParallelProgressDialog.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Resources.h"
#include "UICommon/UICommon.h"
@ -367,7 +366,6 @@ void FilesystemWidget::ExtractDirectory(const DiscIO::Partition& partition, cons
dialog.Reset();
});
SetQWidgetWindowDecorations(dialog.GetRaw());
dialog.GetRaw()->exec();
future.get();
}

View File

@ -19,7 +19,6 @@
#include "DolphinQt/Config/Mapping/MappingWindow.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipCheckBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
FreeLookWidget::FreeLookWidget(QWidget* parent) : QWidget(parent)
@ -104,7 +103,6 @@ void FreeLookWidget::OnFreeLookControllerConfigured()
MappingWindow* window = new MappingWindow(this, MappingWindow::Type::MAPPING_FREELOOK, index);
window->setAttribute(Qt::WA_DeleteOnClose, true);
window->setWindowModality(Qt::WindowModality::WindowModal);
SetQWidgetWindowDecorations(window);
window->show();
}

View File

@ -24,7 +24,6 @@
#include "DolphinQt/Config/Mapping/GCPadWiiUConfigDialog.h"
#include "DolphinQt/Config/Mapping/MappingWindow.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/QtUtils/SignalBlocking.h"
#include "DolphinQt/Settings.h"
@ -140,7 +139,6 @@ void GamecubeControllersWidget::OnGCPadConfigure(size_t index)
case SerialInterface::SIDEVICE_WIIU_ADAPTER:
{
GCPadWiiUConfigDialog dialog(static_cast<int>(index), this);
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
return;
}
@ -166,7 +164,6 @@ void GamecubeControllersWidget::OnGCPadConfigure(size_t index)
MappingWindow* window = new MappingWindow(this, type, static_cast<int>(index));
window->setAttribute(Qt::WA_DeleteOnClose, true);
window->setWindowModality(Qt::WindowModality::WindowModal);
SetQWidgetWindowDecorations(window);
window->show();
}

View File

@ -30,7 +30,6 @@
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/QtUtils.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/QtUtils/WrapInScrollArea.h"
GeckoCodeWidget::GeckoCodeWidget(std::string game_id, std::string gametdb_id, u16 game_revision,
@ -210,7 +209,6 @@ void GeckoCodeWidget::AddCode()
code.enabled = true;
m_cheat_code_editor->SetGeckoCode(&code);
SetQWidgetWindowDecorations(m_cheat_code_editor);
if (m_cheat_code_editor->exec() == QDialog::Rejected)
return;
@ -228,7 +226,6 @@ void GeckoCodeWidget::EditCode()
const int index = item->data(Qt::UserRole).toInt();
m_cheat_code_editor->SetGeckoCode(&m_gecko_codes[index]);
SetQWidgetWindowDecorations(m_cheat_code_editor);
if (m_cheat_code_editor->exec() == QDialog::Rejected)
return;

View File

@ -25,7 +25,6 @@
#include "DolphinQt/Config/Graphics/PostProcessingConfigWindow.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipPushButton.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
#include "VideoCommon/PostProcessing.h"
@ -629,7 +628,6 @@ void EnhancementsWidget::AddDescriptions()
void EnhancementsWidget::ConfigureColorCorrection()
{
ColorCorrectionConfigWindow dialog(this);
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
}
@ -637,6 +635,5 @@ void EnhancementsWidget::ConfigurePostProcessingShader()
{
const std::string shader = ReadSetting(Config::GFX_ENHANCE_POST_SHADER);
PostProcessingConfigWindow dialog(this, shader);
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
}

View File

@ -27,7 +27,6 @@
#include "DolphinQt/Config/Graphics/GraphicsWindow.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipComboBox.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
#include "VideoCommon/VideoBackendBase.h"
@ -199,7 +198,6 @@ void GeneralWidget::BackendWarning()
confirm_sw.setWindowTitle(tr("Confirm backend change"));
confirm_sw.setText(tr(warningMessage->c_str()));
SetQWidgetWindowDecorations(&confirm_sw);
if (confirm_sw.exec() != QMessageBox::Yes)
{
m_backend_combo->setCurrentIndex(m_previous_backend);

View File

@ -11,7 +11,6 @@
#include "Core/FreeLookManager.h"
#include "DolphinQt/Config/ControllerInterface/ControllerInterfaceWindow.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "InputCommon/InputConfig.h"
FreeLookRotation::FreeLookRotation(MappingWindow* window) : MappingWidget(window)
@ -34,7 +33,6 @@ void FreeLookRotation::CreateMainLayout()
ControllerInterfaceWindow* window = new ControllerInterfaceWindow(this);
window->setAttribute(Qt::WA_DeleteOnClose, true);
window->setWindowModality(Qt::WindowModality::WindowModal);
SetQWidgetWindowDecorations(window);
window->show();
});
m_main_layout->addLayout(alternate_input_layout, 0, 0, 1, -1);

View File

@ -28,7 +28,6 @@
#include "DolphinQt/Config/Mapping/MappingWindow.h"
#include "DolphinQt/QtUtils/BlockUserInputFilter.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
#include "InputCommon/ControlReference/ControlReference.h"
@ -259,8 +258,6 @@ IOWindow::IOWindow(MappingWindow* window, ControllerEmu::EmulatedController* con
: QDialog(window), m_reference(ref), m_original_expression(ref->GetExpression()),
m_controller(controller), m_type(type)
{
SetQWidgetWindowDecorations(this);
CreateMainLayout();
connect(window, &MappingWindow::Update, this, &IOWindow::Update);

View File

@ -18,7 +18,6 @@
#include "DolphinQt/Config/Mapping/MappingIndicator.h"
#include "DolphinQt/Config/Mapping/MappingNumeric.h"
#include "DolphinQt/Config/Mapping/MappingWindow.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "InputCommon/ControllerEmu/Control/Control.h"
#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h"
@ -282,7 +281,6 @@ void MappingWidget::ShowAdvancedControlGroupDialog(ControllerEmu::ControlGroup*
// Enable "Close" button functionality.
connect(button_box, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
}

View File

@ -51,7 +51,6 @@
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/QtUtils.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/QtUtils/WindowActivationEventFilter.h"
#include "DolphinQt/QtUtils/WrapInScrollArea.h"
#include "DolphinQt/Settings.h"
@ -271,7 +270,6 @@ void MappingWindow::OnDeleteProfilePressed()
error.setIcon(QMessageBox::Critical);
error.setWindowTitle(tr("Error"));
error.setText(tr("The profile '%1' does not exist").arg(profile_name));
SetQWidgetWindowDecorations(&error);
error.exec();
return;
}
@ -284,7 +282,6 @@ void MappingWindow::OnDeleteProfilePressed()
confirm.setInformativeText(tr("This cannot be undone!"));
confirm.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
SetQWidgetWindowDecorations(&confirm);
if (confirm.exec() != QMessageBox::Yes)
{
return;
@ -312,7 +309,6 @@ void MappingWindow::OnLoadProfilePressed()
error.setIcon(QMessageBox::Critical);
error.setWindowTitle(tr("Error"));
error.setText(tr("The profile '%1' does not exist").arg(m_profiles_combo->currentText()));
SetQWidgetWindowDecorations(&error);
error.exec();
return;
}

View File

@ -15,7 +15,6 @@
#include "DolphinQt/Config/ControllerInterface/ControllerInterfaceWindow.h"
#include "DolphinQt/QtUtils/QtUtils.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "InputCommon/InputConfig.h"
@ -43,7 +42,6 @@ void WiimoteEmuExtensionMotionInput::CreateNunchukLayout()
warning_layout->addWidget(warning_input_sources_button);
connect(warning_input_sources_button, &QPushButton::clicked, this, [this] {
ControllerInterfaceWindow window{this};
SetQWidgetWindowDecorations(&window);
window.exec();
});
layout->addLayout(warning_layout, 0, 0, 1, -1);

View File

@ -16,7 +16,6 @@
#include "DolphinQt/Config/ControllerInterface/ControllerInterfaceWindow.h"
#include "DolphinQt/QtUtils/QtUtils.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "InputCommon/InputConfig.h"
@ -41,7 +40,6 @@ void WiimoteEmuMotionControlIMU::CreateMainLayout()
warning_layout->addWidget(warning_input_sources_button);
connect(warning_input_sources_button, &QPushButton::clicked, this, [this] {
ControllerInterfaceWindow window{this};
SetQWidgetWindowDecorations(&window);
window.exec();
});

View File

@ -16,7 +16,6 @@
#include "DolphinQt/Config/HardcoreWarningWidget.h"
#include "DolphinQt/Config/NewPatchDialog.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "UICommon/GameFile.h"
@ -94,7 +93,6 @@ void PatchesWidget::OnAdd()
bool new_patch_confirmed = false;
{
NewPatchDialog dialog(this, patch);
SetQWidgetWindowDecorations(&dialog);
new_patch_confirmed = dialog.exec();
}
if (new_patch_confirmed)
@ -124,7 +122,6 @@ void PatchesWidget::OnEdit()
bool new_patch_confirmed = false;
{
NewPatchDialog dialog(this, patch);
SetQWidgetWindowDecorations(&dialog);
new_patch_confirmed = dialog.exec();
}
if (new_patch_confirmed)

View File

@ -21,7 +21,6 @@
#include "DiscIO/Volume.h"
#include "DiscIO/VolumeVerifier.h"
#include "DolphinQt/QtUtils/ParallelProgressDialog.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
VerifyWidget::VerifyWidget(std::shared_ptr<DiscIO::Volume> volume) : m_volume(std::move(volume))
@ -180,7 +179,6 @@ void VerifyWidget::Verify()
progress.Reset();
return verifier.GetResult();
});
SetQWidgetWindowDecorations(progress.GetRaw());
progress.GetRaw()->exec();
std::optional<DiscIO::VolumeVerifier::Result> result = future.get();

View File

@ -37,7 +37,6 @@
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/QueueOnObject.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/QtUtils/SignalBlocking.h"
#include "DolphinQt/Settings.h"
@ -378,7 +377,6 @@ void WiimoteControllersWidget::OnWiimoteConfigure(size_t index)
MappingWindow* window = new MappingWindow(this, type, static_cast<int>(index));
window->setAttribute(Qt::WA_DeleteOnClose, true);
window->setWindowModality(Qt::WindowModality::WindowModal);
SetQWidgetWindowDecorations(window);
window->show();
}

View File

@ -31,7 +31,6 @@
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/ParallelProgressDialog.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "UICommon/GameFile.h"
#include "UICommon/UICommon.h"
@ -283,7 +282,6 @@ bool ConvertDialog::ShowAreYouSureDialog(const QString& text)
warning.setInformativeText(text);
warning.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
SetQWidgetWindowDecorations(&warning);
return warning.exec() == QMessageBox::Yes;
}
@ -408,7 +406,6 @@ void ConvertDialog::Convert()
.arg(dst_info.fileName()));
confirm_replace.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
SetQWidgetWindowDecorations(&confirm_replace);
if (confirm_replace.exec() == QMessageBox::No)
continue;
}
@ -519,7 +516,6 @@ void ConvertDialog::Convert()
break;
}
SetQWidgetWindowDecorations(progress_dialog.GetRaw());
progress_dialog.GetRaw()->exec();
if (!success.get())
{

View File

@ -47,7 +47,6 @@
#include "DolphinQt/Host.h"
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Resources.h"
#include "DolphinQt/Settings.h"

View File

@ -30,7 +30,6 @@
#include "DolphinQt/Debugger/BreakpointDialog.h"
#include "DolphinQt/Debugger/MemoryWidget.h"
#include "DolphinQt/Host.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Resources.h"
#include "DolphinQt/Settings.h"
@ -443,7 +442,6 @@ void BreakpointWidget::OnNewBreakpoint()
{
BreakpointDialog* dialog = new BreakpointDialog(this);
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
SetQWidgetWindowDecorations(dialog);
dialog->exec();
}
@ -454,7 +452,6 @@ void BreakpointWidget::OnEditBreakpoint(u32 address, bool is_instruction_bp)
auto* dialog = new BreakpointDialog(
this, m_system.GetPowerPC().GetBreakPoints().GetRegularBreakpoint(address));
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
SetQWidgetWindowDecorations(dialog);
dialog->exec();
}
else
@ -462,7 +459,6 @@ void BreakpointWidget::OnEditBreakpoint(u32 address, bool is_instruction_bp)
auto* dialog =
new BreakpointDialog(this, m_system.GetPowerPC().GetMemChecks().GetMemCheck(address));
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
SetQWidgetWindowDecorations(dialog);
dialog->exec();
}

View File

@ -40,7 +40,6 @@
#include "DolphinQt/Debugger/PatchInstructionDialog.h"
#include "DolphinQt/Host.h"
#include "DolphinQt/QtUtils/FromStdString.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Resources.h"
#include "DolphinQt/Settings.h"
@ -743,7 +742,6 @@ void CodeViewWidget::AutoStep(CodeTrace::AutoStop option)
.arg(QString::fromStdString(fmt::format("{:#x}", fmt::join(mem_out, ", "))));
msgbox.setInformativeText(msgtext);
SetQWidgetWindowDecorations(&msgbox);
msgbox.exec();
} while (msgbox.clickedButton() == (QAbstractButton*)run_button);
@ -1031,7 +1029,6 @@ void CodeViewWidget::DoPatchInstruction(bool assemble)
if (assemble)
{
AssembleInstructionDialog dialog(this, addr, debug_interface.ReadInstruction(guard, addr));
SetQWidgetWindowDecorations(&dialog);
if (dialog.exec() == QDialog::Accepted)
{
debug_interface.SetPatch(guard, addr, dialog.GetCode());
@ -1041,7 +1038,6 @@ void CodeViewWidget::DoPatchInstruction(bool assemble)
else
{
PatchInstructionDialog dialog(this, addr, debug_interface.ReadInstruction(guard, addr));
SetQWidgetWindowDecorations(&dialog);
if (dialog.exec() == QDialog::Accepted)
{
debug_interface.SetPatch(guard, addr, dialog.GetCode());

View File

@ -29,7 +29,6 @@
#include "Core/System.h"
#include "DolphinQt/Debugger/BranchWatchDialog.h"
#include "DolphinQt/Host.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
static const QString BOX_SPLITTER_STYLESHEET = QStringLiteral(
@ -222,7 +221,6 @@ void CodeWidget::OnBranchWatchDialog()
m_branch_watch_dialog = new BranchWatchDialog(m_system, m_system.GetPowerPC().GetBranchWatch(),
m_ppc_symbol_db, this, this);
}
SetQWidgetWindowDecorations(m_branch_watch_dialog);
m_branch_watch_dialog->show();
m_branch_watch_dialog->raise();
m_branch_watch_dialog->activateWindow();

View File

@ -18,7 +18,6 @@
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
#include "DolphinQt/Host.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
RegisterWidget::RegisterWidget(QWidget* parent)
@ -309,7 +308,6 @@ void RegisterWidget::AutoStep(const std::string& reg) const
break;
// Can keep running and try again after a time out.
SetQWidgetWindowDecorations(&msgbox);
msgbox.exec();
if (msgbox.clickedButton() != (QAbstractButton*)run_button)
break;

View File

@ -16,7 +16,6 @@
#include "DolphinQt/DiscordJoinRequestDialog.h"
#include "DolphinQt/QtUtils/RunOnObject.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
DiscordHandler::DiscordHandler(QWidget* parent) : QObject{parent}, m_parent{parent}
{
@ -61,7 +60,6 @@ void DiscordHandler::ShowNewJoinRequest(const std::string& id, const std::string
std::lock_guard<std::mutex> lock(m_request_dialogs_mutex);
m_request_dialogs.emplace_front(m_parent, id, discord_tag, avatar);
DiscordJoinRequestDialog& request_dialog = m_request_dialogs.front();
SetQWidgetWindowDecorations(&request_dialog);
request_dialog.show();
request_dialog.raise();
request_dialog.activateWindow();

View File

@ -29,7 +29,6 @@
#include "Core/System.h"
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Resources.h"
#include "DolphinQt/Settings.h"
#include "DolphinQt/Settings/GameCubePane.h"
@ -492,7 +491,6 @@ void GBAWidget::contextMenuEvent(QContextMenuEvent* event)
size_menu->addAction(x4_action);
menu->move(event->globalPos());
SetQWidgetWindowDecorations(menu);
menu->show();
}

View File

@ -42,7 +42,6 @@
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
using namespace ExpansionInterface;
@ -695,7 +694,6 @@ void GCMemcardManager::FixChecksums()
void GCMemcardManager::CreateNewCard(Slot slot)
{
GCMemcardCreateNewDialog dialog(this);
SetQWidgetWindowDecorations(&dialog);
if (dialog.exec() == QDialog::Accepted)
m_slot_file_edit[slot]->setText(QString::fromStdString(dialog.GetMemoryCardPath()));
}

View File

@ -67,7 +67,6 @@
#include "DolphinQt/QtUtils/DoubleClickEventFilter.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/ParallelProgressDialog.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Resources.h"
#include "DolphinQt/Settings.h"
#include "DolphinQt/WiiUpdate.h"
@ -588,7 +587,6 @@ void GameList::OpenProperties()
&GameList::OpenAchievementSettings);
#endif // USE_RETRO_ACHIEVEMENTS
SetQWidgetWindowDecorations(properties);
properties->show();
}
@ -643,7 +641,6 @@ void GameList::ConvertFile()
return;
ConvertDialog dialog{std::move(games), this};
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
}
@ -661,7 +658,6 @@ void GameList::InstallWAD()
result_dialog.setWindowTitle(success ? tr("Success") : tr("Failure"));
result_dialog.setText(success ? tr("Successfully installed this title to the NAND.") :
tr("Failed to install this title to the NAND."));
SetQWidgetWindowDecorations(&result_dialog);
result_dialog.exec();
}
@ -679,7 +675,6 @@ void GameList::UninstallWAD()
"this title from the NAND without deleting its save data. Continue?"));
warning_dialog.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
SetQWidgetWindowDecorations(&warning_dialog);
if (warning_dialog.exec() == QMessageBox::No)
return;
@ -691,7 +686,6 @@ void GameList::UninstallWAD()
result_dialog.setWindowTitle(success ? tr("Success") : tr("Failure"));
result_dialog.setText(success ? tr("Successfully removed this title from the NAND.") :
tr("Failed to remove this title from the NAND."));
SetQWidgetWindowDecorations(&result_dialog);
result_dialog.exec();
}
@ -860,7 +854,6 @@ void GameList::DeleteFile()
confirm_dialog.setInformativeText(tr("This cannot be undone!"));
confirm_dialog.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
SetQWidgetWindowDecorations(&confirm_dialog);
if (confirm_dialog.exec() == QMessageBox::Yes)
{
for (const auto& game : GetSelectedGames())
@ -886,7 +879,6 @@ void GameList::DeleteFile()
"delete the file or whether it's still in use."));
error_dialog.setStandardButtons(QMessageBox::Retry | QMessageBox::Abort);
SetQWidgetWindowDecorations(&error_dialog);
if (error_dialog.exec() == QMessageBox::Abort)
break;
}

View File

@ -26,7 +26,6 @@
#include "Core/System.h"
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Resources.h"
#include "DolphinQt/Settings.h"
@ -159,7 +158,6 @@ void InfinityBaseWindow::LoadFigure(FigureUIPosition slot)
void InfinityBaseWindow::CreateFigure(FigureUIPosition slot)
{
CreateFigureDialog create_dlg(this, slot);
SetQWidgetWindowDecorations(&create_dlg);
if (create_dlg.exec() == CreateFigureDialog::Accepted)
{
LoadFigurePath(slot, create_dlg.GetFilePath());

View File

@ -92,7 +92,6 @@ static bool QtMsgAlertHandler(const char* caption, const char* text, bool yes_no
return QMessageBox::NoIcon;
}());
SetQWidgetWindowDecorations(&message_box);
const int button = message_box.exec();
if (button == QMessageBox::Yes)
return true;
@ -170,6 +169,8 @@ int main(int argc, char* argv[])
const std::vector<std::string> args = parser->args();
#ifdef _WIN32
QtUtils::InstallWindowDecorationFilter(&app);
FreeConsole();
#endif
@ -281,7 +282,6 @@ int main(int argc, char* argv[])
"This authorization can be revoked at any time through Dolphin's "
"settings."));
SetQWidgetWindowDecorations(&analytics_prompt);
const int answer = analytics_prompt.exec();
Config::SetBase(Config::MAIN_ANALYTICS_PERMISSION_ASKED, true);

View File

@ -112,7 +112,6 @@
#include "DolphinQt/QtUtils/ParallelProgressDialog.h"
#include "DolphinQt/QtUtils/QueueOnObject.h"
#include "DolphinQt/QtUtils/RunOnObject.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/QtUtils/WindowActivationEventFilter.h"
#include "DolphinQt/RenderWidget.h"
#include "DolphinQt/ResourcePackManager.h"
@ -243,7 +242,6 @@ MainWindow::MainWindow(Core::System& system, std::unique_ptr<BootParameters> boo
restoreGeometry(settings.value(QStringLiteral("mainwindow/geometry")).toByteArray());
if (!Settings::Instance().IsBatchModeEnabled())
{
SetQWidgetWindowDecorations(this);
show();
}
@ -1299,7 +1297,6 @@ void MainWindow::ShowFreeLookWindow()
#endif // USE_RETRO_ACHIEVEMENTS
}
SetQWidgetWindowDecorations(m_freelook_window);
m_freelook_window->show();
m_freelook_window->raise();
m_freelook_window->activateWindow();
@ -1313,7 +1310,6 @@ void MainWindow::ShowSettingsWindow()
InstallHotkeyFilter(m_settings_window);
}
SetQWidgetWindowDecorations(m_settings_window);
m_settings_window->show();
m_settings_window->raise();
m_settings_window->activateWindow();
@ -1334,7 +1330,6 @@ void MainWindow::ShowGeneralWindow()
void MainWindow::ShowAboutDialog()
{
AboutDialog about{this};
SetQWidgetWindowDecorations(&about);
about.exec();
}
@ -1346,7 +1341,6 @@ void MainWindow::ShowHotkeyDialog()
InstallHotkeyFilter(m_hotkey_window);
}
SetQWidgetWindowDecorations(m_hotkey_window);
m_hotkey_window->show();
m_hotkey_window->raise();
m_hotkey_window->activateWindow();
@ -1369,7 +1363,6 @@ void MainWindow::ShowGraphicsWindow()
InstallHotkeyFilter(m_graphics_window);
}
SetQWidgetWindowDecorations(m_graphics_window);
m_graphics_window->show();
m_graphics_window->raise();
m_graphics_window->activateWindow();
@ -1377,7 +1370,6 @@ void MainWindow::ShowGraphicsWindow()
void MainWindow::ShowNetPlaySetupDialog()
{
SetQWidgetWindowDecorations(m_netplay_setup_dialog);
m_netplay_setup_dialog->show();
m_netplay_setup_dialog->raise();
m_netplay_setup_dialog->activateWindow();
@ -1388,7 +1380,6 @@ void MainWindow::ShowNetPlayBrowser()
auto* browser = new NetPlayBrowser(this);
browser->setAttribute(Qt::WA_DeleteOnClose, true);
connect(browser, &NetPlayBrowser::Join, this, &MainWindow::NetPlayJoin);
SetQWidgetWindowDecorations(browser);
browser->exec();
}
@ -1401,7 +1392,6 @@ void MainWindow::ShowFIFOPlayer()
[this](const QString& path) { StartGame(path, ScanForSecondDisc::No); });
}
SetQWidgetWindowDecorations(m_fifo_window);
m_fifo_window->show();
m_fifo_window->raise();
m_fifo_window->activateWindow();
@ -1414,7 +1404,6 @@ void MainWindow::ShowSkylanderPortal()
m_skylander_window = new SkylanderPortalWindow();
}
SetQWidgetWindowDecorations(m_skylander_window);
m_skylander_window->show();
m_skylander_window->raise();
m_skylander_window->activateWindow();
@ -1427,7 +1416,6 @@ void MainWindow::ShowInfinityBase()
m_infinity_window = new InfinityBaseWindow();
}
SetQWidgetWindowDecorations(m_infinity_window);
m_infinity_window->show();
m_infinity_window->raise();
m_infinity_window->activateWindow();
@ -1852,7 +1840,6 @@ void MainWindow::OnImportNANDBackup()
dialog.Reset();
});
SetQWidgetWindowDecorations(dialog.GetRaw());
dialog.GetRaw()->exec();
result.wait();
@ -1966,7 +1953,6 @@ void MainWindow::ShowTASInput()
const auto si_device = Config::Get(Config::GetInfoForSIDevice(i));
if (si_device == SerialInterface::SIDEVICE_GC_GBA_EMULATED)
{
SetQWidgetWindowDecorations(m_gba_tas_input_windows[i]);
m_gba_tas_input_windows[i]->show();
m_gba_tas_input_windows[i]->raise();
m_gba_tas_input_windows[i]->activateWindow();
@ -1974,7 +1960,6 @@ void MainWindow::ShowTASInput()
else if (si_device != SerialInterface::SIDEVICE_NONE &&
si_device != SerialInterface::SIDEVICE_GC_GBA)
{
SetQWidgetWindowDecorations(m_gc_tas_input_windows[i]);
m_gc_tas_input_windows[i]->show();
m_gc_tas_input_windows[i]->raise();
m_gc_tas_input_windows[i]->activateWindow();
@ -1986,7 +1971,6 @@ void MainWindow::ShowTASInput()
if (Config::Get(Config::GetInfoForWiimoteSource(i)) == WiimoteSource::Emulated &&
(!Core::IsRunning(m_system) || m_system.IsWii()))
{
SetQWidgetWindowDecorations(m_wii_tas_input_windows[i]);
m_wii_tas_input_windows[i]->show();
m_wii_tas_input_windows[i]->raise();
m_wii_tas_input_windows[i]->activateWindow();
@ -2012,7 +1996,6 @@ void MainWindow::ShowAchievementsWindow()
m_achievements_window = new AchievementsWindow(this);
}
SetQWidgetWindowDecorations(m_achievements_window);
m_achievements_window->show();
m_achievements_window->raise();
m_achievements_window->activateWindow();
@ -2037,7 +2020,6 @@ void MainWindow::ShowMemcardManager()
{
GCMemcardManager manager(this);
SetQWidgetWindowDecorations(&manager);
manager.exec();
}
@ -2045,13 +2027,11 @@ void MainWindow::ShowResourcePackManager()
{
ResourcePackManager manager(this);
SetQWidgetWindowDecorations(&manager);
manager.exec();
}
void MainWindow::ShowCheatsManager()
{
SetQWidgetWindowDecorations(m_cheats_manager);
m_cheats_manager->show();
}
@ -2070,7 +2050,6 @@ void MainWindow::ShowRiivolutionBootWidget(const UICommon::GameFile& game)
auto& disc = std::get<BootParameters::Disc>(boot_params->parameters);
RiivolutionBootWidget w(disc.volume->GetGameID(), disc.volume->GetRevision(),
disc.volume->GetDiscNumber(), game.GetFilePath(), this);
SetQWidgetWindowDecorations(&w);
#ifdef USE_RETRO_ACHIEVEMENTS
connect(&w, &RiivolutionBootWidget::OpenAchievementSettings, this,

View File

@ -67,7 +67,6 @@
#include "DolphinQt/QtUtils/NonAutodismissibleMenu.h"
#include "DolphinQt/QtUtils/ParallelProgressDialog.h"
#include "DolphinQt/QtUtils/QueueOnObject.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
#include "DolphinQt/Updater.h"
@ -1393,7 +1392,6 @@ void MenuBar::CheckNAND()
{
NANDRepairDialog dialog(result, this);
SetQWidgetWindowDecorations(&dialog);
if (dialog.exec() != QDialog::Accepted)
return;
}
@ -1564,7 +1562,6 @@ void MenuBar::GenerateSymbolsFromRSOAuto()
return matches;
});
SetQWidgetWindowDecorations(progress.GetRaw());
progress.GetRaw()->exec();
const auto matches = future.get();

View File

@ -14,7 +14,6 @@
#include "Common/Config/Config.h"
#include "Core/Config/MainSettings.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Resources.h"
bool NKitWarningDialog::ShowUnlessDisabled(QWidget* parent)
@ -23,7 +22,6 @@ bool NKitWarningDialog::ShowUnlessDisabled(QWidget* parent)
return true;
NKitWarningDialog dialog(parent);
SetQWidgetWindowDecorations(&dialog);
return dialog.exec() == QDialog::Accepted;
}

View File

@ -26,7 +26,6 @@
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
NetPlayBrowser::NetPlayBrowser(QWidget* parent) : QDialog(parent)
@ -301,7 +300,6 @@ void NetPlayBrowser::accept()
dialog.setWindowModality(Qt::WindowModal);
dialog.setTextEchoMode(QLineEdit::Password);
SetQWidgetWindowDecorations(&dialog);
if (dialog.exec() != QDialog::Accepted)
return;

View File

@ -54,7 +54,6 @@
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/QueueOnObject.h"
#include "DolphinQt/QtUtils/RunOnObject.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Resources.h"
#include "DolphinQt/Settings.h"
#include "DolphinQt/Settings/GameCubePane.h"
@ -215,7 +214,6 @@ void NetPlayDialog::CreateMainLayout()
m_game_digest_menu->addAction(tr("Other game..."), this, [this] {
GameListDialog gld(m_game_list_model, this);
SetQWidgetWindowDecorations(&gld);
if (gld.exec() != QDialog::Accepted)
return;
Settings::Instance().GetNetPlayServer()->ComputeGameDigest(
@ -337,7 +335,6 @@ void NetPlayDialog::ConnectWidgets()
Settings::Instance().GetNetPlayServer()->KickPlayer(id);
});
connect(m_assign_ports_button, &QPushButton::clicked, [this] {
SetQWidgetWindowDecorations(m_pad_mapping);
m_pad_mapping->exec();
Settings::Instance().GetNetPlayServer()->SetPadMapping(m_pad_mapping->GetGCPadArray());
@ -383,7 +380,6 @@ void NetPlayDialog::ConnectWidgets()
connect(m_game_button, &QPushButton::clicked, [this] {
GameListDialog gld(m_game_list_model, this);
SetQWidgetWindowDecorations(&gld);
if (gld.exec() == QDialog::Accepted)
{
Settings& settings = Settings::Instance();

View File

@ -5,8 +5,6 @@
#include <QApplication>
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
ModalMessageBox::ModalMessageBox(QWidget* parent, Qt::WindowModality modality)
: QMessageBox(parent != nullptr ? parent->window() : nullptr)
{
@ -31,7 +29,6 @@ static inline int ExecMessageBox(ModalMessageBox::Icon icon, QWidget* parent, co
msg.setDefaultButton(default_button);
msg.setDetailedText(detailed_text);
SetQWidgetWindowDecorations(&msg);
return msg.exec();
}

View File

@ -1,25 +1,81 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#if defined(_WIN32)
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include <QApplication>
#include <QEvent>
#include <QWidget>
#include <dwmapi.h>
#include "DolphinQt/Settings.h"
#ifdef _WIN32
#include <dwmapi.h>
#endif
namespace
{
void SetQWidgetWindowDecorations(QWidget* widget)
{
#ifdef _WIN32
if (!Settings::Instance().IsThemeDark())
return;
BOOL use_dark_title_bar = TRUE;
DwmSetWindowAttribute(HWND(widget->winId()),
20 /* DWMWINDOWATTRIBUTE::DWMWA_USE_IMMERSIVE_DARK_MODE */,
&use_dark_title_bar, DWORD(sizeof(use_dark_title_bar)));
#endif
constexpr DWORD attribute = 20; // DWMWINDOWATTRIBUTE::DWMWA_USE_IMMERSIVE_DARK_MODE
constexpr BOOL use_dark_title_bar = TRUE;
DwmSetWindowAttribute(HWND(widget->winId()), attribute, &use_dark_title_bar,
DWORD(sizeof(use_dark_title_bar)));
}
class WindowDecorationFilter final : public QObject
{
public:
using QObject::QObject;
bool eventFilter(QObject* obj, QEvent* event) override
{
if (event->type() == QEvent::Show || event->type() == QEvent::ApplicationPaletteChange)
{
SetQWidgetWindowDecorations(static_cast<QWidget*>(obj));
}
return QObject::eventFilter(obj, event);
}
};
class WindowDecorationFilterInstaller final : public QObject
{
public:
using QObject::QObject;
bool eventFilter(QObject* obj, QEvent* event) override
{
if (event->type() == QEvent::WinIdChange)
{
auto* const widget = qobject_cast<QWidget*>(obj);
// Install the real filter on actual Window QWidgets.
// This avoids the need for a qobject_cast on literally every QEvent::Show.
if (widget && widget->isWindow())
widget->installEventFilter(m_decoration_filter);
}
return QObject::eventFilter(obj, event);
}
private:
QObject* const m_decoration_filter = new WindowDecorationFilter{this};
};
} // namespace
namespace QtUtils
{
void InstallWindowDecorationFilter(QApplication* app)
{
app->installEventFilter(new WindowDecorationFilterInstaller{app});
}
} // namespace QtUtils
#endif

View File

@ -3,7 +3,14 @@
#pragma once
class QWidget;
#if defined(_WIN32)
// Changes the window decorations (title bar) to dark if the user uses dark mode on Windows.
void SetQWidgetWindowDecorations(QWidget* widget);
class QApplication;
namespace QtUtils
{
// Changes the window decorations (title bar) for Windows "Dark" mode or "Dark" Dolphin Style.
void InstallWindowDecorationFilter(QApplication*);
} // namespace QtUtils
#endif

View File

@ -14,7 +14,6 @@
#include "Common/FileUtil.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "UICommon/ResourcePack/Manager.h"
ResourcePackManager::ResourcePackManager(QWidget* widget) : QDialog(widget)
@ -241,7 +240,6 @@ void ResourcePackManager::Remove()
box.setIcon(QMessageBox::Warning);
box.setStandardButtons(QMessageBox::Yes | QMessageBox::Abort);
SetQWidgetWindowDecorations(&box);
if (box.exec() != QMessageBox::Yes)
return;

View File

@ -39,7 +39,6 @@
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/QtUtils/SignalBlocking.h"
#include "DolphinQt/Settings.h"
#include "DolphinQt/Settings/BroadbandAdapterSettingsDialog.h"
@ -381,28 +380,24 @@ void GameCubePane::OnConfigPressed(ExpansionInterface::Slot slot)
{
// TODO: convert MappingWindow to use Slot?
MappingWindow dialog(this, MappingWindow::Type::MAPPING_GC_MICROPHONE, static_cast<int>(slot));
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
return;
}
case ExpansionInterface::EXIDeviceType::Ethernet:
{
BroadbandAdapterSettingsDialog dialog(this, BroadbandAdapterSettingsDialog::Type::Ethernet);
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
return;
}
case ExpansionInterface::EXIDeviceType::EthernetXLink:
{
BroadbandAdapterSettingsDialog dialog(this, BroadbandAdapterSettingsDialog::Type::XLinkKai);
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
return;
}
case ExpansionInterface::EXIDeviceType::EthernetTapServer:
{
BroadbandAdapterSettingsDialog dialog(this, BroadbandAdapterSettingsDialog::Type::TapServer);
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
return;
}
@ -410,14 +405,12 @@ void GameCubePane::OnConfigPressed(ExpansionInterface::Slot slot)
{
BroadbandAdapterSettingsDialog dialog(this,
BroadbandAdapterSettingsDialog::Type::ModemTapServer);
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
return;
}
case ExpansionInterface::EXIDeviceType::EthernetBuiltIn:
{
BroadbandAdapterSettingsDialog dialog(this, BroadbandAdapterSettingsDialog::Type::BuiltIn);
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
return;
}

View File

@ -29,7 +29,6 @@
#include "DolphinQt/Config/ToolTipControls/ToolTipComboBox.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipPushButton.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/QtUtils/SignalBlocking.h"
#include "DolphinQt/Settings.h"
@ -361,7 +360,6 @@ void GeneralPane::GenerateNewIdentity()
message_box.setIcon(QMessageBox::Information);
message_box.setWindowTitle(tr("Identity Generation"));
message_box.setText(tr("New identity generated."));
SetQWidgetWindowDecorations(&message_box);
message_box.exec();
}
#endif

View File

@ -36,7 +36,6 @@
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
#include "DolphinQt/QtUtils/ParallelProgressDialog.h"
#include "DolphinQt/QtUtils/QtUtils.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/QtUtils/SignalBlocking.h"
#include "DolphinQt/Settings.h"
#include "DolphinQt/Settings/USBDeviceAddToWhitelistDialog.h"
@ -284,7 +283,6 @@ void WiiPane::CreateSDCard()
progress_dialog.Reset();
return good;
});
SetQWidgetWindowDecorations(progress_dialog.GetRaw());
progress_dialog.GetRaw()->exec();
if (!success.get())
ModalMessageBox::warning(this, tr(Common::SD_PACK_TEXT), tr("Conversion failed."));
@ -309,7 +307,6 @@ void WiiPane::CreateSDCard()
progress_dialog.Reset();
return good;
});
SetQWidgetWindowDecorations(progress_dialog.GetRaw());
progress_dialog.GetRaw()->exec();
if (!success.get())
ModalMessageBox::warning(this, tr(Common::SD_UNPACK_TEXT), tr("Conversion failed."));
@ -467,7 +464,6 @@ void WiiPane::OnUSBWhitelistAddButton()
USBDeviceAddToWhitelistDialog usb_whitelist_dialog(this);
connect(&usb_whitelist_dialog, &USBDeviceAddToWhitelistDialog::accepted, this,
&WiiPane::PopulateUSBPassthroughListWidget);
SetQWidgetWindowDecorations(&usb_whitelist_dialog);
usb_whitelist_dialog.exec();
}

View File

@ -18,7 +18,6 @@
#include "Core/System.h"
#include "DolphinQt/QtUtils/QtUtils.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
SkylanderModifyDialog::SkylanderModifyDialog(QWidget* parent, u8 slot)
: QDialog(parent), m_slot(slot)
@ -107,8 +106,6 @@ SkylanderModifyDialog::SkylanderModifyDialog(QWidget* parent, u8 slot)
this->setLayout(layout);
SetQWidgetWindowDecorations(this);
if (should_show)
{
this->show();

View File

@ -35,7 +35,6 @@
#include "Core/System.h"
#include "DolphinQt/QtUtils/DolphinFileDialog.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Resources.h"
#include "DolphinQt/Settings.h"
#include "SkylanderModifyDialog.h"
@ -635,7 +634,6 @@ void SkylanderPortalWindow::CreateSkylanderAdvanced()
connect(buttons, &QDialogButtonBox::rejected, create_window, &QDialog::reject);
SetQWidgetWindowDecorations(create_window);
create_window->show();
create_window->raise();
}

View File

@ -29,7 +29,6 @@
#include "DolphinQt/QtUtils/AspectRatioWidget.h"
#include "DolphinQt/QtUtils/QueueOnObject.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/TAS/IRWidget.h"
#include "DolphinQt/TAS/TASCheckBox.h"
#include "DolphinQt/TAS/TASSpinBox.h"
@ -435,21 +434,15 @@ void WiiTASInputWindow::UpdateControlVisibility()
if (m_active_extension == WiimoteEmu::ExtensionNumber::NUNCHUK)
{
setWindowTitle(tr("Wii TAS Input %1 - Wii Remote + Nunchuk").arg(m_num + 1));
SetQWidgetWindowDecorations(m_ir_box);
m_ir_box->show();
SetQWidgetWindowDecorations(m_nunchuk_stick_box);
m_nunchuk_stick_box->show();
m_classic_right_stick_box->hide();
m_classic_left_stick_box->hide();
SetQWidgetWindowDecorations(m_remote_accelerometer_box);
m_remote_accelerometer_box->show();
m_remote_gyroscope_box->setVisible(m_is_motion_plus_attached);
SetQWidgetWindowDecorations(m_nunchuk_accelerometer_box);
m_nunchuk_accelerometer_box->show();
m_triggers_box->hide();
SetQWidgetWindowDecorations(m_nunchuk_buttons_box);
m_nunchuk_buttons_box->show();
SetQWidgetWindowDecorations(m_remote_buttons_box);
m_remote_buttons_box->show();
m_classic_buttons_box->hide();
}
@ -458,18 +451,14 @@ void WiiTASInputWindow::UpdateControlVisibility()
setWindowTitle(tr("Wii TAS Input %1 - Classic Controller").arg(m_num + 1));
m_ir_box->hide();
m_nunchuk_stick_box->hide();
SetQWidgetWindowDecorations(m_classic_right_stick_box);
m_classic_right_stick_box->show();
SetQWidgetWindowDecorations(m_classic_left_stick_box);
m_classic_left_stick_box->show();
m_remote_accelerometer_box->hide();
m_remote_gyroscope_box->hide();
m_nunchuk_accelerometer_box->hide();
SetQWidgetWindowDecorations(m_triggers_box);
m_triggers_box->show();
m_remote_buttons_box->hide();
m_nunchuk_buttons_box->hide();
SetQWidgetWindowDecorations(m_classic_buttons_box);
m_classic_buttons_box->show();
}
else
@ -479,12 +468,10 @@ void WiiTASInputWindow::UpdateControlVisibility()
m_nunchuk_stick_box->hide();
m_classic_right_stick_box->hide();
m_classic_left_stick_box->hide();
SetQWidgetWindowDecorations(m_remote_accelerometer_box);
m_remote_accelerometer_box->show();
m_remote_gyroscope_box->setVisible(m_is_motion_plus_attached);
m_nunchuk_accelerometer_box->hide();
m_triggers_box->hide();
SetQWidgetWindowDecorations(m_remote_buttons_box);
m_remote_buttons_box->show();
m_nunchuk_buttons_box->hide();
m_classic_buttons_box->hide();

View File

@ -17,7 +17,6 @@
#include "Common/Version.h"
#include "DolphinQt/QtUtils/RunOnObject.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
#include "DolphinQt/Settings.h"
// Refer to docs/autoupdate_overview.md for a detailed overview of the autoupdate process
@ -101,7 +100,6 @@ void Updater::OnUpdateAvailable(const NewVersionInformation& info)
connect(buttons, &QDialogButtonBox::accepted, dialog, &QDialog::accept);
connect(buttons, &QDialogButtonBox::rejected, dialog, &QDialog::reject);
SetQWidgetWindowDecorations(dialog);
return dialog->exec();
});

View File

@ -21,7 +21,6 @@
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/QueueOnObject.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
namespace WiiUpdate
{
@ -130,7 +129,6 @@ static WiiUtils::UpdateResult ShowProgress(QWidget* parent, Callable function, A
return res;
});
SetQWidgetWindowDecorations(&dialog);
dialog.exec();
return result.get();
}

View File

@ -180,8 +180,8 @@ if(ENABLE_SDL)
ControllerInterface/SDL/SDLGamepad.cpp
ControllerInterface/SDL/SDLGamepad.h
)
target_link_libraries(inputcommon PRIVATE SDL2::SDL2)
target_compile_definitions(inputcommon PUBLIC HAVE_SDL2=1)
target_link_libraries(inputcommon PRIVATE SDL3::SDL3)
target_compile_definitions(inputcommon PUBLIC HAVE_SDL3=1)
endif()
if(MSVC)

View File

@ -31,7 +31,7 @@
#define CIFACE_USE_PIPES
#endif
#define CIFACE_USE_DUALSHOCKUDPCLIENT
#if defined(HAVE_SDL2)
#if defined(HAVE_SDL3)
#define CIFACE_USE_SDL
#endif
#if defined(HAVE_HIDAPI)

View File

@ -3,6 +3,7 @@
#include "InputCommon/ControllerInterface/SDL/SDL.h"
#include <span>
#include <thread>
#include <vector>
@ -10,7 +11,7 @@
#include <Windows.h>
#endif
#include <SDL.h>
#include <SDL3/SDL.h>
#include "Common/Event.h"
#include "Common/Logging/Log.h"
@ -31,7 +32,7 @@ public:
void UpdateInput(std::vector<std::weak_ptr<ciface::Core::Device>>& devices_to_remove) override;
private:
void OpenAndAddDevice(int index);
void OpenAndAddDevice(SDL_JoystickID instance_id);
bool HandleEventAndContinue(const SDL_Event& e);
@ -48,10 +49,10 @@ std::unique_ptr<ciface::InputBackend> CreateInputBackend(ControllerInterface* co
static void EnableSDLLogging()
{
SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE);
SDL_LogSetOutputFunction(
SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE);
SDL_SetLogOutputFunction(
[](void*, int category, SDL_LogPriority priority, const char* message) {
std::string category_name;
std::string_view category_name{};
switch (category)
{
case SDL_LOG_CATEGORY_APPLICATION:
@ -81,8 +82,10 @@ static void EnableSDLLogging()
case SDL_LOG_CATEGORY_TEST:
category_name = "test";
break;
case SDL_LOG_CATEGORY_GPU:
category_name = "gpu";
break;
default:
category_name = fmt::format("unknown({})", category);
break;
}
@ -108,8 +111,16 @@ static void EnableSDLLogging()
break;
}
GENERIC_LOG_FMT(Common::Log::LogType::CONTROLLERINTERFACE, log_level, "{}: {}",
category_name, message);
if (category_name.empty())
{
GENERIC_LOG_FMT(Common::Log::LogType::CONTROLLERINTERFACE, log_level, "unknown({}): {}",
category, message);
}
else
{
GENERIC_LOG_FMT(Common::Log::LogType::CONTROLLERINTERFACE, log_level, "{}: {}",
category_name, message);
}
},
nullptr);
}
@ -122,9 +133,8 @@ InputBackend::InputBackend(ControllerInterface* controller_interface)
// This is required on windows so that SDL's joystick code properly pumps window messages
SDL_SetHint(SDL_HINT_JOYSTICK_THREAD, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1");
// We want buttons to come in as positions, not labels
SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0");
SDL_SetHint(SDL_HINT_JOYSTICK_ENHANCED_REPORTS, "1");
// We have our own WGI backend. Enabling SDL's WGI handling creates even more redundant devices.
SDL_SetHint(SDL_HINT_JOYSTICK_WGI, "0");
@ -139,7 +149,7 @@ InputBackend::InputBackend(ControllerInterface* controller_interface)
{
Common::ScopeGuard init_guard([this] { m_init_event.Set(); });
if (SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER) != 0)
if (!SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMEPAD))
{
ERROR_LOG_FMT(CONTROLLERINTERFACE, "SDL failed to initialize");
return;
@ -160,7 +170,7 @@ InputBackend::InputBackend(ControllerInterface* controller_interface)
// duplicate devices. Adding devices will actually "fail" here, as the ControllerInterface
// hasn't finished initializing yet.
SDL_Event e;
while (SDL_PollEvent(&e) != 0)
while (SDL_PollEvent(&e))
{
if (!HandleEventAndContinue(e))
return;
@ -179,7 +189,7 @@ InputBackend::InputBackend(ControllerInterface* controller_interface)
#endif
SDL_Event e;
while (SDL_WaitEvent(&e) != 0)
while (SDL_WaitEvent(&e))
{
if (!HandleEventAndContinue(e))
return;
@ -221,20 +231,20 @@ void InputBackend::PopulateDevices()
SDL_PushEvent(&populate_event);
}
void InputBackend::UpdateInput(std::vector<std::weak_ptr<ciface::Core::Device>>& devices_to_remove)
void InputBackend::UpdateInput(std::vector<std::weak_ptr<ciface::Core::Device>>&)
{
SDL_GameControllerUpdate();
SDL_UpdateGamepads();
}
void InputBackend::OpenAndAddDevice(int index)
void InputBackend::OpenAndAddDevice(SDL_JoystickID instance_id)
{
SDL_GameController* gc = SDL_GameControllerOpen(index);
SDL_Joystick* js = SDL_JoystickOpen(index);
SDL_Gamepad* gc = SDL_OpenGamepad(instance_id);
SDL_Joystick* js = SDL_OpenJoystick(instance_id);
if (js)
if (js != nullptr)
{
if (SDL_JoystickNumButtons(js) > 255 || SDL_JoystickNumAxes(js) > 255 ||
SDL_JoystickNumHats(js) > 255 || SDL_JoystickNumBalls(js) > 255)
if (SDL_GetNumJoystickButtons(js) > 255 || SDL_GetNumJoystickAxes(js) > 255 ||
SDL_GetNumJoystickHats(js) > 255 || SDL_GetNumJoystickBalls(js) > 255)
{
// This device is invalid, don't use it
// Some crazy devices (HP webcam 2100) end up as HID devices
@ -249,17 +259,12 @@ void InputBackend::OpenAndAddDevice(int index)
bool InputBackend::HandleEventAndContinue(const SDL_Event& e)
{
if (e.type == SDL_JOYDEVICEADDED)
if (e.type == SDL_EVENT_JOYSTICK_ADDED)
{
// NOTE: SDL_JOYDEVICEADDED's `jdevice.which` is a device index in SDL2.
// It will change to an "instance ID" in SDL3.
// OpenAndAddDevice impl and calls will need refactoring when changing to SDL3.
static_assert(!SDL_VERSION_ATLEAST(3, 0, 0), "Refactoring is needed for SDL3.");
OpenAndAddDevice(e.jdevice.which);
}
else if (e.type == SDL_JOYDEVICEREMOVED)
else if (e.type == SDL_EVENT_JOYSTICK_REMOVED)
{
// NOTE: SDL_JOYDEVICEREMOVED's `jdevice.which` is an "instance ID".
GetControllerInterface().RemoveDevice([&e](const auto* device) {
return device->GetSource() == "SDL" &&
static_cast<const GameController*>(device)->GetSDLInstanceID() == e.jdevice.which;
@ -268,8 +273,12 @@ bool InputBackend::HandleEventAndContinue(const SDL_Event& e)
else if (e.type == m_populate_event_type)
{
GetControllerInterface().PlatformPopulateDevices([this] {
for (int i = 0; i < SDL_NumJoysticks(); ++i)
OpenAndAddDevice(i);
int joystick_count = 0;
auto* const joystick_ids = SDL_GetJoysticks(&joystick_count);
for (auto instance_id : std::span(joystick_ids, joystick_count))
OpenAndAddDevice(instance_id);
SDL_free(joystick_ids);
});
}
else if (e.type == m_stop_event_type)

View File

@ -4,9 +4,11 @@
#include "InputCommon/ControllerInterface/SDL/SDLGamepad.h"
#include <array>
#include <span>
#include <unordered_set>
#include "Common/Logging/Log.h"
#include "Common/ScopeGuard.h"
namespace ciface::SDL
{
@ -17,16 +19,12 @@ bool IsTriggerAxis(int index)
return index >= 4;
}
GameController::GameController(SDL_GameController* const gamecontroller,
SDL_Joystick* const joystick)
GameController::GameController(SDL_Gamepad* const gamecontroller, SDL_Joystick* const joystick)
: m_gamecontroller(gamecontroller), m_joystick(joystick)
{
const char* name;
if (gamecontroller)
name = SDL_GameControllerName(gamecontroller);
else
name = SDL_JoystickName(joystick);
m_name = name != nullptr ? name : "Unknown";
const char* const sdl_name = (gamecontroller != nullptr) ? SDL_GetGamepadName(gamecontroller) :
SDL_GetJoystickName(joystick);
m_name = (sdl_name != nullptr) ? sdl_name : "Unknown";
// If a Joystick input has a GameController equivalent button/hat we don't add it.
// "Equivalent" axes are still added as hidden/undetectable inputs to handle
@ -35,17 +33,17 @@ GameController::GameController(SDL_GameController* const gamecontroller,
std::unordered_set<int> registered_buttons;
std::unordered_set<int> registered_hats;
std::unordered_set<int> registered_axes;
const auto register_mapping = [&](const SDL_GameControllerButtonBind& bind) {
switch (bind.bindType)
const auto register_mapping = [&](const SDL_GamepadBinding& bind) {
switch (bind.input_type)
{
case SDL_CONTROLLER_BINDTYPE_BUTTON:
registered_buttons.insert(bind.value.button);
case SDL_GAMEPAD_BINDTYPE_BUTTON:
registered_buttons.insert(bind.input.button);
break;
case SDL_CONTROLLER_BINDTYPE_HAT:
registered_hats.insert(bind.value.hat.hat);
case SDL_GAMEPAD_BINDTYPE_HAT:
registered_hats.insert(bind.input.hat.hat);
break;
case SDL_CONTROLLER_BINDTYPE_AXIS:
registered_axes.insert(bind.value.axis);
case SDL_GAMEPAD_BINDTYPE_AXIS:
registered_axes.insert(bind.input.axis.axis);
break;
default:
break;
@ -55,25 +53,22 @@ GameController::GameController(SDL_GameController* const gamecontroller,
if (gamecontroller != nullptr)
{
// Inputs
int binding_count = 0;
auto** bindings = SDL_GetGamepadBindings(gamecontroller, &binding_count);
Common::ScopeGuard free_bindings([&] { SDL_free(bindings); });
// Buttons
for (u8 i = 0; i != size(s_sdl_button_names); ++i)
for (auto* const binding : std::span(bindings, binding_count))
{
SDL_GameControllerButton button = static_cast<SDL_GameControllerButton>(i);
if (SDL_GameControllerHasButton(m_gamecontroller, button))
{
AddInput(new Button(gamecontroller, button));
register_mapping(*binding);
register_mapping(SDL_GameControllerGetBindForButton(gamecontroller, button));
}
}
// Axes
for (u8 i = 0; i != size(s_sdl_axis_names); ++i)
{
SDL_GameControllerAxis axis = static_cast<SDL_GameControllerAxis>(i);
if (SDL_GameControllerHasAxis(m_gamecontroller, axis))
switch (binding->output_type)
{
case SDL_GAMEPAD_BINDTYPE_BUTTON:
AddInput(new Button(gamecontroller, *binding));
break;
case SDL_GAMEPAD_BINDTYPE_AXIS:
{
const auto axis = binding->output.axis.axis;
if (IsTriggerAxis(axis))
{
AddInput(new Axis(m_gamecontroller, 32767, axis));
@ -84,19 +79,23 @@ GameController::GameController(SDL_GameController* const gamecontroller,
AddInput(new Axis(m_gamecontroller, -32768, axis));
AddInput(new Axis(m_gamecontroller, 32767, axis));
}
register_mapping(SDL_GameControllerGetBindForAxis(gamecontroller, axis));
break;
}
default:
break;
}
}
const auto properties = SDL_GetGamepadProperties(m_gamecontroller);
// Rumble
if (SDL_GameControllerHasRumble(m_gamecontroller))
if (SDL_GetBooleanProperty(properties, SDL_PROP_GAMEPAD_CAP_RUMBLE_BOOLEAN, false))
{
AddOutput(new CombinedMotor(*this, &m_low_freq_rumble, &m_high_freq_rumble));
AddOutput(new Rumble("Motor L", *this, &m_low_freq_rumble, &GameController::UpdateRumble));
AddOutput(new Rumble("Motor R", *this, &m_high_freq_rumble, &GameController::UpdateRumble));
}
if (SDL_GameControllerHasRumbleTriggers(m_gamecontroller))
if (SDL_GetBooleanProperty(properties, SDL_PROP_GAMEPAD_CAP_TRIGGER_RUMBLE_BOOLEAN, false))
{
AddOutput(new Rumble("Trigger L", *this, &m_trigger_l_rumble,
&GameController::UpdateRumbleTriggers));
@ -105,7 +104,7 @@ GameController::GameController(SDL_GameController* const gamecontroller,
}
// Touchpad
if (SDL_GameControllerGetNumTouchpads(m_gamecontroller) > 0)
if (SDL_GetNumGamepadTouchpads(m_gamecontroller) > 0)
{
const char* const name_x = "Touchpad X";
AddInput(new NonDetectableDirectionalInput<-1>(name_x, &m_touchpad_x));
@ -119,7 +118,7 @@ GameController::GameController(SDL_GameController* const gamecontroller,
// Motion
const auto add_sensor = [this](SDL_SensorType type, std::string_view sensor_name,
const SDLMotionAxisList& axes) {
if (SDL_GameControllerSetSensorEnabled(m_gamecontroller, type, SDL_TRUE) == 0)
if (SDL_SetGamepadSensorEnabled(m_gamecontroller, type, true))
{
for (const SDLMotionAxis& axis : axes)
{
@ -140,7 +139,7 @@ GameController::GameController(SDL_GameController* const gamecontroller,
// Legacy inputs
// Buttons
int n_legacy_buttons = SDL_JoystickNumButtons(joystick);
int n_legacy_buttons = SDL_GetNumJoystickButtons(joystick);
if (n_legacy_buttons < 0)
{
ERROR_LOG_FMT(CONTROLLERINTERFACE, "Error in SDL_JoystickNumButtons(): {}", SDL_GetError());
@ -155,7 +154,7 @@ GameController::GameController(SDL_GameController* const gamecontroller,
}
// Axes
int n_legacy_axes = SDL_JoystickNumAxes(joystick);
int n_legacy_axes = SDL_GetNumJoystickAxes(joystick);
if (n_legacy_axes < 0)
{
ERROR_LOG_FMT(CONTROLLERINTERFACE, "Error in SDL_JoystickNumAxes(): {}", SDL_GetError());
@ -171,7 +170,7 @@ GameController::GameController(SDL_GameController* const gamecontroller,
}
// Hats
int n_legacy_hats = SDL_JoystickNumHats(joystick);
int n_legacy_hats = SDL_GetNumJoystickHats(joystick);
if (n_legacy_hats < 0)
{
ERROR_LOG_FMT(CONTROLLERINTERFACE, "Error in SDL_JoystickNumHats(): {}", SDL_GetError());
@ -188,16 +187,16 @@ GameController::GameController(SDL_GameController* const gamecontroller,
}
// Haptics
if (SDL_JoystickIsHaptic(m_joystick))
if (SDL_IsJoystickHaptic(m_joystick))
{
m_haptic = SDL_HapticOpenFromJoystick(m_joystick);
m_haptic = SDL_OpenHapticFromJoystick(m_joystick);
if (m_haptic)
{
const unsigned int supported_effects = SDL_HapticQuery(m_haptic);
const unsigned int supported_effects = SDL_GetMaxHapticEffects(m_haptic);
// Disable autocenter:
if (supported_effects & SDL_HAPTIC_AUTOCENTER)
SDL_HapticSetAutocenter(m_haptic, 0);
SDL_SetHapticAutocenter(m_haptic, 0);
// Constant
if (supported_effects & SDL_HAPTIC_CONSTANT)
@ -224,16 +223,19 @@ GameController::GameController(SDL_GameController* const gamecontroller,
}
}
// Needed to make the below power level not "UNKNOWN".
SDL_JoystickUpdate();
// Battery
if (SDL_JoystickPowerLevel const power_level = SDL_JoystickCurrentPowerLevel(m_joystick);
power_level != SDL_JOYSTICK_POWER_UNKNOWN)
{
m_battery_value = GetBatteryValueFromSDLPowerLevel(power_level);
if (UpdateBatteryLevel())
AddInput(new BatteryInput{&m_battery_value});
}
}
bool GameController::UpdateBatteryLevel()
{
int battery_percent = 0;
if (SDL_GetJoystickPowerInfo(m_joystick, &battery_percent) == SDL_POWERSTATE_ERROR)
return false;
m_battery_value = std::max(0, battery_percent);
return true;
}
GameController::~GameController()
@ -241,20 +243,18 @@ GameController::~GameController()
if (m_haptic)
{
// stop/destroy all effects
SDL_HapticStopAll(m_haptic);
SDL_StopHapticEffects(m_haptic);
// close haptic before joystick
SDL_HapticClose(m_haptic);
SDL_CloseHaptic(m_haptic);
m_haptic = nullptr;
}
if (m_gamecontroller)
{
// stop all rumble
SDL_GameControllerRumble(m_gamecontroller, 0, 0, 0);
// close game controller
SDL_GameControllerClose(m_gamecontroller);
SDL_RumbleGamepad(m_gamecontroller, 0, 0, 0);
SDL_CloseGamepad(m_gamecontroller);
}
// close joystick
SDL_JoystickClose(m_joystick);
SDL_CloseJoystick(m_joystick);
}
std::string GameController::GetName() const
@ -267,20 +267,28 @@ std::string GameController::GetSource() const
return "SDL";
}
int GameController::GetSDLInstanceID() const
SDL_JoystickID GameController::GetSDLInstanceID() const
{
return SDL_JoystickInstanceID(m_joystick);
return SDL_GetJoystickID(m_joystick);
}
std::string GameController::Button::GetName() const
{
return s_sdl_button_names[m_button];
const auto button = m_binding.output.button;
if (std::size_t(button) >= std::size(s_sdl_button_names))
return GetLegacyButtonName(button);
return s_sdl_button_names[button];
}
std::string GameController::Axis::GetName() const
{
if (std::size_t(m_axis) >= std::size(s_sdl_axis_names))
return GetLegacyAxisName(m_axis, m_range);
if (IsTriggerAxis(m_axis))
return std::string(s_sdl_axis_names[m_axis]);
return s_sdl_axis_names[m_axis];
bool negative = m_range < 0;
@ -293,12 +301,12 @@ std::string GameController::Axis::GetName() const
ControlState GameController::Button::GetState() const
{
return SDL_GameControllerGetButton(m_gc, m_button);
return SDL_GetGamepadButton(m_gc, m_binding.output.button);
}
ControlState GameController::Axis::GetState() const
{
return ControlState(SDL_GameControllerGetAxis(m_gc, m_axis)) / m_range;
return ControlState(SDL_GetGamepadAxis(m_gc, m_axis)) / m_range;
}
bool GameController::Button::IsMatchingName(std::string_view name) const
@ -306,25 +314,26 @@ bool GameController::Button::IsMatchingName(std::string_view name) const
if (GetName() == name)
return true;
// So that SDL can be a superset of XInput
if (name == "Button A")
return GetName() == "Button S";
if (name == "Button B")
return GetName() == "Button E";
if (name == "Button X")
return GetName() == "Button W";
if (name == "Button Y")
return GetName() == "Button N";
// Positionally match XInput button names.
// e.g. Switch Pro controller A-button matches "Button B".
// e.g. PlayStation controller Circle-button matches "Button B".
if (m_binding.output.button == SDL_GAMEPAD_BUTTON_SOUTH && name == "Button A")
return true;
if (m_binding.output.button == SDL_GAMEPAD_BUTTON_EAST && name == "Button B")
return true;
if (m_binding.output.button == SDL_GAMEPAD_BUTTON_WEST && name == "Button X")
return true;
if (m_binding.output.button == SDL_GAMEPAD_BUTTON_NORTH && name == "Button Y")
return true;
// Match legacy names.
const auto bind = SDL_GameControllerGetBindForButton(m_gc, m_button);
switch (bind.bindType)
// Match the old "Button 0"-like names.
switch (m_binding.input_type)
{
case SDL_CONTROLLER_BINDTYPE_BUTTON:
return name == GetLegacyButtonName(bind.value.button);
case SDL_CONTROLLER_BINDTYPE_HAT:
return name == GetLegacyHatName(bind.value.hat.hat,
GetDirectionFromHatMask(u8(bind.value.hat.hat_mask)));
case SDL_GAMEPAD_BINDTYPE_BUTTON:
return name == GetLegacyButtonName(m_binding.input.button);
case SDL_GAMEPAD_BINDTYPE_HAT:
return name == GetLegacyHatName(m_binding.input.hat.hat,
GetDirectionFromHatMask(m_binding.input.hat.hat_mask));
default:
return false;
}
@ -333,24 +342,24 @@ bool GameController::Button::IsMatchingName(std::string_view name) const
ControlState GameController::MotionInput::GetState() const
{
std::array<float, 3> data{};
SDL_GameControllerGetSensorData(m_gc, m_type, data.data(), (int)data.size());
SDL_GetGamepadSensorData(m_gc, m_type, data.data(), (int)data.size());
return m_scale * data[m_index];
}
// Legacy input
ControlState GameController::LegacyButton::GetState() const
{
return SDL_JoystickGetButton(m_js, m_index);
return SDL_GetJoystickButton(m_js, m_index);
}
ControlState GameController::LegacyAxis::GetState() const
{
return ControlState(SDL_JoystickGetAxis(m_js, m_index)) / m_range;
return ControlState(SDL_GetJoystickAxis(m_js, m_index)) / m_range;
}
ControlState GameController::LegacyHat::GetState() const
{
return (SDL_JoystickGetHat(m_js, m_index) & (1 << m_direction)) > 0;
return (SDL_GetJoystickHat(m_js, m_index) & (1 << m_direction)) > 0;
}
void GameController::HapticEffect::UpdateEffect()
@ -360,22 +369,22 @@ void GameController::HapticEffect::UpdateEffect()
if (m_id < 0)
{
// Upload and try to play the effect.
m_id = SDL_HapticNewEffect(m_haptic, &m_effect);
m_id = SDL_CreateHapticEffect(m_haptic, &m_effect);
if (m_id >= 0)
SDL_HapticRunEffect(m_haptic, m_id, 1);
SDL_RunHapticEffect(m_haptic, m_id, 1);
}
else
{
// Effect is already playing. Update parameters.
SDL_HapticUpdateEffect(m_haptic, m_id, &m_effect);
SDL_UpdateHapticEffect(m_haptic, m_id, &m_effect);
}
}
else if (m_id >= 0)
{
// Stop and remove the effect.
SDL_HapticStopEffect(m_haptic, m_id);
SDL_HapticDestroyEffect(m_haptic, m_id);
SDL_StopHapticEffect(m_haptic, m_id);
SDL_DestroyHapticEffect(m_haptic, m_id);
m_id = -1;
}
}

View File

@ -5,8 +5,8 @@
#include <array>
#include <SDL.h>
#include <SDL_haptic.h>
#include <SDL3/SDL_gamepad.h>
#include <SDL3/SDL_haptic.h>
#include "Common/MathUtil.h"
@ -29,7 +29,7 @@ std::string GetLegacyHatName(int index, int direction)
return "Hat " + std::to_string(index) + ' ' + "NESW"[direction];
}
constexpr int GetDirectionFromHatMask(u8 mask)
constexpr int GetDirectionFromHatMask(int mask)
{
return MathUtil::IntLog2(mask);
}
@ -37,38 +37,6 @@ constexpr int GetDirectionFromHatMask(u8 mask)
static_assert(GetDirectionFromHatMask(SDL_HAT_UP) == 0);
static_assert(GetDirectionFromHatMask(SDL_HAT_LEFT) == 3);
ControlState GetBatteryValueFromSDLPowerLevel(SDL_JoystickPowerLevel sdl_power_level)
{
// Values come from comments in SDL_joystick.h
// A proper percentage will be exposed in SDL3.
ControlState result;
switch (sdl_power_level)
{
case SDL_JOYSTICK_POWER_EMPTY:
result = 0.025;
break;
case SDL_JOYSTICK_POWER_LOW:
result = 0.125;
break;
case SDL_JOYSTICK_POWER_MEDIUM:
result = 0.45;
break;
case SDL_JOYSTICK_POWER_FULL:
result = 0.85;
break;
case SDL_JOYSTICK_POWER_WIRED:
case SDL_JOYSTICK_POWER_MAX:
result = 1.0;
break;
case SDL_JOYSTICK_POWER_UNKNOWN:
default:
result = 0.0;
break;
}
return result * ciface::BATTERY_INPUT_MAX_VALUE;
}
} // namespace
namespace ciface::SDL
@ -82,29 +50,29 @@ private:
{
public:
std::string GetName() const override;
Button(SDL_GameController* gc, SDL_GameControllerButton button) : m_gc(gc), m_button(button) {}
Button(SDL_Gamepad* gc, const SDL_GamepadBinding& binding) : m_gc(gc), m_binding(binding) {}
ControlState GetState() const override;
bool IsMatchingName(std::string_view name) const override;
private:
SDL_GameController* const m_gc;
const SDL_GameControllerButton m_button;
SDL_Gamepad* const m_gc;
const SDL_GamepadBinding m_binding;
};
class Axis : public Core::Device::Input
{
public:
std::string GetName() const override;
Axis(SDL_GameController* gc, Sint16 range, SDL_GameControllerAxis axis)
Axis(SDL_Gamepad* gc, Sint16 range, SDL_GamepadAxis axis)
: m_gc(gc), m_range(range), m_axis(axis)
{
}
ControlState GetState() const override;
private:
SDL_GameController* const m_gc;
SDL_Gamepad* const m_gc;
const Sint16 m_range;
const SDL_GameControllerAxis m_axis;
const SDL_GamepadAxis m_axis;
};
// Legacy inputs
@ -180,7 +148,7 @@ private:
std::string GetName() const override { return m_name; }
void SetState(ControlState state) override
{
const auto new_state = state * std::numeric_limits<Uint16>::max();
const auto new_state = std::lround(state * std::numeric_limits<Uint16>::max());
if (m_state == new_state)
return;
@ -205,7 +173,7 @@ private:
std::string GetName() const override { return "Motor"; }
void SetState(ControlState state) override
{
const auto new_state = state * std::numeric_limits<Uint16>::max();
const auto new_state = std::lround(state * std::numeric_limits<Uint16>::max());
if (m_low_state == new_state && m_high_state == new_state)
return;
@ -327,7 +295,7 @@ private:
class MotionInput : public Input
{
public:
MotionInput(std::string name, SDL_GameController* gc, SDL_SensorType type, int index,
MotionInput(std::string name, SDL_Gamepad* gc, SDL_SensorType type, int index,
ControlState scale)
: m_name(std::move(name)), m_gc(gc), m_type(type), m_index(index), m_scale(scale)
{
@ -340,7 +308,7 @@ private:
private:
std::string m_name;
SDL_GameController* const m_gc;
SDL_Gamepad* const m_gc;
SDL_SensorType const m_type;
int const m_index;
@ -348,26 +316,25 @@ private:
};
public:
GameController(SDL_GameController* const gamecontroller, SDL_Joystick* const joystick);
~GameController();
GameController(SDL_Gamepad* gamecontroller, SDL_Joystick* joystick);
~GameController() override;
std::string GetName() const override;
std::string GetSource() const override;
int GetSDLInstanceID() const;
SDL_JoystickID GetSDLInstanceID() const;
Core::DeviceRemoval UpdateInput() override
{
m_battery_value = GetBatteryValueFromSDLPowerLevel(SDL_JoystickCurrentPowerLevel(m_joystick));
UpdateBatteryLevel();
// We only support one touchpad and one finger.
const int touchpad_index = 0;
const int finger_index = 0;
if (SDL_GameControllerGetNumTouchpads(m_gamecontroller) > touchpad_index &&
SDL_GameControllerGetNumTouchpadFingers(m_gamecontroller, touchpad_index) > finger_index)
if (SDL_GetNumGamepadTouchpads(m_gamecontroller) > touchpad_index &&
SDL_GetNumGamepadTouchpadFingers(m_gamecontroller, touchpad_index) > finger_index)
{
Uint8 state = 0;
SDL_GameControllerGetTouchpadFinger(m_gamecontroller, touchpad_index, finger_index, &state,
&m_touchpad_x, &m_touchpad_y, &m_touchpad_pressure);
SDL_GetGamepadTouchpadFinger(m_gamecontroller, touchpad_index, finger_index, nullptr,
&m_touchpad_x, &m_touchpad_y, &m_touchpad_pressure);
m_touchpad_x = m_touchpad_x * 2 - 1;
m_touchpad_y = m_touchpad_y * 2 - 1;
}
@ -378,23 +345,24 @@ public:
private:
void UpdateRumble()
{
SDL_GameControllerRumble(m_gamecontroller, m_low_freq_rumble, m_high_freq_rumble,
RUMBLE_LENGTH_MS);
SDL_RumbleGamepad(m_gamecontroller, m_low_freq_rumble, m_high_freq_rumble, RUMBLE_LENGTH_MS);
}
void UpdateRumbleTriggers()
{
SDL_GameControllerRumbleTriggers(m_gamecontroller, m_trigger_l_rumble, m_trigger_r_rumble,
RUMBLE_LENGTH_MS);
SDL_RumbleGamepadTriggers(m_gamecontroller, m_trigger_l_rumble, m_trigger_r_rumble,
RUMBLE_LENGTH_MS);
}
bool UpdateBatteryLevel();
Uint16 m_low_freq_rumble = 0;
Uint16 m_high_freq_rumble = 0;
Uint16 m_trigger_l_rumble = 0;
Uint16 m_trigger_r_rumble = 0;
SDL_GameController* const m_gamecontroller;
SDL_Gamepad* const m_gamecontroller;
std::string m_name;
SDL_Joystick* const m_joystick;
SDL_Haptic* m_haptic = nullptr;
@ -413,35 +381,35 @@ struct SDLMotionAxis
using SDLMotionAxisList = std::array<SDLMotionAxis, 6>;
static constexpr std::array<const char*, 21> s_sdl_button_names = {
"Button S", // SDL_CONTROLLER_BUTTON_A
"Button E", // SDL_CONTROLLER_BUTTON_B
"Button W", // SDL_CONTROLLER_BUTTON_X
"Button N", // SDL_CONTROLLER_BUTTON_Y
"Back", // SDL_CONTROLLER_BUTTON_BACK
"Guide", // SDL_CONTROLLER_BUTTON_GUIDE
"Start", // SDL_CONTROLLER_BUTTON_START
"Thumb L", // SDL_CONTROLLER_BUTTON_LEFTSTICK
"Thumb R", // SDL_CONTROLLER_BUTTON_RIGHTSTICK
"Shoulder L", // SDL_CONTROLLER_BUTTON_LEFTSHOULDER
"Shoulder R", // SDL_CONTROLLER_BUTTON_RIGHTSHOULDER
"Pad N", // SDL_CONTROLLER_BUTTON_DPAD_UP
"Pad S", // SDL_CONTROLLER_BUTTON_DPAD_DOWN
"Pad W", // SDL_CONTROLLER_BUTTON_DPAD_LEFT
"Pad E", // SDL_CONTROLLER_BUTTON_DPAD_RIGHT
"Misc 1", // SDL_CONTROLLER_BUTTON_MISC1
"Paddle 1", // SDL_CONTROLLER_BUTTON_PADDLE1
"Paddle 2", // SDL_CONTROLLER_BUTTON_PADDLE2
"Paddle 3", // SDL_CONTROLLER_BUTTON_PADDLE3
"Paddle 4", // SDL_CONTROLLER_BUTTON_PADDLE4
"Touchpad", // SDL_CONTROLLER_BUTTON_TOUCHPAD
"Button S", // SDL_GAMEPAD_BUTTON_SOUTH
"Button E", // SDL_GAMEPAD_BUTTON_EAST
"Button W", // SDL_GAMEPAD_BUTTON_WEST
"Button N", // SDL_GAMEPAD_BUTTON_NORTH
"Back", // SDL_GAMEPAD_BUTTON_BACK
"Guide", // SDL_GAMEPAD_BUTTON_GUIDE
"Start", // SDL_GAMEPAD_BUTTON_START
"Thumb L", // SDL_GAMEPAD_BUTTON_LEFT_STICK
"Thumb R", // SDL_GAMEPAD_BUTTON_RIGHT_STICK
"Shoulder L", // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER
"Shoulder R", // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER
"Pad N", // SDL_GAMEPAD_BUTTON_DPAD_UP
"Pad S", // SDL_GAMEPAD_BUTTON_DPAD_DOWN
"Pad W", // SDL_GAMEPAD_BUTTON_DPAD_LEFT
"Pad E", // SDL_GAMEPAD_BUTTON_DPAD_RIGHT
"Misc 1", // SDL_GAMEPAD_BUTTON_MISC1
"Paddle 1", // SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1
"Paddle 2", // SDL_GAMEPAD_BUTTON_LEFT_PADDLE1
"Paddle 3", // SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2
"Paddle 4", // SDL_GAMEPAD_BUTTON_LEFT_PADDLE2
"Touchpad", // SDL_GAMEPAD_BUTTON_TOUCHPAD
};
static constexpr std::array<const char*, 6> s_sdl_axis_names = {
"Left X", // SDL_CONTROLLER_AXIS_LEFTX
"Left Y", // SDL_CONTROLLER_AXIS_LEFTY
"Right X", // SDL_CONTROLLER_AXIS_RIGHTX
"Right Y", // SDL_CONTROLLER_AXIS_RIGHTY
"Trigger L", // SDL_CONTROLLER_AXIS_TRIGGERLEFT
"Trigger R", // SDL_CONTROLLER_AXIS_TRIGGERRIGHT
"Left X", // SDL_GAMEPAD_AXIS_LEFTX
"Left Y", // SDL_GAMEPAD_AXIS_LEFTY
"Right X", // SDL_GAMEPAD_AXIS_RIGHTX
"Right Y", // SDL_GAMEPAD_AXIS_RIGHTY
"Trigger L", // SDL_GAMEPAD_AXIS_LEFT_TRIGGER
"Trigger R", // SDL_GAMEPAD_AXIS_RIGHT_TRIGGER
};
static constexpr SDLMotionAxisList SDL_AXES_ACCELEROMETER = {{
{"Up", 1, 1},

View File

@ -19,8 +19,6 @@ set_target_properties(MacUpdater PROPERTIES
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in"
OUTPUT_NAME "Dolphin Updater")
target_compile_options(MacUpdater PRIVATE -x objective-c++)
# Copy icon into the bundle
target_sources(MacUpdater PRIVATE "${CMAKE_SOURCE_DIR}/Data/Dolphin.icns")
set_source_files_properties("${CMAKE_SOURCE_DIR}/Data/Dolphin.icns" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)

View File

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "VideoCommon/FrameDumpFFMpeg.h"
#include "Common/TimeUtil.h"
#if defined(__FreeBSD__)
#define __STDC_CONSTANT_MACROS 1
@ -124,11 +125,15 @@ std::string GetDumpPath(const std::string& extension, std::time_t time, u32 inde
if (!dump_path.empty())
return dump_path;
const auto local_time = Common::LocalTime(time);
if (!local_time)
return "";
const std::string path_prefix =
File::GetUserPath(D_DUMPFRAMES_IDX) + SConfig::GetInstance().GetGameID();
const std::string base_name =
fmt::format("{}_{:%Y-%m-%d_%H-%M-%S}_{}", path_prefix, fmt::localtime(time), index);
fmt::format("{}_{:%Y-%m-%d_%H-%M-%S}_{}", path_prefix, *local_time, index);
const std::string path = fmt::format("{}.{}", base_name, extension);

View File

@ -45,7 +45,7 @@
<PreprocessorDefinitions>HAS_VULKAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>HAS_LIBMGBA;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(AutoUpdate)'!='false'">AUTOUPDATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>HAVE_SDL2;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>HAVE_SDL3;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>USE_RETRO_ACHIEVEMENTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>RC_CLIENT_SUPPORTS_HASH;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>RC_CLIENT_SUPPORTS_RAINTEGRATION;%(PreprocessorDefinitions)</PreprocessorDefinitions>

View File

@ -81,7 +81,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fmt", "..\Externals\fmt\fmt
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spirv_cross", "..\Externals\spirv_cross\spirv_cross.vcxproj", "{3D780617-EC8C-4721-B9FD-DFC9BB658C7C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL2", "..\Externals\SDL\SDL2.vcxproj", "{8DC244EE-A0BD-4038-BAF7-CFAFA5EB2BAA}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL3", "..\Externals\SDL\SDL3.vcxproj", "{8DC244EE-A0BD-4038-BAF7-CFAFA5EB2BAA}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FatFs", "..\Externals\FatFs\FatFs.vcxproj", "{3F17D282-A77D-4931-B844-903AD0809A5E}"
EndProject