SDL: Added SDL_GetSandbox()

From d6981da5a4e6c1dfc2c60f62b1f401ae276d326c Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Wed, 16 Oct 2024 11:02:49 -0700
Subject: [PATCH] Added SDL_GetSandbox()

This adds support for detecting whether you're running in a sandbox on macOS
---
 CMakeLists.txt                           |  1 -
 include/SDL3/SDL_system.h                | 24 ++++++++++++
 src/SDL.c                                | 38 +++++++++++++++++++
 src/core/linux/SDL_dbus.c                |  3 +-
 src/core/linux/SDL_sandbox.c             | 47 ------------------------
 src/core/linux/SDL_sandbox.h             | 37 -------------------
 src/dynapi/SDL_dynapi.sym                |  1 +
 src/dynapi/SDL_dynapi_overrides.h        |  1 +
 src/dynapi/SDL_dynapi_procs.h            |  1 +
 src/hidapi/SDL_hidapi.c                  |  3 +-
 src/joystick/hidapi/SDL_hidapijoystick.c |  5 +--
 src/joystick/linux/SDL_sysjoystick.c     |  3 +-
 12 files changed, 69 insertions(+), 95 deletions(-)
 delete mode 100644 src/core/linux/SDL_sandbox.c
 delete mode 100644 src/core/linux/SDL_sandbox.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 50796fe667725..efe9b97a299de 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1726,7 +1726,6 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
     sdl_sources(
       "${SDL3_SOURCE_DIR}/src/core/linux/SDL_evdev_capabilities.c"
       "${SDL3_SOURCE_DIR}/src/core/linux/SDL_threadprio.c"
-      "${SDL3_SOURCE_DIR}/src/core/linux/SDL_sandbox.c"
     )
 
     # src/core/unix/*.c is included in a generic if(UNIX) section, elsewhere.
diff --git a/include/SDL3/SDL_system.h b/include/SDL3/SDL_system.h
index 88e318ddf4e8a..e1b372b368997 100644
--- a/include/SDL3/SDL_system.h
+++ b/include/SDL3/SDL_system.h
@@ -565,6 +565,30 @@ extern SDL_DECLSPEC bool SDLCALL SDL_IsTablet(void);
  */
 extern SDL_DECLSPEC bool SDLCALL SDL_IsTV(void);
 
+/**
+ * Application sandbox environment.
+ *
+ * \since This enum is available since SDL 3.1.6.
+ */
+typedef enum SDL_Sandbox
+{
+    SDL_SANDBOX_NONE = 0,
+    SDL_SANDBOX_UNKNOWN,
+    SDL_SANDBOX_FLATPAK,
+    SDL_SANDBOX_SNAP,
+    SDL_SANDBOX_MACOS
+} SDL_Sandbox;
+
+/**
+ * Get the application sandbox environment, if any.
+ *
+ * \returns the application sandbox environment or SDL_SANDBOX_NONE if the application is not running in a sandbox environment.
+ *
+ * \since This function is available since SDL 3.1.6.
+ */
+extern SDL_DECLSPEC SDL_Sandbox SDLCALL SDL_GetSandbox(void);
+
+
 /* Functions used by iOS app delegates to notify SDL about state changes. */
 
 /**
diff --git a/src/SDL.c b/src/SDL.c
index aeef2ec28a38d..bb04a0ee68eda 100644
--- a/src/SDL.c
+++ b/src/SDL.c
@@ -753,6 +753,44 @@ bool SDL_IsTV(void)
 #endif
 }
 
+static SDL_Sandbox SDL_DetectSandbox(void)
+{
+#if defined(SDL_PLATFORM_LINUX)
+    if (access("/.flatpak-info", F_OK) == 0) {
+        return SDL_SANDBOX_FLATPAK;
+    }
+
+    /* For Snap, we check multiple variables because they might be set for
+     * unrelated reasons. This is the same thing WebKitGTK does. */
+    if (SDL_getenv("SNAP") && SDL_getenv("SNAP_NAME") && SDL_getenv("SNAP_REVISION")) {
+        return SDL_SANDBOX_SNAP;
+    }
+
+    if (access("/run/host/container-manager", F_OK) == 0) {
+        return SDL_SANDBOX_UNKNOWN;
+    }
+
+#elif defined(SDL_PLATFORM_MACOS)
+    if (SDL_getenv("APP_SANDBOX_CONTAINER_ID")) {
+        return SDL_SANDBOX_MACOS;
+    }
+#endif
+
+    return SDL_SANDBOX_NONE;
+}
+
+SDL_Sandbox SDL_GetSandbox(void)
+{
+    static SDL_Sandbox sandbox;
+    static bool sandbox_initialized;
+
+    if (!sandbox_initialized) {
+        sandbox = SDL_DetectSandbox();
+        sandbox_initialized = true;
+    }
+    return sandbox;
+}
+
 #ifdef SDL_PLATFORM_WIN32
 
 #if (!defined(HAVE_LIBC) || defined(__WATCOMC__)) && !defined(SDL_STATIC_LIB)
