WinRT: added SDL_*ScreenSaver() support; fixed crash when restoring app from screensaver
authorDavid Ludwig <dludwig@pobox.com>
Mon, 29 Aug 2016 20:27:21 -0400
changeset 10293db77073d402d
parent 10292 7b037d1387a0
child 10294 1ed0064677af
WinRT: added SDL_*ScreenSaver() support; fixed crash when restoring app from screensaver
src/video/winrt/SDL_winrtvideo.cpp
src/video/winrt/SDL_winrtvideo_cpp.h
     1.1 --- a/src/video/winrt/SDL_winrtvideo.cpp	Tue Aug 16 12:02:22 2016 -0700
     1.2 +++ b/src/video/winrt/SDL_winrtvideo.cpp	Mon Aug 29 20:27:21 2016 -0400
     1.3 @@ -31,6 +31,7 @@
     1.4  /* Windows includes */
     1.5  #include <agile.h>
     1.6  #include <windows.graphics.display.h>
     1.7 +#include <windows.system.display.h>
     1.8  #include <dxgi.h>
     1.9  #include <dxgi1_2.h>
    1.10  using namespace Windows::ApplicationModel::Core;
    1.11 @@ -41,7 +42,8 @@
    1.12  
    1.13  
    1.14  /* [re]declare Windows GUIDs locally, to limit the amount of external lib(s) SDL has to link to */
    1.15 -static const GUID IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48,{ 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
    1.16 +static const GUID IID_IDisplayRequest   = { 0xe5732044, 0xf49f, 0x4b60, { 0x8d, 0xd4, 0x5e, 0x7e, 0x3a, 0x63, 0x2a, 0xc0 } };
    1.17 +static const GUID IID_IDXGIFactory2     = { 0x50c83a1c, 0xe072, 0x4c48, { 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
    1.18  
    1.19  
    1.20  /* SDL includes */
    1.21 @@ -83,6 +85,11 @@
    1.22  static SDL_bool WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info);
    1.23  
    1.24  
    1.25 +/* Misc functions */
    1.26 +static ABI::Windows::System::Display::IDisplayRequest * WINRT_CreateDisplayRequest(_THIS);
    1.27 +extern void WINRT_SuspendScreenSaver(_THIS);
    1.28 +
    1.29 +
    1.30  /* SDL-internal globals: */
    1.31  SDL_Window * WINRT_GlobalSDLWindow = NULL;
    1.32  
    1.33 @@ -140,6 +147,7 @@
    1.34      device->SetDisplayMode = WINRT_SetDisplayMode;
    1.35      device->PumpEvents = WINRT_PumpEvents;
    1.36      device->GetWindowWMInfo = WINRT_GetWindowWMInfo;
    1.37 +    device->SuspendScreenSaver = WINRT_SuspendScreenSaver;
    1.38  
    1.39  #if NTDDI_VERSION >= NTDDI_WIN10
    1.40      device->HasScreenKeyboardSupport = WINRT_HasScreenKeyboardSupport;
    1.41 @@ -173,13 +181,17 @@
    1.42  int
    1.43  WINRT_VideoInit(_THIS)
    1.44  {
    1.45 +    SDL_VideoData * driverdata = (SDL_VideoData *) _this->driverdata;
    1.46      if (WINRT_InitModes(_this) < 0) {
    1.47          return -1;
    1.48      }
    1.49      WINRT_InitMouse(_this);
    1.50      WINRT_InitTouch(_this);
    1.51      WINRT_InitGameBar(_this);
    1.52 -
    1.53 +    if (driverdata) {
    1.54 +        /* Initialize screensaver-disabling support */
    1.55 +        driverdata->displayRequest = WINRT_CreateDisplayRequest(_this);
    1.56 +    }
    1.57      return 0;
    1.58  }
    1.59  
    1.60 @@ -421,6 +433,11 @@
    1.61  void
    1.62  WINRT_VideoQuit(_THIS)
    1.63  {
    1.64 +    SDL_VideoData * driverdata = (SDL_VideoData *) _this->driverdata;
    1.65 +    if (driverdata && driverdata->displayRequest) {
    1.66 +        driverdata->displayRequest->Release();
    1.67 +        driverdata->displayRequest = NULL;
    1.68 +    }
    1.69      WINRT_QuitGameBar(_this);
    1.70      WINRT_QuitMouse(_this);
    1.71  }
    1.72 @@ -491,7 +508,7 @@
    1.73          // data->coreWindow->PointerPosition is not supported on WinPhone 8.0
    1.74          latestFlags |= SDL_WINDOW_MOUSE_FOCUS;
    1.75  #else
    1.76 -        if (data->coreWindow->Bounds.Contains(data->coreWindow->PointerPosition)) {
    1.77 +        if (data->coreWindow->Visible && data->coreWindow->Bounds.Contains(data->coreWindow->PointerPosition)) {
    1.78              latestFlags |= SDL_WINDOW_MOUSE_FOCUS;
    1.79          }
    1.80  #endif
    1.81 @@ -761,6 +778,65 @@
    1.82      return SDL_FALSE;
    1.83  }
    1.84  
    1.85 +static ABI::Windows::System::Display::IDisplayRequest *
    1.86 +WINRT_CreateDisplayRequest(_THIS)
    1.87 +{
    1.88 +    /* Setup a WinRT DisplayRequest object, usable for enabling/disabling screensaver requests */
    1.89 +    wchar_t *wClassName = L"Windows.System.Display.DisplayRequest";
    1.90 +    HSTRING hClassName;
    1.91 +    IActivationFactory *pActivationFactory = NULL;
    1.92 +    IInspectable * pDisplayRequestRaw = nullptr;
    1.93 +    ABI::Windows::System::Display::IDisplayRequest * pDisplayRequest = nullptr;
    1.94 +    HRESULT hr;
    1.95 +
    1.96 +    hr = ::WindowsCreateString(wClassName, (UINT32)wcslen(wClassName), &hClassName);
    1.97 +    if (FAILED(hr)) {
    1.98 +        goto done;
    1.99 +    }
   1.100 +
   1.101 +    hr = Windows::Foundation::GetActivationFactory(hClassName, &pActivationFactory);
   1.102 +    if (FAILED(hr)) {
   1.103 +        goto done;
   1.104 +    }
   1.105 +
   1.106 +    hr = pActivationFactory->ActivateInstance(&pDisplayRequestRaw);
   1.107 +    if (FAILED(hr)) {
   1.108 +        goto done;
   1.109 +    }
   1.110 +
   1.111 +    hr = pDisplayRequestRaw->QueryInterface(IID_IDisplayRequest, (void **) &pDisplayRequest);
   1.112 +    if (FAILED(hr)) {
   1.113 +        goto done;
   1.114 +    }
   1.115 +
   1.116 +done:
   1.117 +    if (pDisplayRequestRaw) {
   1.118 +        pDisplayRequestRaw->Release();
   1.119 +    }
   1.120 +    if (pActivationFactory) {
   1.121 +        pActivationFactory->Release();
   1.122 +    }
   1.123 +    if (hClassName) {
   1.124 +        ::WindowsDeleteString(hClassName);
   1.125 +    }
   1.126 +
   1.127 +    return pDisplayRequest;
   1.128 +}
   1.129 +
   1.130 +void
   1.131 +WINRT_SuspendScreenSaver(_THIS)
   1.132 +{
   1.133 +    SDL_VideoData *driverdata = (SDL_VideoData *)_this->driverdata;
   1.134 +    if (driverdata->displayRequest) {
   1.135 +        ABI::Windows::System::Display::IDisplayRequest * displayRequest = (ABI::Windows::System::Display::IDisplayRequest *) driverdata->displayRequest;
   1.136 +        if (_this->suspend_screensaver) {
   1.137 +            displayRequest->RequestActive();
   1.138 +        } else {
   1.139 +            displayRequest->RequestRelease();
   1.140 +        }
   1.141 +    }
   1.142 +}
   1.143 +
   1.144  #endif /* SDL_VIDEO_DRIVER_WINRT */
   1.145  
   1.146  /* vi: set ts=4 sw=4 expandtab: */
     2.1 --- a/src/video/winrt/SDL_winrtvideo_cpp.h	Tue Aug 16 12:02:22 2016 -0700
     2.2 +++ b/src/video/winrt/SDL_winrtvideo_cpp.h	Mon Aug 29 20:27:21 2016 -0400
     2.3 @@ -51,6 +51,12 @@
     2.4         These are just a struct with a 64-bit integer inside them
     2.5      */
     2.6      Windows::Foundation::EventRegistrationToken gameBarIsInputRedirectedToken;
     2.7 +
     2.8 +    /* A WinRT DisplayRequest, used for implementing SDL_*ScreenSaver() functions.
     2.9 +     * This is really a pointer to a 'ABI::Windows::System::Display::IDisplayRequest *',
    2.10 +     * It's casted to 'IUnknown *', to help with building SDL.
    2.11 +    */
    2.12 +    IUnknown *displayRequest;
    2.13  } SDL_VideoData;
    2.14  
    2.15  /* The global, WinRT, SDL Window.