Atlas - SDL_gdk.cpp

Home / ext / SDL / src / core / gdk Lines: 1 | Size: 5473 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 23extern "C" { 24#include "../windows/SDL_windows.h" 25#include "../../events/SDL_events_c.h" 26} 27#include <XGameRuntime.h> 28#include <xsapi-c/services_c.h> 29#include <appnotify.h> 30 31static XTaskQueueHandle GDK_GlobalTaskQueue; 32 33PAPPSTATE_REGISTRATION hPLM = {}; 34PAPPCONSTRAIN_REGISTRATION hCPLM = {}; 35HANDLE plmSuspendComplete = nullptr; 36 37extern "C" 38bool SDL_GetGDKTaskQueue(XTaskQueueHandle *outTaskQueue) 39{ 40 // If this is the first call, first create the global task queue. 41 if (!GDK_GlobalTaskQueue) { 42 HRESULT hr; 43 44 hr = XTaskQueueCreate(XTaskQueueDispatchMode::ThreadPool, 45 XTaskQueueDispatchMode::Manual, 46 &GDK_GlobalTaskQueue); 47 if (FAILED(hr)) { 48 return SDL_SetError("[GDK] Could not create global task queue"); 49 } 50 51 // The initial call gets the non-duplicated handle so they can clean it up 52 *outTaskQueue = GDK_GlobalTaskQueue; 53 } else { 54 // Duplicate the global task queue handle into outTaskQueue 55 if (FAILED(XTaskQueueDuplicateHandle(GDK_GlobalTaskQueue, outTaskQueue))) { 56 return SDL_SetError("[GDK] Unable to acquire global task queue"); 57 } 58 } 59 60 return true; 61} 62 63extern "C" 64void GDK_DispatchTaskQueue(void) 65{ 66 /* If there is no global task queue, don't do anything. 67 * This gives the option to opt-out for those who want to handle everything themselves. 68 */ 69 if (GDK_GlobalTaskQueue) { 70 // Dispatch any callbacks which are ready. 71 while (XTaskQueueDispatch(GDK_GlobalTaskQueue, XTaskQueuePort::Completion, 0)) 72 ; 73 } 74} 75 76extern "C" 77bool GDK_RegisterChangeNotifications(void) 78{ 79 // Register suspend/resume handling 80 plmSuspendComplete = CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE); 81 if (!plmSuspendComplete) { 82 return SDL_SetError("[GDK] Unable to create plmSuspendComplete event"); 83 } 84 auto rascn = [](BOOLEAN quiesced, PVOID context) { 85 SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[GDK] in RegisterAppStateChangeNotification handler"); 86 if (quiesced) { 87 ResetEvent(plmSuspendComplete); 88 SDL_SendAppEvent(SDL_EVENT_DID_ENTER_BACKGROUND); 89 90 // To defer suspension, we must wait to exit this callback. 91 // IMPORTANT: The app must call SDL_GDKSuspendComplete() to release this lock. 92 (void)WaitForSingleObject(plmSuspendComplete, INFINITE); 93 94 SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[GDK] in RegisterAppStateChangeNotification handler: plmSuspendComplete event signaled."); 95 } else { 96 SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_FOREGROUND); 97 } 98 }; 99 if (RegisterAppStateChangeNotification(rascn, NULL, &hPLM)) { 100 return SDL_SetError("[GDK] Unable to call RegisterAppStateChangeNotification"); 101 } 102 103 // Register constrain/unconstrain handling 104 auto raccn = [](BOOLEAN constrained, PVOID context) { 105 SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[GDK] in RegisterAppConstrainedChangeNotification handler"); 106 SDL_VideoDevice *_this = SDL_GetVideoDevice(); 107 if (_this) { 108 if (constrained && !((_this->windows) && _this->windows->text_input_active)) { 109 SDL_SetKeyboardFocus(NULL); 110 } else { 111 SDL_SetKeyboardFocus(_this->windows); 112 } 113 } 114 }; 115 if (RegisterAppConstrainedChangeNotification(raccn, NULL, &hCPLM)) { 116 return SDL_SetError("[GDK] Unable to call RegisterAppConstrainedChangeNotification"); 117 } 118 119 return true; 120} 121 122extern "C" 123void GDK_UnregisterChangeNotifications(void) 124{ 125 // Unregister suspend/resume handling 126 UnregisterAppStateChangeNotification(hPLM); 127 CloseHandle(plmSuspendComplete); 128 129 // Unregister constrain/unconstrain handling 130 UnregisterAppConstrainedChangeNotification(hCPLM); 131} 132 133extern "C" 134void SDL_GDKSuspendComplete() 135{ 136 if (plmSuspendComplete) { 137 SetEvent(plmSuspendComplete); 138 } 139} 140 141extern "C" 142bool SDL_GetGDKDefaultUser(XUserHandle *outUserHandle) 143{ 144 XAsyncBlock block = { 0 }; 145 HRESULT result; 146 147 if (FAILED(result = XUserAddAsync(XUserAddOptions::AddDefaultUserAllowingUI, &block))) { 148 return WIN_SetErrorFromHRESULT("XUserAddAsync", result); 149 } 150 151 do { 152 result = XUserAddResult(&block, outUserHandle); 153 } while (result == E_PENDING); 154 if (FAILED(result)) { 155 return WIN_SetErrorFromHRESULT("XUserAddResult", result); 156 } 157 158 return true; 159} 160
[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.