src/events/SDL_events.c
author Sam Lantinga
Sun, 22 Jun 2014 11:02:56 -0700
changeset 8910 c23ffe72934c
parent 8860 c4133d635375
child 9437 569cfb86df95
permissions -rw-r--r--
Partial fix for bug 2556 - add compilation flag -Wshadow

I added -Wshadow and then turned it off again because of massive variable shadowing in the blit macros.

Feel free to go through that code and fix these if you want. Just uncomment CheckWarnShadow in configure.in if you want to try this.
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@8149
     3
  Copyright (C) 1997-2014 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@0
    27
#include "SDL_syswm.h"
slouken@2984
    28
#include "SDL_thread.h"
slouken@1361
    29
#include "SDL_events_c.h"
slouken@1361
    30
#include "../timer/SDL_timer_c.h"
slouken@1361
    31
#if !SDL_JOYSTICK_DISABLED
slouken@1361
    32
#include "../joystick/SDL_joystick_c.h"
slouken@1361
    33
#endif
slouken@5123
    34
#include "../video/SDL_sysvideo.h"
slouken@0
    35
slouken@7306
    36
/* An arbitrary limit so we don't have unbounded growth */
slouken@7306
    37
#define SDL_MAX_QUEUED_EVENTS   65535
slouken@7306
    38
slouken@0
    39
/* Public data -- the event filter */
slouken@0
    40
SDL_EventFilter SDL_EventOK = NULL;
slouken@1895
    41
void *SDL_EventOKParam;
slouken@4429
    42
slouken@5146
    43
typedef struct SDL_EventWatcher {
slouken@5146
    44
    SDL_EventFilter callback;
slouken@5146
    45
    void *userdata;
slouken@5146
    46
    struct SDL_EventWatcher *next;
slouken@5146
    47
} SDL_EventWatcher;
slouken@5146
    48
slouken@5146
    49
static SDL_EventWatcher *SDL_event_watchers = NULL;
slouken@5146
    50
slouken@4429
    51
typedef struct {
slouken@4429
    52
    Uint32 bits[8];
slouken@4429
    53
} SDL_DisabledEventBlock;
slouken@4429
    54
slouken@4429
    55
static SDL_DisabledEventBlock *SDL_disabled_events[256];
slouken@4429
    56
static Uint32 SDL_userevents = SDL_USEREVENT;
slouken@0
    57
slouken@0
    58
/* Private data -- event queue */
slouken@7304
    59
typedef struct _SDL_EventEntry
slouken@7304
    60
{
slouken@7304
    61
    SDL_Event event;
slouken@7304
    62
    SDL_SysWMmsg msg;
slouken@7304
    63
    struct _SDL_EventEntry *prev;
slouken@7304
    64
    struct _SDL_EventEntry *next;
slouken@7304
    65
} SDL_EventEntry;
slouken@7304
    66
slouken@7304
    67
typedef struct _SDL_SysWMEntry
slouken@7304
    68
{
slouken@7304
    69
    SDL_SysWMmsg msg;
slouken@7304
    70
    struct _SDL_SysWMEntry *next;
slouken@7304
    71
} SDL_SysWMEntry;
slouken@7304
    72
slouken@1895
    73
static struct
slouken@1895
    74
{
slouken@1895
    75
    SDL_mutex *lock;
slouken@7304
    76
    volatile SDL_bool active;
slouken@7306
    77
    volatile int count;
slouken@7304
    78
    SDL_EventEntry *head;
slouken@7304
    79
    SDL_EventEntry *tail;
slouken@7304
    80
    SDL_EventEntry *free;
slouken@7304
    81
    SDL_SysWMEntry *wmmsg_used;
slouken@7304
    82
    SDL_SysWMEntry *wmmsg_free;
slouken@7304
    83
} SDL_EventQ = { NULL, SDL_TRUE };
slouken@0
    84
slouken@0
    85
slouken@0
    86
/* Public functions */
slouken@0
    87
slouken@1895
    88
void
slouken@1895
    89
