src/events/SDL_events.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 18 Feb 2019 07:50:33 -0800
changeset 12612 07c39cbbeacf
parent 12503 806492103856
child 12630 a26e3c61e35f
permissions -rw-r--r--
Fixed bug 4500 - Heap-Buffer Overflow in Map1toN pertaining to SDL_pixels.c

Petr Pisar

The reproducer has these data in BITMAPINFOHEADER:

biSize = 40
biBitCount = 8
biClrUsed = 131075

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