From c1a2d58f96569da4ddfa07f2acb2198e34b68e80 Mon Sep 17 00:00:00 2001
From: Frank Praznik <[EMAIL REDACTED]>
Date: Mon, 26 Jun 2023 15:48:45 -0400
Subject: [PATCH] Implement SDL_GetWindowWMInfo
---
src/sdl2_compat.c | 176 ++++++++++++++++++++++++++++++++++------------
src/sdl2_compat.h | 140 ++++++++++++++++++++++++++++++++++++
2 files changed, 270 insertions(+), 46 deletions(-)
diff --git a/src/sdl2_compat.c b/src/sdl2_compat.c
index d5776e0..d023d46 100644
--- a/src/sdl2_compat.c
+++ b/src/sdl2_compat.c
@@ -667,27 +667,6 @@ BOOL WINAPI _DllMainCRTStartup(HANDLE dllhandle, DWORD reason, LPVOID reserved)
#define SDL2_RENDERER_TARGETTEXTURE 0x00000008
-/* this enum changed in SDL3. */
-typedef enum
-{
- SDL2_SYSWM_UNKNOWN,
- SDL2_SYSWM_WINDOWS,
- SDL2_SYSWM_X11,
- SDL2_SYSWM_DIRECTFB,
- SDL2_SYSWM_COCOA,
- SDL2_SYSWM_UIKIT,
- SDL2_SYSWM_WAYLAND,
- SDL2_SYSWM_MIR,
- SDL2_SYSWM_WINRT,
- SDL2_SYSWM_ANDROID,
- SDL2_SYSWM_VIVANTE,
- SDL2_SYSWM_OS2,
- SDL2_SYSWM_HAIKU,
- SDL2_SYSWM_KMSDRM,
- SDL2_SYSWM_RISCOS
-} SDL2_SYSWM_TYPE;
-
-
/* Events changed in SDL3; notably, the `timestamp` field moved from
32 bit milliseconds to 64-bit nanoseconds, and the padding of the union
changed, so all the SDL2 structs have to be reproduced here. */
@@ -1285,30 +1264,6 @@ SDL_LOG_IMPL(Critical, CRITICAL)
#undef SDL_LOG_IMPL
-#if 0
-static SDL2_SYSWM_TYPE
-SysWmType3to2(const SDL_SYSWM_TYPE typ3)
-{
- switch (typ3) {
- case SDL_SYSWM_UNKNOWN: return SDL2_SYSWM_UNKNOWN;
- case SDL_SYSWM_ANDROID: return SDL2_SYSWM_ANDROID;
- case SDL_SYSWM_COCOA: return SDL2_SYSWM_COCOA;
- case SDL_SYSWM_HAIKU: return SDL2_SYSWM_HAIKU;
- case SDL_SYSWM_KMSDRM: return SDL2_SYSWM_KMSDRM;
- case SDL_SYSWM_RISCOS: return SDL2_SYSWM_RISCOS;
- case SDL_SYSWM_UIKIT: return SDL2_SYSWM_UIKIT;
- case SDL_SYSWM_VIVANTE: return SDL2_SYSWM_VIVANTE;
- case SDL_SYSWM_WAYLAND: return SDL2_SYSWM_WAYLAND;
- case SDL_SYSWM_WINDOWS: return SDL2_SYSWM_WINDOWS;
- case SDL_SYSWM_WINRT: return SDL2_SYSWM_WINRT;
- case SDL_SYSWM_X11: return SDL2_SYSWM_X11;
- default: break;
- }
- return SDL2_SYSWM_UNKNOWN;
-}
-#endif
-
-
/* (current) strategy for SDL_Events:
in sdl12-compat, we built our own event queue, so when the SDL2 queue is pumped, we
took the events we cared about and added them to the sdl12-compat queue, and otherwise
@@ -2333,10 +2288,139 @@ SDL_GetTicks64(void)
return SDL3_GetTicks();
}
+static SDL_bool
+SysWMInfo3to2(SDL_SysWMinfo *wminfo3, SDL2_SysWMinfo *wminfo2)
+{
+ switch (wminfo3->subsystem) {
+#if defined(SDL_ENABLE_SYSWM_ANDROID)
+ case SDL_SYSWM_ANDROID:
+ wminfo2->subsystem = SDL2_SYSWM_ANDROID;
+ wminfo2->info.android.window = wminfo3->info.android.window;
+ wminfo2->info.android.surface = wminfo3->info.android.surface;
+ break;
+#endif
+#if defined(SDL_ENABLE_SYSWM_COCOA)
+ case SDL_SYSWM_COCOA:
+ wminfo2->subsystem = SDL2_SYSWM_COCOA;
+ wminfo2->info.cocoa.window = wminfo3->info.cocoa.window;
+ break;
+#endif
+#if defined(SDL_ENABLE_SYSWM_DIRECTFB)
+ case SDL_SYSWM_DIRECTFB:
+ wminfo2->info.dfb.dfb = wminfo3->info.dfb.dfb;
+ wminfo2->info.dfb.window = wminfo3->info.dfb.window;
+ wminfo2->info.dfb.surface = wminfo3->info.dfb.surface;
+ break;
+#endif
+#if defined(SDL_ENABLE_SYSWM_KMSDRM)
+ case SDL_SYSWM_KMSDRM:
+ wminfo2->subsystem = SDL2_SYSWM_KMSDRM;
+ wminfo2->info.kmsdrm.dev_index = wminfo3->info.kmsdrm.dev_index;
+ wminfo2->info.kmsdrm.drm_fd = wminfo3->info.kmsdrm.drm_fd;
+ wminfo2->info.kmsdrm.gbm_dev = wminfo3->info.kmsdrm.gbm_dev;
+ break;
+#endif
+#if defined(SDL_ENABLE_SYSWM_OS2)
+ case SDL_SYSWM_OS2:
+ wminfo2->subsystem = SDL2_SYSWM_OS2;
+ wminfo2->info.os2.hwnd = wminfo3->info.os2.hwnd;
+ wminfo2->info.os2.hwndFrame = wminfo3->info.os2.hwndFrame;
+ break;
+#endif
+#if defined(SDL_ENABLE_SYSWM_UIKIT)
+ case SDL_SYSWM_COCOA:
+ wminfo2->subsystem = SDL2_SYSWM_UIKIT;
+ wminfo2->info.uikit.window = wminfo3->info.uikit.window;
+ break;
+#endif
+#if defined(SDL_ENABLE_SYSWM_VIVANTE)
+ case SDL_SYSWM_VIVANTE:
+ wminfo2->subsystem = SDL2_SYSWM_VIVANTE;
+ wminfo2->info.vivante.display = wminfo3->info.vivante.display;
+ wminfo2->info.vivante.window = wminfo3->info.vivante.window;
+ break;
+#endif
+#if defined(SDL_ENABLE_SYSWM_WAYLAND)
+ case SDL_SYSWM_WAYLAND: {
+ Uint32 version2 = SDL_VERSIONNUM((Uint32)wminfo2->version.major,
+ (Uint32)wminfo2->version.minor,
+ (Uint32)wminfo2->version.patch);
+
+ /* Before 2.0.6, it was possible to build an SDL with Wayland support
+ * (SDL_SysWMinfo will be large enough to hold Wayland info), but build
+ * your app against SDL headers that didn't have Wayland support
+ * (SDL_SysWMinfo could be smaller than Wayland needs. This would lead
+ * to an app properly using SDL_GetWindowWMInfo() but we'd accidentally
+ * overflow memory on the stack or heap. To protect against this, we've
+ * padded out the struct unconditionally in the headers and Wayland will
+ * just return an error for older apps using this function. Those apps
+ * will need to be recompiled against newer headers or not use Wayland,
+ * maybe by forcing SDL_VIDEODRIVER=x11.
+ */
+ if (version2 < SDL_VERSIONNUM(2, 0, 6)) {
+ wminfo2->subsystem = SDL2_SYSWM_UNKNOWN;
+ SDL_SetError("Version must be 2.0.6 or newer");
+ return SDL_FALSE;
+ }
+
+ wminfo2->subsystem = SDL2_SYSWM_WAYLAND;
+ wminfo2->info.wl.display = wminfo3->info.wl.display;
+ wminfo2->info.wl.surface = wminfo3->info.wl.surface;
+ wminfo2->info.wl.shell_surface = NULL; /* Deprecated */
+
+ if (version2 >= SDL_VERSIONNUM(2, 0, 15)) {
+ wminfo2->info.wl.egl_window = wminfo3->info.wl.egl_window;
+ wminfo2->info.wl.xdg_surface = wminfo3->info.wl.xdg_surface;
+ if (version2 >= SDL_VERSIONNUM(2, 0, 17)) {
+ wminfo2->info.wl.xdg_toplevel = wminfo3->info.wl.xdg_toplevel;
+ if (version2 >= SDL_VERSIONNUM(2, 0, 22)) {
+ wminfo2->info.wl.xdg_popup = wminfo3->info.wl.xdg_popup;
+ wminfo2->info.wl.xdg_positioner =
+ wminfo3->info.wl.xdg_positioner;
+ }
+ }
+ }
+ } break;
+#endif
+#if defined(SDL_ENABLE_SYSWM_WINDOWS)
+ case SDL_SYSWM_WINDOWS:
+ wminfo2->subsystem = SDL2_SYSWM_WINDOWS;
+ wminfo2->info.win.window = wminfo3->info.win.window;
+ wminfo2->info.win.hdc = wminfo3->info.win.hdc;
+ wminfo2->info.win.hinstance = wminfo3->info.win.hinstance;
+ break;
+#endif
+#if defined(SDL_ENABLE_SYSWM_WINRT)
+ case SDL_SYSWM_WINRT:
+ wminfo2->subsystem = SDL2_SYSWM_WINRT;
+ wminfo2->info.winrt.window = wminfo3->info.winrt.window;
+ break;
+#endif
+#if defined(SDL_ENABLE_SYSWM_X11)
+ case SDL_SYSWM_X11:
+ wminfo2->subsystem = SDL2_SYSWM_X11;
+ wminfo2->info.x11.display = wminfo3->info.x11.display;
+ wminfo2->info.x11.window = wminfo3->info.x11.window;
+ break;
+#endif
+ default:
+ wminfo2->subsystem = SDL2_SYSWM_UNKNOWN;
+ return SDL_FALSE;
+ }
+
+ return SDL_TRUE;
+}
+
DECLSPEC SDL_bool SDLCALL
SDL_GetWindowWMInfo(SDL_Window *window, SDL_SysWMinfo *wminfo)
{
- SDL3_Unsupported(); /* !!! FIXME: write me. */
+ SDL_SysWMinfo wminfo3;
+ SDL3_zero(wminfo3);
+
+ if (SDL3_GetWindowWMInfo(window, &wminfo3, SDL_VERSIONNUM(3, 0, 0)) == 0) {
+ return SysWMInfo3to2(&wminfo3, (SDL2_SysWMinfo*)wminfo);
+ }
+
return SDL_FALSE;
}
diff --git a/src/sdl2_compat.h b/src/sdl2_compat.h
index 501765d..e4abf0e 100644
--- a/src/sdl2_compat.h
+++ b/src/sdl2_compat.h
@@ -108,4 +108,144 @@ typedef struct SDL2_AudioStream
SDL_AudioFormat dst_format;
} SDL2_AudioStream;
+typedef enum
+{
+ SDL2_SYSWM_UNKNOWN,
+ SDL2_SYSWM_WINDOWS,
+ SDL2_SYSWM_X11,
+ SDL2_SYSWM_DIRECTFB,
+ SDL2_SYSWM_COCOA,
+ SDL2_SYSWM_UIKIT,
+ SDL2_SYSWM_WAYLAND,
+ SDL2_SYSWM_MIR, /* no longer available, left for API/ABI compatibility. */
+ SDL2_SYSWM_WINRT,
+ SDL2_SYSWM_ANDROID,
+ SDL2_SYSWM_VIVANTE,
+ SDL2_SYSWM_OS2,
+ SDL2_SYSWM_HAIKU,
+ SDL2_SYSWM_KMSDRM,
+ SDL2_SYSWM_RISCOS
+} SDL2_SYSWM_TYPE;
+
+struct SDL2_SysWMinfo
+{
+ SDL_version version;
+ SDL2_SYSWM_TYPE subsystem;
+ union
+ {
+#if defined(SDL_ENABLE_SYSWM_WINDOWS)
+ struct
+ {
+ HWND window; /**< The window handle */
+ HDC hdc; /**< The window device context */
+ HINSTANCE hinstance; /**< The instance handle */
+ } win;
+#endif
+#if defined(SDL_ENABLE_SYSWM_WINRT)
+ struct
+ {
+ IInspectable * window; /**< The WinRT CoreWindow */
+ } winrt;
+#endif
+#if defined(SDL_ENABLE_SYSWM_X11)
+ struct
+ {
+ Display *display; /**< The X11 display */
+ Window window; /**< The X11 window */
+ } x11;
+#endif
+#if defined(SDL_ENABLE_SYSWM_DIRECTFB)
+ struct
+ {
+ IDirectFB *dfb; /**< The directfb main interface */
+ IDirectFBWindow *window; /**< The directfb window handle */
+ IDirectFBSurface *surface; /**< The directfb client surface */
+ } dfb;
+#endif
+#if defined(SDL_ENABLE_SYSWM_COCOA)
+ struct
+ {
+#if defined(__OBJC__) && defined(__has_feature)
+#if __has_feature(objc_arc)
+ NSWindow __unsafe_unretained *window; /**< The Cocoa window */
+#else
+ NSWindow *window; /**< The Cocoa window */
+#endif
+#else
+ NSWindow *window; /**< The Cocoa window */
+#endif
+ } cocoa;
+#endif
+#if defined(SDL_ENABLE_SYSWM_UIKIT)
+ struct
+ {
+#if defined(__OBJC__) && defined(__has_feature)
+#if __has_feature(objc_arc)
+ UIWindow __unsafe_unretained *window; /**< The UIKit window */
+#else
+ UIWindow *window; /**< The UIKit window */
+#endif
+#else
+ UIWindow *window; /**< The UIKit window */
+#endif
+ GLuint framebuffer; /**< The GL view's Framebuffer Object. It must be bound when rendering to the screen using GL. */
+ GLuint colorbuffer; /**< The GL view's color Renderbuffer Object. It must be bound when SDL_GL_SwapWindow is called. */
+ GLuint resolveFramebuffer; /**< The Framebuffer Object which holds the resolve color Renderbuffer, when MSAA is used. */
+ } uikit;
+#endif
+#if defined(SDL_ENABLE_SYSWM_WAYLAND)
+ struct
+ {
+ struct wl_display *display; /**< Wayland display */
+ struct wl_surface *surface; /**< Wayland surface */
+ void *shell_surface; /**< DEPRECATED Wayland shell_surface (window manager handle) */
+ struct wl_egl_window *egl_window; /**< Wayland EGL window (native window) */
+ struct xdg_surface *xdg_surface; /**< Wayland xdg surface (window manager handle) */
+ struct xdg_toplevel *xdg_toplevel; /**< Wayland xdg toplevel role */
+ struct xdg_popup *xdg_popup; /**< Wayland xdg popup role */
+ struct xdg_positioner *xdg_positioner; /**< Wayland xdg positioner, for popup */
+ } wl;
+#endif
+
+#if defined(SDL_ENABLE_SYSWM_ANDROID)
+ struct
+ {
+ ANativeWindow *window;
+ EGLSurface surface;
+ } android;
+#endif
+
+#if defined(SDL_ENABLE_SYSWM_OS2)
+ struct
+ {
+ HWND hwnd; /**< The window handle */
+ HWND hwndFrame; /**< The frame window handle */
+ } os2;
+#endif
+
+#if defined(SDL_ENABLE_SYSWM_VIVANTE)
+ struct
+ {
+ EGLNativeDisplayType display;
+ EGLNativeWindowType window;
+ } vivante;
+#endif
+
+#if defined(SDL_ENABLE_SYSWM_KMSDRM)
+ struct
+ {
+ int dev_index; /**< Device index (ex: the X in /dev/dri/cardX) */
+ int drm_fd; /**< DRM FD (unavailable on Vulkan windows) */
+ struct gbm_device *gbm_dev; /**< GBM device (unavailable on Vulkan windows) */
+ } kmsdrm;
+#endif
+
+ /* Make sure this union is always 64 bytes (8 64-bit pointers). */
+ /* Be careful not to overflow this if you add a new target! */
+ Uint8 dummy[64];
+ } info;
+};
+
+typedef struct SDL2_SysWMinfo SDL2_SysWMinfo;
+
#endif /* sdl2_compat_h */