| | |
| | | /* |
| | | Simple DirectMedia Layer |
| | | Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org> |
| | | Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org> |
| | | |
| | | This software is provided 'as-is', without any express or implied |
| | | warranty. In no event will the authors be held liable for any damages |
| | |
| | | #include "../video/SDL_sysvideo.h" |
| | | #include "SDL_syswm.h" |
| | | |
| | | /*#define SDL_DEBUG_EVENTS 1*/ |
| | | #undef SDL_PRIs64 |
| | | #ifdef __WIN32__ |
| | | #define SDL_PRIs64 "I64d" |
| | | #else |
| | | #define SDL_PRIs64 "lld" |
| | | #endif |
| | | |
| | | /* An arbitrary limit so we don't have unbounded growth */ |
| | | #define SDL_MAX_QUEUED_EVENTS 65535 |
| | |
| | | } 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; |
| | |
| | | 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); |
| | |
| | | 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", \ |
| | |
| | | #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, |
| | |
| | | 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", \ |
| | |
| | | |
| | | |
| | | 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)", \ |
| | | (uint) event->tfinger.timestamp, (long long) event->tfinger.touchId, \ |
| | | (long long) event->tfinger.fingerId, event->tfinger.x, event->tfinger.y, \ |
| | | SDL_snprintf(details, sizeof (details), " (timestamp=%u touchid=%"SDL_PRIs64" fingerid=%"SDL_PRIs64" 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) |
| | | SDL_EVENT_CASE(SDL_FINGERDOWN) PRINT_FINGER_EVENT(event); break; |
| | | SDL_EVENT_CASE(SDL_FINGERUP) PRINT_FINGER_EVENT(event); break; |
| | |
| | | #undef PRINT_FINGER_EVENT |
| | | |
| | | #define PRINT_DOLLAR_EVENT(event) \ |
| | | printf("(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, \ |
| | | SDL_snprintf(details, sizeof (details), " (timestamp=%u touchid=%"SDL_PRIs64" gestureid=%"SDL_PRIs64" 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); |
| | | SDL_EVENT_CASE(SDL_DOLLARGESTURE) PRINT_DOLLAR_EVENT(event); break; |
| | | SDL_EVENT_CASE(SDL_DOLLARRECORD) PRINT_DOLLAR_EVENT(event); break; |
| | | #undef PRINT_DOLLAR_EVENT |
| | | |
| | | SDL_EVENT_CASE(SDL_MULTIGESTURE) |
| | | printf("(timestamp=%u touchid=%lld dtheta=%f ddist=%f x=%f y=%f numfingers=%u)", |
| | | (uint) event->mgesture.timestamp, (long long) event->mgesture.touchId, |
| | | SDL_snprintf(details, sizeof (details), " (timestamp=%u touchid=%"SDL_PRIs64" 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 |
| | |
| | | #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 |
| | | |
| | | |
| | | |
| | |
| | | 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) { |
| | |
| | | } |
| | | #endif |
| | | |
| | | SDL_SendPendingQuit(); /* in case we had a signal handler fire, etc. */ |
| | | SDL_SendPendingSignalEvents(); /* in case we had a signal handler fire, etc. */ |
| | | } |
| | | |
| | | /* Public functions */ |
| | |
| | | /* Timeout expired and no events */ |
| | | return 0; |
| | | } |
| | | SDL_Delay(10); |
| | | SDL_Delay(1); |
| | | break; |
| | | default: |
| | | /* Has events */ |
| | |
| | | return SDL_SendAppEvent(SDL_KEYMAPCHANGED); |
| | | } |
| | | |
| | | 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: */ |