SDL: Optimized SDL_HasEvent() and SDL_HasEvents()

From d9a7da4fac7c89ccda943994e9083f939d370e1f Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Wed, 25 Sep 2024 21:20:00 -0700
Subject: [PATCH] Optimized SDL_HasEvent() and SDL_HasEvents()

Also document the counting behavior of SDL_PEEKEVENT.

Fixes https://github.com/libsdl-org/SDL/issues/6209
---
 include/SDL3/SDL_events.h |  2 +-
 src/events/SDL_events.c   | 20 ++++++++++++++++++--
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h
index e8fddab842e7d..ecd64eb68dc5f 100644
--- a/include/SDL3/SDL_events.h
+++ b/include/SDL3/SDL_events.h
@@ -1011,7 +1011,7 @@ typedef enum SDL_EventAction
  *   event queue.
  * - `SDL_PEEKEVENT`: `numevents` events at the front of the event queue,
  *   within the specified minimum and maximum type, will be returned to the
- *   caller and will _not_ be removed from the queue.
+ *   caller and will _not_ be removed from the queue. If you pass NULL for `events`, then `numevents` is ignored and the total number of matching events will be returned.
  * - `SDL_GETEVENT`: up to `numevents` events at the front of the event queue,
  *   within the specified minimum and maximum type, will be returned to the
  *   caller and will be removed from the queue.
diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c
index 81bed4459fb24..6f2ee9058119b 100644
--- a/src/events/SDL_events.c
+++ b/src/events/SDL_events.c
@@ -1105,12 +1105,28 @@ int SDL_PeepEvents(SDL_Event *events, int numevents, SDL_EventAction action,
 
 bool SDL_HasEvent(Uint32 type)
 {
-    return SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, type, type) > 0;
+    return SDL_HasEvents(type, type);
 }
 
 bool SDL_HasEvents(Uint32 minType, Uint32 maxType)
 {
-    return SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, minType, maxType) > 0;
+    bool found = false;
+
+    SDL_LockMutex(SDL_EventQ.lock);
+    {
+        if (SDL_EventQ.active) {
+            for (SDL_EventEntry *entry = SDL_EventQ.head; entry; entry = entry->next) {
+                const Uint32 type = entry->event.type;
+                if (minType <= type && type <= maxType) {
+                    found = true;
+                    break;
+                }
+            }
+        }
+    }
+    SDL_UnlockMutex(SDL_EventQ.lock);
+
+    return found;
 }
 
 void SDL_FlushEvent(Uint32 type)