src/events/SDL_events.c
author Ethan Lee <flibitijibibo@flibitijibibo.com>
Wed, 17 Jul 2019 23:20:57 -0400
changeset 12950 05dddfb66b85
parent 12897 25998acc4810
permissions -rw-r--r--
Copypaste SDL_NSLog to UIKit backend, document it as such
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@12503
     3
  Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
slouken@0
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@0
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@0
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@0
    20
*/
icculus@8093
    21
#include "../SDL_internal.h"
slouken@0
    22
slouken@0
    23
/* General event handling code for SDL */
slouken@0
    24
slouken@0
    25
#include "SDL.h"
slouken@2984
    26
#include "SDL_events.h"
slouken@2984
    27
#include "SDL_thread.h"
slouken@1361
    28
#include "SDL_events_c.h"
slouken@1361
    29
#include "../timer/SDL_timer_c.h"
slouken@1361
    30
#if !SDL_JOYSTICK_DISABLED
slouken@1361
    31
#include "../joystick/SDL_joystick_c.h"
slouken@1361
    32
#endif
slouken@5123
    33
#include "../video/SDL_sysvideo.h"
slouken@11383
    34
#include "SDL_syswm.h"
slouken@0
    35
slouken@7306
    36
/* An arbitrary limit so we don't have unbounded growth */
slouken@7306
    37
#define SDL_MAX_QUEUED_EVENTS   65535
slouken@7306
    38
slouken@5146
    39
typedef struct SDL_EventWatcher {
slouken@5146
    40
    SDL_EventFilter callback;
slouken@5146
    41
    void *userdata;
slouken@11587
    42
    SDL_bool removed;
slouken@5146
    43
} SDL_EventWatcher;
slouken@5146
    44
slouken@11584
    45
static SDL_mutex *SDL_event_watchers_lock;
slouken@11584
    46
static SDL_EventWatcher SDL_EventOK;
slouken@5146
    47
static SDL_EventWatcher *SDL_event_watchers = NULL;
slouken@11584
    48
static int SDL_event_watchers_count = 0;
slouken@11587
    49
static SDL_bool SDL_event_watchers_dispatching = SDL_FALSE;
slouken@11587
    50
static SDL_bool SDL_event_watchers_removed = SDL_FALSE;
slouken@5146
    51
slouken@4429
    52
typedef struct {
slouken@4429
    53
    Uint32 bits[8];
slouken@4429
    54
} SDL_DisabledEventBlock;
slouken@4429
    55
slouken@4429
    56
static SDL_DisabledEventBlock *SDL_disabled_events[256];
slouken@4429
    57
static Uint32 SDL_userevents = SDL_USEREVENT;
slouken@0
    58
slouken@0
    59
/* Private data -- event queue */
slouken@7304
    60
typedef struct _SDL_EventEntry
slouken@7304
    61
{
slouken@7304
    62
    SDL_Event event;
slouken@7304
    63
    SDL_SysWMmsg msg;
slouken@7304
    64
    struct _SDL_EventEntry *prev;
slouken@7304
    65
    struct _SDL_EventEntry *next;
slouken@7304
    66
} SDL_EventEntry;
slouken@7304
    67
slouken@7304
    68
typedef struct _SDL_SysWMEntry
slouken@7304
    69
{
slouken@7304
    70
    SDL_SysWMmsg msg;
slouken@7304
    71
    struct _SDL_SysWMEntry *next;
slouken@7304
    72
} SDL_SysWMEntry;
slouken@7304
    73
slouken@1895
    74
static struct
slouken@1895
    75
{
slouken@1895
    76
    SDL_mutex *lock;
icculus@10003
    77
    SDL_atomic_t active;
icculus@10003
    78
    SDL_atomic_t count;
icculus@10003
    79
    int max_events_seen;
slouken@7304
    80
    SDL_EventEntry *head;
slouken@7304
    81
    SDL_EventEntry *tail;
slouken@7304
    82
    SDL_EventEntry *free;
slouken@7304
    83
    SDL_SysWMEntry *wmmsg_used;
slouken@7304
    84
    SDL_SysWMEntry *wmmsg_free;
icculus@10003
    85
} SDL_EventQ = { NULL, { 1 }, { 0 }, 0, NULL, NULL, NULL, NULL, NULL };
slouken@0
    86
slouken@0
    87
icculus@12630
    88
/* 0 (default) means no logging, 1 means logging, 2 means logging with mouse and finger motion */
icculus@12630
    89
static int SDL_DoEventLogging = 0;
icculus@10573
    90
icculus@12630
    91
static void SDLCALL
icculus@12630
    92
SDL_EventLoggingChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
icculus@12630
    93
{
icculus@12630
    94
    SDL_DoEventLogging = (hint && *hint) ? SDL_max(SDL_min(SDL_atoi(hint), 2), 0) : 0;
icculus@12630
    95
}
icculus@10573
    96
icculus@10573
    97
static void
icculus@12630
    98
SDL_LogEvent(const SDL_Event *event)
icculus@10573
    99
{
icculus@12630
   100
    char name[32];
icculus@12630
   101
    char details[128];
icculus@10573
   102
icculus@12630
   103
    /* mouse/finger motion are spammy, ignore these if they aren't demanded. */
icculus@12630
   104
    if ( (SDL_DoEventLogging < 2) &&
icculus@12630
   105
            ( (event->type == SDL_MOUSEMOTION) ||
icculus@12630
   106
              (event->type == SDL_FINGERMOTION) ) ) {
icculus@10573
   107
        return;
icculus@10573
   108
    }
icculus@10573
   109
icculus@12630
   110
    /* this is to make SDL_snprintf() calls cleaner. */
icculus@12630
   111
    #define uint unsigned int
icculus@12630
   112
icculus@12630
   113
    name[0] = '\0';
icculus@12630
   114
    details[0] = '\0';
icculus@12630
   115
icculus@12630
   116
    /* !!! FIXME: This code is kinda ugly, sorry. */
icculus@12630
   117
icculus@12630
   118
    if ((event->type >= SDL_USEREVENT) && (event->type <= SDL_LASTEVENT)) {
icculus@12630
   119
        char plusstr[16];
icculus@12630
   120
        SDL_strlcpy(name, "SDL_USEREVENT", sizeof (name));
icculus@12630
   121
        if (event->type > SDL_USEREVENT) {
icculus@12630
   122
            SDL_snprintf(plusstr, sizeof (plusstr), "+%u", ((uint) event->type) - SDL_USEREVENT);
icculus@12630
   123
        } else {
icculus@12630
   124
            plusstr[0] = '\0';
icculus@12630
   125
        }
icculus@12630
   126
        SDL_snprintf(details, sizeof (details), "%s (timestamp=%u windowid=%u code=%d data1=%p data2=%p)",
icculus@12630
   127
                plusstr, (uint) event->user.timestamp, (uint) event->user.windowID,
icculus@12630
   128
                (int) event->user.code, event->user.data1, event->user.data2);
icculus@12630
   129
    }
icculus@12630
   130
icculus@10573
   131
    switch (event->type) {
icculus@12630
   132
        #define SDL_EVENT_CASE(x) case x: SDL_strlcpy(name, #x, sizeof (name));
icculus@12630
   133
        SDL_EVENT_CASE(SDL_FIRSTEVENT) SDL_strlcpy(details, " (THIS IS PROBABLY A BUG!)", sizeof (details)); break;
icculus@12630
   134
        SDL_EVENT_CASE(SDL_QUIT) SDL_snprintf(details, sizeof (details), " (timestamp=%u)", (uint) event->quit.timestamp); break;
icculus@10573
   135
        SDL_EVENT_CASE(SDL_APP_TERMINATING) break;
icculus@10573
   136
        SDL_EVENT_CASE(SDL_APP_LOWMEMORY) break;
icculus@10573
   137
        SDL_EVENT_CASE(SDL_APP_WILLENTERBACKGROUND) break;
icculus@10573
   138
        SDL_EVENT_CASE(SDL_APP_DIDENTERBACKGROUND) break;
icculus@10573
   139
        SDL_EVENT_CASE(SDL_APP_WILLENTERFOREGROUND) break;
icculus@10573
   140
        SDL_EVENT_CASE(SDL_APP_DIDENTERFOREGROUND) break;
icculus@10573
   141
        SDL_EVENT_CASE(SDL_KEYMAPCHANGED) break;
philipp@10580
   142
        SDL_EVENT_CASE(SDL_CLIPBOARDUPDATE) break;
icculus@10573
   143
        SDL_EVENT_CASE(SDL_RENDER_TARGETS_RESET) break;
icculus@10573
   144
        SDL_EVENT_CASE(SDL_RENDER_DEVICE_RESET) break;
icculus@10573
   145
icculus@12630
   146
        SDL_EVENT_CASE(SDL_WINDOWEVENT) {
icculus@12630
   147
            char name2[64];
icculus@10573
   148
            switch(event->window.event) {
icculus@12630
   149
                case SDL_WINDOWEVENT_NONE: SDL_strlcpy(name2, "SDL_WINDOWEVENT_NONE (THIS IS PROBABLY A BUG!)", sizeof (name2)); break;
icculus@12630
   150
                #define SDL_WINDOWEVENT_CASE(x) case x: SDL_strlcpy(name2, #x, sizeof (name2)); break
icculus@10573
   151
                SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_SHOWN);
icculus@10573
   152
                SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_HIDDEN);
icculus@10573
   153
                SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_EXPOSED);
icculus@10573
   154
                SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_MOVED);
