diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj
index 09563a63d3..5bf000436f 100644
--- a/VisualC-GDK/SDL/SDL.vcxproj
+++ b/VisualC-GDK/SDL/SDL.vcxproj
@@ -442,6 +442,7 @@
+
@@ -676,6 +677,7 @@
+
diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters
index dd2c4639cf..f760877e21 100644
--- a/VisualC-GDK/SDL/SDL.vcxproj.filters
+++ b/VisualC-GDK/SDL/SDL.vcxproj.filters
@@ -39,6 +39,7 @@
+
@@ -333,6 +334,7 @@
+
diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj
index 07a16f7079..a15978a29c 100644
--- a/VisualC/SDL/SDL.vcxproj
+++ b/VisualC/SDL/SDL.vcxproj
@@ -354,6 +354,7 @@
+
@@ -558,6 +559,7 @@
+
diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters
index c0a23b4318..d653ee05f1 100644
--- a/VisualC/SDL/SDL.vcxproj.filters
+++ b/VisualC/SDL/SDL.vcxproj.filters
@@ -534,6 +534,9 @@
events
+
+ events
+
events
@@ -1076,6 +1079,9 @@
events
+
+ events
+
events
diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj
index 8e4f9fa033..2a63a2eead 100644
--- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj
+++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj
@@ -512,6 +512,8 @@
F3D46B122D20625800D9CBDF /* SDL_egl.h in Headers */ = {isa = PBXBuildFile; fileRef = F3D46A8E2D20625800D9CBDF /* SDL_egl.h */; settings = {ATTRIBUTES = (Public, ); }; };
F3D46B132D20625800D9CBDF /* SDL_filesystem.h in Headers */ = {isa = PBXBuildFile; fileRef = F3D46A922D20625800D9CBDF /* SDL_filesystem.h */; settings = {ATTRIBUTES = (Public, ); }; };
F3D60A8328C16A1900788A3A /* SDL_hidapi_wii.c in Sources */ = {isa = PBXBuildFile; fileRef = F3D60A8228C16A1800788A3A /* SDL_hidapi_wii.c */; };
+ F3D8BDFC2D6D2C7000B22FA1 /* SDL_eventwatch_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3D8BDFB2D6D2C7000B22FA1 /* SDL_eventwatch_c.h */; };
+ F3D8BDFD2D6D2C7000B22FA1 /* SDL_eventwatch.c in Sources */ = {isa = PBXBuildFile; fileRef = F3D8BDFA2D6D2C7000B22FA1 /* SDL_eventwatch.c */; };
F3DDCC562AFD42B600B0842B /* SDL_clipboard_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC4D2AFD42B500B0842B /* SDL_clipboard_c.h */; };
F3DDCC5B2AFD42B600B0842B /* SDL_video_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC522AFD42B600B0842B /* SDL_video_c.h */; };
F3DDCC5D2AFD42B600B0842B /* SDL_rect_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC542AFD42B600B0842B /* SDL_rect_impl.h */; };
@@ -1079,6 +1081,8 @@
F3D46AC82D20625800D9CBDF /* SDL_video.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_video.h; sourceTree = ""; };
F3D46AC92D20625800D9CBDF /* SDL_vulkan.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_vulkan.h; sourceTree = ""; };
F3D60A8228C16A1800788A3A /* SDL_hidapi_wii.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_wii.c; sourceTree = ""; };
+ F3D8BDFA2D6D2C7000B22FA1 /* SDL_eventwatch.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SDL_eventwatch.c; sourceTree = ""; };
+ F3D8BDFB2D6D2C7000B22FA1 /* SDL_eventwatch_c.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_eventwatch_c.h; sourceTree = ""; };
F3DDCC4D2AFD42B500B0842B /* SDL_clipboard_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_clipboard_c.h; sourceTree = ""; };
F3DDCC522AFD42B600B0842B /* SDL_video_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_video_c.h; sourceTree = ""; };
F3DDCC542AFD42B600B0842B /* SDL_rect_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_rect_impl.h; sourceTree = ""; };
@@ -2209,29 +2213,31 @@
A7D8A93623E2514000DCD162 /* scancodes_linux.h */,
A7D8A92C23E2514000DCD162 /* scancodes_windows.h */,
A7D8A94123E2514000DCD162 /* scancodes_xfree86.h */,
- F3C2CB202C5DDDB2004D7998 /* SDL_categories_c.h */,
F3C2CB212C5DDDB2004D7998 /* SDL_categories.c */,
- A7D8A93923E2514000DCD162 /* SDL_clipboardevents_c.h */,
+ F3C2CB202C5DDDB2004D7998 /* SDL_categories_c.h */,
A7D8A93A23E2514000DCD162 /* SDL_clipboardevents.c */,
- A7D8A93123E2514000DCD162 /* SDL_displayevents_c.h */,
+ A7D8A93923E2514000DCD162 /* SDL_clipboardevents_c.h */,
A7D8A92D23E2514000DCD162 /* SDL_displayevents.c */,
- A7D8A92E23E2514000DCD162 /* SDL_dropevents_c.h */,
+ A7D8A93123E2514000DCD162 /* SDL_displayevents_c.h */,
A7D8A93B23E2514000DCD162 /* SDL_dropevents.c */,
- A7D8A94223E2514000DCD162 /* SDL_events_c.h */,
+ A7D8A92E23E2514000DCD162 /* SDL_dropevents_c.h */,
A7D8A93523E2514000DCD162 /* SDL_events.c */,
- A7D8A93D23E2514000DCD162 /* SDL_keyboard_c.h */,
+ A7D8A94223E2514000DCD162 /* SDL_events_c.h */,
+ F3D8BDFA2D6D2C7000B22FA1 /* SDL_eventwatch.c */,
+ F3D8BDFB2D6D2C7000B22FA1 /* SDL_eventwatch_c.h */,
A7D8A93823E2514000DCD162 /* SDL_keyboard.c */,
- F31013C62C24E98200FBE946 /* SDL_keymap_c.h */,
+ A7D8A93D23E2514000DCD162 /* SDL_keyboard_c.h */,
F31013C52C24E98200FBE946 /* SDL_keymap.c */,
- A7D8A92B23E2514000DCD162 /* SDL_mouse_c.h */,
+ F31013C62C24E98200FBE946 /* SDL_keymap_c.h */,
A7D8A92A23E2514000DCD162 /* SDL_mouse.c */,
- 63134A232A7902FD0021E9A6 /* SDL_pen_c.h */,
+ A7D8A92B23E2514000DCD162 /* SDL_mouse_c.h */,
63134A242A7902FD0021E9A6 /* SDL_pen.c */,
+ 63134A232A7902FD0021E9A6 /* SDL_pen_c.h */,
A7D8A93C23E2514000DCD162 /* SDL_quit.c */,
- A7D8A93723E2514000DCD162 /* SDL_touch_c.h */,
A7D8A93E23E2514000DCD162 /* SDL_touch.c */,
- A7D8A94323E2514000DCD162 /* SDL_windowevents_c.h */,
+ A7D8A93723E2514000DCD162 /* SDL_touch_c.h */,
A7D8A92F23E2514000DCD162 /* SDL_windowevents.c */,
+ A7D8A94323E2514000DCD162 /* SDL_windowevents_c.h */,
);
path = events;
sourceTree = "";
@@ -2707,6 +2713,7 @@
A7D8B3D423E2514300DCD162 /* yuv_rgb.h in Headers */,
F3FA5A252B59ACE000FEAD97 /* yuv_rgb_common.h in Headers */,
F3FA5A1D2B59ACE000FEAD97 /* yuv_rgb_internal.h in Headers */,
+ F3D8BDFC2D6D2C7000B22FA1 /* SDL_eventwatch_c.h in Headers */,
F3FA5A242B59ACE000FEAD97 /* yuv_rgb_lsx.h in Headers */,
F3FA5A1E2B59ACE000FEAD97 /* yuv_rgb_lsx_func.h in Headers */,
F3FA5A1F2B59ACE000FEAD97 /* yuv_rgb_sse.h in Headers */,
@@ -2965,6 +2972,7 @@
566E26CF246274CC00718109 /* SDL_syslocale.m in Sources */,
A7D8AFC023E2514200DCD162 /* SDL_egl.c in Sources */,
A7D8AC3323E2514100DCD162 /* SDL_RLEaccel.c in Sources */,
+ F3D8BDFD2D6D2C7000B22FA1 /* SDL_eventwatch.c in Sources */,
F3EFA5F02D5AB97300BCF22F /* SDL_stb.c in Sources */,
A7D8BBB123E2514500DCD162 /* SDL_assert.c in Sources */,
A7D8B3DA23E2514300DCD162 /* SDL_bmp.c in Sources */,
diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c
index ebce863bb5..e7216ee408 100644
--- a/src/events/SDL_events.c
+++ b/src/events/SDL_events.c
@@ -23,6 +23,8 @@
// General event handling code for SDL
#include "SDL_events_c.h"
+#include "SDL_eventwatch_c.h"
+#include "SDL_windowevents_c.h"
#include "../SDL_hints_c.h"
#include "../audio/SDL_audio_c.h"
#include "../camera/SDL_camera_c.h"
@@ -98,19 +100,7 @@ typedef struct SDL2_SysWMmsg
} msg;
} SDL2_SysWMmsg;
-typedef struct SDL_EventWatcher
-{
- SDL_EventFilter callback;
- void *userdata;
- bool removed;
-} SDL_EventWatcher;
-
-static SDL_Mutex *SDL_event_watchers_lock;
-static SDL_EventWatcher SDL_EventOK;
-static SDL_EventWatcher *SDL_event_watchers = NULL;
-static int SDL_event_watchers_count = 0;
-static bool SDL_event_watchers_dispatching = false;
-static bool SDL_event_watchers_removed = false;
+static SDL_EventWatchList SDL_event_watchers;
static SDL_AtomicInt SDL_sentinel_pending;
static Uint32 SDL_last_event_id = 0;
@@ -938,16 +928,8 @@ void SDL_StopEventLoop(void)
SDL_disabled_events[i] = NULL;
}
- if (SDL_event_watchers_lock) {
- SDL_DestroyMutex(SDL_event_watchers_lock);
- SDL_event_watchers_lock = NULL;
- }
- if (SDL_event_watchers) {
- SDL_free(SDL_event_watchers);
- SDL_event_watchers = NULL;
- SDL_event_watchers_count = 0;
- }
- SDL_zero(SDL_EventOK);
+ SDL_QuitEventWatchList(&SDL_event_watchers);
+ SDL_QuitWindowEventWatch();
SDL_Mutex *lock = NULL;
if (SDL_EventQ.lock) {
@@ -981,17 +963,19 @@ bool SDL_StartEventLoop(void)
}
SDL_LockMutex(SDL_EventQ.lock);
- if (SDL_event_watchers_lock == NULL) {
- SDL_event_watchers_lock = SDL_CreateMutex();
- if (SDL_event_watchers_lock == NULL) {
- SDL_UnlockMutex(SDL_EventQ.lock);
- return false;
- }
+ if (!SDL_InitEventWatchList(&SDL_event_watchers)) {
+ SDL_UnlockMutex(SDL_EventQ.lock);
+ return false;
}
#endif // !SDL_THREADS_DISABLED
+ SDL_InitWindowEventWatch();
+
SDL_EventQ.active = true;
+
+#ifndef SDL_THREADS_DISABLED
SDL_UnlockMutex(SDL_EventQ.lock);
+#endif
return true;
}
@@ -1735,44 +1719,11 @@ bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS)
static bool SDL_CallEventWatchers(SDL_Event *event)
{
- if ((SDL_EventOK.callback || SDL_event_watchers_count > 0) &&
- (event->common.type != SDL_EVENT_POLL_SENTINEL)) {
- SDL_LockMutex(SDL_event_watchers_lock);
- {
- if (SDL_EventOK.callback && !SDL_EventOK.callback(SDL_EventOK.userdata, event)) {
- SDL_UnlockMutex(SDL_event_watchers_lock);
- return false;
- }
-
- if (SDL_event_watchers_count > 0) {
- // Make sure we only dispatch the current watcher list
- int i, event_watchers_count = SDL_event_watchers_count;
-
- SDL_event_watchers_dispatching = true;
- for (i = 0; i < event_watchers_count; ++i) {
- if (!SDL_event_watchers[i].removed) {
- SDL_event_watchers[i].callback(SDL_event_watchers[i].userdata, event);
- }
- }
- SDL_event_watchers_dispatching = false;
-
- if (SDL_event_watchers_removed) {
- for (i = SDL_event_watchers_count; i--;) {
- if (SDL_event_watchers[i].removed) {
- --SDL_event_watchers_count;
- if (i < SDL_event_watchers_count) {
- SDL_memmove(&SDL_event_watchers[i], &SDL_event_watchers[i + 1], (SDL_event_watchers_count - i) * sizeof(SDL_event_watchers[i]));
- }
- }
- }
- SDL_event_watchers_removed = false;
- }
- }
- }
- SDL_UnlockMutex(SDL_event_watchers_lock);
+ if (event->common.type == SDL_EVENT_POLL_SENTINEL) {
+ return true;
}
- return true;
+ return SDL_DispatchEventWatchList(&SDL_event_watchers, event);
}
bool SDL_PushEvent(SDL_Event *event)
@@ -1796,11 +1747,11 @@ bool SDL_PushEvent(SDL_Event *event)
void SDL_SetEventFilter(SDL_EventFilter filter, void *userdata)
{
SDL_EventEntry *event, *next;
- SDL_LockMutex(SDL_event_watchers_lock);
+ SDL_LockMutex(SDL_event_watchers.lock);
{
// Set filter and discard pending events
- SDL_EventOK.callback = filter;
- SDL_EventOK.userdata = userdata;
+ SDL_event_watchers.filter.callback = filter;
+ SDL_event_watchers.filter.userdata = userdata;
if (filter) {
// Cut all events not accepted by the filter
SDL_LockMutex(SDL_EventQ.lock);
@@ -1815,18 +1766,18 @@ void SDL_SetEventFilter(SDL_EventFilter filter, void *userdata)
SDL_UnlockMutex(SDL_EventQ.lock);
}
}
- SDL_UnlockMutex(SDL_event_watchers_lock);
+ SDL_UnlockMutex(SDL_event_watchers.lock);
}
bool SDL_GetEventFilter(SDL_EventFilter *filter, void **userdata)
{
SDL_EventWatcher event_ok;
- SDL_LockMutex(SDL_event_watchers_lock);
+ SDL_LockMutex(SDL_event_watchers.lock);
{
- event_ok = SDL_EventOK;
+ event_ok = SDL_event_watchers.filter;
}
- SDL_UnlockMutex(SDL_event_watchers_lock);
+ SDL_UnlockMutex(SDL_event_watchers.lock);
if (filter) {
*filter = event_ok.callback;
@@ -1839,53 +1790,12 @@ bool SDL_GetEventFilter(SDL_EventFilter *filter, void **userdata)
bool SDL_AddEventWatch(SDL_EventFilter filter, void *userdata)
{
- bool result = true;
-
- SDL_LockMutex(SDL_event_watchers_lock);
- {
- SDL_EventWatcher *event_watchers;
-
- event_watchers = (SDL_EventWatcher *)SDL_realloc(SDL_event_watchers, (SDL_event_watchers_count + 1) * sizeof(*event_watchers));
- if (event_watchers) {
- SDL_EventWatcher *watcher;
-
- SDL_event_watchers = event_watchers;
- watcher = &SDL_event_watchers[SDL_event_watchers_count];
- watcher->callback = filter;
- watcher->userdata = userdata;
- watcher->removed = false;
- ++SDL_event_watchers_count;
- } else {
- result = false;
- }
- }
- SDL_UnlockMutex(SDL_event_watchers_lock);
-
- return result;
+ return SDL_AddEventWatchList(&SDL_event_watchers, filter, userdata);
}
void SDL_RemoveEventWatch(SDL_EventFilter filter, void *userdata)
{
- SDL_LockMutex(SDL_event_watchers_lock);
- {
- int i;
-
- for (i = 0; i < SDL_event_watchers_count; ++i) {
- if (SDL_event_watchers[i].callback == filter && SDL_event_watchers[i].userdata == userdata) {
- if (SDL_event_watchers_dispatching) {
- SDL_event_watchers[i].removed = true;
- SDL_event_watchers_removed = true;
- } else {
- --SDL_event_watchers_count;
- if (i < SDL_event_watchers_count) {
- SDL_memmove(&SDL_event_watchers[i], &SDL_event_watchers[i + 1], (SDL_event_watchers_count - i) * sizeof(SDL_event_watchers[i]));
- }
- }
- break;
- }
- }
- }
- SDL_UnlockMutex(SDL_event_watchers_lock);
+ SDL_RemoveEventWatchList(&SDL_event_watchers, filter, userdata);
}
void SDL_FilterEvents(SDL_EventFilter filter, void *userdata)
diff --git a/src/events/SDL_eventwatch.c b/src/events/SDL_eventwatch.c
new file mode 100644
index 0000000000..08e7248c6a
--- /dev/null
+++ b/src/events/SDL_eventwatch.c
@@ -0,0 +1,143 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2025 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_internal.h"
+
+#include "SDL_eventwatch_c.h"
+
+
+bool SDL_InitEventWatchList(SDL_EventWatchList *list)
+{
+ if (list->lock == NULL) {
+ list->lock = SDL_CreateMutex();
+ if (list->lock == NULL) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void SDL_QuitEventWatchList(SDL_EventWatchList *list)
+{
+ if (list->lock) {
+ SDL_DestroyMutex(list->lock);
+ list->lock = NULL;
+ }
+ if (list->watchers) {
+ SDL_free(list->watchers);
+ list->watchers = NULL;
+ list->count = 0;
+ }
+ SDL_zero(list->filter);
+}
+
+bool SDL_DispatchEventWatchList(SDL_EventWatchList *list, SDL_Event *event)
+{
+ SDL_EventWatcher *filter = &list->filter;
+
+ if (!filter->callback && list->count == 0) {
+ return true;
+ }
+
+ SDL_LockMutex(list->lock);
+ {
+ // Make sure we only dispatch the current watcher list
+ int i, count = list->count;
+
+ if (filter->callback && !filter->callback(filter->userdata, event)) {
+ SDL_UnlockMutex(list->lock);
+ return false;
+ }
+
+ list->dispatching = true;
+ for (i = 0; i < count; ++i) {
+ if (!list->watchers[i].removed) {
+ list->watchers[i].callback(list->watchers[i].userdata, event);
+ }
+ }
+ list->dispatching = false;
+
+ if (list->removed) {
+ for (i = list->count; i--;) {
+ if (list->watchers[i].removed) {
+ --list->count;
+ if (i < list->count) {
+ SDL_memmove(&list->watchers[i], &list->watchers[i + 1], (list->count - i) * sizeof(list->watchers[i]));
+ }
+ }
+ }
+ list->removed = false;
+ }
+ }
+ SDL_UnlockMutex(list->lock);
+
+ return true;
+}
+
+bool SDL_AddEventWatchList(SDL_EventWatchList *list, SDL_EventFilter filter, void *userdata)
+{
+ bool result = true;
+
+ SDL_LockMutex(list->lock);
+ {
+ SDL_EventWatcher *watchers;
+
+ watchers = (SDL_EventWatcher *)SDL_realloc(list->watchers, (list->count + 1) * sizeof(*watchers));
+ if (watchers) {
+ SDL_EventWatcher *watcher;
+
+ list->watchers = watchers;
+ watcher = &list->watchers[list->count];
+ watcher->callback = filter;
+ watcher->userdata = userdata;
+ watcher->removed = false;
+ ++list->count;
+ } else {
+ result = false;
+ }
+ }
+ SDL_UnlockMutex(list->lock);
+
+ return result;
+}
+
+void SDL_RemoveEventWatchList(SDL_EventWatchList *list, SDL_EventFilter filter, void *userdata)
+{
+ SDL_LockMutex(list->lock);
+ {
+ int i;
+
+ for (i = 0; i < list->count; ++i) {
+ if (list->watchers[i].callback == filter && list->watchers[i].userdata == userdata) {
+ if (list->dispatching) {
+ list->watchers[i].removed = true;
+ list->removed = true;
+ } else {
+ --list->count;
+ if (i < list->count) {
+ SDL_memmove(&list->watchers[i], &list->watchers[i + 1], (list->count - i) * sizeof(list->watchers[i]));
+ }
+ }
+ break;
+ }
+ }
+ }
+ SDL_UnlockMutex(list->lock);
+}
diff --git a/src/events/SDL_eventwatch_c.h b/src/events/SDL_eventwatch_c.h
new file mode 100644
index 0000000000..c9aea38c0d
--- /dev/null
+++ b/src/events/SDL_eventwatch_c.h
@@ -0,0 +1,45 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2025 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_internal.h"
+
+typedef struct SDL_EventWatcher
+{
+ SDL_EventFilter callback;
+ void *userdata;
+ bool removed;
+} SDL_EventWatcher;
+
+typedef struct SDL_EventWatchList
+{
+ SDL_Mutex *lock;
+ SDL_EventWatcher filter;
+ SDL_EventWatcher *watchers;
+ int count;
+ bool dispatching;
+ bool removed;
+} SDL_EventWatchList;
+
+
+extern bool SDL_InitEventWatchList(SDL_EventWatchList *list);
+extern void SDL_QuitEventWatchList(SDL_EventWatchList *list);
+extern bool SDL_DispatchEventWatchList(SDL_EventWatchList *list, SDL_Event *event);
+extern bool SDL_AddEventWatchList(SDL_EventWatchList *list, SDL_EventFilter filter, void *userdata);
+extern void SDL_RemoveEventWatchList(SDL_EventWatchList *list, SDL_EventFilter filter, void *userdata);
diff --git a/src/events/SDL_windowevents.c b/src/events/SDL_windowevents.c
index e0364f8ee0..e20cd3ab0d 100644
--- a/src/events/SDL_windowevents.c
+++ b/src/events/SDL_windowevents.c
@@ -23,10 +23,39 @@
// Window event handling code for SDL
#include "SDL_events_c.h"
+#include "SDL_eventwatch_c.h"
#include "SDL_mouse_c.h"
-#include "../render/SDL_sysrender.h"
#include "../tray/SDL_tray_utils.h"
+
+#define NUM_WINDOW_EVENT_WATCH_PRIORITIES (SDL_WINDOW_EVENT_WATCH_NORMAL + 1)
+
+static SDL_EventWatchList SDL_window_event_watchers[NUM_WINDOW_EVENT_WATCH_PRIORITIES];
+
+void SDL_InitWindowEventWatch(void)
+{
+ for (int i = 0; i < SDL_arraysize(SDL_window_event_watchers); ++i) {
+ SDL_InitEventWatchList(&SDL_window_event_watchers[i]);
+ }
+}
+
+void SDL_QuitWindowEventWatch(void)
+{
+ for (int i = 0; i < SDL_arraysize(SDL_window_event_watchers); ++i) {
+ SDL_QuitEventWatchList(&SDL_window_event_watchers[i]);
+ }
+}
+
+void SDL_AddWindowEventWatch(SDL_WindowEventWatchPriority priority, SDL_EventFilter filter, void *userdata)
+{
+ SDL_AddEventWatchList(&SDL_window_event_watchers[priority], filter, userdata);
+}
+
+void SDL_RemoveWindowEventWatch(SDL_WindowEventWatchPriority priority, SDL_EventFilter filter, void *userdata)
+{
+ SDL_RemoveEventWatchList(&SDL_window_event_watchers[priority], filter, userdata);
+}
+
static bool SDLCALL RemoveSupercededWindowEvents(void *userdata, SDL_Event *event)
{
SDL_Event *new_event = (SDL_Event *)userdata;
@@ -191,10 +220,8 @@ bool SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, int data
event.window.data2 = data2;
event.window.windowID = window->id;
- for (int i = 0; i < window->num_renderers; ++i) {
- SDL_Renderer *renderer = window->renderers[i];
- SDL_RendererEventWatch(renderer, &event);
- }
+ SDL_DispatchEventWatchList(&SDL_window_event_watchers[SDL_WINDOW_EVENT_WATCH_EARLY], &event);
+ SDL_DispatchEventWatchList(&SDL_window_event_watchers[SDL_WINDOW_EVENT_WATCH_NORMAL], &event);
if (SDL_EventEnabled(windowevent)) {
// Fixes queue overflow with move/resize events that aren't processed
diff --git a/src/events/SDL_windowevents_c.h b/src/events/SDL_windowevents_c.h
index b7f0681e6d..720430546a 100644
--- a/src/events/SDL_windowevents_c.h
+++ b/src/events/SDL_windowevents_c.h
@@ -23,6 +23,17 @@
#ifndef SDL_windowevents_c_h_
#define SDL_windowevents_c_h_
+typedef enum
+{
+ SDL_WINDOW_EVENT_WATCH_EARLY,
+ SDL_WINDOW_EVENT_WATCH_NORMAL
+} SDL_WindowEventWatchPriority;
+
+extern void SDL_InitWindowEventWatch(void);
+extern void SDL_QuitWindowEventWatch(void);
+extern void SDL_AddWindowEventWatch(SDL_WindowEventWatchPriority priority, SDL_EventFilter filter, void *userdata);
+extern void SDL_RemoveWindowEventWatch(SDL_WindowEventWatchPriority priority, SDL_EventFilter filter, void *userdata);
+
extern bool SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, int data1, int data2);
#endif // SDL_windowevents_c_h_
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index 4c438debc3..52f0b38257 100644
--- a/src/render/SDL_render.c
+++ b/src/render/SDL_render.c
@@ -25,6 +25,7 @@
#include "SDL_sysrender.h"
#include "SDL_render_debug_font.h"
#include "software/SDL_render_sw_c.h"
+#include "../events/SDL_windowevents_c.h"
#include "../video/SDL_pixels_c.h"
#include "../video/SDL_video_c.h"
@@ -820,8 +821,9 @@ const char *SDL_GetRenderDriver(int index)
#endif
}
-void SDL_RendererEventWatch(SDL_Renderer *renderer, SDL_Event *event)
+static bool SDL_RendererEventWatch(void *userdata, SDL_Event *event)
{
+ SDL_Renderer *renderer = (SDL_Renderer *)userdata;
SDL_Window *window = renderer->window;
if (renderer->WindowEvent) {
@@ -849,6 +851,7 @@ void SDL_RendererEventWatch(SDL_Renderer *renderer, SDL_Event *event)
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)
@@ -1107,6 +1110,10 @@ SDL_Renderer *SDL_CreateRendererWithProperties(SDL_PropertiesID props)
SDL_SetRenderViewport(renderer, NULL);
+ if (window) {
+ SDL_AddWindowEventWatch(SDL_WINDOW_EVENT_WATCH_NORMAL, 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) {
@@ -5224,6 +5231,8 @@ void SDL_DestroyRendererWithoutFreeing(SDL_Renderer *renderer)
renderer->destroyed = true;
+ SDL_RemoveWindowEventWatch(SDL_WINDOW_EVENT_WATCH_NORMAL, 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 375419a06a..9c39bb1de7 100644
--- a/src/render/SDL_sysrender.h
+++ b/src/render/SDL_sysrender.h
@@ -339,9 +339,6 @@ 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);
diff --git a/src/video/cocoa/SDL_cocoametalview.m b/src/video/cocoa/SDL_cocoametalview.m
index d856645115..af84e93586 100644
--- a/src/video/cocoa/SDL_cocoametalview.m
+++ b/src/video/cocoa/SDL_cocoametalview.m
@@ -26,6 +26,8 @@
*/
#include "SDL_internal.h"
+#include "../../events/SDL_windowevents_c.h"
+
#import "SDL_cocoametalview.h"
#if defined(SDL_VIDEO_DRIVER_COCOA) && (defined(SDL_VIDEO_VULKAN) || defined(SDL_VIDEO_METAL))
@@ -88,7 +90,7 @@ static bool SDLCALL SDL_MetalViewEventWatch(void *userdata, SDL_Event *event)
self.layer.opaque = opaque;
- SDL_AddEventWatch(SDL_MetalViewEventWatch, (__bridge void *)(self));
+ SDL_AddWindowEventWatch(SDL_WINDOW_EVENT_WATCH_EARLY, SDL_MetalViewEventWatch, (__bridge void *)(self));
[self updateDrawableSize];
}
@@ -98,7 +100,7 @@ static bool SDLCALL SDL_MetalViewEventWatch(void *userdata, SDL_Event *event)
- (void)dealloc
{
- SDL_RemoveEventWatch(SDL_MetalViewEventWatch, (__bridge void *)(self));
+ SDL_RemoveWindowEventWatch(SDL_WINDOW_EVENT_WATCH_EARLY, SDL_MetalViewEventWatch, (__bridge void *)(self));
}
- (NSInteger)tag