Atlas - SDL_windowevents.c
Home / ext / SDL / src / events Lines: 1 | Size: 10893 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 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 RemoveSupersededWindowEvents(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 SDL_VideoDevice *_this; 74 bool post_event = true; 75 bool posted = false; 76 77 if (!window) { 78 return false; 79 } 80 SDL_assert(SDL_ObjectValid(window, SDL_OBJECT_TYPE_WINDOW)); 81 82 switch (windowevent) { 83 case SDL_EVENT_WINDOW_SHOWN: 84 if (!(window->flags & SDL_WINDOW_HIDDEN)) { 85 return false; 86 } 87 window->flags &= ~(SDL_WINDOW_HIDDEN | SDL_WINDOW_MINIMIZED); 88 break; 89 case SDL_EVENT_WINDOW_HIDDEN: 90 if (window->flags & SDL_WINDOW_HIDDEN) { 91 return false; 92 } 93 window->flags |= SDL_WINDOW_HIDDEN; 94 break; 95 case SDL_EVENT_WINDOW_EXPOSED: 96 window->flags &= ~SDL_WINDOW_OCCLUDED; 97 break; 98 case SDL_EVENT_WINDOW_MOVED: 99 window->undefined_x = false; 100 window->undefined_y = false; 101 /* Clear the pending display if this move was not the result of an explicit request, 102 * and the window is not scheduled to become fullscreen when shown. 103 */ 104 if (!window->last_position_pending && !(window->pending_flags & SDL_WINDOW_FULLSCREEN)) { 105 window->pending_displayID = 0; 106 } 107 window->last_position_pending = false; 108 if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { 109 window->windowed.x = data1; 110 window->windowed.y = data2; 111 112 if (!(window->flags & SDL_WINDOW_MAXIMIZED) && !window->tiled) { 113 window->floating.x = data1; 114 window->floating.y = data2; 115 } 116 } 117 if (data1 == window->x && data2 == window->y) { 118 return false; 119 } 120 window->x = data1; 121 window->y = data2; 122 break; 123 case SDL_EVENT_WINDOW_RESIZED: 124 window->last_size_pending = false; 125 if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { 126 window->windowed.w = data1; 127 window->windowed.h = data2; 128 129 if (!(window->flags & SDL_WINDOW_MAXIMIZED) && !window->tiled) { 130 window->floating.w = data1; 131 window->floating.h = data2; 132 } 133 } 134 if (data1 == window->w && data2 == window->h) { 135 SDL_CheckWindowPixelSizeChanged(window); 136 return false; 137 } 138 window->w = data1; 139 window->h = data2; 140 break; 141 case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: 142 if (data1 == window->last_pixel_w && data2 == window->last_pixel_h) { 143 return false; 144 } 145 window->last_pixel_w = data1; 146 window->last_pixel_h = data2; 147 break; 148 case SDL_EVENT_WINDOW_MINIMIZED: 149 if (window->flags & SDL_WINDOW_MINIMIZED) { 150 return false; 151 } 152 window->flags &= ~SDL_WINDOW_MAXIMIZED; 153 window->flags |= SDL_WINDOW_MINIMIZED; 154 break; 155 case SDL_EVENT_WINDOW_MAXIMIZED: 156 if (window->flags & SDL_WINDOW_MAXIMIZED) { 157 return false; 158 } 159 window->flags &= ~SDL_WINDOW_MINIMIZED; 160 window->flags |= SDL_WINDOW_MAXIMIZED; 161 break; 162 case SDL_EVENT_WINDOW_RESTORED: 163 if (!(window->flags & (SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED))) { 164 return false; 165 } 166 window->flags &= ~(SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED); 167 break; 168 case SDL_EVENT_WINDOW_MOUSE_ENTER: 169 if (window->flags & SDL_WINDOW_MOUSE_FOCUS) { 170 return false; 171 } 172 window->flags |= SDL_WINDOW_MOUSE_FOCUS; 173 break; 174 case SDL_EVENT_WINDOW_MOUSE_LEAVE: 175 if (!(window->flags & SDL_WINDOW_MOUSE_FOCUS)) { 176 return false; 177 } 178 window->flags &= ~SDL_WINDOW_MOUSE_FOCUS; 179 break; 180 case SDL_EVENT_WINDOW_FOCUS_GAINED: 181 if (window->flags & SDL_WINDOW_INPUT_FOCUS) { 182 return false; 183 } 184 window->flags |= SDL_WINDOW_INPUT_FOCUS; 185 break; 186 case SDL_EVENT_WINDOW_FOCUS_LOST: 187 if (!(window->flags & SDL_WINDOW_INPUT_FOCUS)) { 188 return false; 189 } 190 window->flags &= ~SDL_WINDOW_INPUT_FOCUS; 191 break; 192 case SDL_EVENT_WINDOW_DISPLAY_CHANGED: 193 if (data1 == 0 || (SDL_DisplayID)data1 == window->displayID) { 194 return false; 195 } 196 window->update_fullscreen_on_display_changed = true; 197 window->displayID = (SDL_DisplayID)data1; 198 break; 199 case SDL_EVENT_WINDOW_OCCLUDED: 200 if (window->flags & SDL_WINDOW_OCCLUDED) { 201 return false; 202 } 203 window->flags |= SDL_WINDOW_OCCLUDED; 204 break; 205 case SDL_EVENT_WINDOW_ENTER_FULLSCREEN: 206 if (window->flags & SDL_WINDOW_FULLSCREEN) { 207 return false; 208 } 209 window->flags |= SDL_WINDOW_FULLSCREEN; 210 break; 211 case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN: 212 if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { 213 return false; 214 } 215 window->flags &= ~SDL_WINDOW_FULLSCREEN; 216 break; 217 default: 218 break; 219 } 220 221 if (window->is_destroying && windowevent != SDL_EVENT_WINDOW_DESTROYED) { 222 return false; 223 } 224 225 // Only post if we are not currently quitting 226 _this = SDL_GetVideoDevice(); 227 if (_this == NULL || _this->is_quitting) { 228 post_event = false; 229 } 230 231 // Post the event, if desired 232 SDL_Event event; 233 event.type = windowevent; 234 event.common.timestamp = 0; 235 event.window.data1 = data1; 236 event.window.data2 = data2; 237 event.window.windowID = window->id; 238 239 SDL_DispatchEventWatchList(&SDL_window_event_watchers[SDL_WINDOW_EVENT_WATCH_EARLY], &event); 240 SDL_DispatchEventWatchList(&SDL_window_event_watchers[SDL_WINDOW_EVENT_WATCH_NORMAL], &event); 241 242 if (post_event && SDL_EventEnabled(windowevent)) { 243 // Fixes queue overflow with move/resize events that aren't processed 244 if (windowevent == SDL_EVENT_WINDOW_MOVED || 245 windowevent == SDL_EVENT_WINDOW_RESIZED || 246 windowevent == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED || 247 windowevent == SDL_EVENT_WINDOW_SAFE_AREA_CHANGED || 248 windowevent == SDL_EVENT_WINDOW_EXPOSED || 249 windowevent == SDL_EVENT_WINDOW_OCCLUDED) { 250 SDL_FilterEvents(RemoveSupersededWindowEvents, &event); 251 } 252 posted = SDL_PushEvent(&event); 253 } 254 255 // Ensure that the window is still valid, as it may have been destroyed in an event handler. 256 window = SDL_GetWindowFromID(event.window.windowID); 257 258 if (window) { 259 switch (windowevent) { 260 case SDL_EVENT_WINDOW_SHOWN: 261 SDL_OnWindowShown(window); 262 break; 263 case SDL_EVENT_WINDOW_HIDDEN: 264 SDL_OnWindowHidden(window); 265 break; 266 case SDL_EVENT_WINDOW_MOVED: 267 SDL_OnWindowMoved(window); 268 break; 269 case SDL_EVENT_WINDOW_RESIZED: 270 SDL_OnWindowResized(window); 271 break; 272 case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: 273 SDL_OnWindowPixelSizeChanged(window); 274 break; 275 case SDL_EVENT_WINDOW_MINIMIZED: 276 SDL_OnWindowMinimized(window); 277 break; 278 case SDL_EVENT_WINDOW_MAXIMIZED: 279 SDL_OnWindowMaximized(window); 280 break; 281 case SDL_EVENT_WINDOW_RESTORED: 282 SDL_OnWindowRestored(window); 283 break; 284 case SDL_EVENT_WINDOW_MOUSE_ENTER: 285 SDL_OnWindowEnter(window); 286 break; 287 case SDL_EVENT_WINDOW_MOUSE_LEAVE: 288 SDL_OnWindowLeave(window); 289 break; 290 case SDL_EVENT_WINDOW_FOCUS_GAINED: 291 SDL_OnWindowFocusGained(window); 292 break; 293 case SDL_EVENT_WINDOW_FOCUS_LOST: 294 SDL_OnWindowFocusLost(window); 295 break; 296 case SDL_EVENT_WINDOW_DISPLAY_CHANGED: 297 SDL_OnWindowDisplayChanged(window); 298 break; 299 default: 300 break; 301 } 302 } 303 304 if (windowevent == SDL_EVENT_WINDOW_CLOSE_REQUESTED && !SDL_HasActiveTrays()) { 305 int count = window ? 0 : 1; 306 for (SDL_Window *n = _this->windows; n; n = n->next) { 307 if (!n->parent && !(n->flags & SDL_WINDOW_HIDDEN)) { 308 ++count; 309 } 310 } 311 312 if (count <= 1) { 313 if (SDL_GetHintBoolean(SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE, true)) { 314 SDL_SendQuit(); // This is the last window in the list, so send the SDL_EVENT_QUIT event 315 } 316 } 317 } 318 319 return posted; 320} 321[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.