SDL_StopEventLoop(void)
slouken@0
    90
{
slouken@4429
    91
    int i;
slouken@7304
    92
    SDL_EventEntry *entry;
slouken@7304
    93
    SDL_SysWMEntry *wmmsg;
slouken@6495
    94
slouken@5123
    95
    if (SDL_EventQ.lock) {
slouken@7304
    96
        SDL_LockMutex(SDL_EventQ.lock);
slouken@5123
    97
    }
slouken@1123
    98
slouken@7304
    99
    SDL_EventQ.active = SDL_FALSE;
slouken@7304
   100
slouken@1895
   101
    /* Clean out EventQ */
slouken@7304
   102
    for (entry = SDL_EventQ.head; entry; ) {
slouken@7304
   103
        SDL_EventEntry *next = entry->next;
slouken@7304
   104
        SDL_free(entry);
slouken@7304
   105
        entry = next;
slouken@7304
   106
    }
slouken@7304
   107
    for (entry = SDL_EventQ.free; entry; ) {
slouken@7304
   108
        SDL_EventEntry *next = entry->next;
slouken@7304
   109
        SDL_free(entry);
slouken@7304
   110
        entry = next;
slouken@7304
   111
    }
slouken@7304
   112
    for (wmmsg = SDL_EventQ.wmmsg_used; wmmsg; ) {
slouken@7304
   113
        SDL_SysWMEntry *next = wmmsg->next;
slouken@7304
   114
        SDL_free(wmmsg);
slouken@7304
   115
        wmmsg = next;
slouken@7304
   116
    }
slouken@7304
   117
    for (wmmsg = SDL_EventQ.wmmsg_free; wmmsg; ) {
slouken@7304
   118
        SDL_SysWMEntry *next = wmmsg->next;
slouken@7304
   119
        SDL_free(wmmsg);
slouken@7304
   120
        wmmsg = next;
slouken@7304
   121
    }
slouken@7306
   122
    SDL_EventQ.count = 0;
slouken@7304
   123
    SDL_EventQ.head = NULL;
slouken@7304
   124
    SDL_EventQ.tail = NULL;
slouken@7304
   125
    SDL_EventQ.free = NULL;
slouken@7304
   126
    SDL_EventQ.wmmsg_used = NULL;
slouken@7304
   127
    SDL_EventQ.wmmsg_free = NULL;
slouken@4429
   128
slouken@4429
   129
    /* Clear disabled event state */
slouken@4429
   130
    for (i = 0; i < SDL_arraysize(SDL_disabled_events); ++i) {
slouken@7719
   131
        SDL_free(SDL_disabled_events[i]);
slouken@7719
   132
        SDL_disabled_events[i] = NULL;
slouken@4429
   133
    }
slouken@5146
   134
slouken@5146
   135
    while (SDL_event_watchers) {
slouken@5146
   136
        SDL_EventWatcher *tmp = SDL_event_watchers;
slouken@5146
   137
        SDL_event_watchers = tmp->next;
slouken@5146
   138
        SDL_free(tmp);
slouken@5146
   139
    }
slouken@7190
   140
    SDL_EventOK = NULL;
slouken@7304
   141
slouken@7304
   142
    if (SDL_EventQ.lock) {
slouken@7304
   143
        SDL_UnlockMutex(SDL_EventQ.lock);
slouken@7304
   144
        SDL_DestroyMutex(SDL_EventQ.lock);
slouken@7304
   145
        SDL_EventQ.lock = NULL;
slouken@7304
   146
    }
slouken@0
   147
}
slouken@0
   148
slouken@0
   149
/* This function (and associated calls) may be called more than once */
slouken@1895
   150
int
slouken@5123
   151
SDL_StartEventLoop(void)
slouken@0
   152
{
slouken@6588
   153
    /* We'll leave the event queue alone, since we might have gotten
slouken@6588
   154
       some important events at launch (like SDL_DROPFILE)
slouken@6588
   155
slouken@6588
   156
       FIXME: Does this introduce any other bugs with events at startup?
slouken@6588
   157
     */
slouken@0
   158
slouken@5123
   159
    /* Create the lock and set ourselves active */
slouken@5123
   160
#if !SDL_THREADS_DISABLED
slouken@6588
   161
    if (!SDL_EventQ.lock) {
slouken@6588
   162
        SDL_EventQ.lock = SDL_CreateMutex();
slouken@6588
   163
    }
slouken@5123
   164
    if (SDL_EventQ.lock == NULL) {
slouken@1895
   165
        return (-1);
slouken@1895
   166
    }
slouken@5123
   167
#endif /* !SDL_THREADS_DISABLED */
icculus@7077
   168
slouken@7190
   169
    /* Process most event types */
icculus@7077
   170
    SDL_EventState(SDL_TEXTINPUT, SDL_DISABLE);
icculus@7077
   171
    SDL_EventState(SDL_TEXTEDITING, SDL_DISABLE);
icculus@7077
   172
    SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE);
icculus@7077
   173
slouken@7304
   174
    SDL_EventQ.active = SDL_TRUE;
slouken@1895
   175
slouken@1895
   176
    return (0);
slouken@0
   177
}
slouken@0
   178
slouken@0
   179
slouken@0
   180
/* Add an event to the event queue -- called with the queue locked */
slouken@1895
   181
static int
slouken@1895
   182
SDL_AddEvent(SDL_Event * event)
slouken@0
   183
{
slouken@7304
   184
    SDL_EventEntry *entry;
slouken@0
   185
slouken@7306
   186
    if (SDL_EventQ.count >= SDL_MAX_QUEUED_EVENTS) {
slouken@7306
   187
        SDL_SetError("Event queue is full (%d events)", SDL_EventQ.count);
slouken@7306
   188
        return 0;
slouken@7306
   189
    }
slouken@7306
   190
slouken@7304
   191
    if (SDL_EventQ.free == NULL) {
slouken@7304
   192
        entry = (SDL_EventEntry *)SDL_malloc(sizeof(*entry));
slouken@7304
   193
        if (!entry) {
slouken@7304
   194
            return 0;
slouken@7304
   195
        }
slouken@1895
   196
    } else {
slouken@7304
   197
        entry = SDL_EventQ.free;
slouken@7304
   198
        SDL_EventQ.free = entry->next;
slouken@7304
   199
    }
slouken@7304
   200
slouken@7304
   201
    entry->event = *event;
slouken@7304
   202
    if (event->type == SDL_SYSWMEVENT) {
slouken@7304
   203
        entry->msg = *event->syswm.msg;
slouken@7305
   204
        entry->event.syswm.msg = &entry->msg;
slouken@1895
   205
    }
slouken@7304
   206
slouken@7304
   207
    if (SDL_EventQ.tail) {
slouken@7304
   208
        SDL_EventQ.tail->next = entry;
slouken@7304
   209
        entry->prev = SDL_EventQ.tail;
slouken@7304
   210
        SDL_EventQ.tail = entry;
slouken@7304
   211
        entry->next = NULL;
slouken@7304
   212
    } else {
slouken@7304
   213
        SDL_assert(!SDL_EventQ.head);
slouken@7304
   214
        SDL_EventQ.head = entry;
slouken@7304
   215
        SDL_EventQ.tail = entry;
slouken@7304
   216
        entry->prev = NULL;
slouken@7304
   217
        entry->next = NULL;
slouken@7304
   218
    }
slouken@7306
   219
    ++SDL_EventQ.count;
slouken@7304
   220
slouken@7304
   221
    return 1;
slouken@0
   222
}
slouken@0
   223
slouken@7304
   224
/* Remove an event from the queue -- called with the queue locked */
slouken@7304
   225
static void
slouken@7304
   226
SDL_CutEvent(SDL_EventEntry *entry)
slouken@0
   227
{
slouken@7304
   228
    if (entry->prev) {
slouken@7304
   229
        entry->prev->next = entry->next;
slouken@7304
   230
    }
slouken@7304
   231
    if (entry->next) {
slouken@7304
   232
        entry->next->prev = entry->prev;
slouken@7304
   233
    }
slouken@0
   234
slouken@7304
   235
    if (entry == SDL_EventQ.head) {
slouken@7304
   236
        SDL_assert(entry->prev == NULL);
slouken@7304
   237
        SDL_EventQ.head = entry->next;
slouken@1895
   238
    }
slouken@7304
   239
    if (entry == SDL_EventQ.tail) {
slouken@7304
   240
        SDL_assert(entry->next == NULL);
slouken@7304
   241
        SDL_EventQ.tail = entry->prev;
slouken@7304
   242
    }
slouken@7304
   243
slouken@7304
   244
    entry->next = SDL_EventQ.free;
slouken@7304
   245
    SDL_EventQ.free = entry;
slouken@7306
   246
    SDL_assert(SDL_EventQ.count > 0);
slouken@7306
   247
    --SDL_EventQ.count;
slouken@0
   248
}
slouken@0
   249
slouken@0
   250
/* Lock the event queue, take a peep at it, and unlock it */
slouken@1895
   251
int
slouken@1895
   252
SDL_PeepEvents(SDL_Event * events, int numevents, SDL_eventaction action,
slouken@4429
   253
               Uint32 minType, Uint32 maxType)
slouken@0
   254
{
slouken@1895
   255
    int i, used;
slouken@0
   256
slouken@1895
   257
    /* Don't look after we've quit */
slouken@1895
   258
    if (!SDL_EventQ.active) {
slouken@7304
   259
        /* We get a few spurious events at shutdown, so don't warn then */
slouken@7304
   260
        if (action != SDL_ADDEVENT) {
slouken@7304
   261
            SDL_SetError("The event system has been shut down");
slouken@7304
   262
        }
slouken@1895
   263
        return (-1);
slouken@1895
   264
    }
slouken@1895
   265
    /* Lock the event queue */
slouken@1895
   266
    used = 0;
slouken@6977
   267
    if (!SDL_EventQ.lock || SDL_LockMutex(SDL_EventQ.lock) == 0) {
slouken@1895
   268
        if (action == SDL_ADDEVENT) {
slouken@1895
   269
            for (i = 0; i < numevents; ++i) {
slouken@1895
   270
                used += SDL_AddEvent(&events[i]);
slouken@1895
   271
            }
slouken@1895
   272
        } else {
slouken@7304
   273
            SDL_EventEntry *entry, *next;
slouken@7304
   274
            SDL_SysWMEntry *wmmsg, *wmmsg_next;
slouken@1895
   275
            SDL_Event tmpevent;
slouken@7304
   276
            Uint32 type;
slouken@0
   277
slouken@1895
   278
            /* If 'events' is NULL, just see if they exist */
slouken@1895
   279
            if (events == NULL) {
slouken@1895
   280
                action = SDL_PEEKEVENT;
slouken@1895
   281
                numevents = 1;
slouken@1895
   282
                events = &tmpevent;
slouken@1895
   283
            }
slouken@7304
   284
slouken@7304
   285
            /* Clean out any used wmmsg data
slouken@7304
   286
               FIXME: Do we want to retain the data for some period of time?
slouken@7304
   287
             */
slouken@7304
   288
            for (wmmsg = SDL_EventQ.wmmsg_used; wmmsg; wmmsg = wmmsg_next) {
slouken@7304
   289
                wmmsg_next = wmmsg->next;
slouken@7304
   290
                wmmsg->next = SDL_EventQ.wmmsg_free;
slouken@7304
   291
                SDL_EventQ.wmmsg_free = wmmsg;
slouken@7304
   292
            }
slouken@7304
   293
            SDL_EventQ.wmmsg_used = NULL;
slouken@7304
   294
slouken@7304
   295
            for (entry = SDL_EventQ.head; entry && used < numevents; entry = next) {
slouken@7304
   296
                next = entry->next;
slouken@7304
   297
                type = entry->event.type;
slouken@4429
   298
                if (minType <= type && type <= maxType) {
slouken@7304
   299
                    events[used] = entry->event;
slouken@7304
   300
                    if (entry->event.type == SDL_SYSWMEVENT) {
slouken@7304
   301
                        /* We need to copy the wmmsg somewhere safe.
slouken@7304
   302
                           For now we'll guarantee it's valid at least until
slouken@7304
   303
                           the next call to SDL_PeepEvents()
slouken@7304
   304
                         */
slouken@7304
   305
                        if (SDL_EventQ.wmmsg_free) {
slouken@7304
   306
                            wmmsg = SDL_EventQ.wmmsg_free;
slouken@7304
   307
                            SDL_EventQ.wmmsg_free = wmmsg->next;
slouken@7304
   308
                        } else {
slouken@7304
   309
                            wmmsg = (SDL_SysWMEntry *)SDL_malloc(sizeof(*wmmsg));
slouken@7304
   310
                        }
slouken@7304
   311
                        wmmsg->msg = *entry->event.syswm.msg;
slouken@7304
   312
                        wmmsg->next = SDL_EventQ.wmmsg_used;
slouken@7304
   313
                        SDL_EventQ.wmmsg_used = wmmsg;
slouken@7304
   314
                        events[used].syswm.msg = &wmmsg->msg;
slouken@7304
   315
                    }
slouken@7304
   316
                    ++used;
slouken@7304
   317
slouken@1895
   318
                    if (action == SDL_GETEVENT) {
slouken@7304
   319
                        SDL_CutEvent(entry);
slouken@1895
   320
                    }
slouken@1895
   321
                }
slouken@1895
   322
            }
slouken@1895
   323
        }
slouken@6977
   324
        SDL_UnlockMutex(SDL_EventQ.lock);
slouken@1895
   325
    } else {
icculus@7037
   326
        return SDL_SetError("Couldn't lock event queue");
slouken@1895
   327
    }
slouken@1895
   328
    return (used);
slouken@1895
   329
}
slouken@1895
   330