diff --git a/src/core/linux/SDL_dbus.c b/src/core/linux/SDL_dbus.c
index e3f132d8658d4..3fd78c75cdac1 100644
--- a/src/core/linux/SDL_dbus.c
+++ b/src/core/linux/SDL_dbus.c
@@ -20,7 +20,6 @@
 */
 #include "SDL_internal.h"
 #include "SDL_dbus.h"
-#include "SDL_sandbox.h"
 #include "../../stdlib/SDL_vacopy.h"
 
 #ifdef SDL_USE_LIBDBUS
@@ -443,7 +442,7 @@ bool SDL_DBus_ScreensaverInhibit(bool inhibit)
         return false;
     }
 
-    if (SDL_DetectSandbox() != SDL_SANDBOX_NONE) {
+    if (SDL_GetSandbox() != SDL_SANDBOX_NONE) {
         const char *bus_name = "org.freedesktop.portal.Desktop";
         const char *path = "/org/freedesktop/portal/desktop";
         const char *interface = "org.freedesktop.portal.Inhibit";
diff --git a/src/core/linux/SDL_sandbox.c b/src/core/linux/SDL_sandbox.c
deleted file mode 100644
index 5a8df84871459..0000000000000
--- a/src/core/linux/SDL_sandbox.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
-  Simple DirectMedia Layer
-  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
-  Copyright (C) 2022 Collabora Ltd.
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-#include "SDL_internal.h"
-
-#include "SDL_sandbox.h"
-
-#include <unistd.h>
-
-SDL_Sandbox SDL_DetectSandbox(void)
-{
-    if (access("/.flatpak-info", F_OK) == 0) {
-        return SDL_SANDBOX_FLATPAK;
-    }
-
-    /* For Snap, we check multiple variables because they might be set for
-     * unrelated reasons. This is the same thing WebKitGTK does. */
-    if (SDL_getenv("SNAP") != NULL &&
-        SDL_getenv("SNAP_NAME") != NULL &&
-        SDL_getenv("SNAP_REVISION") != NULL) {
-        return SDL_SANDBOX_SNAP;
-    }
-
-    if (access("/run/host/container-manager", F_OK) == 0) {
-        return SDL_SANDBOX_UNKNOWN_CONTAINER;
-    }
-
-    return SDL_SANDBOX_NONE;
-}
diff --git a/src/core/linux/SDL_sandbox.h b/src/core/linux/SDL_sandbox.h
deleted file mode 100644
index d480658ce298b..0000000000000
--- a/src/core/linux/SDL_sandbox.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-  Simple DirectMedia Layer
-  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
-  Copyright (C) 2022 Collabora Ltd.
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef SDL_SANDBOX_H
-#define SDL_SANDBOX_H
-
-typedef enum
-{
-    SDL_SANDBOX_NONE = 0,
-    SDL_SANDBOX_UNKNOWN_CONTAINER,
-    SDL_SANDBOX_FLATPAK,
-    SDL_SANDBOX_SNAP,
-} SDL_Sandbox;
-
-// Return the sandbox type currently in use, if any
-SDL_Sandbox SDL_DetectSandbox(void);
-
-#endif // SDL_SANDBOX_H
diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym
index ede5c799fb1bd..e0efccc2b014f 100644
--- a/src/dynapi/SDL_dynapi.sym
+++ b/src/dynapi/SDL_dynapi.sym
@@ -1182,6 +1182,7 @@ SDL3_0.0.0 {
     SDL_SetErrorV;
     SDL_GetDefaultLogOutputFunction;
     SDL_RenderDebugText;
+    SDL_GetSandbox;
     # extra symbols go here (don't modify this line)
   local: *;
 };
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index 682714458fb84..4f5f16d889ecf 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -1207,3 +1207,4 @@
 #define SDL_SetErrorV SDL_SetErrorV_REAL
 #define SDL_GetDefaultLogOutputFunction SDL_GetDefaultLogOutputFunction_REAL
 #define SDL_RenderDebugText SDL_RenderDebugText_REAL
+#define SDL_GetSandbox SDL_GetSandbox_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index 1dedeeb996614..f308ce52efc38 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -1213,3 +1213,4 @@ SDL_DYNAPI_PROC(Uint32,SDL_CalculateGPUTextureFormatSize,(SDL_GPUTextureFormat a
 SDL_DYNAPI_PROC(bool,SDL_SetErrorV,(SDL_PRINTF_FORMAT_STRING const char *a,va_list b),(a,b),return)
 SDL_DYNAPI_PROC(SDL_LogOutputFunction,SDL_GetDefaultLogOutputFunction,(void),(),return)
 SDL_DYNAPI_PROC(bool,SDL_RenderDebugText,(SDL_Renderer *a,float b,float c,const char *d),(a,b,c,d),return)
+SDL_DYNAPI_PROC(SDL_Sandbox,SDL_GetSandbox,(void),(),return)
diff --git a/src/hidapi/SDL_hidapi.c b/src/hidapi/SDL_hidapi.c
index 890bc23475329..81bebf0c3f137 100644
--- a/src/hidapi/SDL_hidapi.c
+++ b/src/hidapi/SDL_hidapi.c
@@ -60,7 +60,6 @@
 #include "../core/linux/SDL_udev.h"
 #ifdef SDL_USE_LIBUDEV
 #include <poll.h>
-#include "../core/linux/SDL_sandbox.h"
 #endif
 
 #ifdef HAVE_INOTIFY
@@ -1144,7 +1143,7 @@ int SDL_hid_init(void)
         SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
                      "udev disabled by SDL_HINT_HIDAPI_UDEV");
         linux_enumeration_method = ENUMERATION_FALLBACK;
-    } else if (SDL_DetectSandbox() != SDL_SANDBOX_NONE) {
+    } else if (SDL_GetSandbox() != SDL_SANDBOX_NONE) {
         SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
                      "Container detected, disabling HIDAPI udev integration");
         linux_enumeration_method = ENUMERATION_FALLBACK;
