summaryrefslogtreecommitdiff
path: root/contrib/SDL-3.2.8/src/events/SDL_windowevents.c
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2025-12-27 12:03:39 -0800
committer3gg <3gg@shellblade.net>2025-12-27 12:03:39 -0800
commit5a079a2d114f96d4847d1ee305d5b7c16eeec50e (patch)
tree8926ab44f168acf787d8e19608857b3af0f82758 /contrib/SDL-3.2.8/src/events/SDL_windowevents.c
Initial commit
Diffstat (limited to 'contrib/SDL-3.2.8/src/events/SDL_windowevents.c')
-rw-r--r--contrib/SDL-3.2.8/src/events/SDL_windowevents.c300
1 files changed, 300 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/events/SDL_windowevents.c b/contrib/SDL-3.2.8/src/events/SDL_windowevents.c
new file mode 100644
index 0000000..e20cd3a
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/events/SDL_windowevents.c
@@ -0,0 +1,300 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 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_c.h"
26#include "SDL_eventwatch_c.h"
27#include "SDL_mouse_c.h"
28#include "../tray/SDL_tray_utils.h"
29
30
31#define NUM_WINDOW_EVENT_WATCH_PRIORITIES (SDL_WINDOW_EVENT_WATCH_NORMAL + 1)
32
33static SDL_EventWatchList SDL_window_event_watchers[NUM_WINDOW_EVENT_WATCH_PRIORITIES];
34
35void SDL_InitWindowEventWatch(void)
36{
37 for (int i = 0; i < SDL_arraysize(SDL_window_event_watchers); ++i) {
38 SDL_InitEventWatchList(&SDL_window_event_watchers[i]);
39 }
40}
41
42void SDL_QuitWindowEventWatch(void)
43{
44 for (int i = 0; i < SDL_arraysize(SDL_window_event_watchers); ++i) {
45 SDL_QuitEventWatchList(&SDL_window_event_watchers[i]);
46 }
47}
48
49void SDL_AddWindowEventWatch(SDL_WindowEventWatchPriority priority, SDL_EventFilter filter, void *userdata)
50{
51 SDL_AddEventWatchList(&SDL_window_event_watchers[priority], filter, userdata);
52}
53
54void SDL_RemoveWindowEventWatch(SDL_WindowEventWatchPriority priority, SDL_EventFilter filter, void *userdata)
55{
56 SDL_RemoveEventWatchList(&SDL_window_event_watchers[priority], filter, userdata);
57}
58
59static bool SDLCALL RemoveSupercededWindowEvents(void *userdata, SDL_Event *event)
60{
61 SDL_Event *new_event = (SDL_Event *)userdata;
62
63 if (event->type == new_event->type &&
64 event->window.windowID == new_event->window.windowID) {
65 // We're about to post a new move event, drop the old one
66 return false;
67 }
68 return true;
69}
70
71bool SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, int data1, int data2)
72{
73 bool posted = false;
74
75 if (!window) {
76 return false;
77 }
78 SDL_assert(SDL_ObjectValid(window, SDL_OBJECT_TYPE_WINDOW));
79
80 if (window->is_destroying && windowevent != SDL_EVENT_WINDOW_DESTROYED) {
81 return false;
82 }
83 switch (windowevent) {
84 case SDL_EVENT_WINDOW_SHOWN:
85 if (!(window->flags & SDL_WINDOW_HIDDEN)) {
86 return false;
87 }
88 window->flags &= ~(SDL_WINDOW_HIDDEN | SDL_WINDOW_MINIMIZED);
89 break;
90 case SDL_EVENT_WINDOW_HIDDEN:
91 if (window->flags & SDL_WINDOW_HIDDEN) {
92 return false;
93 }
94 window->flags |= SDL_WINDOW_HIDDEN;
95 break;
96 case SDL_EVENT_WINDOW_EXPOSED:
97 window->flags &= ~SDL_WINDOW_OCCLUDED;
98 break;
99 case SDL_EVENT_WINDOW_MOVED:
100 window->undefined_x = false;
101 window->undefined_y = false;
102 window->last_position_pending = false;
103 if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
104 window->windowed.x = data1;
105 window->windowed.y = data2;
106
107 if (!(window->flags & SDL_WINDOW_MAXIMIZED) && !window->tiled) {
108 window->floating.x = data1;
109 window->floating.y = data2;
110 }
111 }
112 if (data1 == window->x && data2 == window->y) {
113 return false;
114 }
115 window->x = data1;
116 window->y = data2;
117 break;
118 case SDL_EVENT_WINDOW_RESIZED:
119 window->last_size_pending = false;
120 if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
121 window->windowed.w = data1;
122 window->windowed.h = data2;
123
124 if (!(window->flags & SDL_WINDOW_MAXIMIZED) && !window->tiled) {
125 window->floating.w = data1;
126 window->floating.h = data2;
127 }
128 }
129 if (data1 == window->w && data2 == window->h) {
130 SDL_CheckWindowPixelSizeChanged(window);
131 return false;
132 }
133 window->w = data1;
134 window->h = data2;
135 break;
136 case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
137 if (data1 == window->last_pixel_w && data2 == window->last_pixel_h) {
138 return false;
139 }
140 window->last_pixel_w = data1;
141 window->last_pixel_h = data2;
142 break;
143 case SDL_EVENT_WINDOW_MINIMIZED:
144 if (window->flags & SDL_WINDOW_MINIMIZED) {
145 return false;
146 }
147 window->flags &= ~SDL_WINDOW_MAXIMIZED;
148 window->flags |= SDL_WINDOW_MINIMIZED;
149 break;
150 case SDL_EVENT_WINDOW_MAXIMIZED:
151 if (window->flags & SDL_WINDOW_MAXIMIZED) {
152 return false;
153 }
154 window->flags &= ~SDL_WINDOW_MINIMIZED;
155 window->flags |= SDL_WINDOW_MAXIMIZED;
156 break;
157 case SDL_EVENT_WINDOW_RESTORED:
158 if (!(window->flags & (SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED))) {
159 return false;
160 }
161 window->flags &= ~(SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED);
162 break;
163 case SDL_EVENT_WINDOW_MOUSE_ENTER:
164 if (window->flags & SDL_WINDOW_MOUSE_FOCUS) {
165 return false;
166 }
167 window->flags |= SDL_WINDOW_MOUSE_FOCUS;
168 break;
169 case SDL_EVENT_WINDOW_MOUSE_LEAVE:
170 if (!(window->flags & SDL_WINDOW_MOUSE_FOCUS)) {
171 return false;
172 }
173 window->flags &= ~SDL_WINDOW_MOUSE_FOCUS;
174 break;
175 case SDL_EVENT_WINDOW_FOCUS_GAINED:
176 if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
177 return false;
178 }
179 window->flags |= SDL_WINDOW_INPUT_FOCUS;
180 break;
181 case SDL_EVENT_WINDOW_FOCUS_LOST:
182 if (!(window->flags & SDL_WINDOW_INPUT_FOCUS)) {
183 return false;
184 }
185 window->flags &= ~SDL_WINDOW_INPUT_FOCUS;
186 break;
187 case SDL_EVENT_WINDOW_DISPLAY_CHANGED:
188 if (data1 == 0 || (SDL_DisplayID)data1 == window->last_displayID) {
189 return false;
190 }
191 window->last_displayID = (SDL_DisplayID)data1;
192 break;
193 case SDL_EVENT_WINDOW_OCCLUDED:
194 if (window->flags & SDL_WINDOW_OCCLUDED) {
195 return false;
196 }
197 window->flags |= SDL_WINDOW_OCCLUDED;
198 break;
199 case SDL_EVENT_WINDOW_ENTER_FULLSCREEN:
200 if (window->flags & SDL_WINDOW_FULLSCREEN) {
201 return false;
202 }
203 window->flags |= SDL_WINDOW_FULLSCREEN;
204 break;
205 case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN:
206 if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
207 return false;
208 }
209 window->flags &= ~SDL_WINDOW_FULLSCREEN;
210 break;
211 default:
212 break;
213 }
214
215 // Post the event, if desired
216 SDL_Event event;
217 event.type = windowevent;
218 event.common.timestamp = 0;
219 event.window.data1 = data1;
220 event.window.data2 = data2;
221 event.window.windowID = window->id;
222
223 SDL_DispatchEventWatchList(&SDL_window_event_watchers[SDL_WINDOW_EVENT_WATCH_EARLY], &event);
224 SDL_DispatchEventWatchList(&SDL_window_event_watchers[SDL_WINDOW_EVENT_WATCH_NORMAL], &event);
225
226 if (SDL_EventEnabled(windowevent)) {
227 // Fixes queue overflow with move/resize events that aren't processed
228 if (windowevent == SDL_EVENT_WINDOW_MOVED ||
229 windowevent == SDL_EVENT_WINDOW_RESIZED ||
230 windowevent == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED ||
231 windowevent == SDL_EVENT_WINDOW_SAFE_AREA_CHANGED ||
232 windowevent == SDL_EVENT_WINDOW_EXPOSED ||
233 windowevent == SDL_EVENT_WINDOW_OCCLUDED) {
234 SDL_FilterEvents(RemoveSupercededWindowEvents, &event);
235 }
236 posted = SDL_PushEvent(&event);
237 }
238
239 switch (windowevent) {
240 case SDL_EVENT_WINDOW_SHOWN:
241 SDL_OnWindowShown(window);
242 break;
243 case SDL_EVENT_WINDOW_HIDDEN:
244 SDL_OnWindowHidden(window);
245 break;
246 case SDL_EVENT_WINDOW_MOVED:
247 SDL_OnWindowMoved(window);
248 break;
249 case SDL_EVENT_WINDOW_RESIZED:
250 SDL_OnWindowResized(window);
251 break;
252 case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
253 SDL_OnWindowPixelSizeChanged(window);
254 break;
255 case SDL_EVENT_WINDOW_MINIMIZED:
256 SDL_OnWindowMinimized(window);
257 break;
258 case SDL_EVENT_WINDOW_MAXIMIZED:
259 SDL_OnWindowMaximized(window);
260 break;
261 case SDL_EVENT_WINDOW_RESTORED:
262 SDL_OnWindowRestored(window);
263 break;
264 case SDL_EVENT_WINDOW_MOUSE_ENTER:
265 SDL_OnWindowEnter(window);
266 break;
267 case SDL_EVENT_WINDOW_MOUSE_LEAVE:
268 SDL_OnWindowLeave(window);
269 break;
270 case SDL_EVENT_WINDOW_FOCUS_GAINED:
271 SDL_OnWindowFocusGained(window);
272 break;
273 case SDL_EVENT_WINDOW_FOCUS_LOST:
274 SDL_OnWindowFocusLost(window);
275 break;
276 case SDL_EVENT_WINDOW_DISPLAY_CHANGED:
277 SDL_OnWindowDisplayChanged(window);
278 break;
279 default:
280 break;
281 }
282
283 if (windowevent == SDL_EVENT_WINDOW_CLOSE_REQUESTED && !window->parent && !SDL_HasActiveTrays()) {
284 int toplevel_count = 0;
285 SDL_Window *n;
286 for (n = SDL_GetVideoDevice()->windows; n; n = n->next) {
287 if (!n->parent && !(n->flags & SDL_WINDOW_HIDDEN)) {
288 ++toplevel_count;
289 }
290 }
291
292 if (toplevel_count <= 1) {
293 if (SDL_GetHintBoolean(SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE, true)) {
294 SDL_SendQuit(); // This is the last toplevel window in the list so send the SDL_EVENT_QUIT event
295 }
296 }
297 }
298
299 return posted;
300}