610fad5ce1ffabdbfeb676033bd11d99f7cecbc1
[platform/upstream/SDL.git] / src / events / SDL_windowevents.c
1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2018 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 /* Window event handling code for SDL */
24
25 #include "SDL_events.h"
26 #include "SDL_events_c.h"
27 #include "SDL_mouse_c.h"
28 #include "../video/SDL_sysvideo.h"
29
30
31 static int SDLCALL
32 RemovePendingResizedEvents(void * userdata, SDL_Event *event)
33 {
34     SDL_Event *new_event = (SDL_Event *)userdata;
35
36     if (event->type == SDL_WINDOWEVENT &&
37         event->window.event == SDL_WINDOWEVENT_RESIZED &&
38         event->window.windowID == new_event->window.windowID) {
39         /* We're about to post a new size event, drop the old one */
40         return 0;
41     }
42     return 1;
43 }
44
45 static int SDLCALL
46 RemovePendingSizeChangedEvents(void * userdata, SDL_Event *event)
47 {
48     SDL_Event *new_event = (SDL_Event *)userdata;
49
50     if (event->type == SDL_WINDOWEVENT &&
51         event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED &&
52         event->window.windowID == new_event->window.windowID) {
53         /* We're about to post a new size event, drop the old one */
54         return 0;
55     }
56     return 1;
57 }
58
59 static int SDLCALL
60 RemovePendingMoveEvents(void * userdata, SDL_Event *event)
61 {
62     SDL_Event *new_event = (SDL_Event *)userdata;
63
64     if (event->type == SDL_WINDOWEVENT &&
65         event->window.event == SDL_WINDOWEVENT_MOVED &&
66         event->window.windowID == new_event->window.windowID) {
67         /* We're about to post a new move event, drop the old one */
68         return 0;
69     }
70     return 1;
71 }
72
73 static int SDLCALL
74 RemovePendingExposedEvents(void * userdata, SDL_Event *event)
75 {
76     SDL_Event *new_event = (SDL_Event *)userdata;
77
78     if (event->type == SDL_WINDOWEVENT &&
79         event->window.event == SDL_WINDOWEVENT_EXPOSED &&
80         event->window.windowID == new_event->window.windowID) {
81         /* We're about to post a new exposed event, drop the old one */
82         return 0;
83     }
84     return 1;
85 }
86
87 int
88 SDL_SendWindowEvent(SDL_Window * window, Uint8 windowevent, int data1,
89                     int data2)
90 {
91     int posted;
92
93     if (!window) {
94         return 0;
95     }
96     switch (windowevent) {
97     case SDL_WINDOWEVENT_SHOWN:
98         if (window->flags & SDL_WINDOW_SHOWN) {
99             return 0;
100         }
101         window->flags &= ~SDL_WINDOW_HIDDEN;
102         window->flags |= SDL_WINDOW_SHOWN;
103         SDL_OnWindowShown(window);
104         break;
105     case SDL_WINDOWEVENT_HIDDEN:
106         if (!(window->flags & SDL_WINDOW_SHOWN)) {
107             return 0;
108         }
109         window->flags &= ~SDL_WINDOW_SHOWN;
110         window->flags |= SDL_WINDOW_HIDDEN;
111         SDL_OnWindowHidden(window);
112         break;
113     case SDL_WINDOWEVENT_MOVED:
114         if (SDL_WINDOWPOS_ISUNDEFINED(data1) ||
115             SDL_WINDOWPOS_ISUNDEFINED(data2)) {
116             return 0;
117         }
118         if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
119             window->windowed.x = data1;
120             window->windowed.y = data2;
121         }
122         if (data1 == window->x && data2 == window->y) {
123             return 0;
124         }
125         window->x = data1;
126         window->y = data2;
127         break;
128     case SDL_WINDOWEVENT_RESIZED:
129         if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
130             window->windowed.w = data1;
131             window->windowed.h = data2;
132         }
133         if (data1 == window->w && data2 == window->h) {
134             return 0;
135         }
136         window->w = data1;
137         window->h = data2;
138         SDL_OnWindowResized(window);
139         break;
140     case SDL_WINDOWEVENT_MINIMIZED:
141         if (window->flags & SDL_WINDOW_MINIMIZED) {
142             return 0;
143         }
144         window->flags &= ~SDL_WINDOW_MAXIMIZED;
145         window->flags |= SDL_WINDOW_MINIMIZED;
146         SDL_OnWindowMinimized(window);
147         break;
148     case SDL_WINDOWEVENT_MAXIMIZED:
149         if (window->flags & SDL_WINDOW_MAXIMIZED) {
150             return 0;
151         }
152         window->flags &= ~SDL_WINDOW_MINIMIZED;
153         window->flags |= SDL_WINDOW_MAXIMIZED;
154         break;
155     case SDL_WINDOWEVENT_RESTORED:
156         if (!(window->flags & (SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED))) {
157             return 0;
158         }
159         window->flags &= ~(SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED);
160         SDL_OnWindowRestored(window);
161         break;
162     case SDL_WINDOWEVENT_ENTER:
163         if (window->flags & SDL_WINDOW_MOUSE_FOCUS) {
164             return 0;
165         }
166         window->flags |= SDL_WINDOW_MOUSE_FOCUS;
167         SDL_OnWindowEnter(window);
168         break;
169     case SDL_WINDOWEVENT_LEAVE:
170         if (!(window->flags & SDL_WINDOW_MOUSE_FOCUS)) {
171             return 0;
172         }
173         window->flags &= ~SDL_WINDOW_MOUSE_FOCUS;
174         SDL_OnWindowLeave(window);
175         break;
176     case SDL_WINDOWEVENT_FOCUS_GAINED:
177         if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
178             return 0;
179         }
180         window->flags |= SDL_WINDOW_INPUT_FOCUS;
181         SDL_OnWindowFocusGained(window);
182         break;
183     case SDL_WINDOWEVENT_FOCUS_LOST:
184         if (!(window->flags & SDL_WINDOW_INPUT_FOCUS)) {
185             return 0;
186         }
187         window->flags &= ~SDL_WINDOW_INPUT_FOCUS;
188         SDL_OnWindowFocusLost(window);
189         break;
190     }
191
192     /* Post the event, if desired */
193     posted = 0;
194     if (SDL_GetEventState(SDL_WINDOWEVENT) == SDL_ENABLE) {
195         SDL_Event event;
196         event.type = SDL_WINDOWEVENT;
197         event.window.event = windowevent;
198         event.window.data1 = data1;
199         event.window.data2 = data2;
200         event.window.windowID = window->id;
201
202         /* Fixes queue overflow with resize events that aren't processed */
203         if (windowevent == SDL_WINDOWEVENT_RESIZED) {
204             SDL_FilterEvents(RemovePendingResizedEvents, &event);
205         }
206         if (windowevent == SDL_WINDOWEVENT_SIZE_CHANGED) {
207             SDL_FilterEvents(RemovePendingSizeChangedEvents, &event);
208         }
209         if (windowevent == SDL_WINDOWEVENT_MOVED) {
210             SDL_FilterEvents(RemovePendingMoveEvents, &event);
211         }
212         if (windowevent == SDL_WINDOWEVENT_EXPOSED) {
213             SDL_FilterEvents(RemovePendingExposedEvents, &event);
214         }
215         posted = (SDL_PushEvent(&event) > 0);
216     }
217
218     if (windowevent == SDL_WINDOWEVENT_CLOSE) {
219         if ( !window->prev && !window->next ) {
220             /* This is the last window in the list so send the SDL_QUIT event */
221             SDL_SendQuit();
222         }
223     }
224
225     return (posted);
226 }
227
228 /* vi: set ts=4 sw=4 expandtab: */