slouken@1895
   331
SDL_bool
slouken@4429
   332
SDL_HasEvent(Uint32 type)
slouken@4429
   333
{
slouken@4429
   334
    return (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, type, type) > 0);
slouken@4429
   335
}
slouken@4429
   336
slouken@4429
   337
SDL_bool
slouken@4429
   338
SDL_HasEvents(Uint32 minType, Uint32 maxType)
slouken@4429
   339
{
slouken@4429
   340
    return (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, minType, maxType) > 0);
slouken@4429
   341
}
slouken@4429
   342
slouken@4429
   343
void
slouken@4429
   344
SDL_FlushEvent(Uint32 type)
slouken@1895
   345
{
slouken@4429
   346
    SDL_FlushEvents(type, type);
slouken@4429
   347
}
slouken@4429
   348
slouken@4429
   349
void
slouken@4429
   350
SDL_FlushEvents(Uint32 minType, Uint32 maxType)
slouken@4429
   351
{
slouken@4429
   352
    /* Don't look after we've quit */
slouken@4429
   353
    if (!SDL_EventQ.active) {
slouken@4429
   354
        return;
slouken@4429
   355
    }
slouken@4429
   356
slouken@4460
   357
    /* Make sure the events are current */
slouken@5293
   358
#if 0
slouken@5293
   359
    /* Actually, we can't do this since we might be flushing while processing
slouken@5293
   360
       a resize event, and calling this might trigger further resize events.
slouken@5293
   361
    */
slouken@4460
   362
    SDL_PumpEvents();
slouken@5293
   363
#endif
slouken@4460
   364
slouken@4429
   365
    /* Lock the event queue */
slouken@6977
   366
    if (SDL_LockMutex(SDL_EventQ.lock) == 0) {
slouken@7304
   367
        SDL_EventEntry *entry, *next;
slouken@7304
   368
        Uint32 type;
slouken@7304
   369
        for (entry = SDL_EventQ.head; entry; entry = next) {
slouken@7304
   370
            next = entry->next;
slouken@7304
   371
            type = entry->event.type;
slouken@4429
   372
            if (minType <= type && type <= maxType) {
slouken@7304
   373
                SDL_CutEvent(entry);
slouken@4429
   374
            }
slouken@4429
   375
        }
slouken@6977
   376
        SDL_UnlockMutex(SDL_EventQ.lock);
slouken@4429
   377
    }
slouken@0
   378
}
slouken@0
   379
slouken@0
   380
/* Run the system dependent event loops */
slouken@1895
   381
void
slouken@1895
   382
SDL_PumpEvents(void)
slouken@0
   383
{
slouken@5123
   384
    SDL_VideoDevice *_this = SDL_GetVideoDevice();
slouken@0
   385
slouken@5123
   386
    /* Get events from the video subsystem */
slouken@5123
   387
    if (_this) {
slouken@5123
   388
        _this->PumpEvents(_this);
slouken@5123
   389
    }
slouken@1361
   390
#if !SDL_JOYSTICK_DISABLED
slouken@5123
   391
    /* Check for joystick state change */
icculus@8860
   392
    if ((!SDL_disabled_events[SDL_JOYAXISMOTION >> 8] || SDL_JoystickEventState(SDL_QUERY))) {
slouken@5123
   393
        SDL_JoystickUpdate();
slouken@5123
   394
    }
slouken@0
   395
#endif
slouken@0
   396
}
slouken@0
   397
slouken@0
   398
/* Public functions */
slouken@0
   399
slouken@1895
   400
int
slouken@1895
   401
SDL_PollEvent(SDL_Event * event)
slouken@0
   402
{
slouken@3072
   403
    return SDL_WaitEventTimeout(event, 0);
slouken@1895
   404
}
slouken@0
   405
slouken@1895
   406
int
slouken@1895
   407
SDL_WaitEvent(SDL_Event * event)
slouken@1895
   408
{
slouken@3072
   409
    return SDL_WaitEventTimeout(event, -1);
slouken@3072
   410
}
slouken@3072
   411
slouken@3072
   412
int
slouken@3072
   413
SDL_WaitEventTimeout(SDL_Event * event, int timeout)
slouken@3072
   414
{
slouken@3072
   415
    Uint32 expiration = 0;
slouken@3072
   416
slouken@3072
   417
    if (timeout > 0)
slouken@3072
   418
        expiration = SDL_GetTicks() + timeout;
slouken@3072
   419
slouken@3072
   420
    for (;;) {
slouken@1895
   421
        SDL_PumpEvents();
slouken@4429
   422
        switch (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {
slouken@1895
   423
        case -1:
slouken@1895
   424
            return 0;
slouken@1895
   425
        case 1:
slouken@1895
   426
            return 1;
slouken@1895
   427
        case 0:
slouken@3072
   428
            if (timeout == 0) {
slouken@3072
   429
                /* Polling and no events, just return */
slouken@3072
   430
                return 0;
slouken@3072
   431
            }
slouken@7857
   432
            if (timeout > 0 && SDL_TICKS_PASSED(SDL_GetTicks(), expiration)) {
slouken@3072
   433
                /* Timeout expired and no events */
slouken@3072
   434
                return 0;
slouken@3072
   435
            }
slouken@1895
   436
            SDL_Delay(10);
slouken@3072
   437
            break;
slouken@1895
   438
        }
slouken@1895
   439
    }
slouken@0
   440
}
slouken@0
   441
slouken@1895
   442
int
slouken@1895
   443
SDL_PushEvent(SDL_Event * event)
slouken@0
   444
{
slouken@5146
   445
    SDL_EventWatcher *curr;
slouken@7190
   446
dludwig@7082
   447
    event->common.timestamp = SDL_GetTicks();
slouken@7190
   448
slouken@1895
   449
    if (SDL_EventOK && !SDL_EventOK(SDL_EventOKParam, event)) {
slouken@1895
   450
        return 0;
slouken@1895
   451
    }
slouken@5146
   452
slouken@5146
   453
    for (curr = SDL_event_watchers; curr; curr = curr->next) {
slouken@5146
   454
        curr->callback(curr->userdata, event);
slouken@5146
   455
    }
slouken@5146
   456
slouken@4429
   457
    if (SDL_PeepEvents(event, 1, SDL_ADDEVENT, 0, 0) <= 0) {
slouken@1895
   458
        return -1;
slouken@1895
   459
    }
jim@4657
   460
jim@4657
   461
    SDL_GestureProcessEvent(event);
jim@4657
   462
slouken@1895
   463
    return 1;
slouken@0
   464
}
slouken@0
   465
slouken@1895
   466
void
slouken@1895
   467
SDL_SetEventFilter(SDL_EventFilter filter, void *userdata)
slouken@0
   468
{
slouken@1895
   469
    /* Set filter and discard pending events */
slouken@7201
   470
    SDL_EventOK = NULL;
slouken@7201
   471
    SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT);
slouken@1895
   472
    SDL_EventOKParam = userdata;
slouken@7201
   473
    SDL_EventOK = filter;
slouken@0
   474
}
slouken@0
   475
slouken@1895
   476
SDL_bool
slouken@1895
   477
