SDL: wayland: libdecor support for SetWindowModalFor

From ad310d39009ad4ca57fc39bd6c7dff6964f2291d Mon Sep 17 00:00:00 2001
From: Ethan Lee <[EMAIL REDACTED]>
Date: Wed, 28 Jul 2021 12:31:25 -0400
Subject: [PATCH] wayland: libdecor support for SetWindowModalFor

---
 src/video/wayland/SDL_waylanddyn.h    |  1 +
 src/video/wayland/SDL_waylandsym.h    |  2 ++
 src/video/wayland/SDL_waylandwindow.c | 14 ++++++++++++++
 3 files changed, 17 insertions(+)

diff --git a/src/video/wayland/SDL_waylanddyn.h b/src/video/wayland/SDL_waylanddyn.h
index 62963a505..6cd527316 100644
--- a/src/video/wayland/SDL_waylanddyn.h
+++ b/src/video/wayland/SDL_waylanddyn.h
@@ -138,6 +138,7 @@ void SDL_WAYLAND_UnloadSymbols(void);
 #define libdecor_frame_set_visibility (*WAYLAND_libdecor_frame_set_visibility)
 #define libdecor_frame_is_visible (*WAYLAND_libdecor_frame_is_visible)
 #define libdecor_frame_is_floating (*WAYLAND_libdecor_frame_is_floating)
+#define libdecor_frame_set_parent (*WAYLAND_libdecor_frame_set_parent)
 #define libdecor_frame_get_xdg_surface (*WAYLAND_libdecor_frame_get_xdg_surface)
 #define libdecor_frame_map (*WAYLAND_libdecor_frame_map)
 #define libdecor_state_new (*WAYLAND_libdecor_state_new)
diff --git a/src/video/wayland/SDL_waylandsym.h b/src/video/wayland/SDL_waylandsym.h
index 5e25e8973..10602740b 100644
--- a/src/video/wayland/SDL_waylandsym.h
+++ b/src/video/wayland/SDL_waylandsym.h
@@ -179,6 +179,8 @@ SDL_WAYLAND_SYM(bool, libdecor_frame_has_capability, (struct libdecor_frame *, \
 SDL_WAYLAND_SYM(void, libdecor_frame_set_visibility, (struct libdecor_frame *, bool))
 SDL_WAYLAND_SYM(bool, libdecor_frame_is_visible, (struct libdecor_frame *))
 SDL_WAYLAND_SYM(bool, libdecor_frame_is_floating, (struct libdecor_frame *))
+SDL_WAYLAND_SYM(void, libdecor_frame_set_parent, (struct libdecor_frame *,\
+                                                  struct libdecor_frame *))
 SDL_WAYLAND_SYM(struct xdg_surface *, libdecor_frame_get_xdg_surface, (struct libdecor_frame *))
 SDL_WAYLAND_SYM(void, libdecor_frame_map, (struct libdecor_frame *))
 SDL_WAYLAND_SYM(struct libdecor_state *, libdecor_state_new, (int, int))
diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c
index 424a6a654..7f0f0702b 100644
--- a/src/video/wayland/SDL_waylandwindow.c
+++ b/src/video/wayland/SDL_waylandwindow.c
@@ -595,6 +595,18 @@ Wayland_SetWindowModalFor(_THIS, SDL_Window *modal_window, SDL_Window *parent_wi
     SDL_WindowData *modal_data = modal_window->driverdata;
     SDL_WindowData *parent_data = parent_window->driverdata;
 
+#ifdef HAVE_LIBDECOR_H
+    if (viddata->shell.libdecor) {
+        if (modal_data->shell_surface.libdecor.frame == NULL) {
+            return SDL_SetError("Modal window was hidden");
+        }
+        if (parent_data->shell_surface.libdecor.frame == NULL) {
+            return SDL_SetError("Parent window was hidden");
+        }
+        libdecor_frame_set_parent(modal_data->shell_surface.libdecor.frame,
+                                  parent_data->shell_surface.libdecor.frame);
+    } else
+#endif
     if (viddata->shell.xdg) {
         if (modal_data->shell_surface.xdg.roleobj.toplevel == NULL) {
             return SDL_SetError("Modal window was hidden");
@@ -604,6 +616,8 @@ Wayland_SetWindowModalFor(_THIS, SDL_Window *modal_window, SDL_Window *parent_wi
         }
         xdg_toplevel_set_parent(modal_data->shell_surface.xdg.roleobj.toplevel,
                                 parent_data->shell_surface.xdg.roleobj.toplevel);
+    } else {
+        return SDL_Unsupported();
     }
 
     WAYLAND_wl_display_flush(viddata->display);