Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Easy way to get a windowID from a SDL_Event #10457

Closed
madebr opened this issue Aug 2, 2024 · 2 comments · Fixed by #10459
Closed

Easy way to get a windowID from a SDL_Event #10457

madebr opened this issue Aug 2, 2024 · 2 comments · Fixed by #10459

Comments

@madebr
Copy link
Contributor

madebr commented Aug 2, 2024

I think it would be useful if SDL would get an api to easy extract the windowID from a SDL_Event.
For example, right now you'd need to a big switch or complicated if-else to only keep those event types that have a windowID.

A use case could be filtering events of different windows, and deliver only those events of a specific window.
Example use case: imgui

I prototyped a patch that does that.
It creates an enum that bundles event types into groups (SDL_EVENTGROUP_*)
Using those groups, I can more easily extract the windowID of an event.

Patch
diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h
index 7dda52410..f7caa353d 100644
--- a/include/SDL3/SDL_events.h
+++ b/include/SDL3/SDL_events.h
@@ -919,6 +919,284 @@ typedef union SDL_Event
 /* Make sure we haven't broken binary compatibility */
 SDL_COMPILE_TIME_ASSERT(SDL_Event, sizeof(SDL_Event) == sizeof(((SDL_Event *)NULL)->padding));
 
+/**
+ * Groups of event types
+ *
+ * \since This enum is available since SDL 3.0.0.
+ */
+typedef enum SDL_EventTypeGroup
+{
+    SDL_EVENTGROUP_SYSTEM,              /**< System-wide events can access SDL_Event.common */
+    SDL_EVENTGROUP_DISPLAY,             /**< Events of this group can access SDL_Event.display */
+    SDL_EVENTGROUP_WINDOW,              /**< Events of this group can access SDL_Event.window */
+    SDL_EVENTGROUP_KDEVICE,             /**< Events of this group can access SDL_Event.kdevice */
+    SDL_EVENTGROUP_KEY,                 /**< Events of this group can access SDL_Event.key */
+    SDL_EVENTGROUP_EDIT,                /**< Events of this group can access SDL_Event.edit */
+    SDL_EVENTGROUP_EDIT_CANDIDATES,     /**< Events of this group can access SDL_Event.edit_candidates */
+    SDL_EVENTGROUP_TEXT,                /**< Events of this group can access SDL_Event.text */
+    SDL_EVENTGROUP_MDEVICE,             /**< Events of this group can access SDL_Event.mdevice */
+    SDL_EVENTGROUP_MOTION,              /**< Events of this group can access SDL_Event.motion */
+    SDL_EVENTGROUP_BUTTON,              /**< Events of this group can access SDL_Event.button */
+    SDL_EVENTGROUP_WHEEL,               /**< Events of this group can access SDL_Event.wheel */
+    SDL_EVENTGROUP_JDEVICE,             /**< Events of this group can access SDL_Event.jdevice */
+    SDL_EVENTGROUP_JAXIS,               /**< Events of this group can access SDL_Event.jaxis */
+    SDL_EVENTGROUP_JBALL,               /**< Events of this group can access SDL_Event.jball */
+    SDL_EVENTGROUP_JHAT,                /**< Events of this group can access SDL_Event.jhat */
+    SDL_EVENTGROUP_JBUTTON,             /**< Events of this group can access SDL_Event.jbutton */
+    SDL_EVENTGROUP_JBATTERY,            /**< Events of this group can access SDL_Event.jbattery */
+    SDL_EVENTGROUP_GDEVICE,             /**< Events of this group can access SDL_Event.gdevice */
+    SDL_EVENTGROUP_GAXIS,               /**< Events of this group can access SDL_Event.gaxis */
+    SDL_EVENTGROUP_GBUTTON,             /**< Events of this group can access SDL_Event.gbutton */
+    SDL_EVENTGROUP_GTOUCHPAD,           /**< Events of this group can access SDL_Event.gtouchpad */
+    SDL_EVENTGROUP_GSENSOR,             /**< Events of this group can access SDL_Event.gsensor */
+    SDL_EVENTGROUP_ADEVICE,             /**< Events of this group can access SDL_Event.adevice */
+    SDL_EVENTGROUP_CDEVICE,             /**< Events of this group can access SDL_Event.cdevice */
+    SDL_EVENTGROUP_SENSOR,              /**< Events of this group can access SDL_Event.sensor */
+    SDL_EVENTGROUP_QUIT,                /**< Events of this group can access SDL_Event.quit */
+    SDL_EVENTGROUP_USER,                /**< Events of this group can access SDL_Event.user */
+    SDL_EVENTGROUP_TFINGER,             /**< Events of this group can access SDL_Event.tfinger */
+    SDL_EVENTGROUP_PTIP,                /**< Events of this group can access SDL_Event.ptip */
+    SDL_EVENTGROUP_PMOTION,             /**< Events of this group can access SDL_Event.pmotion */
+    SDL_EVENTGROUP_PBUTTON,             /**< Events of this group can access SDL_Event.pbutton */
+    SDL_EVENTGROUP_DROP,                /**< Events of this group can access SDL_Event.drop */
+    SDL_EVENTGROUP_CLIPBOARD,           /**< Events of this group can access SDL_Event.clipboard */
+} SDL_EventTypeGroup;
+
+/**
+ * Get the group to which an event type belongs.
+ *
+ * \param type Event type of type SDL_EventType
+ *
+ * \returns SDL_EventTypeGroup on success or -1 if there was an error;
+ *          call SDL_GetError() for more information.
+ *
+ * \since This enum is available since SDL 3.0.0.
+ */
+static SDL_EventTypeGroup SDL_GetEventGroupType(Uint32 type) {
+    if (type >= SDL_EVENT_USER && type <= SDL_EVENT_LAST) {
+        return SDL_EVENTGROUP_USER;
+    }
+    switch (type) {
+    default:
+        return SDL_SetError("Unknown event type");
+
+    case SDL_EVENT_KEYMAP_CHANGED:
+    case SDL_EVENT_TERMINATING:
+    case SDL_EVENT_LOW_MEMORY:
+    case SDL_EVENT_WILL_ENTER_BACKGROUND:
+    case SDL_EVENT_DID_ENTER_BACKGROUND:
+    case SDL_EVENT_WILL_ENTER_FOREGROUND:
+    case SDL_EVENT_DID_ENTER_FOREGROUND:
+    case SDL_EVENT_LOCALE_CHANGED:
+    case SDL_EVENT_SYSTEM_THEME_CHANGED:
+    case SDL_EVENT_RENDER_TARGETS_RESET:
+    case SDL_EVENT_RENDER_DEVICE_RESET:
+        return SDL_EVENTGROUP_SYSTEM;
+
+    case SDL_EVENT_QUIT:
+        return SDL_EVENTGROUP_QUIT;
+
+    case SDL_EVENT_DISPLAY_ORIENTATION:
+    case SDL_EVENT_DISPLAY_ADDED:
+    case SDL_EVENT_DISPLAY_REMOVED:
+    case SDL_EVENT_DISPLAY_MOVED:
+    case SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED:
+    case SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED:
+    case SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED:
+        return SDL_EVENTGROUP_DISPLAY;
+
+    case SDL_EVENT_WINDOW_SHOWN:
+    case SDL_EVENT_WINDOW_HIDDEN:
+    case SDL_EVENT_WINDOW_EXPOSED:
+    case SDL_EVENT_WINDOW_MOVED:
+    case SDL_EVENT_WINDOW_RESIZED:
+    case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
+    case SDL_EVENT_WINDOW_METAL_VIEW_RESIZED:
+    case SDL_EVENT_WINDOW_MINIMIZED:
+    case SDL_EVENT_WINDOW_MAXIMIZED:
+    case SDL_EVENT_WINDOW_RESTORED:
+    case SDL_EVENT_WINDOW_MOUSE_ENTER:
+    case SDL_EVENT_WINDOW_MOUSE_LEAVE:
+    case SDL_EVENT_WINDOW_FOCUS_GAINED:
+    case SDL_EVENT_WINDOW_FOCUS_LOST:
+    case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
+    case SDL_EVENT_WINDOW_HIT_TEST:
+    case SDL_EVENT_WINDOW_ICCPROF_CHANGED:
+    case SDL_EVENT_WINDOW_DISPLAY_CHANGED:
+    case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED:
+    case SDL_EVENT_WINDOW_SAFE_AREA_CHANGED:
+    case SDL_EVENT_WINDOW_OCCLUDED:
+    case SDL_EVENT_WINDOW_ENTER_FULLSCREEN:
+    case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN:
+    case SDL_EVENT_WINDOW_DESTROYED:
+    case SDL_EVENT_WINDOW_PEN_ENTER:
+    case SDL_EVENT_WINDOW_PEN_LEAVE:
+    case SDL_EVENT_WINDOW_HDR_STATE_CHANGED:
+        return SDL_EVENTGROUP_WINDOW;
+
+    case SDL_EVENT_KEY_DOWN:
+    case SDL_EVENT_KEY_UP:
+        return SDL_EVENTGROUP_KEY;
+
+    case SDL_EVENT_TEXT_EDITING:
+        return SDL_EVENTGROUP_EDIT;
+
+    case SDL_EVENT_TEXT_INPUT:
+        return SDL_EVENTGROUP_TEXT;
+
+    case SDL_EVENT_KEYBOARD_ADDED:
+    case SDL_EVENT_KEYBOARD_REMOVED:
+        return SDL_EVENTGROUP_KDEVICE;
+
+    case SDL_EVENT_TEXT_EDITING_CANDIDATES:
+        return SDL_EVENTGROUP_EDIT_CANDIDATES;
+
+    case SDL_EVENT_MOUSE_MOTION:
+        return SDL_EVENTGROUP_MOTION;
+
+    case SDL_EVENT_MOUSE_BUTTON_DOWN:
+    case SDL_EVENT_MOUSE_BUTTON_UP:
+        return SDL_EVENTGROUP_BUTTON;
+
+    case SDL_EVENT_MOUSE_WHEEL:
+        return SDL_EVENTGROUP_WHEEL;
+
+    case SDL_EVENT_MOUSE_ADDED:
+    case SDL_EVENT_MOUSE_REMOVED:
+        return SDL_EVENTGROUP_MDEVICE;
+
+    case SDL_EVENT_JOYSTICK_AXIS_MOTION:
+        return SDL_EVENTGROUP_JAXIS;
+
+    case SDL_EVENT_JOYSTICK_BALL_MOTION:
+        return SDL_EVENTGROUP_JBALL;
+
+    case SDL_EVENT_JOYSTICK_HAT_MOTION:
+        return SDL_EVENTGROUP_JHAT;
+
+    case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
+    case SDL_EVENT_JOYSTICK_BUTTON_UP:
+        return SDL_EVENTGROUP_JBUTTON;
+
+    case SDL_EVENT_JOYSTICK_ADDED:
+    case SDL_EVENT_JOYSTICK_REMOVED:
+    case SDL_EVENT_JOYSTICK_UPDATE_COMPLETE:
+        return SDL_EVENTGROUP_JDEVICE;
+
+    case SDL_EVENT_JOYSTICK_BATTERY_UPDATED:
+        return SDL_EVENTGROUP_JBATTERY;
+
+    case SDL_EVENT_GAMEPAD_AXIS_MOTION:
+        return SDL_EVENTGROUP_GAXIS;
+
+    case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
+    case SDL_EVENT_GAMEPAD_BUTTON_UP:
+        return SDL_EVENTGROUP_GBUTTON;
+
+    case SDL_EVENT_GAMEPAD_ADDED:
+    case SDL_EVENT_GAMEPAD_REMOVED:
+    case SDL_EVENT_GAMEPAD_REMAPPED:
+    case SDL_EVENT_GAMEPAD_UPDATE_COMPLETE:
+    case SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED:
+        return SDL_EVENTGROUP_GDEVICE;
+
+    case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN:
+    case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION:
+    case SDL_EVENT_GAMEPAD_TOUCHPAD_UP:
+        return SDL_EVENTGROUP_GTOUCHPAD;
+
+    case SDL_EVENT_GAMEPAD_SENSOR_UPDATE:
+        return SDL_EVENTGROUP_GSENSOR;
+
+    case SDL_EVENT_FINGER_DOWN:
+    case SDL_EVENT_FINGER_UP:
+    case SDL_EVENT_FINGER_MOTION:
+        return SDL_EVENTGROUP_TFINGER;
+
+    case SDL_EVENT_CLIPBOARD_UPDATE:
+        return SDL_EVENTGROUP_CLIPBOARD;
+
+    case SDL_EVENT_DROP_FILE:
+    case SDL_EVENT_DROP_TEXT:
+    case SDL_EVENT_DROP_BEGIN:
+    case SDL_EVENT_DROP_COMPLETE:
+    case SDL_EVENT_DROP_POSITION:
+        return SDL_EVENTGROUP_DROP;
+
+    case SDL_EVENT_AUDIO_DEVICE_ADDED:
+    case SDL_EVENT_AUDIO_DEVICE_REMOVED:
+    case SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED:
+        return SDL_EVENTGROUP_ADEVICE;
+
+    case SDL_EVENT_SENSOR_UPDATE:
+        return SDL_EVENTGROUP_SENSOR;
+
+    case SDL_EVENT_PEN_DOWN:
+    case SDL_EVENT_PEN_UP:
+        return SDL_EVENTGROUP_PTIP;
+
+    case SDL_EVENT_PEN_MOTION:
+        return SDL_EVENTGROUP_PMOTION;
+
+    case SDL_EVENT_PEN_BUTTON_DOWN:
+    case SDL_EVENT_PEN_BUTTON_UP:
+        return SDL_EVENTGROUP_PBUTTON;
+
+    case SDL_EVENT_CAMERA_DEVICE_ADDED:
+    case SDL_EVENT_CAMERA_DEVICE_REMOVED:
+    case SDL_EVENT_CAMERA_DEVICE_APPROVED:
+    case SDL_EVENT_CAMERA_DEVICE_DENIED:
+        return SDL_EVENTGROUP_CDEVICE;
+    }
+}
+
+/**
+ * Get the associated window id of an event.
+ *
+ * \param event SDL event of which to get the window id
+ *
+ * \returns the associated window id on success or 0 if there is no assocated id
+ *
+ * \since This enum is available since SDL 3.0.0.
+ *
+ * \sa SDL_PollEvent
+ * \sa SDL_WaitEvent
+ * \sa SDL_WaitEventTimeout
+ */
+static int SDL_GetWindowIDFromEvent(const SDL_Event *event) {
+    switch (SDL_GetEventGroupType(event->type)) {
+    case SDL_EVENTGROUP_USER:
+        return event->user.windowID;
+    case SDL_EVENTGROUP_WINDOW:
+        return event->window.windowID;
+    case SDL_EVENTGROUP_KEY:
+        return event->key.windowID;
+    case SDL_EVENTGROUP_EDIT:
+        return event->edit.windowID;
+    case SDL_EVENTGROUP_TEXT:
+        return event->text.windowID;
+    case SDL_EVENTGROUP_EDIT_CANDIDATES:
+        return event->edit_candidates.windowID;
+    case SDL_EVENTGROUP_MOTION:
+        return event->motion.windowID;
+    case SDL_EVENTGROUP_BUTTON:
+        return event->button.windowID;
+    case SDL_EVENTGROUP_WHEEL:
+        return event->wheel.windowID;
+    case SDL_EVENTGROUP_TFINGER:
+        return event->tfinger.windowID;
+    case SDL_EVENTGROUP_PTIP:
+        return event->ptip.windowID;
+    case SDL_EVENTGROUP_PMOTION:
+        return event->pmotion.windowID;
+    case SDL_EVENTGROUP_PBUTTON:
+        return event->pbutton.windowID;
+    case SDL_EVENTGROUP_DROP:
+        return event->drop.windowID;
+    default:
+        return 0;
+    }
+}
 
 /* Function prototypes */
 
@slime73
Copy link
Contributor

slime73 commented Aug 2, 2024

Related: #6869 (comment)

@slouken
Copy link
Collaborator

slouken commented Aug 2, 2024

I don't think we want the event groups, but a function to get the window from an event seems useful. Feel free to create a PR that uses the event groups internally and have the function return SDL_Window * instead of an ID?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants