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