update SDL3 from 3.2.20 to 3.4.2

This commit is contained in:
Sven Balzer
2026-04-01 18:25:03 +02:00
parent 1daf4d79f1
commit 05b19704f8
1626 changed files with 124218 additions and 191491 deletions
+17 -9
View File
@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -25,7 +25,7 @@
SDL_Process *SDL_CreateProcess(const char * const *args, bool pipe_stdio)
{
if (!args || !args[0] || !args[0][0]) {
CHECK_PARAM(!args || !args[0] || !args[0][0]) {
SDL_InvalidParamError("args");
return NULL;
}
@@ -45,10 +45,18 @@ SDL_Process *SDL_CreateProcess(const char * const *args, bool pipe_stdio)
SDL_Process *SDL_CreateProcessWithProperties(SDL_PropertiesID props)
{
const char * const *args = SDL_GetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, NULL);
if (!args || !args[0] || !args[0][0]) {
#if defined(SDL_PLATFORM_WINDOWS)
const char *cmdline = SDL_GetStringProperty(props, SDL_PROP_PROCESS_CREATE_CMDLINE_STRING, NULL);
CHECK_PARAM((!args || !args[0] || !args[0][0]) && (!cmdline || !cmdline[0])) {
SDL_SetError("Either SDL_PROP_PROCESS_CREATE_ARGS_POINTER or SDL_PROP_PROCESS_CREATE_CMDLINE_STRING must be valid");
return NULL;
}
#else
CHECK_PARAM(!args || !args[0] || !args[0][0]) {
SDL_InvalidParamError("SDL_PROP_PROCESS_CREATE_ARGS_POINTER");
return NULL;
}
#endif
SDL_Process *process = (SDL_Process *)SDL_calloc(1, sizeof(*process));
if (!process) {
@@ -73,7 +81,7 @@ SDL_Process *SDL_CreateProcessWithProperties(SDL_PropertiesID props)
SDL_PropertiesID SDL_GetProcessProperties(SDL_Process *process)
{
if (!process) {
CHECK_PARAM(!process) {
return SDL_InvalidParamError("process");
}
return process->props;
@@ -90,7 +98,7 @@ void *SDL_ReadProcess(SDL_Process *process, size_t *datasize, int *exitcode)
*exitcode = -1;
}
if (!process) {
CHECK_PARAM(!process) {
SDL_InvalidParamError("process");
return NULL;
}
@@ -110,7 +118,7 @@ void *SDL_ReadProcess(SDL_Process *process, size_t *datasize, int *exitcode)
SDL_IOStream *SDL_GetProcessInput(SDL_Process *process)
{
if (!process) {
CHECK_PARAM(!process) {
SDL_InvalidParamError("process");
return NULL;
}
@@ -126,7 +134,7 @@ SDL_IOStream *SDL_GetProcessInput(SDL_Process *process)
SDL_IOStream *SDL_GetProcessOutput(SDL_Process *process)
{
if (!process) {
CHECK_PARAM(!process) {
SDL_InvalidParamError("process");
return NULL;
}
@@ -142,7 +150,7 @@ SDL_IOStream *SDL_GetProcessOutput(SDL_Process *process)
bool SDL_KillProcess(SDL_Process *process, bool force)
{
if (!process) {
CHECK_PARAM(!process) {
return SDL_InvalidParamError("process");
}
@@ -155,7 +163,7 @@ bool SDL_KillProcess(SDL_Process *process, bool force)
bool SDL_WaitProcess(SDL_Process *process, bool block, int *exitcode)
{
if (!process) {
CHECK_PARAM(!process) {
return SDL_InvalidParamError("process");
}
+6 -1
View File
@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -20,6 +20,9 @@
*/
#include "SDL_internal.h"
#ifndef SDL_sysprocess_h_
#define SDL_sysprocess_h_
typedef struct SDL_ProcessData SDL_ProcessData;
struct SDL_Process
@@ -35,3 +38,5 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
bool SDL_SYS_KillProcess(SDL_Process *process, bool force);
bool SDL_SYS_WaitProcess(SDL_Process *process, bool block, int *exitcode);
void SDL_SYS_DestroyProcess(SDL_Process *process);
#endif // SDL_sysprocess_h_
@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
+32 -1
View File
@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -37,6 +37,12 @@
#include "../../io/SDL_iostream_c.h"
#if defined(HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR_NP) && \
!defined(HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR)
#define HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR
#define posix_spawn_file_actions_addchdir posix_spawn_file_actions_addchdir_np
#endif
#define READ_END 0
#define WRITE_END 1
@@ -156,6 +162,7 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
char * const *args = SDL_GetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, NULL);
SDL_Environment *env = SDL_GetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER, SDL_GetEnvironment());
char **envp = NULL;
const char *working_directory = SDL_GetStringProperty(props, SDL_PROP_PROCESS_CREATE_WORKING_DIRECTORY_STRING, NULL);
SDL_ProcessIO stdin_option = (SDL_ProcessIO)SDL_GetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_NULL);
SDL_ProcessIO stdout_option = (SDL_ProcessIO)SDL_GetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_INHERITED);
SDL_ProcessIO stderr_option = (SDL_ProcessIO)SDL_GetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDERR_NUMBER, SDL_PROCESS_STDIO_INHERITED);
@@ -192,6 +199,30 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
goto posix_spawn_fail_attr;
}
if (working_directory) {
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR
#ifdef SDL_PLATFORM_APPLE
if (__builtin_available(macOS 10.15, *)) {
if (posix_spawn_file_actions_addchdir_np(&fa, working_directory) != 0) {
SDL_SetError("posix_spawn_file_actions_addchdir failed: %s", strerror(errno));
goto posix_spawn_fail_all;
}
} else {
SDL_SetError("Setting the working directory is only supported on macOS 10.15 and newer");
goto posix_spawn_fail_all;
}
#else
if (posix_spawn_file_actions_addchdir(&fa, working_directory) != 0) {
SDL_SetError("posix_spawn_file_actions_addchdir failed: %s", strerror(errno));
goto posix_spawn_fail_all;
}
#endif // SDL_PLATFORM_APPLE
#else
SDL_SetError("Setting the working directory is not supported");
goto posix_spawn_fail_all;
#endif
}
// Background processes don't have access to the terminal
if (process->background) {
if (stdin_option == SDL_PROCESS_STDIO_INHERITED) {
@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -106,9 +106,12 @@ static bool join_arguments(const char * const *args, LPWSTR *args_out)
len = 0;
for (i = 0; args[i]; i++) {
const char *a = args[i];
bool quotes = *a == '\0' || SDL_strpbrk(a, " \r\n\t\v") != NULL;
/* two double quotes to surround an argument with */
len += 2;
if (quotes) {
/* surround the argument with double quote if it is empty or contains whitespaces */
len += 2;
}
for (; *a; a++) {
switch (*a) {
@@ -116,8 +119,8 @@ static bool join_arguments(const char * const *args, LPWSTR *args_out)
len += 2;
break;
case '\\':
/* only escape backslashes that precede a double quote */
len += (a[1] == '"' || a[1] == '\0') ? 2 : 1;
/* only escape backslashes that precede a double quote (including the enclosing double quote) */
len += (a[1] == '"' || (quotes && a[1] == '\0')) ? 2 : 1;
break;
case ' ':
case '^':
@@ -149,8 +152,11 @@ static bool join_arguments(const char * const *args, LPWSTR *args_out)
i_out = 0;
for (i = 0; args[i]; i++) {
const char *a = args[i];
bool quotes = *a == '\0' || SDL_strpbrk(a, " \r\n\t\v") != NULL;
result[i_out++] = '"';
if (quotes) {
result[i_out++] = '"';
}
for (; *a; a++) {
switch (*a) {
case '"':
@@ -163,7 +169,7 @@ static bool join_arguments(const char * const *args, LPWSTR *args_out)
break;
case '\\':
result[i_out++] = *a;
if (a[1] == '"' || a[1] == '\0') {
if (a[1] == '"' || (quotes && a[1] == '\0')) {
result[i_out++] = *a;
}
break;
@@ -188,7 +194,9 @@ static bool join_arguments(const char * const *args, LPWSTR *args_out)
break;
}
}
result[i_out++] = '"';
if (quotes) {
result[i_out++] = '"';
}
result[i_out++] = ' ';
}
SDL_assert(i_out == len);
@@ -237,8 +245,10 @@ static bool join_env(char **env, LPWSTR *env_out)
bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID props)
{
const char * const *args = SDL_GetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, NULL);
const char *cmdline = SDL_GetStringProperty(props, SDL_PROP_PROCESS_CREATE_CMDLINE_STRING, NULL);
SDL_Environment *env = SDL_GetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER, SDL_GetEnvironment());
char **envp = NULL;
const char *working_directory = SDL_GetStringProperty(props, SDL_PROP_PROCESS_CREATE_WORKING_DIRECTORY_STRING, NULL);
SDL_ProcessIO stdin_option = (SDL_ProcessIO)SDL_GetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_NULL);
SDL_ProcessIO stdout_option = (SDL_ProcessIO)SDL_GetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_INHERITED);
SDL_ProcessIO stderr_option = (SDL_ProcessIO)SDL_GetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDERR_NUMBER, SDL_PROCESS_STDIO_INHERITED);
@@ -246,6 +256,7 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
!SDL_HasProperty(props, SDL_PROP_PROCESS_CREATE_STDERR_NUMBER);
LPWSTR createprocess_cmdline = NULL;
LPWSTR createprocess_env = NULL;
LPWSTR createprocess_cwd = NULL;
STARTUPINFOW startup_info;
DWORD creation_flags;
SECURITY_ATTRIBUTES security_attributes;
@@ -284,7 +295,12 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
security_attributes.bInheritHandle = TRUE;
security_attributes.lpSecurityDescriptor = NULL;
if (!join_arguments(args, &createprocess_cmdline)) {
if (cmdline) {
createprocess_cmdline = WIN_UTF8ToString(cmdline);
if (!createprocess_cmdline) {
goto done;
}
} else if (!join_arguments(args, &createprocess_cmdline)) {
goto done;
}
@@ -292,6 +308,13 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
goto done;
}
if (working_directory) {
createprocess_cwd = WIN_UTF8ToStringW(working_directory);
if (!createprocess_cwd) {
goto done;
}
}
// Background processes don't have access to the terminal
// This isn't necessary on Windows, but we keep the same behavior as the POSIX implementation.
if (process->background) {
@@ -428,7 +451,7 @@ bool SDL_SYS_CreateProcessWithProperties(SDL_Process *process, SDL_PropertiesID
}
}
if (!CreateProcessW(NULL, createprocess_cmdline, NULL, NULL, TRUE, creation_flags, createprocess_env, NULL, &startup_info, &data->process_information)) {
if (!CreateProcessW(NULL, createprocess_cmdline, NULL, NULL, TRUE, creation_flags, createprocess_env, createprocess_cwd, &startup_info, &data->process_information)) {
WIN_SetError("CreateProcess");
goto done;
}
@@ -480,6 +503,7 @@ done:
}
SDL_free(createprocess_cmdline);
SDL_free(createprocess_env);
SDL_free(createprocess_cwd);
SDL_free(envp);
if (!result) {
@@ -496,8 +520,31 @@ done:
return result;
}
static BOOL CALLBACK terminate_app(HWND hwnd, LPARAM lparam)
{
DWORD current_proc_id = 0, *term_info = (DWORD *) lparam;
GetWindowThreadProcessId(hwnd, &current_proc_id);
if (current_proc_id == term_info[0] && PostMessage(hwnd, WM_CLOSE, 0, 0)) {
term_info[1]++;
}
return TRUE;
}
bool SDL_SYS_KillProcess(SDL_Process *process, bool force)
{
if (!force) {
// term_info[0] is the process ID, term_info[1] is number of successful tries
DWORD term_info[2];
term_info[0] = process->internal->process_information.dwProcessId;
term_info[1] = 0;
EnumWindows(terminate_app, (LPARAM) &term_info);
if (term_info[1] || PostThreadMessage(process->internal->process_information.dwThreadId, WM_CLOSE, 0, 0)) {
return true;
}
if (GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, term_info[0])) {
return true;
}
}
if (!TerminateProcess(process->internal->process_information.hProcess, 1)) {
return WIN_SetError("TerminateProcess failed");
}