SDL: Add SDL_HINT_APP_NAME and DBUS inhibition hint

From a1ffeda0ed0fb7be473c4bc6ac3391743a5dea6e Mon Sep 17 00:00:00 2001
From: David Gow <[EMAIL REDACTED]>
Date: Sat, 28 Aug 2021 22:52:13 +0800
Subject: [PATCH] Add SDL_HINT_APP_NAME and DBUS inhibition hint

See SDL bug #4703. This implements two new hints:
- SDL_APP_NAME
- SDL_SCREENSAVER_INHIBIT_ACTIVITY_NAME

The former is the successor to SDL_HINT_AUDIO_DEVICE_APP_NAME, and acts
as a generic "application name" used both by audio drivers and DBUS
screensaver inhibition. If SDL_AUDIO_DEVICE_APP_NAME is set, it will
still take priority over SDL_APP_NAME.

The second allows the "activity name" used by
org.freedesktop.ScreenSavver's Inhibit method, which are often shown in
the UI as the reason the screensaver (and/or suspend/other
power-managment features) are disabled.
---
 include/SDL_hints.h                   | 45 +++++++++++++++++++++++++--
 src/audio/pipewire/SDL_pipewire.c     |  5 ++-
 src/audio/pulseaudio/SDL_pulseaudio.c |  8 ++++-
 src/core/linux/SDL_dbus.c             | 12 +++++--
 4 files changed, 64 insertions(+), 6 deletions(-)

diff --git a/include/SDL_hints.h b/include/SDL_hints.h
index f07ee19e49..3d5216c124 100644
--- a/include/SDL_hints.h
+++ b/include/SDL_hints.h
@@ -145,6 +145,26 @@ extern "C" {
  */
 #define SDL_HINT_ANDROID_TRAP_BACK_BUTTON "SDL_ANDROID_TRAP_BACK_BUTTON"
 
+/**
+ *  \brief Specify an application name.
+ * 
+ * This hint lets you specify the application name sent to the OS when
+ * required. For example, this will often appear in volume control applets for
+ * audio streams, and in lists of applications which are inhibiting the
+ * screensaver.  You should use a string that describes your program ("My Game
+ * 2: The Revenge")
+ *
+ * Setting this to "" or leaving it unset will have SDL use a reasonable
+ * default: probably the application's name or "SDL Application" if SDL
+ * doesn't have any better information.
+ *
+ * Note that, for audio streams, this can be overridden with
+ * SDL_HINT_AUDIO_DEVICE_APP_NAME.
+ *
+ * On targets where this is not supported, this hint does nothing.
+ */
+#define SDL_HINT_APP_NAME "SDL_APP_NAME"
+
 /**
  *  \brief  A variable controlling whether controllers used with the Apple TV
  *  generate UI events.
@@ -199,8 +219,9 @@ extern "C" {
  * that describes your program ("My Game 2: The Revenge")
  *
  * Setting this to "" or leaving it unset will have SDL use a reasonable
- * default: probably the application's name or "SDL Application" if SDL
- * doesn't have any better information.
+ * default: this will be the name set with SDL_HINT_APP_NAME, if that hint is
+ * set. Otherwise, it'll probably the application's name or "SDL Application"
+ * if SDL doesn't have any better information.
  *
  * On targets where this is not supported, this hint does nothing.
  */
@@ -1103,6 +1124,26 @@ extern "C" {
  */
 #define SDL_HINT_RPI_VIDEO_LAYER           "SDL_RPI_VIDEO_LAYER"
 
+/**
+ *  \brief Specify an "activity name" for screensaver inhibition.
+ *
+ * Some platforms, notably Linux desktops, list the applications which are
+ * inhibiting the screensaver or other power-saving features.
+ *
+ * This hint lets you specify the "activity name" sent to the OS when
+ * SDL_DisableScreenSaver() is used (or the screensaver is automatically
+ * disabled). The contents of this hint are used when the screensaver is
+ * disabled. You should use a string that describes what your program is doing
+ * (and, therefore, why the screensaver is disabled).  For example, "Playing a
+ * game" or "Watching a video".
+ * 
+ * Setting this to "" or leaving it unset will have SDL use a reasonable
+ * default: "Playing a game" or something similar.
+ *
+ * On targets where this is not supported, this hint does nothing.
+ */
+#define SDL_HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME "SDL_SCREENSAVER_INHIBIT_ACTIVITY_NAME"
+
 /**
  *  \brief Specifies whether SDL_THREAD_PRIORITY_TIME_CRITICAL should be treated as realtime.
  *
diff --git a/src/audio/pipewire/SDL_pipewire.c b/src/audio/pipewire/SDL_pipewire.c
index 3c3b6ca8a8..8af0319622 100644
--- a/src/audio/pipewire/SDL_pipewire.c
+++ b/src/audio/pipewire/SDL_pipewire.c
@@ -1043,7 +1043,10 @@ PIPEWIRE_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     /* Get the hints for the application name, stream name and role */
     app_name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME);
     if (!app_name || *app_name == '\0') {
-        app_name = "SDL Application";
+        app_name = SDL_GetHint(SDL_HINT_APP_NAME);
+        if (!app_name || *app_name == '\0') {   
+            app_name = "SDL Application";
+        }
     }
 
     stream_name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME);
diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c
index d1997aad73..4a1823df19 100644
--- a/src/audio/pulseaudio/SDL_pulseaudio.c
+++ b/src/audio/pulseaudio/SDL_pulseaudio.c
@@ -246,7 +246,13 @@ static const char *
 getAppName(void)
 {
     const char *retval = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME);
-    if (!retval || !*retval) {
+    if (retval && *retval) {
+        return retval;
+    }
+    retval = SDL_GetHint(SDL_HINT_APP_NAME);
+    if (retval && *retval) {
+        return retval;
+    } else {
         const char *verstr = PULSEAUDIO_pa_get_library_version();
         retval = "SDL Application";  /* the "oh well" default. */
         if (verstr != NULL) {
diff --git a/src/core/linux/SDL_dbus.c b/src/core/linux/SDL_dbus.c
index e83da80c7f..df96d76c48 100644
--- a/src/core/linux/SDL_dbus.c
+++ b/src/core/linux/SDL_dbus.c
@@ -19,6 +19,7 @@
   3. This notice may not be removed or altered from any source distribution.
 */
 #include "../../SDL_internal.h"
+#include "SDL_hints.h"
 #include "SDL_dbus.h"
 #include "SDL_atomic.h"
 
@@ -365,8 +366,15 @@ SDL_DBus_ScreensaverInhibit(SDL_bool inhibit)
         const char *interface = "org.freedesktop.ScreenSaver";
 
         if (inhibit) {
-            const char *app = "My SDL application";
-            const char *reason = "Playing a game";
+            const char *app = SDL_GetHint(SDL_HINT_APP_NAME);
+            const char *reason = SDL_GetHint(SDL_HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME);
+            if (!app || !app[0]) {
+               app  = "My SDL application";
+            }
+            if (!reason || !reason[0]) {
+                reason = "Playing a game";
+            }
+
             if (!SDL_DBus_CallMethod(node, path, interface, "Inhibit",
                     DBUS_TYPE_STRING, &app, DBUS_TYPE_STRING, &reason, DBUS_TYPE_INVALID,
                     DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) {