icculus@10573
   155
                SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_RESIZED);
icculus@10573
   156
                SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_SIZE_CHANGED);
icculus@10573
   157
                SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_MINIMIZED);
icculus@10573
   158
                SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_MAXIMIZED);
icculus@10573
   159
                SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_RESTORED);
icculus@10573
   160
                SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_ENTER);
icculus@10573
   161
                SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_LEAVE);
icculus@10573
   162
                SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_FOCUS_GAINED);
icculus@10573
   163
                SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_FOCUS_LOST);
icculus@10573
   164
                SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_CLOSE);
icculus@10573
   165
                SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_TAKE_FOCUS);
icculus@10573
   166
                SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_HIT_TEST);
icculus@10573
   167
                #undef SDL_WINDOWEVENT_CASE
icculus@12630
   168
                default: SDL_strlcpy(name2, "UNKNOWN (bug? fixme?)", sizeof (name2)); break;
icculus@10573
   169
            }
icculus@12630
   170
            SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u event=%s data1=%d data2=%d)",
icculus@12630
   171
                        (uint) event->window.timestamp, (uint) event->window.windowID, name2, (int) event->window.data1, (int) event->window.data2);
icculus@10573
   172
            break;
icculus@12630
   173
        }
icculus@10573
   174
icculus@10573
   175
        SDL_EVENT_CASE(SDL_SYSWMEVENT)
icculus@10573
   176
            /* !!! FIXME: we don't delve further at the moment. */
icculus@12630
   177
            SDL_snprintf(details, sizeof (details), " (timestamp=%u)", (uint) event->syswm.timestamp);
icculus@10573
   178
            break;
icculus@10573
   179
icculus@10573
   180
        #define PRINT_KEY_EVENT(event) \
icculus@12630
   181
            SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u state=%s repeat=%s scancode=%u keycode=%u mod=%u)", \
icculus@10573
   182
                (uint) event->key.timestamp, (uint) event->key.windowID, \
icculus@10573
   183
                event->key.state == SDL_PRESSED ? "pressed" : "released", \
icculus@10573
   184
                event->key.repeat ? "true" : "false", \
icculus@10573
   185
                (uint) event->key.keysym.scancode, \
icculus@10573
   186
                (uint) event->key.keysym.sym, \
icculus@10573
   187
                (uint) event->key.keysym.mod)
icculus@10573
   188
        SDL_EVENT_CASE(SDL_KEYDOWN) PRINT_KEY_EVENT(event); break;
icculus@10573
   189
        SDL_EVENT_CASE(SDL_KEYUP) PRINT_KEY_EVENT(event); break;
icculus@10573
   190
        #undef PRINT_KEY_EVENT
icculus@10573
   191
icculus@10573
   192
        SDL_EVENT_CASE(SDL_TEXTEDITING)
icculus@12630
   193
            SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u text='%s' start=%d length=%d)",
icculus@10573
   194
                (uint) event->edit.timestamp, (uint) event->edit.windowID,
icculus@10573
   195
                event->edit.text, (int) event->edit.start, (int) event->edit.length);
icculus@10573
   196
            break;
icculus@10573
   197
icculus@10573
   198
        SDL_EVENT_CASE(SDL_TEXTINPUT)
icculus@12630
   199
            SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u text='%s')", (uint) event->text.timestamp, (uint) event->text.windowID, event->text.text);
icculus@10573
   200
            break;
icculus@10573
   201
icculus@10573
   202
icculus@10573
   203
        SDL_EVENT_CASE(SDL_MOUSEMOTION)
icculus@12630
   204
            SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u which=%u state=%u x=%d y=%d xrel=%d yrel=%d)",
icculus@10573
   205
                    (uint) event->motion.timestamp, (uint) event->motion.windowID,
icculus@10573
   206
                    (uint) event->motion.which, (uint) event->motion.state,
icculus@10573
   207
                    (int) event->motion.x, (int) event->motion.y,
icculus@10573
   208
                    (int) event->motion.xrel, (int) event->motion.yrel);
icculus@10573
   209
            break;
icculus@10573
   210
icculus@10573
   211
        #define PRINT_MBUTTON_EVENT(event) \
icculus@12630
   212
            SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u which=%u button=%u state=%s clicks=%u x=%d y=%d)", \
icculus@10573
   213
                    (uint) event->button.timestamp, (uint) event->button.windowID, \
icculus@10573
   214
                    (uint) event->button.which, (uint) event->button.button, \
icculus@10573
   215
                    event->button.state == SDL_PRESSED ? "pressed" : "released", \
icculus@10573
   216
                    (uint) event->button.clicks, (int) event->button.x, (int) event->button.y)
icculus@10573
   217
        SDL_EVENT_CASE(SDL_MOUSEBUTTONDOWN) PRINT_MBUTTON_EVENT(event); break;
icculus@10573
   218
        SDL_EVENT_CASE(SDL_MOUSEBUTTONUP) PRINT_MBUTTON_EVENT(event); break;
icculus@10573
   219
        #undef PRINT_MBUTTON_EVENT
icculus@10573
   220
icculus@10573
   221
icculus@10573
   222
        SDL_EVENT_CASE(SDL_MOUSEWHEEL)
icculus@12630
   223
            SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u which=%u x=%d y=%d direction=%s)",
icculus@10573
   224
                    (uint) event->wheel.timestamp, (uint) event->wheel.windowID,
icculus@10573
   225
                    (uint) event->wheel.which, (int) event->wheel.x, (int) event->wheel.y,
icculus@10573
   226
                    event->wheel.direction == SDL_MOUSEWHEEL_NORMAL ? "normal" : "flipped");
icculus@10573
   227
            break;
icculus@10573
   228
icculus@10573
   229
        SDL_EVENT_CASE(SDL_JOYAXISMOTION)
icculus@12630
   230
            SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d axis=%u value=%d)",
icculus@10573
   231
                (uint) event->jaxis.timestamp, (int) event->jaxis.which,
icculus@10573
   232
                (uint) event->jaxis.axis, (int) event->jaxis.value);
icculus@10573
   233
            break;
icculus@10573
   234
icculus@10573
   235
        SDL_EVENT_CASE(SDL_JOYBALLMOTION)
icculus@12630
   236
            SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d ball=%u xrel=%d yrel=%d)",
icculus@10573
   237
                (uint) event->jball.timestamp, (int) event->jball.which,
