WinRT: added SDL_*ScreenSaver() support; fixed crash when restoring app from screensaver
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
diff --git a/src/video/winrt/SDL_winrtvideo.cpp b/src/video/winrt/SDL_winrtvideo.cpp
index e4c29a4..e0e0083 100644
--- a/src/video/winrt/SDL_winrtvideo.cpp
+++ b/src/video/winrt/SDL_winrtvideo.cpp
@@ -31,6 +31,7 @@
/* Windows includes */
#include <agile.h>
#include <windows.graphics.display.h>
+#include <windows.system.display.h>
#include <dxgi.h>
#include <dxgi1_2.h>
using namespace Windows::ApplicationModel::Core;
@@ -41,7 +42,8 @@ using namespace Windows::UI::ViewManagement;
/* [re]declare Windows GUIDs locally, to limit the amount of external lib(s) SDL has to link to */
-static const GUID IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48,{ 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
+static const GUID IID_IDisplayRequest = { 0xe5732044, 0xf49f, 0x4b60, { 0x8d, 0xd4, 0x5e, 0x7e, 0x3a, 0x63, 0x2a, 0xc0 } };
+static const GUID IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48, { 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
/* SDL includes */
@@ -83,6 +85,11 @@ static void WINRT_DestroyWindow(_THIS, SDL_Window * window);
static SDL_bool WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info);
+/* Misc functions */
+static ABI::Windows::System::Display::IDisplayRequest * WINRT_CreateDisplayRequest(_THIS);
+extern void WINRT_SuspendScreenSaver(_THIS);
+
+
/* SDL-internal globals: */
SDL_Window * WINRT_GlobalSDLWindow = NULL;
@@ -140,6 +147,7 @@ WINRT_CreateDevice(int devindex)
device->SetDisplayMode = WINRT_SetDisplayMode;
device->PumpEvents = WINRT_PumpEvents;
device->GetWindowWMInfo = WINRT_GetWindowWMInfo;
+ device->SuspendScreenSaver = WINRT_SuspendScreenSaver;
#if NTDDI_VERSION >= NTDDI_WIN10
device->HasScreenKeyboardSupport = WINRT_HasScreenKeyboardSupport;
@@ -173,13 +181,17 @@ VideoBootStrap WINRT_bootstrap = {
int
WINRT_VideoInit(_THIS)
{
+ SDL_VideoData * driverdata = (SDL_VideoData *) _this->driverdata;
if (WINRT_InitModes(_this) < 0) {
return -1;
}
WINRT_InitMouse(_this);
WINRT_InitTouch(_this);
WINRT_InitGameBar(_this);
-
+ if (driverdata) {
+ /* Initialize screensaver-disabling support */
+ driverdata->displayRequest = WINRT_CreateDisplayRequest(_this);
+ }
return 0;
}
@@ -421,6 +433,11 @@ WINRT_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
void
WINRT_VideoQuit(_THIS)
{
+ SDL_VideoData * driverdata = (SDL_VideoData *) _this->driverdata;
+ if (driverdata && driverdata->displayRequest) {
+ driverdata->displayRequest->Release();
+ driverdata->displayRequest = NULL;
+ }
WINRT_QuitGameBar(_this);
WINRT_QuitMouse(_this);
}
@@ -491,7 +508,7 @@ WINRT_DetectWindowFlags(SDL_Window * window)
// data->coreWindow->PointerPosition is not supported on WinPhone 8.0
latestFlags |= SDL_WINDOW_MOUSE_FOCUS;
#else
- if (data->coreWindow->Bounds.Contains(data->coreWindow->PointerPosition)) {
+ if (data->coreWindow->Visible && data->coreWindow->Bounds.Contains(data->coreWindow->PointerPosition)) {
latestFlags |= SDL_WINDOW_MOUSE_FOCUS;
}
#endif
@@ -761,6 +778,65 @@ WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
return SDL_FALSE;
}
+static ABI::Windows::System::Display::IDisplayRequest *
+WINRT_CreateDisplayRequest(_THIS)
+{
+ /* Setup a WinRT DisplayRequest object, usable for enabling/disabling screensaver requests */
+ wchar_t *wClassName = L"Windows.System.Display.DisplayRequest";
+ HSTRING hClassName;
+ IActivationFactory *pActivationFactory = NULL;
+ IInspectable * pDisplayRequestRaw = nullptr;
+ ABI::Windows::System::Display::IDisplayRequest * pDisplayRequest = nullptr;
+ HRESULT hr;
+
+ hr = ::WindowsCreateString(wClassName, (UINT32)wcslen(wClassName), &hClassName);
+ if (FAILED(hr)) {
+ goto done;
+ }
+
+ hr = Windows::Foundation::GetActivationFactory(hClassName, &pActivationFactory);
+ if (FAILED(hr)) {
+ goto done;
+ }
+
+ hr = pActivationFactory->ActivateInstance(&pDisplayRequestRaw);
+ if (FAILED(hr)) {
+ goto done;
+ }
+
+ hr = pDisplayRequestRaw->QueryInterface(IID_IDisplayRequest, (void **) &pDisplayRequest);
+ if (FAILED(hr)) {
+ goto done;
+ }
+
+done:
+ if (pDisplayRequestRaw) {
+ pDisplayRequestRaw->Release();
+ }
+ if (pActivationFactory) {
+ pActivationFactory->Release();
+ }
+ if (hClassName) {
+ ::WindowsDeleteString(hClassName);
+ }
+
+ return pDisplayRequest;
+}
+
+void
+WINRT_SuspendScreenSaver(_THIS)
+{
+ SDL_VideoData *driverdata = (SDL_VideoData *)_this->driverdata;
+ if (driverdata->displayRequest) {
+ ABI::Windows::System::Display::IDisplayRequest * displayRequest = (ABI::Windows::System::Display::IDisplayRequest *) driverdata->displayRequest;
+ if (_this->suspend_screensaver) {
+ displayRequest->RequestActive();
+ } else {
+ displayRequest->RequestRelease();
+ }
+ }
+}
+
#endif /* SDL_VIDEO_DRIVER_WINRT */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/winrt/SDL_winrtvideo_cpp.h b/src/video/winrt/SDL_winrtvideo_cpp.h
index da5f6ab..7d5ce13 100644
--- a/src/video/winrt/SDL_winrtvideo_cpp.h
+++ b/src/video/winrt/SDL_winrtvideo_cpp.h
@@ -51,6 +51,12 @@ typedef struct SDL_VideoData {
These are just a struct with a 64-bit integer inside them
*/
Windows::Foundation::EventRegistrationToken gameBarIsInputRedirectedToken;
+
+ /* A WinRT DisplayRequest, used for implementing SDL_*ScreenSaver() functions.
+ * This is really a pointer to a 'ABI::Windows::System::Display::IDisplayRequest *',
+ * It's casted to 'IUnknown *', to help with building SDL.
+ */
+ IUnknown *displayRequest;
} SDL_VideoData;
/* The global, WinRT, SDL Window.