SDL: Wayland: Add SDL_HINT_VIDEO_WAYLAND_PREFER_LIBDECOR

From 9c2f46b0d5a5dce636522904fe0afbde78016063 Mon Sep 17 00:00:00 2001
From: David Gow <[EMAIL REDACTED]>
Date: Tue, 12 Apr 2022 15:23:22 +0800
Subject: [PATCH] Wayland: Add SDL_HINT_VIDEO_WAYLAND_PREFER_LIBDECOR

This hint allows libdecor to be used even when xdg-decoration is
available. It's mostly useful for debugging libdecor, but could in
theory be used by applications which want to (for example) bundle their
own libdecor plugins.
---
 include/SDL_hints.h                  | 14 ++++++++++++++
 src/video/wayland/SDL_waylandvideo.c | 25 ++++++++++++++++++++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/include/SDL_hints.h b/include/SDL_hints.h
index 12466e99029..c5371324ada 100644
--- a/include/SDL_hints.h
+++ b/include/SDL_hints.h
@@ -1475,6 +1475,20 @@ extern "C" {
  */
 #define SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR "SDL_VIDEO_WAYLAND_ALLOW_LIBDECOR"
 
+/**
+ *  \brief  A variable controlling whether the libdecor Wayland backend is preferred over native decrations.
+ *
+ *  When this hint is set, libdecor will be used to provide window decorations, even if xdg-decoration is
+ *  available. (Note that, by default, libdecor will use xdg-decoration itself if available).
+ *
+ *  This variable can be set to the following values:
+ *    "0"       - libdecor is enabled only if server-side decorations are unavailable.
+ *    "1"       - libdecor is always enabled if available.
+ *
+ *  libdecor is used over xdg-shell when xdg-decoration protocol is unavailable.
+ */
+#define SDL_HINT_VIDEO_WAYLAND_PREFER_LIBDECOR "SDL_VIDEO_WAYLAND_PREFER_LIBDECOR"
+
 /**
 *  \brief  A variable that is the address of another SDL_Window* (as a hex string formatted with "%p").
 *  
diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c
index 9c325d78a41..bce982fc682 100644
--- a/src/video/wayland/SDL_waylandvideo.c
+++ b/src/video/wayland/SDL_waylandvideo.c
@@ -876,6 +876,29 @@ static const struct wl_registry_listener registry_listener = {
     display_handle_global,
     display_remove_global
 };
+ 
+#ifdef HAVE_LIBDECOR_H
+static SDL_bool should_use_libdecor(SDL_VideoData *data)
+{
+    if (!SDL_WAYLAND_HAVE_WAYLAND_LIBDECOR) {
+        return SDL_FALSE;
+    }
+
+    if (!SDL_GetHintBoolean(SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR, SDL_TRUE)) {
+        return SDL_FALSE;
+    }
+
+    if (SDL_GetHintBoolean(SDL_HINT_VIDEO_WAYLAND_PREFER_LIBDECOR, SDL_FALSE)) {
+        return SDL_TRUE;
+    }
+
+    if (data->decoration_manager) {
+        return SDL_FALSE;
+    }
+
+    return SDL_TRUE;
+}
+#endif
 
 int
 Wayland_VideoInit(_THIS)
@@ -899,7 +922,7 @@ Wayland_VideoInit(_THIS)
 
 #ifdef HAVE_LIBDECOR_H
     /* Don't have server-side decorations? Try client-side instead. */
-    if (!data->decoration_manager && SDL_WAYLAND_HAVE_WAYLAND_LIBDECOR && SDL_GetHintBoolean(SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR, SDL_TRUE)) {
+    if (should_use_libdecor(data)) {
         data->shell.libdecor = libdecor_new(data->display, &libdecor_interface);
 
         /* If libdecor works, we don't need xdg-shell anymore. */