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