SDL_GetEventFilter(SDL_EventFilter * filter, void **userdata)
slouken@0
   478
{
slouken@1895
   479
    if (filter) {
slouken@1895
   480
        *filter = SDL_EventOK;
slouken@1895
   481
    }
slouken@1895
   482
    if (userdata) {
slouken@1895
   483
        *userdata = SDL_EventOKParam;
slouken@1895
   484
    }
slouken@1895
   485
    return SDL_EventOK ? SDL_TRUE : SDL_FALSE;
slouken@0
   486
}
slouken@0
   487
slouken@5146
   488
/* FIXME: This is not thread-safe yet */
slouken@5146
   489
void
slouken@5146
   490
SDL_AddEventWatch(SDL_EventFilter filter, void *userdata)
slouken@5146
   491
{
slouken@8234
   492
    SDL_EventWatcher *watcher, *tail;
slouken@5146
   493
slouken@5146
   494
    watcher = (SDL_EventWatcher *)SDL_malloc(sizeof(*watcher));
slouken@5146
   495
    if (!watcher) {
slouken@5146
   496
        /* Uh oh... */
slouken@5146
   497
        return;
slouken@5146
   498
    }
slouken@8234
   499
slouken@8234
   500
    /* create the watcher */
slouken@5146
   501
    watcher->callback = filter;
slouken@5146
   502
    watcher->userdata = userdata;
slouken@8234
   503
    watcher->next = NULL;
slouken@8234
   504
slouken@8234
   505
    /* add the watcher to the end of the list */
slouken@8234
   506
    if (SDL_event_watchers) {
slouken@8234
   507
        for (tail = SDL_event_watchers; tail->next; tail = tail->next) {
slouken@8234
   508
            continue;
slouken@8234
   509
        }
slouken@8234
   510
        tail->next = watcher;
slouken@8234
   511
    } else {
slouken@8234
   512
        SDL_event_watchers = watcher;
slouken@8234
   513
    }
slouken@5146
   514
}
slouken@5146
   515
slouken@5146
   516
/* FIXME: This is not thread-safe yet */
slouken@5146
   517
void
slouken@5146
   518
SDL_DelEventWatch(SDL_EventFilter filter, void *userdata)
slouken@5146
   519
{
slouken@5146
   520
    SDL_EventWatcher *prev = NULL;
slouken@5146
   521
    SDL_EventWatcher *curr;
slouken@5146
   522
slouken@5146
   523
    for (curr = SDL_event_watchers; curr; prev = curr, curr = curr->next) {
slouken@5146
   524
        if (curr->callback == filter && curr->userdata == userdata) {
slouken@5146
   525
            if (prev) {
slouken@5146
   526
                prev->next = curr->next;
slouken@5146
   527
            } else {
slouken@5146
   528
                SDL_event_watchers = curr->next;
slouken@5146
   529
            }
slouken@5146
   530
            SDL_free(curr);
slouken@5146
   531
            break;
slouken@5146
   532
        }
slouken@5146
   533
    }
slouken@5146
   534
}
slouken@5146
   535
slouken@1895
   536
void
slouken@1895
   537
SDL_FilterEvents(SDL_EventFilter filter, void *userdata)
slouken@0
   538
{
slouken@8791
   539
    if (SDL_EventQ.lock && SDL_LockMutex(SDL_EventQ.lock) == 0) {
slouken@7304
   540
        SDL_EventEntry *entry, *next;
slouken@7304
   541
        for (entry = SDL_EventQ.head; entry; entry = next) {
slouken@7304
   542
            next = entry->next;
slouken@7304
   543
            if (!filter(userdata, &entry->event)) {
slouken@7304
   544
                SDL_CutEvent(entry);
slouken@1895
   545
            }
slouken@1895
   546
        }
slouken@7304
   547
        SDL_UnlockMutex(SDL_EventQ.lock);
slouken@1895
   548
    }
slouken@1895
   549
}
slouken@1895
   550
slouken@1895
   551
Uint8
slouken@4429
   552
