Atlas - SDL_windowevents.c
Home / ext / SDL / src / events Lines: 1 | Size: 11060 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2026 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 // The window might be destroyed in an event handler, so cache the topmost status first. 232 const bool window_is_topmost = !window->parent; 233 234 // Post the event, if desired 235 SDL_Event event; 236 event.type = windowevent; 237 event.common.timestamp = 0; 238 event.window.data1 = data1; 239 event.window.data2 = data2; 240 event.window.windowID = window->id; 241 242 SDL_DispatchEventWatchList(&SDL_window_event_watchers[SDL_WINDOW_EVENT_WATCH_EARLY], &event); 243 SDL_DispatchEventWatchList(&SDL_window_event_watchers[SDL_WINDOW_EVENT_WATCH_NORMAL], &event); 244 245 if (post_event && SDL_EventEnabled(windowevent)) { 246 // Fixes queue overflow with move/resize events that aren't processed 247 if (windowevent == SDL_EVENT_WINDOW_MOVED || 248 windowevent == SDL_EVENT_WINDOW_RESIZED || 249 windowevent == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED || 250 windowevent == SDL_EVENT_WINDOW_SAFE_AREA_CHANGED || 251 windowevent == SDL_EVENT_WINDOW_EXPOSED || 252 windowevent == SDL_EVENT_WINDOW_OCCLUDED) { 253 SDL_FilterEvents(RemoveSupersededWindowEvents, &event); 254 } 255 posted = SDL_PushEvent(&event); 256 } 257 258 // Ensure that the window is still valid, as it may have been destroyed in an event handler. 259 window = SDL_GetWindowFromID(event.window.windowID); 260 261 if (window) { 262 switch (windowevent) { 263 case SDL_EVENT_WINDOW_SHOWN: 264 SDL_OnWindowShown(window); 265 break; 266 case SDL_EVENT_WINDOW_HIDDEN: 267 SDL_OnWindowHidden(window); 268 break; 269 case SDL_EVENT_WINDOW_MOVED: 270 SDL_OnWindowMoved(window); 271 break; 272 case SDL_EVENT_WINDOW_RESIZED: 273 SDL_OnWindowResized(window); 274 break; 275 case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: 276 SDL_OnWindowPixelSizeChanged(window); 277 break; 278 case SDL_EVENT_WINDOW_MINIMIZED: 279 SDL_OnWindowMinimized(window); 280 break; 281 case SDL_EVENT_WINDOW_MAXIMIZED: 282 SDL_OnWindowMaximized(window); 283 break; 284 case SDL_EVENT_WINDOW_RESTORED: 285 SDL_OnWindowRestored(window); 286 break; 287 case SDL_EVENT_WINDOW_MOUSE_ENTER: 288 SDL_OnWindowEnter(window); 289 break; 290 case SDL_EVENT_WINDOW_MOUSE_LEAVE: 291 SDL_OnWindowLeave(window); 292 break; 293 case SDL_EVENT_WINDOW_FOCUS_GAINED: 294 SDL_OnWindowFocusGained(window); 295 break; 296 case SDL_EVENT_WINDOW_FOCUS_LOST: 297 SDL_OnWindowFocusLost(window); 298 break; 299 case SDL_EVENT_WINDOW_DISPLAY_CHANGED: 300 SDL_OnWindowDisplayChanged(window); 301 break; 302 default: 303 break; 304 } 305 } 306 307 if (windowevent == SDL_EVENT_WINDOW_CLOSE_REQUESTED && window_is_topmost && !SDL_HasActiveTrays()) { 308 int count = window ? 0 : 1; 309 for (SDL_Window *n = _this->windows; n; n = n->next) { 310 if (!n->parent && !(n->flags & SDL_WINDOW_HIDDEN)) { 311 ++count; 312 } 313 } 314 315 if (count <= 1) { 316 if (SDL_GetHintBoolean(SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE, true)) { 317 SDL_SendQuit(); // This is the last window in the list, so send the SDL_EVENT_QUIT event 318 } 319 } 320 } 321 322 return posted; 323} 324[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.