From 911bf6241b28437255dca540096eb0228577258b Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 15 Mar 2019 14:08:30 -0400 Subject: [PATCH] events: Make debug logging of the event queue a hint instead of an #ifdef. This makes it easy to toggle it on when debugging a new platform (or just getting more visibility into an app) without having to rebuild SDL. --- include/SDL_hints.h | 23 ++++++ src/SDL.c | 6 +- src/events/SDL_events.c | 159 +++++++++++++++++++++++++------------- src/events/SDL_events_c.h | 5 +- 4 files changed, 132 insertions(+), 61 deletions(-) diff --git a/include/SDL_hints.h b/include/SDL_hints.h index 3c91277c9..cd5adb260 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -1078,6 +1078,29 @@ extern "C" { #define SDL_HINT_RENDER_BATCHING "SDL_RENDER_BATCHING" +/** + * \brief A variable controlling whether SDL logs all events pushed onto its internal queue. + * + * This variable can be set to the following values: + * + * "0" - Don't log any events (default) + * "1" - Log all events except mouse and finger motion, which are pretty spammy. + * "2" - Log all events. + * + * This is generally meant to be used to debug SDL itself, but can be useful + * for application developers that need better visibility into what is going + * on in the event queue. Logged events are sent through SDL_Log(), which + * means by default they appear on stdout on most platforms or maybe + * OutputDebugString() on Windows, and can be funneled by the app with + * SDL_LogSetOutputFunction(), etc. + * + * This hint can be toggled on and off at runtime, if you only need to log + * events for a small subset of program execution. + */ +#define SDL_HINT_EVENT_LOGGING "SDL_EVENT_LOGGING" + + + /** * \brief An enumeration of hint priorities */ diff --git a/src/SDL.c b/src/SDL.c index be9eee838..6e8017810 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -139,10 +139,9 @@ SDL_InitSubSystem(Uint32 flags) if ((flags & SDL_INIT_EVENTS)) { #if !SDL_EVENTS_DISABLED if (SDL_PrivateShouldInitSubsystem(SDL_INIT_EVENTS)) { - if (SDL_StartEventLoop() < 0) { + if (SDL_EventsInit() < 0) { return (-1); } - SDL_QuitInit(); } SDL_PrivateSubsystemRefCountIncr(SDL_INIT_EVENTS); #else @@ -333,8 +332,7 @@ SDL_QuitSubSystem(Uint32 flags) #if !SDL_EVENTS_DISABLED if ((flags & SDL_INIT_EVENTS)) { if (SDL_PrivateShouldQuitSubsystem(SDL_INIT_EVENTS)) { - SDL_QuitQuit(); - SDL_StopEventLoop(); + SDL_EventsQuit(); } SDL_PrivateSubsystemRefCountDecr(SDL_INIT_EVENTS); } diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 2f5bfd796..1177d6c41 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -33,8 +33,6 @@ #include "../video/SDL_sysvideo.h" #include "SDL_syswm.h" -/*#define SDL_DEBUG_EVENTS 1*/ - /* An arbitrary limit so we don't have unbounded growth */ #define SDL_MAX_QUEUED_EVENTS 65535 @@ -87,32 +85,53 @@ static struct } SDL_EventQ = { NULL, { 1 }, { 0 }, 0, NULL, NULL, NULL, NULL, NULL }; -#ifdef SDL_DEBUG_EVENTS +/* 0 (default) means no logging, 1 means logging, 2 means logging with mouse and finger motion */ +static int SDL_DoEventLogging = 0; -/* this is to make printf() calls cleaner. */ -#define uint unsigned int +static void SDLCALL +SDL_EventLoggingChanged(void *userdata, const char *name, const char *oldValue, const char *hint) +{ + SDL_DoEventLogging = (hint && *hint) ? SDL_max(SDL_min(SDL_atoi(hint), 2), 0) : 0; +} static void -SDL_DebugPrintEvent(const SDL_Event *event) +SDL_LogEvent(const SDL_Event *event) { - /* !!! FIXME: This code is kinda ugly, sorry. */ - printf("SDL EVENT: "); + char name[32]; + char details[128]; - if ((event->type >= SDL_USEREVENT) && (event->type <= SDL_LASTEVENT)) { - printf("SDL_USEREVENT"); - if (event->type > SDL_USEREVENT) { - printf("+%u", ((uint) event->type) - SDL_USEREVENT); - } - printf(" (timestamp=%u windowid=%u code=%d data1=%p data2=%p)", - (uint) event->user.timestamp, (uint) event->user.windowID, - (int) event->user.code, event->user.data1, event->user.data2); + /* mouse/finger motion are spammy, ignore these if they aren't demanded. */ + if ( (SDL_DoEventLogging < 2) && + ( (event->type == SDL_MOUSEMOTION) || + (event->type == SDL_FINGERMOTION) ) ) { return; } + /* this is to make SDL_snprintf() calls cleaner. */ + #define uint unsigned int + + name[0] = '\0'; + details[0] = '\0'; + + /* !!! FIXME: This code is kinda ugly, sorry. */ + + if ((event->type >= SDL_USEREVENT) && (event->type <= SDL_LASTEVENT)) { + char plusstr[16]; + SDL_strlcpy(name, "SDL_USEREVENT", sizeof (name)); + if (event->type > SDL_USEREVENT) { + SDL_snprintf(plusstr, sizeof (plusstr), "+%u", ((uint) event->type) - SDL_USEREVENT); + } else { + plusstr[0] = '\0'; + } + SDL_snprintf(details, sizeof (details), "%s (timestamp=%u windowid=%u code=%d data1=%p data2=%p)", + plusstr, (uint) event->user.timestamp, (uint) event->user.windowID, + (int) event->user.code, event->user.data1, event->user.data2); + } + switch (event->type) { - #define SDL_EVENT_CASE(x) case x: printf("%s", #x); - SDL_EVENT_CASE(SDL_FIRSTEVENT) printf("(THIS IS PROBABLY A BUG!)"); break; - SDL_EVENT_CASE(SDL_QUIT) printf("(timestamp=%u)", (uint) event->quit.timestamp); break; + #define SDL_EVENT_CASE(x) case x: SDL_strlcpy(name, #x, sizeof (name)); + SDL_EVENT_CASE(SDL_FIRSTEVENT) SDL_strlcpy(details, " (THIS IS PROBABLY A BUG!)", sizeof (details)); break; + SDL_EVENT_CASE(SDL_QUIT) SDL_snprintf(details, sizeof (details), " (timestamp=%u)", (uint) event->quit.timestamp); break; SDL_EVENT_CASE(SDL_APP_TERMINATING) break; SDL_EVENT_CASE(SDL_APP_LOWMEMORY) break; SDL_EVENT_CASE(SDL_APP_WILLENTERBACKGROUND) break; @@ -123,15 +142,12 @@ SDL_DebugPrintEvent(const SDL_Event *event) SDL_EVENT_CASE(SDL_CLIPBOARDUPDATE) break; SDL_EVENT_CASE(SDL_RENDER_TARGETS_RESET) break; SDL_EVENT_CASE(SDL_RENDER_DEVICE_RESET) break; - #undef SDL_EVENT_CASE - #define SDL_EVENT_CASE(x) case x: printf("%s ", #x); - - SDL_EVENT_CASE(SDL_WINDOWEVENT) - printf("(timestamp=%u windowid=%u event=", (uint) event->window.timestamp, (uint) event->window.windowID); + SDL_EVENT_CASE(SDL_WINDOWEVENT) { + char name2[64]; switch(event->window.event) { - case SDL_WINDOWEVENT_NONE: printf("none(THIS IS PROBABLY A BUG!)"); break; - #define SDL_WINDOWEVENT_CASE(x) case x: printf("%s", #x); break + case SDL_WINDOWEVENT_NONE: SDL_strlcpy(name2, "SDL_WINDOWEVENT_NONE (THIS IS PROBABLY A BUG!)", sizeof (name2)); break; + #define SDL_WINDOWEVENT_CASE(x) case x: SDL_strlcpy(name2, #x, sizeof (name2)); break SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_SHOWN); SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_HIDDEN); SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_EXPOSED); @@ -149,18 +165,20 @@ SDL_DebugPrintEvent(const SDL_Event *event) SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_TAKE_FOCUS); SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_HIT_TEST); #undef SDL_WINDOWEVENT_CASE - default: printf("UNKNOWN(bug? fixme?)"); break; + default: SDL_strlcpy(name2, "UNKNOWN (bug? fixme?)", sizeof (name2)); break; } - printf(" data1=%d data2=%d)", (int) event->window.data1, (int) event->window.data2); + SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u event=%s data1=%d data2=%d)", + (uint) event->window.timestamp, (uint) event->window.windowID, name2, (int) event->window.data1, (int) event->window.data2); break; + } SDL_EVENT_CASE(SDL_SYSWMEVENT) - printf("(timestamp=%u)", (uint) event->syswm.timestamp); /* !!! FIXME: we don't delve further at the moment. */ + SDL_snprintf(details, sizeof (details), " (timestamp=%u)", (uint) event->syswm.timestamp); break; #define PRINT_KEY_EVENT(event) \ - printf("(timestamp=%u windowid=%u state=%s repeat=%s scancode=%u keycode=%u mod=%u)", \ + SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u state=%s repeat=%s scancode=%u keycode=%u mod=%u)", \ (uint) event->key.timestamp, (uint) event->key.windowID, \ event->key.state == SDL_PRESSED ? "pressed" : "released", \ event->key.repeat ? "true" : "false", \ @@ -172,18 +190,18 @@ SDL_DebugPrintEvent(const SDL_Event *event) #undef PRINT_KEY_EVENT SDL_EVENT_CASE(SDL_TEXTEDITING) - printf("(timestamp=%u windowid=%u text='%s' start=%d length=%d)", + SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u text='%s' start=%d length=%d)", (uint) event->edit.timestamp, (uint) event->edit.windowID, event->edit.text, (int) event->edit.start, (int) event->edit.length); break; SDL_EVENT_CASE(SDL_TEXTINPUT) - printf("(timestamp=%u windowid=%u text='%s')", (uint) event->text.timestamp, (uint) event->text.windowID, event->text.text); + SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u text='%s')", (uint) event->text.timestamp, (uint) event->text.windowID, event->text.text); break; SDL_EVENT_CASE(SDL_MOUSEMOTION) - printf("(timestamp=%u windowid=%u which=%u state=%u x=%d y=%d xrel=%d yrel=%d)", + SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u which=%u state=%u x=%d y=%d xrel=%d yrel=%d)", (uint) event->motion.timestamp, (uint) event->motion.windowID, (uint) event->motion.which, (uint) event->motion.state, (int) event->motion.x, (int) event->motion.y, @@ -191,7 +209,7 @@ SDL_DebugPrintEvent(const SDL_Event *event) break; #define PRINT_MBUTTON_EVENT(event) \ - printf("(timestamp=%u windowid=%u which=%u button=%u state=%s clicks=%u x=%d y=%d)", \ + SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u which=%u button=%u state=%s clicks=%u x=%d y=%d)", \ (uint) event->button.timestamp, (uint) event->button.windowID, \ (uint) event->button.which, (uint) event->button.button, \ event->button.state == SDL_PRESSED ? "pressed" : "released", \ @@ -202,65 +220,65 @@ SDL_DebugPrintEvent(const SDL_Event *event) SDL_EVENT_CASE(SDL_MOUSEWHEEL) - printf("(timestamp=%u windowid=%u which=%u x=%d y=%d direction=%s)", + SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u which=%u x=%d y=%d direction=%s)", (uint) event->wheel.timestamp, (uint) event->wheel.windowID, (uint) event->wheel.which, (int) event->wheel.x, (int) event->wheel.y, event->wheel.direction == SDL_MOUSEWHEEL_NORMAL ? "normal" : "flipped"); break; SDL_EVENT_CASE(SDL_JOYAXISMOTION) - printf("(timestamp=%u which=%d axis=%u value=%d)", + SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d axis=%u value=%d)", (uint) event->jaxis.timestamp, (int) event->jaxis.which, (uint) event->jaxis.axis, (int) event->jaxis.value); break; SDL_EVENT_CASE(SDL_JOYBALLMOTION) - printf("(timestamp=%u which=%d ball=%u xrel=%d yrel=%d)", + SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d ball=%u xrel=%d yrel=%d)", (uint) event->jball.timestamp, (int) event->jball.which, (uint) event->jball.ball, (int) event->jball.xrel, (int) event->jball.yrel); break; SDL_EVENT_CASE(SDL_JOYHATMOTION) - printf("(timestamp=%u which=%d hat=%u value=%u)", + SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d hat=%u value=%u)", (uint) event->jhat.timestamp, (int) event->jhat.which, (uint) event->jhat.hat, (uint) event->jhat.value); break; #define PRINT_JBUTTON_EVENT(event) \ - printf("(timestamp=%u which=%d button=%u state=%s)", \ + SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d button=%u state=%s)", \ (uint) event->jbutton.timestamp, (int) event->jbutton.which, \ (uint) event->jbutton.button, event->jbutton.state == SDL_PRESSED ? "pressed" : "released") SDL_EVENT_CASE(SDL_JOYBUTTONDOWN) PRINT_JBUTTON_EVENT(event); break; SDL_EVENT_CASE(SDL_JOYBUTTONUP) PRINT_JBUTTON_EVENT(event); break; #undef PRINT_JBUTTON_EVENT - #define PRINT_JOYDEV_EVENT(event) printf("(timestamp=%u which=%d)", (uint) event->jdevice.timestamp, (int) event->jdevice.which) + #define PRINT_JOYDEV_EVENT(event) SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d)", (uint) event->jdevice.timestamp, (int) event->jdevice.which) SDL_EVENT_CASE(SDL_JOYDEVICEADDED) PRINT_JOYDEV_EVENT(event); break; SDL_EVENT_CASE(SDL_JOYDEVICEREMOVED) PRINT_JOYDEV_EVENT(event); break; #undef PRINT_JOYDEV_EVENT SDL_EVENT_CASE(SDL_CONTROLLERAXISMOTION) - printf("(timestamp=%u which=%d axis=%u value=%d)", + SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d axis=%u value=%d)", (uint) event->caxis.timestamp, (int) event->caxis.which, (uint) event->caxis.axis, (int) event->caxis.value); break; #define PRINT_CBUTTON_EVENT(event) \ - printf("(timestamp=%u which=%d button=%u state=%s)", \ + SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d button=%u state=%s)", \ (uint) event->cbutton.timestamp, (int) event->cbutton.which, \ (uint) event->cbutton.button, event->cbutton.state == SDL_PRESSED ? "pressed" : "released") SDL_EVENT_CASE(SDL_CONTROLLERBUTTONDOWN) PRINT_CBUTTON_EVENT(event); break; SDL_EVENT_CASE(SDL_CONTROLLERBUTTONUP) PRINT_CBUTTON_EVENT(event); break; #undef PRINT_CBUTTON_EVENT - #define PRINT_CONTROLLERDEV_EVENT(event) printf("(timestamp=%u which=%d)", (uint) event->cdevice.timestamp, (int) event->cdevice.which) + #define PRINT_CONTROLLERDEV_EVENT(event) SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d)", (uint) event->cdevice.timestamp, (int) event->cdevice.which) SDL_EVENT_CASE(SDL_CONTROLLERDEVICEADDED) PRINT_CONTROLLERDEV_EVENT(event); break; SDL_EVENT_CASE(SDL_CONTROLLERDEVICEREMOVED) PRINT_CONTROLLERDEV_EVENT(event); break; SDL_EVENT_CASE(SDL_CONTROLLERDEVICEREMAPPED) PRINT_CONTROLLERDEV_EVENT(event); break; #undef PRINT_CONTROLLERDEV_EVENT #define PRINT_FINGER_EVENT(event) \ - printf("(timestamp=%u touchid=%lld fingerid=%lld x=%f y=%f dx=%f dy=%f pressure=%f)", \ + SDL_snprintf(details, sizeof (details), " (timestamp=%u touchid=%lld fingerid=%lld x=%f y=%f dx=%f dy=%f pressure=%f)", \ (uint) event->tfinger.timestamp, (long long) event->tfinger.touchId, \ (long long) event->tfinger.fingerId, event->tfinger.x, event->tfinger.y, \ event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure) @@ -270,7 +288,7 @@ SDL_DebugPrintEvent(const SDL_Event *event) #undef PRINT_FINGER_EVENT #define PRINT_DOLLAR_EVENT(event) \ - printf("(timestamp=%u touchid=%lld gestureid=%lld numfingers=%u error=%f x=%f y=%f)", \ + SDL_snprintf(details, sizeof (details), " (timestamp=%u touchid=%lld gestureid=%lld numfingers=%u error=%f x=%f y=%f)", \ (uint) event->dgesture.timestamp, (long long) event->dgesture.touchId, \ (long long) event->dgesture.gestureId, (uint) event->dgesture.numFingers, \ event->dgesture.error, event->dgesture.x, event->dgesture.y); @@ -279,20 +297,20 @@ SDL_DebugPrintEvent(const SDL_Event *event) #undef PRINT_DOLLAR_EVENT SDL_EVENT_CASE(SDL_MULTIGESTURE) - printf("(timestamp=%u touchid=%lld dtheta=%f ddist=%f x=%f y=%f numfingers=%u)", + SDL_snprintf(details, sizeof (details), " (timestamp=%u touchid=%lld dtheta=%f ddist=%f x=%f y=%f numfingers=%u)", (uint) event->mgesture.timestamp, (long long) event->mgesture.touchId, event->mgesture.dTheta, event->mgesture.dDist, event->mgesture.x, event->mgesture.y, (uint) event->mgesture.numFingers); break; - #define PRINT_DROP_EVENT(event) printf("(file='%s' timestamp=%u windowid=%u)", event->drop.file, (uint) event->drop.timestamp, (uint) event->drop.windowID) + #define PRINT_DROP_EVENT(event) SDL_snprintf(details, sizeof (details), " (file='%s' timestamp=%u windowid=%u)", event->drop.file, (uint) event->drop.timestamp, (uint) event->drop.windowID) SDL_EVENT_CASE(SDL_DROPFILE) PRINT_DROP_EVENT(event); break; SDL_EVENT_CASE(SDL_DROPTEXT) PRINT_DROP_EVENT(event); break; SDL_EVENT_CASE(SDL_DROPBEGIN) PRINT_DROP_EVENT(event); break; SDL_EVENT_CASE(SDL_DROPCOMPLETE) PRINT_DROP_EVENT(event); break; #undef PRINT_DROP_EVENT - #define PRINT_AUDIODEV_EVENT(event) printf("(timestamp=%u which=%u iscapture=%s)", (uint) event->adevice.timestamp, (uint) event->adevice.which, event->adevice.iscapture ? "true" : "false"); + #define PRINT_AUDIODEV_EVENT(event) SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%u iscapture=%s)", (uint) event->adevice.timestamp, (uint) event->adevice.which, event->adevice.iscapture ? "true" : "false"); SDL_EVENT_CASE(SDL_AUDIODEVICEADDED) PRINT_AUDIODEV_EVENT(event); break; SDL_EVENT_CASE(SDL_AUDIODEVICEREMOVED) PRINT_AUDIODEV_EVENT(event); break; #undef PRINT_AUDIODEV_EVENT @@ -300,14 +318,19 @@ SDL_DebugPrintEvent(const SDL_Event *event) #undef SDL_EVENT_CASE default: - printf("UNKNOWN SDL EVENT #%u! (Bug? FIXME?)", (uint) event->type); + if (!name[0]) { + SDL_strlcpy(name, "UNKNOWN", sizeof (name)); + SDL_snprintf(details, sizeof (details), " #%u! (Bug? FIXME?)", (uint) event->type); + } break; } - printf("\n"); + if (name[0]) { + SDL_Log("SDL EVENT: %s%s", name, details); + } + + #undef uint } -#undef uint -#endif @@ -451,9 +474,9 @@ SDL_AddEvent(SDL_Event * event) SDL_EventQ.free = entry->next; } - #ifdef SDL_DEBUG_EVENTS - SDL_DebugPrintEvent(event); - #endif + if (SDL_DoEventLogging) { + SDL_LogEvent(event); + } entry->event = *event; if (event->type == SDL_SYSWMEVENT) { @@ -975,4 +998,30 @@ SDL_SendKeymapChangedEvent(void) return SDL_SendAppEvent(SDL_KEYMAPCHANGED); } + +extern int SDL_QuitInit(void); +extern void SDL_QuitQuit(void); + +int +SDL_EventsInit(void) +{ + SDL_AddHintCallback(SDL_HINT_EVENT_LOGGING, SDL_EventLoggingChanged, NULL); + if (SDL_StartEventLoop() < 0) { + SDL_DelHintCallback(SDL_HINT_EVENT_LOGGING, SDL_EventLoggingChanged, NULL); + return -1; + } + + SDL_QuitInit(); + + return 0; +} + +void +SDL_EventsQuit(void) +{ + SDL_QuitQuit(); + SDL_StopEventLoop(); + SDL_DelHintCallback(SDL_HINT_EVENT_LOGGING, SDL_EventLoggingChanged, NULL); +} + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/events/SDL_events_c.h b/src/events/SDL_events_c.h index bd3e6442d..6d6809633 100644 --- a/src/events/SDL_events_c.h +++ b/src/events/SDL_events_c.h @@ -47,9 +47,10 @@ extern int SDL_SendAppEvent(SDL_EventType eventType); extern int SDL_SendSysWMEvent(SDL_SysWMmsg * message); extern int SDL_SendKeymapChangedEvent(void); -extern int SDL_QuitInit(void); extern int SDL_SendQuit(void); -extern void SDL_QuitQuit(void); + +extern int SDL_EventsInit(void); +extern void SDL_EventsQuit(void); extern void SDL_SendPendingQuit(void);