icculus@10573
   238
                (uint) event->jball.ball, (int) event->jball.xrel, (int) event->jball.yrel);
icculus@10573
   239
            break;
icculus@10573
   240
icculus@10573
   241
        SDL_EVENT_CASE(SDL_JOYHATMOTION)
icculus@12630
   242
            SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d hat=%u value=%u)",
icculus@10573
   243
                (uint) event->jhat.timestamp, (int) event->jhat.which,
icculus@10573
   244
                (uint) event->jhat.hat, (uint) event->jhat.value);
icculus@10573
   245
            break;
icculus@10573
   246
icculus@10573
   247
        #define PRINT_JBUTTON_EVENT(event) \
icculus@12630
   248
            SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d button=%u state=%s)", \
icculus@10573
   249
                (uint) event->jbutton.timestamp, (int) event->jbutton.which, \
icculus@10573
   250
                (uint) event->jbutton.button, event->jbutton.state == SDL_PRESSED ? "pressed" : "released")
icculus@10573
   251
        SDL_EVENT_CASE(SDL_JOYBUTTONDOWN) PRINT_JBUTTON_EVENT(event); break;
icculus@10573
   252
        SDL_EVENT_CASE(SDL_JOYBUTTONUP) PRINT_JBUTTON_EVENT(event); break;
icculus@10573
   253
        #undef PRINT_JBUTTON_EVENT
icculus@10573
   254
icculus@12630
   255
        #define PRINT_JOYDEV_EVENT(event) SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d)", (uint) event->jdevice.timestamp, (int) event->jdevice.which)
icculus@10573
   256
        SDL_EVENT_CASE(SDL_JOYDEVICEADDED) PRINT_JOYDEV_EVENT(event); break;
icculus@10573
   257
        SDL_EVENT_CASE(SDL_JOYDEVICEREMOVED) PRINT_JOYDEV_EVENT(event); break;
icculus@10573
   258
        #undef PRINT_JOYDEV_EVENT
icculus@10573
   259
icculus@10573
   260
        SDL_EVENT_CASE(SDL_CONTROLLERAXISMOTION)
icculus@12630
   261
            SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d axis=%u value=%d)",
icculus@10573
   262
                (uint) event->caxis.timestamp, (int) event->caxis.which,
icculus@10573
   263
                (uint) event->caxis.axis, (int) event->caxis.value);
icculus@10573
   264
            break;
icculus@10573
   265
icculus@10573
   266
        #define PRINT_CBUTTON_EVENT(event) \
icculus@12630
   267
            SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d button=%u state=%s)", \
icculus@10573
   268
                (uint) event->cbutton.timestamp, (int) event->cbutton.which, \
icculus@10573
   269
                (uint) event->cbutton.button, event->cbutton.state == SDL_PRESSED ? "pressed" : "released")
icculus@10573
   270
        SDL_EVENT_CASE(SDL_CONTROLLERBUTTONDOWN) PRINT_CBUTTON_EVENT(event); break;
icculus@10573
   271
        SDL_EVENT_CASE(SDL_CONTROLLERBUTTONUP) PRINT_CBUTTON_EVENT(event); break;
icculus@10573
   272
        #undef PRINT_CBUTTON_EVENT
icculus@10573
   273
icculus@12630
   274
        #define PRINT_CONTROLLERDEV_EVENT(event) SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d)", (uint) event->cdevice.timestamp, (int) event->cdevice.which)
icculus@10573
   275
        SDL_EVENT_CASE(SDL_CONTROLLERDEVICEADDED) PRINT_CONTROLLERDEV_EVENT(event); break;
icculus@10573
   276
        SDL_EVENT_CASE(SDL_CONTROLLERDEVICEREMOVED) PRINT_CONTROLLERDEV_EVENT(event); break;
icculus@10573
   277
        SDL_EVENT_CASE(SDL_CONTROLLERDEVICEREMAPPED) PRINT_CONTROLLERDEV_EVENT(event); break;
icculus@10573
   278
        #undef PRINT_CONTROLLERDEV_EVENT
icculus@10573
   279
icculus@10573
   280
        #define PRINT_FINGER_EVENT(event) \
slouken@12897
   281
            SDL_snprintf(details, sizeof (details), " (timestamp=%u touchid=%"SDL_PRIs64" fingerid=%"SDL_PRIs64" x=%f y=%f dx=%f dy=%f pressure=%f)", \
slouken@12897
   282
                (uint) event->tfinger.timestamp, event->tfinger.touchId, \
slouken@12897
   283
                event->tfinger.fingerId, event->tfinger.x, event->tfinger.y, \
icculus@10573
   284
                event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure)
icculus@10573
   285
        SDL_EVENT_CASE(SDL_FINGERDOWN) PRINT_FINGER_EVENT(event); break;
icculus@10573
   286
        SDL_EVENT_CASE(SDL_FINGERUP) PRINT_FINGER_EVENT(event); break;
icculus@10573
   287
        SDL_EVENT_CASE(SDL_FINGERMOTION) PRINT_FINGER_EVENT(event); break;
icculus@10573
   288
        #undef PRINT_FINGER_EVENT
icculus@10573
   289
icculus@10573
   290
        #define PRINT_DOLLAR_EVENT(event) \
slouken@12897
   291
            SDL_snprintf(details, sizeof (details), " (timestamp=%u touchid=%"SDL_PRIs64" gestureid=%"SDL_PRIs64" numfingers=%u error=%f x=%f y=%f)", \
slouken@12897
   292
                (uint) event->dgesture.timestamp, event->dgesture.touchId, \
slouken@12897
   293
                event->dgesture.gestureId, (uint) event->dgesture.numFingers, \
icculus@10573
   294
                event->dgesture.error, event->dgesture.x, event->dgesture.y);
icculus@10573
   295
        SDL_EVENT_CASE(SDL_DOLLARGESTURE) PRINT_DOLLAR_EVENT(event); break;
icculus@10573
   296
        SDL_EVENT_CASE(SDL_DOLLARRECORD) PRINT_DOLLAR_EVENT(event); break;
icculus@10573
   297
        #undef PRINT_DOLLAR_EVENT
icculus@10573
   298
icculus@10573
   299
        SDL_EVENT_CASE(SDL_MULTIGESTURE)
slouken@12897
   300
            SDL_snprintf(details, sizeof (details), " (timestamp=%u touchid=%"SDL_PRIs64" dtheta=%f ddist=%f x=%f y=%f numfingers=%u)",
slouken@12897
   301
                (uint) event->mgesture.timestamp, event->mgesture.touchId,
icculus@10573
   302
                event->mgesture.dTheta, event->mgesture.dDist,
icculus@10573
   303
                event->mgesture.x, event->mgesture.y, (uint) event->mgesture.numFingers);
icculus@10573
   304
            break;
icculus@10573
   305
icculus@12630
   306
        #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)
icculus@10573
   307
        SDL_EVENT_CASE(SDL_DROPFILE) PRINT_DROP_EVENT(event); break;
icculus@10573
   308
        SDL_EVENT_CASE(SDL_DROPTEXT) PRINT_DROP_EVENT(event); break;
icculus@10573
   309
        SDL_EVENT_CASE(SDL_DROPBEGIN) PRINT_DROP_EVENT(event); break;
icculus@10573
   310
        SDL_EVENT_CASE(SDL_DROPCOMPLETE) PRINT_DROP_EVENT(event); break;
icculus@10573
   311
        #undef PRINT_DROP_EVENT
icculus@10573
   312
icculus@12630
   313
        #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");
icculus@10573
   314
        SDL_EVENT_CASE(SDL_AUDIODEVICEADDED) PRINT_AUDIODEV_EVENT(event); break;
icculus@10573
   315
        SDL_EVENT_CASE(SDL_AUDIODEVICEREMOVED) PRINT_AUDIODEV_EVENT(event); break;
icculus@10573
   316
        #undef PRINT_AUDIODEV_EVENT
