update SDL3 from 3.2.20 to 3.4.2
This commit is contained in:
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, ¤t_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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user