SDL_EventState(Uint32 type, int state)
slouken@1895
   553
{
slouken@1895
   554
    Uint8 current_state;
slouken@4429
   555
    Uint8 hi = ((type >> 8) & 0xff);
slouken@4429
   556
    Uint8 lo = (type & 0xff);
slouken@0
   557
slouken@4429
   558
    if (SDL_disabled_events[hi] &&
slouken@4429
   559
        (SDL_disabled_events[hi]->bits[lo/32] & (1 << (lo&31)))) {
slouken@4429
   560
        current_state = SDL_DISABLE;
slouken@4429
   561
    } else {
slouken@4429
   562
        current_state = SDL_ENABLE;
slouken@1895
   563
    }
slouken@0
   564
slouken@4429
   565
    if (state != current_state)
slouken@4429
   566
    {
slouken@4429
   567
        switch (state) {
slouken@4429
   568
        case SDL_DISABLE:
slouken@4429
   569
            /* Disable this event type and discard pending events */
slouken@4429
   570
            if (!SDL_disabled_events[hi]) {
slouken@4429
   571
                SDL_disabled_events[hi] = (SDL_DisabledEventBlock*) SDL_calloc(1, sizeof(SDL_DisabledEventBlock));
slouken@4429
   572
                if (!SDL_disabled_events[hi]) {
slouken@4429
   573
                    /* Out of memory, nothing we can do... */
slouken@4429
   574
                    break;
slouken@4429
   575
                }
slouken@4429
   576
            }
slouken@4429
   577
            SDL_disabled_events[hi]->bits[lo/32] |= (1 << (lo&31));
slouken@4429
   578
            SDL_FlushEvent(type);
slouken@4429
   579
            break;
slouken@4429
   580
        case SDL_ENABLE:
slouken@4429
   581
            SDL_disabled_events[hi]->bits[lo/32] &= ~(1 << (lo&31));
slouken@4429
   582
            break;
slouken@4429
   583
        default:
slouken@4429
   584
            /* Querying state... */
slouken@4429
   585
            break;
slouken@1895
   586
        }
slouken@1895
   587
    }
slouken@4429
   588
slouken@4429
   589
    return current_state;
slouken@4429
   590
}
slouken@4429
   591
slouken@4429
   592
Uint32
slouken@4429
   593
SDL_RegisterEvents(int numevents)
slouken@4429
   594
{
slouken@4429
   595
    Uint32 event_base;
slouken@4429
   596
icculus@7611
   597
    if ((numevents > 0) && (SDL_userevents+numevents <= SDL_LASTEVENT)) {
slouken@4429
   598
        event_base = SDL_userevents;
slouken@4429
   599
        SDL_userevents += numevents;
slouken@4429
   600
    } else {
slouken@4429
   601
        event_base = (Uint32)-1;
slouken@4429
   602
    }
slouken@4429
   603
    return event_base;
slouken@0
   604
}
slouken@0
   605
slouken@7190
   606
int
slouken@7190
   607
SDL_SendAppEvent(SDL_EventType eventType)
slouken@7190
   608
{
slouken@7190
   609
    int posted;
slouken@7190
   610
slouken@7190
   611
    posted = 0;
slouken@7190
   612
    if (SDL_GetEventState(eventType) == SDL_ENABLE) {
slouken@7190
   613
        SDL_Event event;
slouken@7190
   614
        event.type = eventType;
slouken@7190
   615
        posted = (SDL_PushEvent(&event) > 0);
slouken@7190
   616
    }
slouken@7190
   617
    return (posted);
slouken@7190
   618
}
slouken@7190
   619
slouken@1895
   620
int
slouken@1895
   621
SDL_SendSysWMEvent(SDL_SysWMmsg * message)
slouken@0
   622
{
slouken@1895
   623
    int posted;
slouken@0
   624
slouken@1895
   625
    posted = 0;
slouken@4429
   626
    if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
slouken@1895
   627
        SDL_Event event;
slouken@1895
   628
        SDL_memset(&event, 0, sizeof(event));
slouken@1895
   629
        event.type = SDL_SYSWMEVENT;
slouken@1895
   630
        event.syswm.msg = message;
slouken@1895
   631
        posted = (SDL_PushEvent(&event) > 0);
slouken@1895
   632
    }
slouken@1895
   633
    /* Update internal event state */
slouken@1895
   634
    return (posted);
slouken@0
   635
}
slouken@1895
   636
slouken@1895
   637
/* vi: set ts=4 sw=4 expandtab: */