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 /* 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
RemovePendingResizedEvents(void * userdata,SDL_Event * event)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
RemovePendingSizeChangedEvents(void * userdata,SDL_Event * event)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
RemovePendingMoveEvents(void * userdata,SDL_Event * event)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
RemovePendingExposedEvents(void * userdata,SDL_Event * event)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
SDL_SendWindowEvent(SDL_Window * window,Uint8 windowevent,int data1,int data2)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: */
229