diff --git a/src/joystick/hidapi/SDL_hidapijoystick.c b/src/joystick/hidapi/SDL_hidapijoystick.c
index 7399c10f6af2d..f5ca002bc4aad 100644
--- a/src/joystick/hidapi/SDL_hidapijoystick.c
+++ b/src/joystick/hidapi/SDL_hidapijoystick.c
@@ -31,9 +31,6 @@
 #include "../windows/SDL_rawinputjoystick_c.h"
 #endif
 
-#ifdef SDL_USE_LIBUDEV
-#include "../../core/linux/SDL_sandbox.h"
-#endif
 
 struct joystick_hwdata
 {
@@ -586,7 +583,7 @@ static bool HIDAPI_JoystickInit(void)
             SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
                          "udev disabled by SDL_HINT_HIDAPI_UDEV");
             linux_enumeration_method = ENUMERATION_FALLBACK;
-        } else if (SDL_DetectSandbox() != SDL_SANDBOX_NONE) {
+        } else if (SDL_GetSandbox() != SDL_SANDBOX_NONE) {
             SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
                          "Container detected, disabling HIDAPI udev integration");
             linux_enumeration_method = ENUMERATION_FALLBACK;
diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c
index 1e85eac2f1cd0..d1eb66dd15bf1 100644
--- a/src/joystick/linux/SDL_sysjoystick.c
+++ b/src/joystick/linux/SDL_sysjoystick.c
@@ -124,7 +124,6 @@
 
 #include "../../core/linux/SDL_evdev_capabilities.h"
 #include "../../core/linux/SDL_udev.h"
-#include "../../core/linux/SDL_sandbox.h"
 
 #if 0
 #define DEBUG_INPUT_EVENTS 1
@@ -1069,7 +1068,7 @@ static bool LINUX_JoystickInit(void)
             SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
                          "udev disabled by SDL_JOYSTICK_DISABLE_UDEV");
             enumeration_method = ENUMERATION_FALLBACK;
-        } else if (SDL_DetectSandbox() != SDL_SANDBOX_NONE) {
+        } else if (SDL_GetSandbox() != SDL_SANDBOX_NONE) {
             SDL_LogDebug(SDL_LOG_CATEGORY_INPUT,
                          "Container detected, disabling udev integration");
             enumeration_method = ENUMERATION_FALLBACK;