icculus@10573
   317
icculus@10573
   318
        #undef SDL_EVENT_CASE
icculus@10573
   319
icculus@10573
   320
        default:
icculus@12630
   321
            if (!name[0]) {
icculus@12630
   322
                SDL_strlcpy(name, "UNKNOWN", sizeof (name));
icculus@12630
   323
                SDL_snprintf(details, sizeof (details), " #%u! (Bug? FIXME?)", (uint) event->type);
icculus@12630
   324
            }
icculus@10573
   325
            break;
icculus@10573
   326
    }
icculus@10573
   327
icculus@12630
   328
    if (name[0]) {
icculus@12630
   329
        SDL_Log("SDL EVENT: %s%s", name, details);
icculus@12630
   330
    }
icculus@12630
   331
icculus@12630
   332
    #undef uint
icculus@10573
   333
}
icculus@10573
   334
icculus@10573
   335
icculus@10573
   336
slouken@0
   337
/* Public functions */
slouken@0
   338
slouken@1895
   339
void
slouken@1895
   340
SDL_StopEventLoop(void)
slouken@0
   341
{
icculus@9437
   342
    const char *report = SDL_GetHint("SDL_EVENT_QUEUE_STATISTICS");
slouken@4429
   343
    int i;
slouken@7304
   344
    SDL_EventEntry *entry;
slouken@7304
   345
    SDL_SysWMEntry *wmmsg;
slouken@6495
   346
slouken@5123
   347
    if (SDL_EventQ.lock) {
slouken@7304
   348
        SDL_LockMutex(SDL_EventQ.lock);
slouken@5123
   349
    }
slouken@1123
   350
icculus@10003
   351
    SDL_AtomicSet(&SDL_EventQ.active, 0);
slouken@7304
   352
icculus@9437
   353
    if (report && SDL_atoi(report)) {
icculus@9437
   354
        SDL_Log("SDL EVENT QUEUE: Maximum events in-flight: %d\n",
icculus@9437
   355
                SDL_EventQ.max_events_seen);
icculus@9437
   356
    }
icculus@9437
   357
slouken@1895
   358
    /* Clean out EventQ */
slouken@7304
   359
    for (entry = SDL_EventQ.head; entry; ) {
slouken@7304
   360
        SDL_EventEntry *next = entry->next;
slouken@7304
   361
        SDL_free(entry);
slouken@7304
   362
        entry = next;
slouken@7304
   363
    }
slouken@7304
   364
    for (entry = SDL_EventQ.free; entry; ) {
slouken@7304
   365
        SDL_EventEntry *next = entry->next;
slouken@7304
   366
        SDL_free(entry);
slouken@7304
   367
        entry = next;
slouken@7304
   368
    }
slouken@7304
   369
    for (wmmsg = SDL_EventQ.wmmsg_used; wmmsg; ) {
slouken@7304
   370
        SDL_SysWMEntry *next = wmmsg->next;
slouken@7304
   371
        SDL_free(wmmsg);
slouken@7304
   372
        wmmsg = next;
slouken@7304
   373
    }
slouken@7304
   374
    for (wmmsg = SDL_EventQ.wmmsg_free; wmmsg; ) {
slouken@7304
   375
        SDL_SysWMEntry *next = wmmsg->next;
slouken@7304
   376
        SDL_free(wmmsg);
slouken@7304
   377
        wmmsg = next;
slouken@7304
   378
    }
icculus@9437
   379
icculus@10003
   380
    SDL_AtomicSet(&SDL_EventQ.count, 0);
icculus@9437
   381
    SDL_EventQ.max_events_seen = 0;
slouken@7304
   382
    SDL_EventQ.head = NULL;
slouken@7304
   383
    SDL_EventQ.tail = NULL;
slouken@7304
   384
    SDL_EventQ.free = NULL;
slouken@7304
   385
    SDL_EventQ.wmmsg_used = NULL;
slouken@7304
   386
    SDL_EventQ.wmmsg_free = NULL;
slouken@4429
   387
slouken@4429
   388
    /* Clear disabled event state */
slouken@4429
   389
    for (i = 0; i < SDL_arraysize(SDL_disabled_events); ++i) {
slouken@7719
   390
        SDL_free(SDL_disabled_events[i]);
slouken@7719
   391
        SDL_disabled_events[i] = NULL;
slouken@4429
   392
    }
slouken@5146
   393
slouken@11584
   394
    if (SDL_event_watchers_lock) {
slouken@11584
   395
        SDL_DestroyMutex(SDL_event_watchers_lock);
slouken@11584
   396
        SDL_event_watchers_lock = NULL;
slouken@5146
   397
    }
slouken@11587
   398
    if (SDL_event_watchers) {
slouken@11584
   399
        SDL_free(SDL_event_watchers);
slouken@11584
   400
        SDL_event_watchers = NULL;
slouken@11584
   401
        SDL_event_watchers_count = 0;
slouken@11584
   402
    }
slouken@11584
   403
    SDL_zero(SDL_EventOK);
slouken@7304
   404
slouken@7304
   405
    if (SDL_EventQ.lock) {
slouken@7304
   406
        SDL_UnlockMutex(SDL_EventQ.lock);
slouken@7304
   407
        SDL_DestroyMutex(SDL_EventQ.lock);
slouken@7304
   408
        SDL_EventQ.lock = NULL;
slouken@7304
   409
    }
slouken@0
   410
}
slouken@0
   411
slouken@0
   412
/* This function (and associated calls) may be called more than once */
slouken@1895
   413
int
slouken@5123
   414
SDL_StartEventLoop(void)
slouken@0
   415
{
slouken@6588
   416
    /* We'll leave the event queue alone, since we might have gotten
slouken@6588
   417
       some important events at launch (like SDL_DROPFILE)
slouken@6588
   418
slouken@6588
   419
       FIXME: Does this introduce any other bugs with events at startup?
slouken@6588
   420
     */
slouken@0
   421
slouken@5123
   422
    /* Create the lock and set ourselves active */
slouken@5123
   423
#if !SDL_THREADS_DISABLED
slouken@6588
   424
    if (!SDL_EventQ.lock) {
slouken@6588
   425
        SDL_EventQ.lock = SDL_CreateMutex();
slouken@11584
   426
        if (SDL_EventQ.lock == NULL) {
slouken@11584
   427
            return -1;
slouken@11584
   428
        }
slouken@6588
   429
    }
slouken@11584
   430
slouken@11584
   431
    if (!SDL_event_watchers_lock) {
slouken@11584
   432
        SDL_event_watchers_lock = SDL_CreateMutex();
slouken@11584
   433
        if (SDL_event_watchers_lock == NULL) {
slouken@11584
   434
            return -1;
slouken@11584
   435
        }
slouken@1895
   436
    }
slouken@5123
   437
#endif /* !SDL_THREADS_DISABLED */
icculus@7077
   438
slouken@7190
   439
    /* Process most event types */
icculus@7077
   440
    SDL_EventState(SDL_TEXTINPUT, SDL_DISABLE);
icculus@7077
   441
    SDL_EventState(SDL_TEXTEDITING, SDL_DISABLE);
icculus@7077
   442
    SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE);
slouken@12267
   443
#if 0 /* Leave these events enabled so apps can respond to items being dragged onto them at startup */
icculus@12070
   444
    SDL_EventState(SDL_DROPFILE, SDL_DISABLE);
icculus@12070
   445
    SDL_EventState(SDL_DROPTEXT, SDL_DISABLE);
slouken@12267
   446
#endif
icculus@7077
   447
icculus@10003
   448
    SDL_AtomicSet(&SDL_EventQ.active, 1);
slouken@0
   449
icculus@10003
   450
    return 0;
slouken@0
   451
}
slouken@0
   452
slouken@0
   453
slouken@0
   454
/* Add an event to the event queue -- called with the queue locked */
slouken@1895
   455
static int
slouken@1895
   456
