Skip to content

Commit

Permalink
WinRT: added SDL_*ScreenSaver() support; fixed crash when restoring a…
Browse files Browse the repository at this point in the history
…pp from screensaver
  • Loading branch information
DavidLudwig committed Aug 30, 2016
1 parent 651107a commit 5020fe8
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 3 deletions.
82 changes: 79 additions & 3 deletions src/video/winrt/SDL_winrtvideo.cpp
Expand Up @@ -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;
Expand All @@ -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 */
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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: */
6 changes: 6 additions & 0 deletions src/video/winrt/SDL_winrtvideo_cpp.h
Expand Up @@ -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.
Expand Down

0 comments on commit 5020fe8

Please sign in to comment.