| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- /*
- Simple DirectMedia Layer
- Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- #include "SDL_internal.h"
- // Window event handling code for SDL
- #include "SDL_events_c.h"
- #include "SDL_eventwatch_c.h"
- #include "SDL_mouse_c.h"
- #include "../tray/SDL_tray_utils.h"
- #define NUM_WINDOW_EVENT_WATCH_PRIORITIES (SDL_WINDOW_EVENT_WATCH_NORMAL + 1)
- static SDL_EventWatchList SDL_window_event_watchers[NUM_WINDOW_EVENT_WATCH_PRIORITIES];
- void SDL_InitWindowEventWatch(void)
- {
- for (int i = 0; i < SDL_arraysize(SDL_window_event_watchers); ++i) {
- SDL_InitEventWatchList(&SDL_window_event_watchers[i]);
- }
- }
- void SDL_QuitWindowEventWatch(void)
- {
- for (int i = 0; i < SDL_arraysize(SDL_window_event_watchers); ++i) {
- SDL_QuitEventWatchList(&SDL_window_event_watchers[i]);
- }
- }
- void SDL_AddWindowEventWatch(SDL_WindowEventWatchPriority priority, SDL_EventFilter filter, void *userdata)
- {
- SDL_AddEventWatchList(&SDL_window_event_watchers[priority], filter, userdata);
- }
- void SDL_RemoveWindowEventWatch(SDL_WindowEventWatchPriority priority, SDL_EventFilter filter, void *userdata)
- {
- SDL_RemoveEventWatchList(&SDL_window_event_watchers[priority], filter, userdata);
- }
- static bool SDLCALL RemoveSupersededWindowEvents(void *userdata, SDL_Event *event)
- {
- SDL_Event *new_event = (SDL_Event *)userdata;
- if (event->type == new_event->type &&
- event->window.windowID == new_event->window.windowID) {
- // We're about to post a new move event, drop the old one
- return false;
- }
- return true;
- }
- bool SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, int data1, int data2)
- {
- SDL_VideoDevice *_this;
- bool post_event = true;
- bool posted = false;
- if (!window) {
- return false;
- }
- SDL_assert(SDL_ObjectValid(window, SDL_OBJECT_TYPE_WINDOW));
- switch (windowevent) {
- case SDL_EVENT_WINDOW_SHOWN:
- if (!(window->flags & SDL_WINDOW_HIDDEN)) {
- return false;
- }
- window->flags &= ~(SDL_WINDOW_HIDDEN | SDL_WINDOW_MINIMIZED);
- break;
- case SDL_EVENT_WINDOW_HIDDEN:
- if (window->flags & SDL_WINDOW_HIDDEN) {
- return false;
- }
- window->flags |= SDL_WINDOW_HIDDEN;
- break;
- case SDL_EVENT_WINDOW_EXPOSED:
- window->flags &= ~SDL_WINDOW_OCCLUDED;
- break;
- case SDL_EVENT_WINDOW_MOVED:
- window->undefined_x = false;
- window->undefined_y = false;
- /* Clear the pending display if this move was not the result of an explicit request,
- * and the window is not scheduled to become fullscreen when shown.
- */
- if (!window->last_position_pending && !(window->pending_flags & SDL_WINDOW_FULLSCREEN)) {
- window->pending_displayID = 0;
- }
- window->last_position_pending = false;
- if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
- window->windowed.x = data1;
- window->windowed.y = data2;
- if (!(window->flags & SDL_WINDOW_MAXIMIZED) && !window->tiled) {
- window->floating.x = data1;
- window->floating.y = data2;
- }
- }
- if (data1 == window->x && data2 == window->y) {
- return false;
- }
- window->x = data1;
- window->y = data2;
- break;
- case SDL_EVENT_WINDOW_RESIZED:
- window->last_size_pending = false;
- if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
- window->windowed.w = data1;
- window->windowed.h = data2;
- if (!(window->flags & SDL_WINDOW_MAXIMIZED) && !window->tiled) {
- window->floating.w = data1;
- window->floating.h = data2;
- }
- }
- if (data1 == window->w && data2 == window->h) {
- SDL_CheckWindowPixelSizeChanged(window);
- return false;
- }
- window->w = data1;
- window->h = data2;
- break;
- case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
- if (data1 == window->last_pixel_w && data2 == window->last_pixel_h) {
- return false;
- }
- window->last_pixel_w = data1;
- window->last_pixel_h = data2;
- break;
- case SDL_EVENT_WINDOW_MINIMIZED:
- if (window->flags & SDL_WINDOW_MINIMIZED) {
- return false;
- }
- window->flags &= ~SDL_WINDOW_MAXIMIZED;
- window->flags |= SDL_WINDOW_MINIMIZED;
- break;
- case SDL_EVENT_WINDOW_MAXIMIZED:
- if (window->flags & SDL_WINDOW_MAXIMIZED) {
- return false;
- }
- window->flags &= ~SDL_WINDOW_MINIMIZED;
- window->flags |= SDL_WINDOW_MAXIMIZED;
- break;
- case SDL_EVENT_WINDOW_RESTORED:
- if (!(window->flags & (SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED))) {
- return false;
- }
- window->flags &= ~(SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED);
- break;
- case SDL_EVENT_WINDOW_MOUSE_ENTER:
- if (window->flags & SDL_WINDOW_MOUSE_FOCUS) {
- return false;
- }
- window->flags |= SDL_WINDOW_MOUSE_FOCUS;
- break;
- case SDL_EVENT_WINDOW_MOUSE_LEAVE:
- if (!(window->flags & SDL_WINDOW_MOUSE_FOCUS)) {
- return false;
- }
- window->flags &= ~SDL_WINDOW_MOUSE_FOCUS;
- break;
- case SDL_EVENT_WINDOW_FOCUS_GAINED:
- if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
- return false;
- }
- window->flags |= SDL_WINDOW_INPUT_FOCUS;
- break;
- case SDL_EVENT_WINDOW_FOCUS_LOST:
- if (!(window->flags & SDL_WINDOW_INPUT_FOCUS)) {
- return false;
- }
- window->flags &= ~SDL_WINDOW_INPUT_FOCUS;
- break;
- case SDL_EVENT_WINDOW_DISPLAY_CHANGED:
- if (data1 == 0 || (SDL_DisplayID)data1 == window->displayID) {
- return false;
- }
- window->update_fullscreen_on_display_changed = true;
- window->displayID = (SDL_DisplayID)data1;
- break;
- case SDL_EVENT_WINDOW_OCCLUDED:
- if (window->flags & SDL_WINDOW_OCCLUDED) {
- return false;
- }
- window->flags |= SDL_WINDOW_OCCLUDED;
- break;
- case SDL_EVENT_WINDOW_ENTER_FULLSCREEN:
- if (window->flags & SDL_WINDOW_FULLSCREEN) {
- return false;
- }
- window->flags |= SDL_WINDOW_FULLSCREEN;
- break;
- case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN:
- if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
- return false;
- }
- window->flags &= ~SDL_WINDOW_FULLSCREEN;
- break;
- default:
- break;
- }
- if (window->is_destroying && windowevent != SDL_EVENT_WINDOW_DESTROYED) {
- return false;
- }
- // Only post if we are not currently quitting
- _this = SDL_GetVideoDevice();
- if (_this == NULL || _this->is_quitting) {
- post_event = false;
- }
- // Post the event, if desired
- SDL_Event event;
- event.type = windowevent;
- event.common.timestamp = 0;
- event.window.data1 = data1;
- event.window.data2 = data2;
- event.window.windowID = window->id;
- SDL_DispatchEventWatchList(&SDL_window_event_watchers[SDL_WINDOW_EVENT_WATCH_EARLY], &event);
- SDL_DispatchEventWatchList(&SDL_window_event_watchers[SDL_WINDOW_EVENT_WATCH_NORMAL], &event);
- if (post_event && SDL_EventEnabled(windowevent)) {
- // Fixes queue overflow with move/resize events that aren't processed
- if (windowevent == SDL_EVENT_WINDOW_MOVED ||
- windowevent == SDL_EVENT_WINDOW_RESIZED ||
- windowevent == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED ||
- windowevent == SDL_EVENT_WINDOW_SAFE_AREA_CHANGED ||
- windowevent == SDL_EVENT_WINDOW_EXPOSED ||
- windowevent == SDL_EVENT_WINDOW_OCCLUDED) {
- SDL_FilterEvents(RemoveSupersededWindowEvents, &event);
- }
- posted = SDL_PushEvent(&event);
- }
- // Ensure that the window is still valid, as it may have been destroyed in an event handler.
- window = SDL_GetWindowFromID(event.window.windowID);
- if (window) {
- switch (windowevent) {
- case SDL_EVENT_WINDOW_SHOWN:
- SDL_OnWindowShown(window);
- break;
- case SDL_EVENT_WINDOW_HIDDEN:
- SDL_OnWindowHidden(window);
- break;
- case SDL_EVENT_WINDOW_MOVED:
- SDL_OnWindowMoved(window);
- break;
- case SDL_EVENT_WINDOW_RESIZED:
- SDL_OnWindowResized(window);
- break;
- case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
- SDL_OnWindowPixelSizeChanged(window);
- break;
- case SDL_EVENT_WINDOW_MINIMIZED:
- SDL_OnWindowMinimized(window);
- break;
- case SDL_EVENT_WINDOW_MAXIMIZED:
- SDL_OnWindowMaximized(window);
- break;
- case SDL_EVENT_WINDOW_RESTORED:
- SDL_OnWindowRestored(window);
- break;
- case SDL_EVENT_WINDOW_MOUSE_ENTER:
- SDL_OnWindowEnter(window);
- break;
- case SDL_EVENT_WINDOW_MOUSE_LEAVE:
- SDL_OnWindowLeave(window);
- break;
- case SDL_EVENT_WINDOW_FOCUS_GAINED:
- SDL_OnWindowFocusGained(window);
- break;
- case SDL_EVENT_WINDOW_FOCUS_LOST:
- SDL_OnWindowFocusLost(window);
- break;
- case SDL_EVENT_WINDOW_DISPLAY_CHANGED:
- SDL_OnWindowDisplayChanged(window);
- break;
- default:
- break;
- }
- }
- if (windowevent == SDL_EVENT_WINDOW_CLOSE_REQUESTED && !SDL_HasActiveTrays()) {
- int count = window ? 0 : 1;
- for (SDL_Window *n = _this->windows; n; n = n->next) {
- if (!n->parent && !(n->flags & SDL_WINDOW_HIDDEN)) {
- ++count;
- }
- }
- if (count <= 1) {
- if (SDL_GetHintBoolean(SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE, true)) {
- SDL_SendQuit(); // This is the last window in the list, so send the SDL_EVENT_QUIT event
- }
- }
- }
- return posted;
- }
|