better check for clock_gettime_nsec_np() -- cf. bug #5467.
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
21 #include "../../SDL_internal.h"
23 #if SDL_VIDEO_DRIVER_WINRT
25 /* WinRT SDL video driver implementation
27 Initial work on this was done by David Ludwig (dludwig@pobox.com), and
28 was based off of SDL's "dummy" video driver.
31 /* Windows includes */
33 #include <windows.graphics.display.h>
34 #include <windows.system.display.h>
37 using namespace Windows::ApplicationModel::Core;
38 using namespace Windows::Foundation;
39 using namespace Windows::Graphics::Display;
40 using namespace Windows::UI::Core;
41 using namespace Windows::UI::ViewManagement;
44 /* [re]declare Windows GUIDs locally, to limit the amount of external lib(s) SDL has to link to */
45 static const GUID IID_IDisplayRequest = { 0xe5732044, 0xf49f, 0x4b60, { 0x8d, 0xd4, 0x5e, 0x7e, 0x3a, 0x63, 0x2a, 0xc0 } };
46 static const GUID IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48, { 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
51 #include "SDL_video.h"
52 #include "SDL_mouse.h"
53 #include "../SDL_sysvideo.h"
54 #include "../SDL_pixels_c.h"
55 #include "../../events/SDL_events_c.h"
56 #include "../../render/SDL_sysrender.h"
57 #include "SDL_syswm.h"
58 #include "SDL_winrtopengles.h"
59 #include "../../core/windows/SDL_windows.h"
62 #include "../../core/winrt/SDL_winrtapp_direct3d.h"
63 #include "../../core/winrt/SDL_winrtapp_xaml.h"
64 #include "SDL_winrtvideo_cpp.h"
65 #include "SDL_winrtevents_c.h"
66 #include "SDL_winrtgamebar_cpp.h"
67 #include "SDL_winrtmouse_c.h"
69 #include "SDL_system.h"
72 /* Initialization/Query functions */
73 static int WINRT_VideoInit(_THIS);
74 static int WINRT_InitModes(_THIS);
75 static int WINRT_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
76 static void WINRT_VideoQuit(_THIS);
79 /* Window functions */
80 static int WINRT_CreateWindow(_THIS, SDL_Window * window);
81 static void WINRT_SetWindowSize(_THIS, SDL_Window * window);
82 static void WINRT_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
83 static void WINRT_DestroyWindow(_THIS, SDL_Window * window);
84 static SDL_bool WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info);
88 static ABI::Windows::System::Display::IDisplayRequest * WINRT_CreateDisplayRequest(_THIS);
89 extern void WINRT_SuspendScreenSaver(_THIS);
92 /* SDL-internal globals: */
93 SDL_Window * WINRT_GlobalSDLWindow = NULL;
96 /* WinRT driver bootstrap functions */
99 WINRT_DeleteDevice(SDL_VideoDevice * device)
101 if (device->driverdata) {
102 SDL_VideoData * video_data = (SDL_VideoData *)device->driverdata;
103 if (video_data->winrtEglWindow) {
104 video_data->winrtEglWindow->Release();
106 SDL_free(video_data);
112 static SDL_VideoDevice *
113 WINRT_CreateDevice(int devindex)
115 SDL_VideoDevice *device;
118 /* Initialize all variables that we clean on shutdown */
119 device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
125 data = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
131 device->driverdata = data;
133 /* Set the function pointers */
134 device->VideoInit = WINRT_VideoInit;
135 device->VideoQuit = WINRT_VideoQuit;
136 device->CreateSDLWindow = WINRT_CreateWindow;
137 device->SetWindowSize = WINRT_SetWindowSize;
138 device->SetWindowFullscreen = WINRT_SetWindowFullscreen;
139 device->DestroyWindow = WINRT_DestroyWindow;
140 device->SetDisplayMode = WINRT_SetDisplayMode;
141 device->PumpEvents = WINRT_PumpEvents;
142 device->GetWindowWMInfo = WINRT_GetWindowWMInfo;
143 device->SuspendScreenSaver = WINRT_SuspendScreenSaver;
145 #if NTDDI_VERSION >= NTDDI_WIN10
146 device->HasScreenKeyboardSupport = WINRT_HasScreenKeyboardSupport;
147 device->ShowScreenKeyboard = WINRT_ShowScreenKeyboard;
148 device->HideScreenKeyboard = WINRT_HideScreenKeyboard;
149 device->IsScreenKeyboardShown = WINRT_IsScreenKeyboardShown;
152 #ifdef SDL_VIDEO_OPENGL_EGL
153 device->GL_LoadLibrary = WINRT_GLES_LoadLibrary;
154 device->GL_GetProcAddress = WINRT_GLES_GetProcAddress;
155 device->GL_UnloadLibrary = WINRT_GLES_UnloadLibrary;
156 device->GL_CreateContext = WINRT_GLES_CreateContext;
157 device->GL_MakeCurrent = WINRT_GLES_MakeCurrent;
158 device->GL_SetSwapInterval = WINRT_GLES_SetSwapInterval;
159 device->GL_GetSwapInterval = WINRT_GLES_GetSwapInterval;
160 device->GL_SwapWindow = WINRT_GLES_SwapWindow;
161 device->GL_DeleteContext = WINRT_GLES_DeleteContext;
163 device->free = WINRT_DeleteDevice;
168 #define WINRTVID_DRIVER_NAME "winrt"
169 VideoBootStrap WINRT_bootstrap = {
170 WINRTVID_DRIVER_NAME, "SDL WinRT video driver",
175 WINRT_VideoInit(_THIS)
177 SDL_VideoData * driverdata = (SDL_VideoData *) _this->driverdata;
178 if (WINRT_InitModes(_this) < 0) {
181 WINRT_InitMouse(_this);
182 WINRT_InitTouch(_this);
183 WINRT_InitGameBar(_this);
185 /* Initialize screensaver-disabling support */
186 driverdata->displayRequest = WINRT_CreateDisplayRequest(_this);
192 Uint32 D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat);
195 WINRT_DXGIModeToSDLDisplayMode(const DXGI_MODE_DESC * dxgiMode, SDL_DisplayMode * sdlMode)
198 sdlMode->w = dxgiMode->Width;
199 sdlMode->h = dxgiMode->Height;
200 sdlMode->refresh_rate = dxgiMode->RefreshRate.Numerator / dxgiMode->RefreshRate.Denominator;
201 sdlMode->format = D3D11_DXGIFormatToSDLPixelFormat(dxgiMode->Format);
205 WINRT_AddDisplaysForOutput (_THIS, IDXGIAdapter1 * dxgiAdapter1, int outputIndex)
208 IDXGIOutput * dxgiOutput = NULL;
209 DXGI_OUTPUT_DESC dxgiOutputDesc;
210 SDL_VideoDisplay display;
211 char * displayName = NULL;
213 DXGI_MODE_DESC * dxgiModes = NULL;
214 int functionResult = -1; /* -1 for failure, 0 for success */
215 DXGI_MODE_DESC modeToMatch, closestMatch;
219 hr = dxgiAdapter1->EnumOutputs(outputIndex, &dxgiOutput);
221 if (hr != DXGI_ERROR_NOT_FOUND) {
222 WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIAdapter1::EnumOutputs failed", hr);
227 hr = dxgiOutput->GetDesc(&dxgiOutputDesc);
229 WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDesc failed", hr);
233 SDL_zero(modeToMatch);
234 modeToMatch.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
235 modeToMatch.Width = (dxgiOutputDesc.DesktopCoordinates.right - dxgiOutputDesc.DesktopCoordinates.left);
236 modeToMatch.Height = (dxgiOutputDesc.DesktopCoordinates.bottom - dxgiOutputDesc.DesktopCoordinates.top);
237 hr = dxgiOutput->FindClosestMatchingMode(&modeToMatch, &closestMatch, NULL);
238 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
239 /* DXGI_ERROR_NOT_CURRENTLY_AVAILABLE gets returned by IDXGIOutput::FindClosestMatchingMode
240 when running under the Windows Simulator, which uses Remote Desktop (formerly known as Terminal
241 Services) under the hood. According to the MSDN docs for the similar function,
242 IDXGIOutput::GetDisplayModeList, DXGI_ERROR_NOT_CURRENTLY_AVAILABLE is returned if and
243 when an app is run under a Terminal Services session, hence the assumption.
245 In this case, just add an SDL display mode, with approximated values.
247 SDL_DisplayMode mode;
249 display.name = "Windows Simulator / Terminal Services Display";
250 mode.w = (dxgiOutputDesc.DesktopCoordinates.right - dxgiOutputDesc.DesktopCoordinates.left);
251 mode.h = (dxgiOutputDesc.DesktopCoordinates.bottom - dxgiOutputDesc.DesktopCoordinates.top);
252 mode.format = DXGI_FORMAT_B8G8R8A8_UNORM;
253 mode.refresh_rate = 0; /* Display mode is unknown, so just fill in zero, as specified by SDL's header files */
254 display.desktop_mode = mode;
255 display.current_mode = mode;
256 if ( ! SDL_AddDisplayMode(&display, &mode)) {
259 } else if (FAILED(hr)) {
260 WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::FindClosestMatchingMode failed", hr);
263 displayName = WIN_StringToUTF8(dxgiOutputDesc.DeviceName);
264 display.name = displayName;
265 WINRT_DXGIModeToSDLDisplayMode(&closestMatch, &display.desktop_mode);
266 display.current_mode = display.desktop_mode;
268 hr = dxgiOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &numModes, NULL);
270 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
271 // TODO, WinRT: make sure display mode(s) are added when using Terminal Services / Windows Simulator
273 WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDisplayModeList [get mode list size] failed", hr);
277 dxgiModes = (DXGI_MODE_DESC *)SDL_calloc(numModes, sizeof(DXGI_MODE_DESC));
283 hr = dxgiOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &numModes, dxgiModes);
285 WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDisplayModeList [get mode contents] failed", hr);
289 for (UINT i = 0; i < numModes; ++i) {
290 SDL_DisplayMode sdlMode;
291 WINRT_DXGIModeToSDLDisplayMode(&dxgiModes[i], &sdlMode);
292 SDL_AddDisplayMode(&display, &sdlMode);
296 if (SDL_AddVideoDisplay(&display, SDL_FALSE) < 0) {
300 functionResult = 0; /* 0 for Success! */
306 dxgiOutput->Release();
309 SDL_free(displayName);
311 return functionResult;
315 WINRT_AddDisplaysForAdapter (_THIS, IDXGIFactory2 * dxgiFactory2, int adapterIndex)
318 IDXGIAdapter1 * dxgiAdapter1;
320 hr = dxgiFactory2->EnumAdapters1(adapterIndex, &dxgiAdapter1);
322 if (hr != DXGI_ERROR_NOT_FOUND) {
323 WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIFactory1::EnumAdapters1() failed", hr);
328 for (int outputIndex = 0; ; ++outputIndex) {
329 if (WINRT_AddDisplaysForOutput(_this, dxgiAdapter1, outputIndex) < 0) {
330 /* HACK: The Windows App Certification Kit 10.0 can fail, when
331 running the Store Apps' test, "Direct3D Feature Test". The
332 certification kit's error is:
334 "Application App was not running at the end of the test. It likely crashed or was terminated for having become unresponsive."
336 This was caused by SDL/WinRT's DXGI failing to report any
337 outputs. Attempts to get the 1st display-output from the
338 1st display-adapter can fail, with IDXGIAdapter::EnumOutputs
339 returning DXGI_ERROR_NOT_FOUND. This could be a bug in Windows,
340 the Windows App Certification Kit, or possibly in SDL/WinRT's
341 display detection code. Either way, try to detect when this
342 happens, and use a hackish means to create a reasonable-as-possible
343 'display mode'. -- DavidL
345 if (adapterIndex == 0 && outputIndex == 0) {
346 SDL_VideoDisplay display;
347 SDL_DisplayMode mode;
348 #if SDL_WINRT_USE_APPLICATIONVIEW
349 ApplicationView ^ appView = ApplicationView::GetForCurrentView();
351 CoreWindow ^ coreWin = CoreWindow::GetForCurrentThread();
354 display.name = "DXGI Display-detection Workaround";
356 /* HACK: ApplicationView's VisibleBounds property, appeared, via testing, to
357 give a better approximation of display-size, than did CoreWindow's
358 Bounds property, insofar that ApplicationView::VisibleBounds seems like
359 it will, at least some of the time, give the full display size (during the
360 failing test), whereas CoreWindow might not. -- DavidL
363 #if (NTDDI_VERSION >= NTDDI_WIN10) || (SDL_WINRT_USE_APPLICATIONVIEW && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
364 mode.w = WINRT_DIPS_TO_PHYSICAL_PIXELS(appView->VisibleBounds.Width);
365 mode.h = WINRT_DIPS_TO_PHYSICAL_PIXELS(appView->VisibleBounds.Height);
367 /* On platform(s) that do not support VisibleBounds, such as Windows 8.1,
368 fall back to CoreWindow's Bounds property.
370 mode.w = WINRT_DIPS_TO_PHYSICAL_PIXELS(coreWin->Bounds.Width);
371 mode.h = WINRT_DIPS_TO_PHYSICAL_PIXELS(coreWin->Bounds.Height);
374 mode.format = DXGI_FORMAT_B8G8R8A8_UNORM;
375 mode.refresh_rate = 0; /* Display mode is unknown, so just fill in zero, as specified by SDL's header files */
376 display.desktop_mode = mode;
377 display.current_mode = mode;
378 if ((SDL_AddDisplayMode(&display, &mode) < 0) ||
379 (SDL_AddVideoDisplay(&display, SDL_FALSE) < 0))
381 return SDL_SetError("Failed to apply DXGI Display-detection workaround");
389 dxgiAdapter1->Release();
394 WINRT_InitModes(_THIS)
396 /* HACK: Initialize a single display, for whatever screen the app's
397 CoreApplicationView is on.
398 TODO, WinRT: Try initializing multiple displays, one for each monitor.
399 Appropriate WinRT APIs for this seem elusive, though. -- DavidL
403 IDXGIFactory2 * dxgiFactory2 = NULL;
405 hr = CreateDXGIFactory1(IID_IDXGIFactory2, (void **)&dxgiFactory2);
407 WIN_SetErrorFromHRESULT(__FUNCTION__ ", CreateDXGIFactory1() failed", hr);
411 for (int adapterIndex = 0; ; ++adapterIndex) {
412 if (WINRT_AddDisplaysForAdapter(_this, dxgiFactory2, adapterIndex) < 0) {
421 WINRT_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
427 WINRT_VideoQuit(_THIS)
429 SDL_VideoData * driverdata = (SDL_VideoData *) _this->driverdata;
430 if (driverdata && driverdata->displayRequest) {
431 driverdata->displayRequest->Release();
432 driverdata->displayRequest = NULL;
434 WINRT_QuitGameBar(_this);
435 WINRT_QuitMouse(_this);
438 static const Uint32 WINRT_DetectableFlags =
439 SDL_WINDOW_MAXIMIZED |
440 SDL_WINDOW_FULLSCREEN_DESKTOP |
443 SDL_WINDOW_MOUSE_FOCUS;
446 WINRT_DetectWindowFlags(SDL_Window * window)
448 Uint32 latestFlags = 0;
449 SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
450 bool is_fullscreen = false;
452 #if SDL_WINRT_USE_APPLICATIONVIEW
454 is_fullscreen = data->appView->IsFullScreen;
456 #elif (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION == NTDDI_WIN8)
457 is_fullscreen = true;
460 if (data->coreWindow.Get()) {
462 SDL_VideoDisplay * display = SDL_GetDisplayForWindow(window);
463 int w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
464 int h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
466 #if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION > NTDDI_WIN8)
467 // On all WinRT platforms, except for WinPhone 8.0, rotate the
468 // window size. This is needed to properly calculate
469 // fullscreen vs. maximized.
470 const DisplayOrientations currentOrientation = WINRT_DISPLAY_PROPERTY(CurrentOrientation);
471 switch (currentOrientation) {
472 #if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
473 case DisplayOrientations::Landscape:
474 case DisplayOrientations::LandscapeFlipped:
476 case DisplayOrientations::Portrait:
477 case DisplayOrientations::PortraitFlipped:
487 if (display->desktop_mode.w != w || display->desktop_mode.h != h) {
488 latestFlags |= SDL_WINDOW_MAXIMIZED;
490 latestFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
494 if (data->coreWindow->Visible) {
495 latestFlags |= SDL_WINDOW_SHOWN;
497 latestFlags |= SDL_WINDOW_HIDDEN;
500 #if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) && (NTDDI_VERSION < NTDDI_WINBLUE)
501 // data->coreWindow->PointerPosition is not supported on WinPhone 8.0
502 latestFlags |= SDL_WINDOW_MOUSE_FOCUS;
504 if (data->coreWindow->Visible && data->coreWindow->Bounds.Contains(data->coreWindow->PointerPosition)) {
505 latestFlags |= SDL_WINDOW_MOUSE_FOCUS;
513 // TODO, WinRT: consider removing WINRT_UpdateWindowFlags, and just calling WINRT_DetectWindowFlags as-appropriate (with appropriate calls to SDL_SendWindowEvent)
515 WINRT_UpdateWindowFlags(SDL_Window * window, Uint32 mask)
517 mask &= WINRT_DetectableFlags;
519 Uint32 apply = WINRT_DetectWindowFlags(window);
520 if ((apply & mask) & SDL_WINDOW_FULLSCREEN) {
521 window->last_fullscreen_flags = window->flags; // seems necessary to programmatically un-fullscreen, via SDL APIs
523 window->flags = (window->flags & ~mask) | (apply & mask);
528 WINRT_IsCoreWindowActive(CoreWindow ^ coreWindow)
530 /* WinRT does not appear to offer API(s) to determine window-activation state,
531 at least not that I am aware of in Win8 - Win10. As such, SDL tracks this
532 itself, via window-activation events.
534 If there *is* an API to track this, it should probably get used instead
535 of the following hack (that uses "SDLHelperWindowActivationState").
538 if (coreWindow->CustomProperties->HasKey("SDLHelperWindowActivationState")) {
539 CoreWindowActivationState activationState = \
540 safe_cast<CoreWindowActivationState>(coreWindow->CustomProperties->Lookup("SDLHelperWindowActivationState"));
541 return (activationState != CoreWindowActivationState::Deactivated);
544 /* Assume that non-SDL tracked windows are active, although this should
545 probably be avoided, if possible.
547 This might not even be possible, in normal SDL use, at least as of
548 this writing (Dec 22, 2015; via latest hg.libsdl.org/SDL clone) -- DavidL
554 WINRT_CreateWindow(_THIS, SDL_Window * window)
556 // Make sure that only one window gets created, at least until multimonitor
558 if (WINRT_GlobalSDLWindow != NULL) {
559 SDL_SetError("WinRT only supports one window");
563 SDL_WindowData *data = new SDL_WindowData; /* use 'new' here as SDL_WindowData may use WinRT/C++ types */
568 window->driverdata = data;
569 data->sdlWindow = window;
571 /* To note, when XAML support is enabled, access to the CoreWindow will not
572 be possible, at least not via the SDL/XAML thread. Attempts to access it
573 from there will throw exceptions. As such, the SDL_WindowData's
574 'coreWindow' field will only be set (to a non-null value) if XAML isn't
577 if (!WINRT_XAMLWasEnabled) {
578 data->coreWindow = CoreWindow::GetForCurrentThread();
579 #if SDL_WINRT_USE_APPLICATIONVIEW
580 data->appView = ApplicationView::GetForCurrentView();
584 /* Make note of the requested window flags, before they start getting changed. */
585 const Uint32 requestedFlags = window->flags;
587 #if SDL_VIDEO_OPENGL_EGL
588 /* Setup the EGL surface, but only if OpenGL ES 2 was requested. */
589 if (!(window->flags & SDL_WINDOW_OPENGL)) {
590 /* OpenGL ES 2 wasn't requested. Don't set up an EGL surface. */
591 data->egl_surface = EGL_NO_SURFACE;
593 /* OpenGL ES 2 was reuqested. Set up an EGL surface. */
594 SDL_VideoData * video_data = (SDL_VideoData *)_this->driverdata;
596 /* Call SDL_EGL_ChooseConfig and eglCreateWindowSurface directly,
597 * rather than via SDL_EGL_CreateSurface, as older versions of
598 * ANGLE/WinRT may require that a C++ object, ComPtr<IUnknown>,
599 * be passed into eglCreateWindowSurface.
601 if (SDL_EGL_ChooseConfig(_this) != 0) {
603 SDL_snprintf(buf, sizeof(buf), "SDL_EGL_ChooseConfig failed: %s", SDL_GetError());
604 return SDL_SetError("%s", buf);
607 if (video_data->winrtEglWindow) { /* ... is the 'old' version of ANGLE/WinRT being used? */
608 /* Attempt to create a window surface using older versions of
611 Microsoft::WRL::ComPtr<IUnknown> cpp_winrtEglWindow = video_data->winrtEglWindow;
612 data->egl_surface = ((eglCreateWindowSurface_Old_Function)_this->egl_data->eglCreateWindowSurface)(
613 _this->egl_data->egl_display,
614 _this->egl_data->egl_config,
615 cpp_winrtEglWindow, NULL);
616 if (data->egl_surface == NULL) {
617 return SDL_EGL_SetError("unable to create EGL native-window surface", "eglCreateWindowSurface");
619 } else if (data->coreWindow.Get() != nullptr) {
620 /* Attempt to create a window surface using newer versions of
623 IInspectable * coreWindowAsIInspectable = reinterpret_cast<IInspectable *>(data->coreWindow.Get());
624 data->egl_surface = _this->egl_data->eglCreateWindowSurface(
625 _this->egl_data->egl_display,
626 _this->egl_data->egl_config,
627 coreWindowAsIInspectable,
629 if (data->egl_surface == NULL) {
630 return SDL_EGL_SetError("unable to create EGL native-window surface", "eglCreateWindowSurface");
633 return SDL_SetError("No supported means to create an EGL window surface are available");
638 /* Determine as many flags dynamically, as possible. */
640 SDL_WINDOW_BORDERLESS |
641 SDL_WINDOW_RESIZABLE;
643 #if SDL_VIDEO_OPENGL_EGL
644 if (data->egl_surface) {
645 window->flags |= SDL_WINDOW_OPENGL;
649 if (WINRT_XAMLWasEnabled) {
650 /* TODO, WinRT: set SDL_Window size, maybe position too, from XAML control */
653 window->flags |= SDL_WINDOW_SHOWN;
654 SDL_SetMouseFocus(NULL); // TODO: detect this
655 SDL_SetKeyboardFocus(NULL); // TODO: detect this
657 /* WinRT 8.x apps seem to live in an environment where the OS controls the
658 app's window size, with some apps being fullscreen, depending on
659 user choice of various things. For now, just adapt the SDL_Window to
660 whatever Windows set-up as the native-window's geometry.
662 window->x = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Left);
663 window->y = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Top);
664 #if NTDDI_VERSION < NTDDI_WIN10
665 /* On WinRT 8.x / pre-Win10, just use the size we were given. */
666 window->w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
667 window->h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
669 /* On Windows 10, we occasionally get control over window size. For windowed
672 bool didSetSize = false;
673 if (!(requestedFlags & SDL_WINDOW_FULLSCREEN)) {
674 const Windows::Foundation::Size size(WINRT_PHYSICAL_PIXELS_TO_DIPS(window->w),
675 WINRT_PHYSICAL_PIXELS_TO_DIPS(window->h));
676 didSetSize = data->appView->TryResizeView(size);
679 /* We either weren't able to set the window size, or a request for
680 fullscreen was made. Get window-size info from the OS.
682 window->w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
683 window->h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
687 WINRT_UpdateWindowFlags(
689 0xffffffff /* Update any window flag(s) that WINRT_UpdateWindow can handle */
692 /* Try detecting if the window is active */
693 bool isWindowActive = WINRT_IsCoreWindowActive(data->coreWindow.Get());
694 if (isWindowActive) {
695 SDL_SetKeyboardFocus(window);
699 /* Make sure the WinRT app's IFramworkView can post events on
702 WINRT_GlobalSDLWindow = window;
709 WINRT_SetWindowSize(_THIS, SDL_Window * window)
711 #if NTDDI_VERSION >= NTDDI_WIN10
712 SDL_WindowData * data = (SDL_WindowData *)window->driverdata;
713 const Windows::Foundation::Size size(WINRT_PHYSICAL_PIXELS_TO_DIPS(window->w),
714 WINRT_PHYSICAL_PIXELS_TO_DIPS(window->h));
715 data->appView->TryResizeView(size); // TODO, WinRT: return failure (to caller?) from TryResizeView()
720 WINRT_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
722 #if NTDDI_VERSION >= NTDDI_WIN10
723 SDL_WindowData * data = (SDL_WindowData *)window->driverdata;
724 bool isWindowActive = WINRT_IsCoreWindowActive(data->coreWindow.Get());
725 if (isWindowActive) {
727 if (!data->appView->IsFullScreenMode) {
728 data->appView->TryEnterFullScreenMode(); // TODO, WinRT: return failure (to caller?) from TryEnterFullScreenMode()
731 if (data->appView->IsFullScreenMode) {
732 data->appView->ExitFullScreenMode();
741 WINRT_DestroyWindow(_THIS, SDL_Window * window)
743 SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
745 if (WINRT_GlobalSDLWindow == window) {
746 WINRT_GlobalSDLWindow = NULL;
750 // Delete the internal window data:
753 window->driverdata = NULL;
758 WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
760 SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
762 if (info->version.major <= SDL_MAJOR_VERSION) {
763 info->subsystem = SDL_SYSWM_WINRT;
764 info->info.winrt.window = reinterpret_cast<IInspectable *>(data->coreWindow.Get());
767 SDL_SetError("Application not compiled with SDL %d.%d",
768 SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
774 static ABI::Windows::System::Display::IDisplayRequest *
775 WINRT_CreateDisplayRequest(_THIS)
777 /* Setup a WinRT DisplayRequest object, usable for enabling/disabling screensaver requests */
778 wchar_t *wClassName = L"Windows.System.Display.DisplayRequest";
780 IActivationFactory *pActivationFactory = NULL;
781 IInspectable * pDisplayRequestRaw = nullptr;
782 ABI::Windows::System::Display::IDisplayRequest * pDisplayRequest = nullptr;
785 hr = ::WindowsCreateString(wClassName, (UINT32)wcslen(wClassName), &hClassName);
790 hr = Windows::Foundation::GetActivationFactory(hClassName, &pActivationFactory);
795 hr = pActivationFactory->ActivateInstance(&pDisplayRequestRaw);
800 hr = pDisplayRequestRaw->QueryInterface(IID_IDisplayRequest, (void **) &pDisplayRequest);
806 if (pDisplayRequestRaw) {
807 pDisplayRequestRaw->Release();
809 if (pActivationFactory) {
810 pActivationFactory->Release();
813 ::WindowsDeleteString(hClassName);
816 return pDisplayRequest;
820 WINRT_SuspendScreenSaver(_THIS)
822 SDL_VideoData *driverdata = (SDL_VideoData *)_this->driverdata;
823 if (driverdata && driverdata->displayRequest) {
824 ABI::Windows::System::Display::IDisplayRequest * displayRequest = (ABI::Windows::System::Display::IDisplayRequest *) driverdata->displayRequest;
825 if (_this->suspend_screensaver) {
826 displayRequest->RequestActive();
828 displayRequest->RequestRelease();
833 #endif /* SDL_VIDEO_DRIVER_WINRT */
835 /* vi: set ts=4 sw=4 expandtab: */