src/events/SDL_events.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 22 Jun 2015 23:36:06 -0700
changeset 9776 952ff8a5076f
parent 9720 fd60d77139fc
child 9898 0da384bef562
permissions -rw-r--r--
Fixed bug 3030 - SDL_RecreateWindow fails to restore title, icon, etc.

Adam M.

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