1 | /* |
2 | Simple DirectMedia Layer |
3 | Copyright (C) 1997-2021 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 |
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 |
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 |
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 |
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 | |