From b13166f31a1d1b315744e6cc45901173d99590c7 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Mon, 8 Aug 2022 11:02:38 -0400
Subject: [PATCH] syswm: Added a magic hack so apps can access actual SDL2
SysWM information.
Fixes #186.
---
CMakeLists.txt | 1 +
include/SDL/SDL_syswm.h | 16 +++++
src/SDL12_compat.c | 127 +++++++++++++++++++++++++++++++++++++++-
test/README | 1 +
test/testsyswm2on12.c | 113 +++++++++++++++++++++++++++++++++++
5 files changed, 257 insertions(+), 1 deletion(-)
create mode 100644 test/testsyswm2on12.c
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e7a847cd7..70cdb5a33 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -217,6 +217,7 @@ if(SDL12TESTS)
test_program(torturethread "test/torturethread.c")
test_program(testdyngl "test/testdyngl.c")
test_program(testgl "test/testgl.c")
+ test_program(testsyswm2on12 "test/testsyswm2on12.c")
if(OPENGL_FOUND)
if(CMAKE_VERSION VERSION_LESS 3.10 OR NOT OPENGL_opengl_LIBRARY)
target_link_libraries(testgl ${OPENGL_gl_LIBRARY})
diff --git a/include/SDL/SDL_syswm.h b/include/SDL/SDL_syswm.h
index 007618d10..af1931126 100644
--- a/include/SDL/SDL_syswm.h
+++ b/include/SDL/SDL_syswm.h
@@ -120,6 +120,22 @@ real SDL-1.2 available to you. */
#include "begin_code.h"
+/* SPECIAL CASE FOR SDL12-COMPAT: if version.major == 2, we'll fill in this struct with the native window handle. */
+/* This is not part of the real 1.2 API! */
+typedef struct SDL_SysWMinfo2on12
+{
+ SDL_version version;
+ SDL_SYSWM_TYPE subsystem;
+ void *data1;
+ void *data2;
+ void *data3;
+ void *data4;
+ void *data5;
+ void *data6;
+ void *data7;
+ void *data8;
+} SDL_SysWMinfo2on12;
+
extern DECLSPEC int SDLCALL SDL_GetWMInfo(SDL_SysWMinfo *info);
#include "close_code.h"
diff --git a/src/SDL12_compat.c b/src/SDL12_compat.c
index 1339644fd..022900341 100644
--- a/src/SDL12_compat.c
+++ b/src/SDL12_compat.c
@@ -641,6 +641,22 @@ typedef struct SDL12_SysWMinfo
#endif
} SDL12_SysWMinfo;
+/* SPECIAL CASE FOR SDL12-COMPAT: if version.major == 2, we'll fill in this struct with the native window handle. */
+/* This is not part of the real 1.2 API! */
+typedef struct SDL12_SysWMinfo2on12
+{
+ SDL_version version;
+ SDL12_SYSWM_TYPE subsystem;
+ void *data1;
+ void *data2;
+ void *data3;
+ void *data4;
+ void *data5;
+ void *data6;
+ void *data7;
+ void *data8;
+} SDL12_SysWMinfo2on12;
+
typedef enum
{
@@ -6451,9 +6467,10 @@ SDL_GetWMInfo(SDL12_SysWMinfo *info12)
SDL_SysWMinfo info20;
SDL_bool temp_window = SDL_FALSE;
SDL_Window *win20 = VideoWindow20;
+ const SDL_bool do_2on12 = ((info12->version.major == 2) && (info12->version.minor == 0) && (info12->version.major == 2) && (info12->version.patch == 0));
int rc;
- if (info12->version.major > 1) {
+ if ((info12->version.major > 1) && !do_2on12) {
SDL20_SetError("Requested version is unsupported");
return 0; /* some programs only test against 0, not -1 */
} else if (!SupportSysWM) {
@@ -6482,6 +6499,114 @@ SDL_GetWMInfo(SDL12_SysWMinfo *info12)
return 0; /* some programs only test against 0, not -1 */
}
+ /* SPECIAL CASE FOR SDL12-COMPAT: if version.major == 2, we'll fill in this struct with the native window handle. */
+ if (do_2on12) {
+ SDL12_SysWMinfo2on12 *wminfo2 = (SDL12_SysWMinfo2on12 *) info12;
+ SDL_zerop(wminfo2);
+ SDL20_memcpy(&wminfo2->version, &info20.version, sizeof (wminfo2->version));
+ wminfo2->subsystem = info20.subsystem; /* these do not map to SDL 1.2 values! You're on your own! */
+
+ switch (info20.subsystem) {
+ #if defined(SDL_VIDEO_DRIVER_WINDOWS)
+ case SDL_SYSWM_WINDOWS:
+ wminfo2->data1 = (void *) info20.info.win.window;
+ wminfo2->data2 = (void *) info20.info.win.hdc;
+ wminfo2->data3 = (void *) info20.info.win.hinstance;
+ break;
+ #endif
+
+ #if defined(SDL_VIDEO_DRIVER_WINRT)
+ case SDL_SYSWM_WINRT:
+ wminfo2->data1 = (void *) info20.info.winrt.window;
+ break;
+ #endif
+
+ #if defined(SDL_VIDEO_DRIVER_X11)
+ case SDL_SYSWM_X11:
+ wminfo2->data1 = (void *) info20.info.x11.display;
+ wminfo2->data2 = (void *) info20.info.x11.window;
+ break;
+ #endif
+
+ #if defined(SDL_VIDEO_DRIVER_DIRECTFB)
+ case SDL_SYSWM_DIRECTFB:
+ wminfo2->data1 = (void *) info20.info.dfb.dfb;
+ wminfo2->data2 = (void *) info20.info.dfb.window;
+ wminfo2->data3 = (void *) info20.info.dfb.surface;
+ break;
+ #endif
+
+ #if defined(SDL_VIDEO_DRIVER_COCOA)
+ case SDL_SYSWM_COCOA:
+ wminfo2->data1 = (void *) info20.info.cocoa.window;
+ break;
+ #endif
+
+ #if defined(SDL_VIDEO_DRIVER_UIKIT)
+ case SDL_SYSWM_UIKIT:
+ wminfo2->data1 = (void *) info20.info.uikit.window;
+ wminfo2->data2 = (void *) info20.info.uikit.framebuffer;
+ wminfo2->data3 = (void *) info20.info.uikit.colorbuffer;
+ wminfo2->data4 = (void *) info20.info.uikit.resolveFramebuffer;
+ break;
+ #endif
+
+ #if defined(SDL_VIDEO_DRIVER_WAYLAND)
+ case SDL_SYSWM_WAYLAND:
+ wminfo2->data1 = (void *) info20.info.wl.display;
+ wminfo2->data2 = (void *) info20.info.wl.surface;
+ wminfo2->data3 = (void *) info20.info.wl.shell_surface;
+ wminfo2->data4 = (void *) info20.info.wl.egl_window;
+ wminfo2->data5 = (void *) info20.info.wl.xdg_surface;
+ wminfo2->data6 = (void *) info20.info.wl.xdg_toplevel;
+ wminfo2->data7 = (void *) info20.info.wl.xdg_popup;
+ wminfo2->data8 = (void *) info20.info.wl.xdg_positioner;
+ break;
+ #endif
+
+ #if defined(SDL_VIDEO_DRIVER_MIR) /* no longer available, left for API/ABI compatibility. Remove in 2.1! */
+ case SDL_SYSWM_MIR:
+ wminfo2->data1 = (void *) info20.info.mir.connection;
+ wminfo2->data2 = (void *) info20.info.mir.surface;
+ break;
+ #endif
+
+ #if defined(SDL_VIDEO_DRIVER_ANDROID)
+ case SDL_SYSWM_ANDROID:
+ wminfo2->data1 = (void *) info20.info.android.window;
+ wminfo2->data2 = (void *) info20.info.android.surface;
+ break;
+ #endif
+
+ #if defined(SDL_VIDEO_DRIVER_OS2)
+ case SDL_SYSWM_OS2:
+ wminfo2->data1 = (void *) info20.info.os2.hwnd;
+ wminfo2->data2 = (void *) info20.info.os2.hwndFrame;
+ break;
+ #endif
+
+ #if defined(SDL_VIDEO_DRIVER_VIVANTE)
+ case SDL_SYSWM_VIVANTE:
+ wminfo2->data1 = (void *) info20.info.vivante.display;
+ wminfo2->data2 = (void *) info20.info.vivante.window;
+ break;
+ #endif
+
+ #if defined(SDL_VIDEO_DRIVER_KMSDRM)
+ case SDL_SYSWM_KMSDRM:
+ wminfo2->data1 = (void *) (size_t) info20.info.kmsdrm.dev_index;
+ wminfo2->data2 = (void *) (size_t) info20.info.kmsdrm.drm_fd;
+ wminfo2->data3 = (void *) (size_t) info20.info.kmsdrm.gbm_dev;
+ break;
+ #endif
+
+ default:
+ return 0;
+ }
+
+ return 1;
+ }
+
#if defined(SDL_VIDEO_DRIVER_WINDOWS)
SDL_assert(info20.subsystem == SDL_SYSWM_WINDOWS);
info12->window = temp_window ? 0 : info20.info.win.window;
diff --git a/test/README b/test/README
index e158b4e42..a77450a7b 100644
--- a/test/README
+++ b/test/README
@@ -33,3 +33,4 @@ These are test programs for the SDL library:
testwm Test window manager -- title, icon, events
threadwin Test multi-threaded event handling
torturethread Simple test for thread creation/destruction
+ testsyswm2on12 Simple test for SDL_SysWM2on12 compatibility magic.
\ No newline at end of file
diff --git a/test/testsyswm2on12.c b/test/testsyswm2on12.c
new file mode 100644
index 000000000..c4ee0dad2
--- /dev/null
+++ b/test/testsyswm2on12.c
@@ -0,0 +1,113 @@
+/* this isn't a classic SDL 1.2 test program, this tests a little
+ compatibility magic that only exists in sdl12-compat. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "SDL.h"
+#include "SDL_syswm.h"
+
+/* so this will compile with classic 1.2 headers... */
+#ifndef SDL12_COMPAT_HEADERS
+#include "begin_code.h"
+typedef struct SDL_SysWMinfo2on12
+{
+ SDL_version version;
+ SDL_SYSWM_TYPE subsystem;
+ void *data1;
+ void *data2;
+ void *data3;
+ void *data4;
+ void *data5;
+ void *data6;
+ void *data7;
+ void *data8;
+} SDL_SysWMinfo2on12;
+#include "end_code.h"
+#endif
+
+typedef enum
+{
+ SDL20_SYSWM_UNKNOWN,
+ SDL20_SYSWM_WINDOWS,
+ SDL20_SYSWM_X11,
+ SDL20_SYSWM_DIRECTFB,
+ SDL20_SYSWM_COCOA,
+ SDL20_SYSWM_UIKIT,
+ SDL20_SYSWM_WAYLAND,
+ SDL20_SYSWM_MIR,
+ SDL20_SYSWM_WINRT,
+ SDL20_SYSWM_ANDROID,
+ SDL20_SYSWM_VIVANTE,
+ SDL20_SYSWM_OS2,
+ SDL20_SYSWM_HAIKU,
+ SDL20_SYSWM_KMSDRM,
+ SDL20_SYSWM_RISCOS
+} SDL20_SYSWM_TYPE;
+
+static const char *
+subsystem_name(const SDL20_SYSWM_TYPE typ)
+{
+ static char unrecognized[64];
+ switch (typ) {
+ case SDL20_SYSWM_UNKNOWN: return "Unknown";
+ case SDL20_SYSWM_WINDOWS: return "Windows";
+ case SDL20_SYSWM_X11: return "X11";
+ case SDL20_SYSWM_DIRECTFB: return "DirectFB";
+ case SDL20_SYSWM_COCOA: return "Cocoa";
+ case SDL20_SYSWM_UIKIT: return "UIKit";
+ case SDL20_SYSWM_WAYLAND: return "Wayland";
+ case SDL20_SYSWM_MIR: return "Mir";
+ case SDL20_SYSWM_WINRT: return "WinRT";
+ case SDL20_SYSWM_ANDROID: return "Android";
+ case SDL20_SYSWM_VIVANTE: return "Vivante";
+ case SDL20_SYSWM_OS2: return "OS/2";
+ case SDL20_SYSWM_HAIKU: return "Haiku";
+ case SDL20_SYSWM_KMSDRM: return "KMSDRM";
+ case SDL20_SYSWM_RISCOS: return "RiscOS";
+ default: break;
+ }
+
+ snprintf(unrecognized, sizeof (unrecognized), "Unrecognized (%d)", (int) typ);
+ return unrecognized;
+}
+
+int main(int argc, char **argv)
+{
+ SDL_SysWMinfo2on12 syswm_info;
+
+ if (SDL_Init(SDL_INIT_VIDEO) < 0) {
+ fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ if (SDL_SetVideoMode(640, 480, 32, 0) == NULL) {
+ fprintf(stderr, "Couldn't create an SDL window: %s\n", SDL_GetError());
+ SDL_Quit();
+ return 1;
+ }
+
+ SDL_memset(&syswm_info, '\0', sizeof (syswm_info));
+ syswm_info.version.major = 2; /* this triggers magic in sdl12-compat */
+
+ /* obviously this should fail with classic SDL 1.2. */
+ if (SDL_GetWMInfo((SDL_SysWMinfo *) &syswm_info) != 1) {
+ fprintf(stderr, "Failed to get syswm 2on12 info: %s\n", SDL_GetError());
+ } else {
+ printf("SysWM2on12 info:\n");
+ printf("Version: %d.%d.%d\n", syswm_info.version.major, syswm_info.version.minor, syswm_info.version.patch);
+ printf("Subsystem: %s\n", subsystem_name(syswm_info.subsystem));
+ printf("data1: %p\n", syswm_info.data1);
+ printf("data2: %p\n", syswm_info.data2);
+ printf("data3: %p\n", syswm_info.data3);
+ printf("data4: %p\n", syswm_info.data4);
+ printf("data5: %p\n", syswm_info.data5);
+ printf("data6: %p\n", syswm_info.data6);
+ printf("data7: %p\n", syswm_info.data7);
+ printf("data8: %p\n", syswm_info.data8);
+ }
+
+ SDL_Quit();
+ return 0;
+}
+