SDL_AddEvent(SDL_Event * event)
slouken@0
   457
{
slouken@7304
   458
    SDL_EventEntry *entry;
icculus@10003
   459
    const int initial_count = SDL_AtomicGet(&SDL_EventQ.count);
icculus@10003
   460
    int final_count;
slouken@0
   461
icculus@10003
   462
    if (initial_count >= SDL_MAX_QUEUED_EVENTS) {
icculus@10003
   463
        SDL_SetError("Event queue is full (%d events)", initial_count);
slouken@7306
   464
        return 0;
slouken@7306
   465
    }
slouken@7306
   466
slouken@7304
   467
    if (SDL_EventQ.free == NULL) {
slouken@7304
   468
        entry = (SDL_EventEntry *)SDL_malloc(sizeof(*entry));
slouken@7304
   469
        if (!entry) {
slouken@7304
   470
            return 0;
slouken@7304
   471
        }
slouken@1895
   472
    } else {
slouken@7304
   473
        entry = SDL_EventQ.free;
slouken@7304
   474
        SDL_EventQ.free = entry->next;
slouken@1895
   475
    }
slouken@7304
   476
icculus@12630
   477
    if (SDL_DoEventLogging) {
icculus@12630
   478
        SDL_LogEvent(event);
icculus@12630
   479
    }
icculus@10573
   480
slouken@7304
   481
    entry->event = *event;
slouken@7304
   482
    if (event->type == SDL_SYSWMEVENT) {
slouken@7304
   483
        entry->msg = *event->syswm.msg;
slouken@7305
   484
        entry->event.syswm.msg = &entry->msg;
slouken@7304
   485
    }
slouken@7304
   486
slouken@7304
   487
    if (SDL_EventQ.tail) {
slouken@7304
   488
        SDL_EventQ.tail->next = entry;
slouken@7304
   489
        entry->prev = SDL_EventQ.tail;
slouken@7304
   490
        SDL_EventQ.tail = entry;
slouken@7304
   491
        entry->next = NULL;
slouken@7304
   492
    } else {
slouken@7304
   493
        SDL_assert(!SDL_EventQ.head);
slouken@7304
   494
        SDL_EventQ.head = entry;
slouken@7304
   495
        SDL_EventQ.tail = entry;
slouken@7304
   496
        entry->prev = NULL;
slouken@7304
   497
        entry->next = NULL;
slouken@7304
   498
    }
slouken@7304
   499
icculus@10003
   500
    final_count = SDL_AtomicAdd(&SDL_EventQ.count, 1) + 1;
icculus@10003
   501
    if (final_count > SDL_EventQ.max_events_seen) {
icculus@10003
   502
        SDL_EventQ.max_events_seen = final_count;
icculus@9437
   503
    }
icculus@9437
   504
slouken@7304
   505
    return 1;
slouken@0
   506
}
slouken@0
   507
slouken@7304
   508
/* Remove an event from the queue -- called with the queue locked */
slouken@7304
   509
static void
slouken@7304
   510
SDL_CutEvent(SDL_EventEntry *entry)
slouken@0
   511
{
slouken@7304
   512
    if (entry->prev) {
slouken@7304
   513
        entry->prev->next = entry->next;
slouken@7304
   514
    }
slouken@7304
   515
    if (entry->next) {
slouken@7304
   516
        entry->next->prev = entry->prev;
slouken@7304
   517
    }
slouken@0
   518
slouken@7304
   519
    if (entry == SDL_EventQ.head) {
slouken@7304
   520
        SDL_assert(entry->prev == NULL);
slouken@7304
   521
        SDL_EventQ.head = entry->next;
slouken@1895
   522
    }
slouken@7304
   523
    if (entry == SDL_EventQ.tail) {
slouken@7304
   524
        SDL_assert(entry->next == NULL);
slouken@7304
   525
        SDL_EventQ.tail = entry->prev;
slouken@7304
   526
    }
slouken@7304
   527
slouken@7304
   528
    entry->next = SDL_EventQ.free;
slouken@7304
   529
    SDL_EventQ.free = entry;
icculus@10003
   530
    SDL_assert(SDL_AtomicGet(&SDL_EventQ.count) > 0);
icculus@10003
   531
    SDL_AtomicAdd(&SDL_EventQ.count, -1);
slouken@0
   532
}
slouken@0
   533
slouken@0
   534
/* Lock the event queue, take a peep at it, and unlock it */
slouken@1895
   535
int
slouken@1895
   536
SDL_PeepEvents(SDL_Event * events, int numevents, SDL_eventaction action,
slouken@4429
   537
               Uint32 minType, Uint32 maxType)
slouken@0
   538
{
slouken@1895
   539
    int i, used;
slouken@0
   540
slouken@1895
   541
    /* Don't look after we've quit */
icculus@10003
   542
    if (!SDL_AtomicGet(&SDL_EventQ.active)) {
slouken@7304
   543
        /* We get a few spurious events at shutdown, so don't warn then */
slouken@7304
   544
        if (action != SDL_ADDEVENT) {
slouken@7304
   545
            SDL_SetError("The event system has been shut down");
slouken@7304
   546
        }
slouken@1895
   547
        return (-1);
slouken@1895
   548
    }
slouken@1895
   549
    /* Lock the event queue */
slouken@1895
   550
    used = 0;
slouken@6977
   551
    if (!SDL_EventQ.lock || SDL_LockMutex(SDL_EventQ.lock) == 0) {
slouken@1895
   552
        if (action == SDL_ADDEVENT) {
slouken@1895
   553
            for (i = 0; i < numevents; ++i) {
slouken@1895
   554
                used += SDL_AddEvent(&events[i]);
slouken@1895
   555
            }
slouken@1895
   556
        } else {
slouken@7304
   557
            SDL_EventEntry *entry, *next;
slouken@7304
   558
            SDL_SysWMEntry *wmmsg, *wmmsg_next;
slouken@7304
   559
            Uint32 type;
slouken@0
   560
slouken@10060
   561
            if (action == SDL_GETEVENT) {
slouken@10060
   562
                /* Clean out any used wmmsg data
slouken@10060
   563
                   FIXME: Do we want to retain the data for some period of time?
slouken@10060
   564
                 */
slouken@10060
   565
                for (wmmsg = SDL_EventQ.wmmsg_used; wmmsg; wmmsg = wmmsg_next) {
slouken@10060
   566
                    wmmsg_next = wmmsg->next;
slouken@10060
   567
                    wmmsg->next = SDL_EventQ.wmmsg_free;
slouken@10060
   568
                    SDL_EventQ.wmmsg_free = wmmsg;
slouken@10060
   569
                }
slouken@10060
   570
                SDL_EventQ.wmmsg_used = NULL;
slouken@1895
   571
            }
slouken@7304
   572
slouken@10060
   573
            for (entry = SDL_EventQ.head; entry && (!events || used < numevents); entry = next) {
slouken@7304
   574
                next = entry->next;
slouken@7304
   575
                type = entry->event.type;
slouken@4429
   576
                if (minType <= type && type <= maxType) {
slouken@10060
   577
                    if (events) {
slouken@10060
   578
                        events[used] = entry->event;
slouken@10060
   579
                        if (entry->event.type == SDL_SYSWMEVENT) {
slouken@10060
   580
                            /* We need to copy the wmmsg somewhere safe.
slouken@10060
   581
                               For now we'll guarantee it's valid at least until
slouken@10060
   582
                               the next call to SDL_PeepEvents()
slouken@10060
   583
                             */
slouken@10060
   584
                            if (SDL_EventQ.wmmsg_free) {
slouken@10060
   585
                                wmmsg = SDL_EventQ.wmmsg_free;
slouken@10060
   586
                                SDL_EventQ.wmmsg_free = wmmsg->next;
slouken@10060
   587
                            } else {
slouken@10060
   588
                                wmmsg = (SDL_SysWMEntry *)SDL_malloc(sizeof(*wmmsg));
slouken@10060
   589
                            }
slouken@10060
   590
                            wmmsg->msg = *entry->event.syswm.msg;
slouken@10060
   591
                            wmmsg->next = SDL_EventQ.wmmsg_used;
slouken@10060
   592
                            SDL_EventQ.wmmsg_used = wmmsg;
slouken@10060
   593
                            events[used].syswm.msg = &wmmsg->msg;
slouken@7304
   594
                        }
slouken@10060
   595
slouken@10060
   596
                        if (action == SDL_GETEVENT) {
slouken@10060
   597
                            SDL_CutEvent(entry);
slouken@10060
   598
                        }
slouken@7304
   599
                    }
slouken@7304
   600
                    ++used;
slouken@1895
   601
                }
slouken@1895
   602
            }
slouken@1895
   603
        }
slouken@10488
   604
        if (SDL_EventQ.lock) {
slouken@10488
   605
            SDL_UnlockMutex(SDL_EventQ.lock);
slouken@10488
   606
        }
slouken@1895
   607
    } else {
icculus@7037
   608
        return SDL_SetError("Couldn't lock event queue");
slouken@1895
   609
    }
slouken@1895
   610
    return (used);
slouken@1895
   611
}
slouken@1895
   612
