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