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