slouken@1895
   613
SDL_bool
slouken@4429
   614
SDL_HasEvent(Uint32 type)
slouken@1895
   615
{
slouken@4429
   616
    return (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, type, type) > 0);
slouken@4429
   617
}
slouken@4429
   618
slouken@4429
   619
SDL_bool
slouken@4429
   620
SDL_HasEvents(Uint32 minType, Uint32 maxType)
slouken@4429
   621
{
slouken@4429
   622
    return (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, minType, maxType) > 0);
slouken@4429
   623
}
slouken@4429
   624
slouken@4429
   625
void
slouken@4429
   626
SDL_FlushEvent(Uint32 type)
slouken@4429
   627
{
slouken@4429
   628
    SDL_FlushEvents(type, type);
slouken@4429
   629
}
slouken@4429
   630
slouken@4429
   631
void
slouken@4429
   632
SDL_FlushEvents(Uint32 minType, Uint32 maxType)
slouken@4429
   633
{
icculus@12070
   634
    /* !!! FIXME: we need to manually SDL_free() the strings in TEXTINPUT and
icculus@12070
   635
       drag'n'drop events if we're flushing them without passing them to the
icculus@12070
   636
       app, but I don't know if this is the right place to do that. */
icculus@12070
   637
slouken@4429
   638
    /* Don't look after we've quit */
icculus@10003
   639
    if (!SDL_AtomicGet(&SDL_EventQ.active)) {
slouken@4429
   640
        return;
slouken@4429
   641
    }
slouken@4429
   642
slouken@4460
   643
    /* Make sure the events are current */
slouken@5293
   644
#if 0
slouken@5293
   645
    /* Actually, we can't do this since we might be flushing while processing
slouken@5293
   646
       a resize event, and calling this might trigger further resize events.
slouken@5293
   647
    */
slouken@4460
   648
    SDL_PumpEvents();
slouken@5293
   649
#endif
slouken@4460
   650
slouken@4429
   651
    /* Lock the event queue */
slouken@11584
   652
    if (!SDL_EventQ.lock || SDL_LockMutex(SDL_EventQ.lock) == 0) {
slouken@7304
   653
        SDL_EventEntry *entry, *next;
slouken@7304
   654
        Uint32 type;
slouken@7304
   655
        for (entry = SDL_EventQ.head; entry; entry = next) {
slouken@7304
   656
            next = entry->next;
slouken@7304
   657
            type = entry->event.type;
slouken@4429
   658
            if (minType <= type && type <= maxType) {
slouken@7304
   659
                SDL_CutEvent(entry);
slouken@4429
   660
            }
slouken@4429
   661
        }
slouken@11584
   662
        if (SDL_EventQ.lock) {
slouken@11584
   663
            SDL_UnlockMutex(SDL_EventQ.lock);
slouken@11584
   664
        }
slouken@4429
   665
    }
slouken@0
   666
}
slouken@0
   667
slouken@0
   668
/* Run the system dependent event loops */
slouken@1895
   669
void
slouken@1895
   670
SDL_PumpEvents(void)
slouken@0
   671
{
slouken@5123
   672
    SDL_VideoDevice *_this = SDL_GetVideoDevice();
slouken@0
   673
slouken@5123
   674
    /* Get events from the video subsystem */
slouken@5123
   675
    if (_this) {
slouken@5123
   676
        _this->PumpEvents(_this);
slouken@5123
   677
    }
slouken@1361
   678
#if !SDL_JOYSTICK_DISABLED
slouken@5123
   679
    /* Check for joystick state change */
icculus@8860
   680
    if ((!SDL_disabled_events[SDL_JOYAXISMOTION >> 8] || SDL_JoystickEventState(SDL_QUERY))) {
slouken@5123
   681
        SDL_JoystickUpdate();
slouken@5123
   682
    }
slouken@0
   683
#endif
icculus@9720
   684
slouken@12130
   685
#if !SDL_SENSOR_DISABLED
slouken@12130
   686
    /* Check for sensor state change */
slouken@12130
   687
    if (!SDL_disabled_events[SDL_SENSORUPDATE >> 8]) {
slouken@12130
   688
        SDL_SensorUpdate();
slouken@12130
   689
    }
slouken@12130
   690
#endif
slouken@12130
   691
icculus@12631
   692
    SDL_SendPendingSignalEvents();  /* in case we had a signal handler fire, etc. */
slouken@0
   693
}
slouken@0
   694
slouken@0
   695
/* Public functions */
slouken@0
   696
slouken@1895
   697
int
slouken@1895
   698
SDL_PollEvent(SDL_Event * event)
slouken@0
   699
{
slouken@3072
   700
    return SDL_WaitEventTimeout(event, 0);
slouken@0
   701
}
slouken@0
   702
slouken@1895
   703
int
slouken@1895
   704
SDL_WaitEvent(SDL_Event * event)
slouken@0
   705
{
slouken@3072
   706
    return SDL_WaitEventTimeout(event, -1);
slouken@3072
   707
}
slouken@3072
   708
slouken@3072
   709
int
slouken@3072
   710
