SDL: Let the renderer always see window events

From ad8429f1b0bc5312ab01ade14d37c596a4f780b0 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 6 Feb 2025 14:25:00 -0800
Subject: [PATCH] Let the renderer always see window events

These are necessary for proper operation of the renderer and shouldn't be blocked by event filters, etc.
---
 src/events/SDL_windowevents.c | 20 +++++++----
 src/render/SDL_render.c       | 63 +++++++++++++----------------------
 src/render/SDL_sysrender.h    |  6 ++++
 3 files changed, 42 insertions(+), 47 deletions(-)

diff --git a/src/events/SDL_windowevents.c b/src/events/SDL_windowevents.c
index 2258ce793c837..fe02450b2102f 100644
--- a/src/events/SDL_windowevents.c
+++ b/src/events/SDL_windowevents.c
@@ -24,6 +24,7 @@
 
 #include "SDL_events_c.h"
 #include "SDL_mouse_c.h"
+#include "../render/SDL_sysrender.h"
 #include "../tray/SDL_tray_utils.h"
 
 static bool SDLCALL RemoveSupercededWindowEvents(void *userdata, SDL_Event *event)
@@ -183,14 +184,19 @@ bool SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, int data
     }
 
     // Post the event, if desired
-    if (SDL_EventEnabled(windowevent)) {
-        SDL_Event event;
-        event.type = windowevent;
-        event.common.timestamp = 0;
-        event.window.data1 = data1;
-        event.window.data2 = data2;
-        event.window.windowID = window->id;
+    SDL_Event event;
+    event.type = windowevent;
+    event.common.timestamp = 0;
+    event.window.data1 = data1;
+    event.window.data2 = data2;
+    event.window.windowID = window->id;
+
+    SDL_Renderer *renderer = (SDL_Renderer *)SDL_GetPointerProperty(window->props, SDL_PROP_WINDOW_RENDERER_POINTER, NULL);
+    if (renderer) {
+        SDL_RendererEventWatch(renderer, &event);
+    }
 
+    if (SDL_EventEnabled(windowevent)) {
         // Fixes queue overflow with move/resize events that aren't processed
         if (windowevent == SDL_EVENT_WINDOW_MOVED ||
             windowevent == SDL_EVENT_WINDOW_RESIZED ||
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index b6d6db7162d3d..4051eab5b901b 100644
--- a/src/render/SDL_render.c
+++ b/src/render/SDL_render.c
@@ -45,9 +45,6 @@ this should probably be removed at some point in the future.  --ryan. */
 #define DONT_DRAW_WHILE_HIDDEN 0
 #endif
 
-#define SDL_PROP_WINDOW_RENDERER_POINTER "SDL.internal.window.renderer"
-#define SDL_PROP_TEXTURE_PARENT_POINTER "SDL.internal.texture.parent"
-
 #define CHECK_RENDERER_MAGIC_BUT_NOT_DESTROYED_FLAG(renderer, result)   \
     if (!SDL_ObjectValid(renderer, SDL_OBJECT_TYPE_RENDERER)) {         \
         SDL_InvalidParamError("renderer");                              \
@@ -821,43 +818,35 @@ const char *SDL_GetRenderDriver(int index)
 #endif
 }
 
-static bool SDLCALL SDL_RendererEventWatch(void *userdata, SDL_Event *event)
+void SDL_RendererEventWatch(SDL_Renderer *renderer, SDL_Event *event)
 {
-    SDL_Renderer *renderer = (SDL_Renderer *)userdata;
+    SDL_Window *window = renderer->window;
 
-    if (event->type >= SDL_EVENT_WINDOW_FIRST && event->type <= SDL_EVENT_WINDOW_LAST) {
-        SDL_Window *window = SDL_GetWindowFromID(event->window.windowID);
-        if (window == renderer->window) {
-            if (renderer->WindowEvent) {
-                renderer->WindowEvent(renderer, &event->window);
-            }
+    if (renderer->WindowEvent) {
+        renderer->WindowEvent(renderer, &event->window);
+    }
 
-            if (event->type == SDL_EVENT_WINDOW_RESIZED ||
-                event->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED ||
-                event->type == SDL_EVENT_WINDOW_METAL_VIEW_RESIZED) {
-                UpdateLogicalPresentation(renderer);
-            } else if (event->type == SDL_EVENT_WINDOW_HIDDEN) {
-                renderer->hidden = true;
-            } else if (event->type == SDL_EVENT_WINDOW_SHOWN) {
-                if (!(SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED)) {
-                    renderer->hidden = false;
-                }
-            } else if (event->type == SDL_EVENT_WINDOW_MINIMIZED) {
-                renderer->hidden = true;
-            } else if (event->type == SDL_EVENT_WINDOW_RESTORED ||
-                       event->type == SDL_EVENT_WINDOW_MAXIMIZED) {
-                if (!(SDL_GetWindowFlags(window) & SDL_WINDOW_HIDDEN)) {
-                    renderer->hidden = false;
-                }
-            } else if (event->type == SDL_EVENT_WINDOW_DISPLAY_CHANGED) {
-                UpdateHDRProperties(renderer);
-            }
+    if (event->type == SDL_EVENT_WINDOW_RESIZED ||
+        event->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED ||
+        event->type == SDL_EVENT_WINDOW_METAL_VIEW_RESIZED) {
+        UpdateLogicalPresentation(renderer);
+    } else if (event->type == SDL_EVENT_WINDOW_HIDDEN) {
+        renderer->hidden = true;
+    } else if (event->type == SDL_EVENT_WINDOW_SHOWN) {
+        if (!(SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED)) {
+            renderer->hidden = false;
         }
-    } else if (event->type == SDL_EVENT_WINDOW_HDR_STATE_CHANGED) {
+    } else if (event->type == SDL_EVENT_WINDOW_MINIMIZED) {
+        renderer->hidden = true;
+    } else if (event->type == SDL_EVENT_WINDOW_RESTORED ||
+               event->type == SDL_EVENT_WINDOW_MAXIMIZED) {
+        if (!(SDL_GetWindowFlags(window) & SDL_WINDOW_HIDDEN)) {
+            renderer->hidden = false;
+        }
+    } else if (event->type == SDL_EVENT_WINDOW_DISPLAY_CHANGED ||
+               event->type == SDL_EVENT_WINDOW_HDR_STATE_CHANGED) {
         UpdateHDRProperties(renderer);
     }
-
-    return true;
 }
 
 bool SDL_CreateWindowAndRenderer(const char *title, int width, int height, SDL_WindowFlags window_flags, SDL_Window **window, SDL_Renderer **renderer)
@@ -1115,10 +1104,6 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
 
     SDL_SetRenderViewport(renderer, NULL);
 
-    if (window) {
-        SDL_AddEventWatch(SDL_RendererEventWatch, renderer);
-    }
-
     int vsync = (int)SDL_GetNumberProperty(props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER, 0);
     if (!SDL_SetRenderVSync(renderer, vsync)) {
         if (vsync == 0) {
@@ -5217,8 +5202,6 @@ void SDL_DestroyRendererWithoutFreeing(SDL_Renderer *renderer)
 
     renderer->destroyed = true;
 
-    SDL_RemoveEventWatch(SDL_RendererEventWatch, renderer);
-
     if (renderer->window) {
         SDL_PropertiesID props = SDL_GetWindowProperties(renderer->window);
         if (SDL_GetPointerProperty(props, SDL_PROP_WINDOW_RENDERER_POINTER, NULL) == renderer) {
diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h
index 9c39bb1de71f4..980c8ffd146df 100644
--- a/src/render/SDL_sysrender.h
+++ b/src/render/SDL_sysrender.h
@@ -32,6 +32,9 @@
 extern "C" {
 #endif
 
+#define SDL_PROP_WINDOW_RENDERER_POINTER "SDL.internal.window.renderer"
+#define SDL_PROP_TEXTURE_PARENT_POINTER "SDL.internal.texture.parent"
+
 typedef enum SDL_TextureAddressMode
 {
     SDL_TEXTURE_ADDRESS_AUTO,
@@ -339,6 +342,9 @@ extern SDL_RenderDriver GPU_RenderDriver;
 // Clean up any renderers at shutdown
 extern void SDL_QuitRender(void);
 
+// Handle window events for a renderer
+extern void SDL_RendererEventWatch(SDL_Renderer *renderer, SDL_Event *event);
+
 // Add a supported texture format to a renderer
 extern bool SDL_AddSupportedTextureFormat(SDL_Renderer *renderer, SDL_PixelFormat format);