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