SDL_WaitEventTimeout(SDL_Event * event, int timeout)
slouken@3072
   711
{
slouken@3072
   712
    Uint32 expiration = 0;
slouken@3072
   713
slouken@3072
   714
    if (timeout > 0)
slouken@3072
   715
        expiration = SDL_GetTicks() + timeout;
slouken@3072
   716
slouken@3072
   717
    for (;;) {
slouken@1895
   718
        SDL_PumpEvents();
slouken@4429
   719
        switch (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {
slouken@1895
   720
        case -1:
slouken@1895
   721
            return 0;
slouken@1895
   722
        case 0:
slouken@3072
   723
            if (timeout == 0) {
slouken@3072
   724
                /* Polling and no events, just return */
slouken@3072
   725
                return 0;
slouken@3072
   726
            }
slouken@7857
   727
            if (timeout > 0 && SDL_TICKS_PASSED(SDL_GetTicks(), expiration)) {
slouken@3072
   728
                /* Timeout expired and no events */
slouken@3072
   729
                return 0;
slouken@3072
   730
            }
slouken@1895
   731
            SDL_Delay(10);
slouken@3072
   732
            break;
slouken@10106
   733
        default:
slouken@10106
   734
            /* Has events */
slouken@10106
   735
            return 1;
slouken@1895
   736
        }
slouken@1895
   737
    }
slouken@0
   738
}
slouken@0
   739
slouken@1895
   740
int
slouken@1895
   741
SDL_PushEvent(SDL_Event * event)
slouken@0
   742
{
dludwig@7082
   743
    event->common.timestamp = SDL_GetTicks();
slouken@7190
   744
slouken@11588
   745
    if (SDL_EventOK.callback || SDL_event_watchers_count > 0) {
slouken@11584
   746
        if (!SDL_event_watchers_lock || SDL_LockMutex(SDL_event_watchers_lock) == 0) {
slouken@11587
   747
            if (SDL_EventOK.callback && !SDL_EventOK.callback(SDL_EventOK.userdata, event)) {
slouken@11587
   748
                if (SDL_event_watchers_lock) {
slouken@11587
   749
                    SDL_UnlockMutex(SDL_event_watchers_lock);
slouken@11587
   750
                }
slouken@11587
   751
                return 0;
slouken@11587
   752
            }
slouken@11584
   753
slouken@11584
   754
            if (SDL_event_watchers_count > 0) {
slouken@11587
   755
                /* Make sure we only dispatch the current watcher list */
slouken@11587
   756
                int i, event_watchers_count = SDL_event_watchers_count;
slouken@11587
   757
slouken@11587
   758
                SDL_event_watchers_dispatching = SDL_TRUE;
slouken@11587
   759
                for (i = 0; i < event_watchers_count; ++i) {
slouken@11587
   760
                    if (!SDL_event_watchers[i].removed) {
slouken@11587
   761
                        SDL_event_watchers[i].callback(SDL_event_watchers[i].userdata, event);
slouken@11587
   762
                    }
slouken@11587
   763
                }
slouken@11587
   764
                SDL_event_watchers_dispatching = SDL_FALSE;
slouken@11587
   765
slouken@11587
   766
                if (SDL_event_watchers_removed) {
slouken@11587
   767
                    for (i = SDL_event_watchers_count; i--; ) {
slouken@11587
   768
                        if (SDL_event_watchers[i].removed) {
slouken@11587
   769
                            --SDL_event_watchers_count;
slouken@11587
   770
                            if (i < SDL_event_watchers_count) {
slouken@11588
   771
                                SDL_memmove(&SDL_event_watchers[i], &SDL_event_watchers[i+1], (SDL_event_watchers_count - i) * sizeof(SDL_event_watchers[i]));
slouken@11587
   772
                            }
slouken@11587
   773
                        }
slouken@11587
   774
                    }
slouken@11587
   775
                    SDL_event_watchers_removed = SDL_FALSE;
slouken@11584
   776
                }
slouken@11584
   777
            }
slouken@11584
   778
slouken@11584
   779
            if (SDL_event_watchers_lock) {
slouken@11584
   780
                SDL_UnlockMutex(SDL_event_watchers_lock);
slouken@11584
   781
            }
slouken@11584
   782
        }
slouken@5146
   783
    }
slouken@5146
   784
slouken@4429
   785
    if (SDL_PeepEvents(event, 1, SDL_ADDEVENT, 0, 0) <= 0) {
slouken@1895
   786
        return -1;
slouken@1895
   787
    }
jim@4657
   788
jim@4657
   789
    SDL_GestureProcessEvent(event);
jim@4657
   790
slouken@1895
   791
    return 1;
slouken@0
   792
}
slouken@0
   793
slouken@1895
   794
void
slouken@1895
   795
SDL_SetEventFilter(SDL_EventFilter filter, void *userdata)
slouken@0
   796
{
slouken@11584
   797
    if (!SDL_event_watchers_lock || SDL_LockMutex(SDL_event_watchers_lock) == 0) {
slouken@11584
   798
        /* Set filter and discard pending events */
slouken@11584
   799
        SDL_EventOK.callback = filter;
slouken@11584
   800
        SDL_EventOK.userdata = userdata;
slouken@11584
   801
        SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT);
slouken@11584
   802
slouken@11584
   803
        if (SDL_event_watchers_lock) {
slouken@11584
   804
            SDL_UnlockMutex(SDL_event_watchers_lock);
slouken@11584
   805
        }
slouken@11584
   806
    }
slouken@0
   807
}
slouken@0
   808
slouken@1895
   809
SDL_bool
slouken@1895
   810
SDL_GetEventFilter(SDL_EventFilter * filter, void **userdata)
slouken@0
   811
{
slouken@11584
   812
    SDL_EventWatcher event_ok;
slouken@11584
   813
slouken@11584
   814
    if (!SDL_event_watchers_lock || SDL_LockMutex(SDL_event_watchers_lock) == 0) {
slouken@11584
   815
        event_ok = SDL_EventOK;
slouken@11584
   816
slouken@11584
   817
        if (SDL_event_watchers_lock) {
slouken@11584
   818
            SDL_UnlockMutex(SDL_event_watchers_lock);
slouken@11584
   819
        }
slouken@11584
   820
    } else {
slouken@11584
   821
        SDL_zero(event_ok);
slouken@11584
   822
    }
slouken@11584
   823
slouken@1895
   824
    if (filter) {
slouken@11584
   825
        *filter = event_ok.callback;
slouken@1895
   826
    }
slouken@1895
   827
    if (userdata) {
slouken@11584
   828
        *userdata = event_ok.userdata;
slouken@1895
   829
    }
slouken@11584
   830
    return event_ok.callback ? SDL_TRUE : SDL_FALSE;
slouken@0
   831
}
slouken@0
   832
slouken@5146
   833
void
slouken@5146
   834
SDL_AddEventWatch(SDL_EventFilter filter, void *userdata)
slouken@5146
   835
{
slouken@11584
   836
    if (!SDL_event_watchers_lock || SDL_LockMutex(SDL_event_watchers_lock) == 0) {
slouken@11584
   837
        SDL_EventWatcher *event_watchers;
slouken@5146
   838
slouken@11597
   839
        event_watchers = SDL_realloc(SDL_event_watchers, (SDL_event_watchers_count + 1) * sizeof(*event_watchers));
slouken@11584
   840
        if (event_watchers) {
slouken@11584
   841
            SDL_EventWatcher *watcher;
slouken@8234
   842
slouken@11584
   843
            SDL_event_watchers = event_watchers;
slouken@11584
   844
            watcher = &SDL_event_watchers[SDL_event_watchers_count];
slouken@11584
   845
            watcher->callback = filter;
slouken@11584
   846
            watcher->userdata = userdata;
slouken@11587
   847
            watcher->removed = SDL_FALSE;
slouken@11584
   848
            ++SDL_event_watchers_count;
slouken@11584
   849
        }
slouken@8234
   850
slouken@11584
   851
        if (SDL_event_watchers_lock) {
slouken@11584
   852
            SDL_UnlockMutex(SDL_event_watchers_lock);
slouken@8234
   853
        }
slouken@8234
   854
    }
slouken@5146
   855
}
slouken@5146
   856
slouken@5146
   857
void
slouken@5146
   858
SDL_DelEventWatch(SDL_EventFilter filter, void *userdata)
slouken@5146
   859
{
slouken@11584
   860
    if (!SDL_event_watchers_lock || SDL_LockMutex(SDL_event_watchers_lock) == 0) {
slouken@11584
   861
        int i;
slouken@5146
   862
slouken@11584
   863
        for (i = 0; i < SDL_event_watchers_count; ++i) {
slouken@11584
   864
            if (SDL_event_watchers[i].callback == filter && SDL_event_watchers[i].userdata == userdata) {
slouken@11587
   865
                if (SDL_event_watchers_dispatching) {
slouken@11587
   866
                    SDL_event_watchers[i].removed = SDL_TRUE;
slouken@11587
   867
                    SDL_event_watchers_removed = SDL_TRUE;
slouken@11587
   868
                } else {
slouken@11587
   869
                    --SDL_event_watchers_count;
slouken@11587
   870
                    if (i < SDL_event_watchers_count) {
slouken@11588
   871
                        SDL_memmove(&SDL_event_watchers[i], &SDL_event_watchers[i+1], (SDL_event_watchers_count - i) * sizeof(SDL_event_watchers[i]));
slouken@11587
   872
                    }
slouken@11584
   873
                }
slouken@11584
   874
                break;
slouken@5146
   875
            }
slouken@11584
   876
        }
slouken@11584
   877
slouken@11584
   878
        if (SDL_event_watchers_lock) {
slouken@11584
   879
            SDL_UnlockMutex(SDL_event_watchers_lock);
slouken@5146
   880
        }
slouken@5146
   881
    }
slouken@5146
   882
}
slouken@5146
   883
slouken@1895
   884
void
slouken@1895
   885
SDL_FilterEvents(SDL_EventFilter filter, void *userdata)
slouken@0
   886
{
slouken@11584
   887
    if (!SDL_EventQ.lock || SDL_LockMutex(SDL_EventQ.lock) == 0) {
slouken@7304
   888
        SDL_EventEntry *entry, *next;
slouken@7304
   889
        for (entry = SDL_EventQ.head; entry; entry = next) {
slouken@7304
   890
            next = entry->next;
slouken@7304
   891
            if (!filter(userdata, &entry->event)) {
slouken@7304
   892
                SDL_CutEvent(entry);
slouken@1895
   893
            }
slouken@1895
   894
        }
slouken@11584
   895
        if (SDL_EventQ.lock) {
slouken@11584
   896
            SDL_UnlockMutex(SDL_EventQ.lock);
slouken@11584
   897
        }
slouken@1895
   898
    }
slouken@1895
   899
}
slouken@0
   900
slouken@1895
   901
Uint8
slouken@4429
   902
SDL_EventState(Uint32 type, int state)
slouken@1895
   903
{
icculus@12070
   904
    const SDL_bool isdnd = ((state == SDL_DISABLE) || (state == SDL_ENABLE)) &&
icculus@12070
   905
                           ((type == SDL_DROPFILE) || (type == SDL_DROPTEXT));
slouken@1895
   906
    Uint8 current_state;
slouken@4429
   907
    Uint8 hi = ((type >> 8) & 0xff);
slouken@4429
   908
    Uint8 lo = (type & 0xff);
slouken@1895
   909
slouken@4429
   910
    if (SDL_disabled_events[hi] &&
slouken@4429
   911
        (SDL_disabled_events[hi]->bits[lo/32] & (1 << (lo&31)))) {
slouken@4429
   912
        current_state = SDL_DISABLE;
slouken@4429
   913
    } else {
slouken@4429
   914
        current_state = SDL_ENABLE;
slouken@1895
   915
    }
slouken@1895
   916
slouken@4429
   917
    if (state != current_state)
slouken@4429
   918
    {
slouken@4429
   919
        switch (state) {
slouken@4429
   920
        case SDL_DISABLE:
slouken@4429
   921
            /* Disable this event type and discard pending events */
slouken@4429
   922
            if (!SDL_disabled_events[hi]) {
slouken@4429
   923
                SDL_disabled_events[hi] = (SDL_DisabledEventBlock*) SDL_calloc(1, sizeof(SDL_DisabledEventBlock));
slouken@4429
   924
                if (!SDL_disabled_events[hi]) {
slouken@4429
   925
                    /* Out of memory, nothing we can do... */
slouken@4429
   926
                    break;
slouken@4429
   927
                }
slouken@4429
   928
            }
slouken@4429
   929
            SDL_disabled_events[hi]->bits[lo/32] |= (1 << (lo&31));
slouken@4429
   930
            SDL_FlushEvent(type);
slouken@4429
   931
            break;
slouken@4429
   932
        case SDL_ENABLE:
slouken@4429
   933
            SDL_disabled_events[hi]->bits[lo/32] &= ~(1 << (lo&31));
slouken@4429
   934
            break;
slouken@4429
   935
        default:
slouken@4429
   936
            /* Querying state... */
slouken@4429
   937
            break;
slouken@1895
   938
        }
slouken@1895
   939
    }
slouken@4429
   940
icculus@12070
   941
    /* turn off drag'n'drop support if we've disabled the events.
icculus@12070
   942
       This might change some UI details at the OS level. */
icculus@12070
   943
    if (isdnd) {
icculus@12070
   944
        SDL_ToggleDragAndDropSupport();
icculus@12070
   945
    }
icculus@12070
   946
slouken@4429
   947
    return current_state;
slouken@4429
   948
}
slouken@4429
   949
slouken@4429
   950
Uint32
slouken@4429
   951
SDL_RegisterEvents(int numevents)
slouken@4429
   952
{
slouken@4429
   953
    Uint32 event_base;
slouken@4429
   954
icculus@7611
   955
    if ((numevents > 0) && (SDL_userevents+numevents <= SDL_LASTEVENT)) {
slouken@4429
   956
        event_base = SDL_userevents;
slouken@4429
   957
        SDL_userevents += numevents;
slouken@4429
   958
    } else {
slouken@4429
   959
        event_base = (Uint32)-1;
slouken@4429
   960
    }
slouken@4429
   961
    return event_base;
slouken@0
   962
}
slouken@0
   963
slouken@7190
   964
int
slouken@7190
   965
SDL_SendAppEvent(SDL_EventType eventType)
slouken@7190
   966
{
slouken@7190
   967
    int posted;
slouken@7190
   968
slouken@7190
   969
    posted = 0;
slouken@7190
   970
    if (SDL_GetEventState(eventType) == SDL_ENABLE) {
slouken@7190
   971
        SDL_Event event;
slouken@7190
   972
        event.type = eventType;
slouken@7190
   973
        posted = (SDL_PushEvent(&event) > 0);
slouken@7190
   974
    }
slouken@7190
   975
    return (posted);
slouken@7190
   976
}
slouken@7190
   977
slouken@1895
   978
int
slouken@1895
   979
SDL_SendSysWMEvent(SDL_SysWMmsg * message)
slouken@0
   980
{
slouken@1895
   981
    int posted;
slouken@0
   982
slouken@1895
   983
    posted = 0;
slouken@4429
   984
    if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
slouken@1895
   985
        SDL_Event event;
slouken@1895
   986
        SDL_memset(&event, 0, sizeof(event));
slouken@1895
   987
        event.type = SDL_SYSWMEVENT;
slouken@1895
   988
        event.syswm.msg = message;
slouken@1895
   989
        posted = (SDL_PushEvent(&event) > 0);
slouken@1895
   990
    }
slouken@1895
   991
    /* Update internal event state */
slouken@1895
   992
    return (posted);
slouken@0
   993
}
slouken@1895
   994
slouken@9898
   995
int
slouken@9898
   996
SDL_SendKeymapChangedEvent(void)
slouken@9898
   997
{
slouken@9898
   998
    return SDL_SendAppEvent(SDL_KEYMAPCHANGED);
slouken@9898
   999
}
slouken@9898
  1000
icculus@12630
  1001
int
icculus@12630
  1002
SDL_EventsInit(void)
icculus@12630
  1003
{
icculus@12630
  1004
    SDL_AddHintCallback(SDL_HINT_EVENT_LOGGING, SDL_EventLoggingChanged, NULL);
icculus@12630
  1005
    if (SDL_StartEventLoop() < 0) {
icculus@12630
  1006
        SDL_DelHintCallback(SDL_HINT_EVENT_LOGGING, SDL_EventLoggingChanged, NULL);
icculus@12630
  1007
        return -1;
icculus@12630
  1008
    }
icculus@12630
  1009
icculus@12630
  1010
    SDL_QuitInit();
icculus@12630
  1011
icculus@12630
  1012
    return 0;
icculus@12630
  1013
}
icculus@12630
  1014
icculus@12630
  1015
void
icculus@12630
  1016
SDL_EventsQuit(void)
icculus@12630
  1017
{
icculus@12630
  1018
    SDL_QuitQuit();
icculus@12630
  1019
    SDL_StopEventLoop();
icculus@12630
  1020
    SDL_DelHintCallback(SDL_HINT_EVENT_LOGGING, SDL_EventLoggingChanged, NULL);
icculus@12630
  1021
}
icculus@12630
  1022
slouken@1895
  1023
/* vi: set ts=4 sw=4 expandtab: */