src/video/winrt/SDL_winrtvideo.cpp
author Sam Lantinga
Fri, 27 Jan 2017 21:23:27 -0800
changeset 10861 71d8f9afb690
parent 10740 bb53965b659d
child 10945 1300a3135d61
permissions -rw-r--r--
Fixed bug 3569 - GL_UpdateViewport leaves PROJECTION matrix selected

Tom Seddon

GL_ActivateRenderer may call GL_UpdateViewport, which leaves the GL_PROJECTION matrix selected. But after GL_ResetState, the GL_MODELVIEW matrix is selected, suggesting that's the intended default state.

It seems at least like these should be consistent. Presumably GL_UpdateViewport should be doing a glMatrixMode(GL_MODELVIEW) before it finishes.
dludwig@8327
     1
/*
dludwig@8327
     2
  Simple DirectMedia Layer
slouken@10737
     3
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
dludwig@8327
     4
dludwig@8327
     5
  This software is provided 'as-is', without any express or implied
dludwig@8327
     6
  warranty.  In no event will the authors be held liable for any damages
dludwig@8327
     7
  arising from the use of this software.
dludwig@8327
     8
dludwig@8327
     9
  Permission is granted to anyone to use this software for any purpose,
dludwig@8327
    10
  including commercial applications, and to alter it and redistribute it
dludwig@8327
    11
  freely, subject to the following restrictions:
dludwig@8327
    12
dludwig@8327
    13
  1. The origin of this software must not be misrepresented; you must not
dludwig@8327
    14
     claim that you wrote the original software. If you use this software
dludwig@8327
    15
     in a product, an acknowledgment in the product documentation would be
dludwig@8327
    16
     appreciated but is not required.
dludwig@8327
    17
  2. Altered source versions must be plainly marked as such, and must not be
dludwig@8327
    18
     misrepresented as being the original software.
dludwig@8327
    19
  3. This notice may not be removed or altered from any source distribution.
dludwig@8327
    20
*/
dludwig@8600
    21
#include "../../SDL_internal.h"
dludwig@8327
    22
dludwig@8327
    23
#if SDL_VIDEO_DRIVER_WINRT
dludwig@8327
    24
dludwig@8327
    25
/* WinRT SDL video driver implementation
dludwig@8327
    26
dludwig@8327
    27
   Initial work on this was done by David Ludwig (dludwig@pobox.com), and
dludwig@8327
    28
   was based off of SDL's "dummy" video driver.
dludwig@8327
    29
 */
dludwig@8327
    30
dludwig@8494
    31
/* Windows includes */
dludwig@8494
    32
#include <agile.h>
dludwig@9924
    33
#include <windows.graphics.display.h>
dludwig@10293
    34
#include <windows.system.display.h>
dludwig@9924
    35
#include <dxgi.h>
dludwig@9924
    36
#include <dxgi1_2.h>
dludwig@9924
    37
using namespace Windows::ApplicationModel::Core;
dludwig@9924
    38
using namespace Windows::Foundation;
dludwig@9925
    39
using namespace Windows::Graphics::Display;
dludwig@8494
    40
using namespace Windows::UI::Core;
dludwig@9924
    41
using namespace Windows::UI::ViewManagement;
dludwig@9924
    42
dludwig@9924
    43
dludwig@9924
    44
/* [re]declare Windows GUIDs locally, to limit the amount of external lib(s) SDL has to link to */
dludwig@10293
    45
static const GUID IID_IDisplayRequest   = { 0xe5732044, 0xf49f, 0x4b60, { 0x8d, 0xd4, 0x5e, 0x7e, 0x3a, 0x63, 0x2a, 0xc0 } };
dludwig@10293
    46
static const GUID IID_IDXGIFactory2     = { 0x50c83a1c, 0xe072, 0x4c48, { 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
dludwig@8494
    47
dludwig@8494
    48
dludwig@8494
    49
/* SDL includes */
dludwig@8329
    50
extern "C" {
dludwig@8327
    51
#include "SDL_video.h"
dludwig@8327
    52
#include "SDL_mouse.h"
dludwig@8327
    53
#include "../SDL_sysvideo.h"
dludwig@8327
    54
#include "../SDL_pixels_c.h"
dludwig@8327
    55
#include "../../events/SDL_events_c.h"
dludwig@8400
    56
#include "../../render/SDL_sysrender.h"
dludwig@8411
    57
#include "SDL_syswm.h"
dludwig@8541
    58
#include "SDL_winrtopengles.h"
dludwig@9924
    59
#include "../../core/windows/SDL_windows.h"
dludwig@8329
    60
}
dludwig@8327
    61
dludwig@8522
    62
#include "../../core/winrt/SDL_winrtapp_direct3d.h"
dludwig@8522
    63
#include "../../core/winrt/SDL_winrtapp_xaml.h"
dludwig@8512
    64
#include "SDL_winrtvideo_cpp.h"
dludwig@8327
    65
#include "SDL_winrtevents_c.h"
dludwig@10222
    66
#include "SDL_winrtgamebar_cpp.h"
dludwig@8516
    67
#include "SDL_winrtmouse_c.h"
dludwig@8505
    68
#include "SDL_main.h"
dludwig@8505
    69
#include "SDL_system.h"
dludwig@8755
    70
//#include "SDL_log.h"
dludwig@8327
    71
dludwig@8327
    72
dludwig@8327
    73
/* Initialization/Query functions */
dludwig@8327
    74
static int WINRT_VideoInit(_THIS);
dludwig@8374
    75
static int WINRT_InitModes(_THIS);
dludwig@8327
    76
static int WINRT_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
dludwig@8327
    77
static void WINRT_VideoQuit(_THIS);
dludwig@8327
    78
dludwig@8494
    79
dludwig@8333
    80
/* Window functions */
dludwig@8522
    81
static int WINRT_CreateWindow(_THIS, SDL_Window * window);
dludwig@9931
    82
static void WINRT_SetWindowSize(_THIS, SDL_Window * window);
dludwig@9931
    83
static void WINRT_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
dludwig@8333
    84
static void WINRT_DestroyWindow(_THIS, SDL_Window * window);
dludwig@8411
    85
static SDL_bool WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info);
dludwig@8333
    86
dludwig@8494
    87
dludwig@10293
    88
/* Misc functions */
dludwig@10293
    89
static ABI::Windows::System::Display::IDisplayRequest * WINRT_CreateDisplayRequest(_THIS);
dludwig@10293
    90
extern void WINRT_SuspendScreenSaver(_THIS);
dludwig@10293
    91
dludwig@10293
    92
dludwig@8515
    93
/* SDL-internal globals: */
dludwig@8497
    94
SDL_Window * WINRT_GlobalSDLWindow = NULL;
dludwig@8498
    95
dludwig@8498
    96
dludwig@8327
    97
/* WinRT driver bootstrap functions */
dludwig@8327
    98
dludwig@8327
    99
static int
dludwig@8327
   100
WINRT_Available(void)
dludwig@8327
   101
{
dludwig@8328
   102
    return (1);
dludwig@8327
   103
}
dludwig@8327
   104
dludwig@8327
   105
static void
dludwig@8327
   106
WINRT_DeleteDevice(SDL_VideoDevice * device)
dludwig@8327
   107
{
dludwig@8663
   108
    if (device->driverdata) {
dludwig@8663
   109
        SDL_VideoData * video_data = (SDL_VideoData *)device->driverdata;
dludwig@8663
   110
        if (video_data->winrtEglWindow) {
dludwig@8663
   111
            video_data->winrtEglWindow->Release();
dludwig@8663
   112
        }
dludwig@8663
   113
        SDL_free(video_data);
dludwig@8663
   114
    }
dludwig@8663
   115
dludwig@8327
   116
    SDL_free(device);
dludwig@8327
   117
}
dludwig@8327
   118
dludwig@8327
   119
static SDL_VideoDevice *
dludwig@8327
   120
WINRT_CreateDevice(int devindex)
dludwig@8327
   121
{
dludwig@8327
   122
    SDL_VideoDevice *device;
dludwig@8663
   123
    SDL_VideoData *data;
dludwig@8327
   124
dludwig@8327
   125
    /* Initialize all variables that we clean on shutdown */
dludwig@8327
   126
    device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
dludwig@8327
   127
    if (!device) {
dludwig@8327
   128
        SDL_OutOfMemory();
dludwig@8327
   129
        return (0);
dludwig@8327
   130
    }
dludwig@8327
   131
dludwig@8663
   132
    data = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
dludwig@8663
   133
    if (!data) {
dludwig@8663
   134
        SDL_OutOfMemory();
philipp@10112
   135
        SDL_free(device);
dludwig@8663
   136
        return (0);
dludwig@8663
   137
    }
dludwig@8663
   138
    device->driverdata = data;
dludwig@8663
   139
dludwig@8327
   140
    /* Set the function pointers */
dludwig@8327
   141
    device->VideoInit = WINRT_VideoInit;
dludwig@8327
   142
    device->VideoQuit = WINRT_VideoQuit;
dludwig@8333
   143
    device->CreateWindow = WINRT_CreateWindow;
dludwig@9931
   144
    device->SetWindowSize = WINRT_SetWindowSize;
dludwig@9931
   145
    device->SetWindowFullscreen = WINRT_SetWindowFullscreen;
dludwig@8333
   146
    device->DestroyWindow = WINRT_DestroyWindow;
dludwig@8327
   147
    device->SetDisplayMode = WINRT_SetDisplayMode;
dludwig@8327
   148
    device->PumpEvents = WINRT_PumpEvents;
dludwig@8411
   149
    device->GetWindowWMInfo = WINRT_GetWindowWMInfo;
dludwig@10293
   150
    device->SuspendScreenSaver = WINRT_SuspendScreenSaver;
dludwig@10163
   151
dludwig@10163
   152
#if NTDDI_VERSION >= NTDDI_WIN10
dludwig@10163
   153
    device->HasScreenKeyboardSupport = WINRT_HasScreenKeyboardSupport;
dludwig@10163
   154
    device->ShowScreenKeyboard = WINRT_ShowScreenKeyboard;
dludwig@10163
   155
    device->HideScreenKeyboard = WINRT_HideScreenKeyboard;
dludwig@10163
   156
    device->IsScreenKeyboardShown = WINRT_IsScreenKeyboardShown;
dludwig@10163
   157
#endif
dludwig@10163
   158
dludwig@8541
   159
#ifdef SDL_VIDEO_OPENGL_EGL
slouken@8582
   160
    device->GL_LoadLibrary = WINRT_GLES_LoadLibrary;
slouken@8582
   161
    device->GL_GetProcAddress = WINRT_GLES_GetProcAddress;
slouken@8582
   162
    device->GL_UnloadLibrary = WINRT_GLES_UnloadLibrary;
slouken@8582
   163
    device->GL_CreateContext = WINRT_GLES_CreateContext;
slouken@8582
   164
    device->GL_MakeCurrent = WINRT_GLES_MakeCurrent;
slouken@8582
   165
    device->GL_SetSwapInterval = WINRT_GLES_SetSwapInterval;
slouken@8582
   166
    device->GL_GetSwapInterval = WINRT_GLES_GetSwapInterval;
slouken@8582
   167
    device->GL_SwapWindow = WINRT_GLES_SwapWindow;
dludwig@8541
   168
    device->GL_DeleteContext = WINRT_GLES_DeleteContext;
dludwig@8541
   169
#endif
dludwig@8433
   170
    device->free = WINRT_DeleteDevice;
dludwig@8327
   171
dludwig@8327
   172
    return device;
dludwig@8327
   173
}
dludwig@8327
   174
dludwig@8494
   175
#define WINRTVID_DRIVER_NAME "winrt"
dludwig@8327
   176
VideoBootStrap WINRT_bootstrap = {
dludwig@8500
   177
    WINRTVID_DRIVER_NAME, "SDL WinRT video driver",
dludwig@8327
   178
    WINRT_Available, WINRT_CreateDevice
dludwig@8327
   179
};
dludwig@8327
   180
dludwig@8327
   181
int
dludwig@8327
   182
WINRT_VideoInit(_THIS)
dludwig@8327
   183
{
dludwig@10293
   184
    SDL_VideoData * driverdata = (SDL_VideoData *) _this->driverdata;
dludwig@8374
   185
    if (WINRT_InitModes(_this) < 0) {
dludwig@8374
   186
        return -1;
dludwig@8374
   187
    }
dludwig@8374
   188
    WINRT_InitMouse(_this);
dludwig@8515
   189
    WINRT_InitTouch(_this);
dludwig@10222
   190
    WINRT_InitGameBar(_this);
dludwig@10293
   191
    if (driverdata) {
dludwig@10293
   192
        /* Initialize screensaver-disabling support */
dludwig@10293
   193
        driverdata->displayRequest = WINRT_CreateDisplayRequest(_this);
dludwig@10293
   194
    }
dludwig@8374
   195
    return 0;
dludwig@8374
   196
}
dludwig@8374
   197
dludwig@9924
   198
extern "C"
dludwig@9924
   199
Uint32 D3D11_DXGIFormatToSDLPixelFormat(DXGI_FORMAT dxgiFormat);
dludwig@9924
   200
dludwig@9924
   201
static void
dludwig@9924
   202
WINRT_DXGIModeToSDLDisplayMode(const DXGI_MODE_DESC * dxgiMode, SDL_DisplayMode * sdlMode)
dludwig@8522
   203
{
dludwig@9924
   204
    SDL_zerop(sdlMode);
dludwig@9924
   205
    sdlMode->w = dxgiMode->Width;
dludwig@9924
   206
    sdlMode->h = dxgiMode->Height;
dludwig@9924
   207
    sdlMode->refresh_rate = dxgiMode->RefreshRate.Numerator / dxgiMode->RefreshRate.Denominator;
dludwig@9924
   208
    sdlMode->format = D3D11_DXGIFormatToSDLPixelFormat(dxgiMode->Format);
dludwig@9924
   209
}
dludwig@8578
   210
dludwig@9924
   211
static int
dludwig@9924
   212
WINRT_AddDisplaysForOutput (_THIS, IDXGIAdapter1 * dxgiAdapter1, int outputIndex)
dludwig@9924
   213
{
dludwig@9924
   214
    HRESULT hr;
dludwig@9924
   215
    IDXGIOutput * dxgiOutput = NULL;
dludwig@9924
   216
    DXGI_OUTPUT_DESC dxgiOutputDesc;
dludwig@9924
   217
    SDL_VideoDisplay display;
dludwig@9924
   218
    char * displayName = NULL;
dludwig@9924
   219
    UINT numModes;
dludwig@9924
   220
    DXGI_MODE_DESC * dxgiModes = NULL;
dludwig@9924
   221
    int functionResult = -1;        /* -1 for failure, 0 for success */
dludwig@9924
   222
    DXGI_MODE_DESC modeToMatch, closestMatch;
dludwig@8522
   223
dludwig@9924
   224
    SDL_zero(display);
dludwig@9924
   225
dludwig@9924
   226
    hr = dxgiAdapter1->EnumOutputs(outputIndex, &dxgiOutput);
dludwig@9924
   227
    if (FAILED(hr)) {
dludwig@9924
   228
        if (hr != DXGI_ERROR_NOT_FOUND) {
dludwig@9924
   229
            WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIAdapter1::EnumOutputs failed", hr);
dludwig@9924
   230
        }
dludwig@9924
   231
        goto done;
dludwig@8522
   232
    }
dludwig@8522
   233
dludwig@9924
   234
    hr = dxgiOutput->GetDesc(&dxgiOutputDesc);
dludwig@9924
   235
    if (FAILED(hr)) {
dludwig@9924
   236
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDesc failed", hr);
dludwig@9924
   237
        goto done;
dludwig@8579
   238
    }
dludwig@8579
   239
dludwig@9924
   240
    SDL_zero(modeToMatch);
dludwig@9924
   241
    modeToMatch.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
dludwig@9924
   242
    modeToMatch.Width = (dxgiOutputDesc.DesktopCoordinates.right - dxgiOutputDesc.DesktopCoordinates.left);
dludwig@9924
   243
    modeToMatch.Height = (dxgiOutputDesc.DesktopCoordinates.bottom - dxgiOutputDesc.DesktopCoordinates.top);
dludwig@9924
   244
    hr = dxgiOutput->FindClosestMatchingMode(&modeToMatch, &closestMatch, NULL);
dludwig@9924
   245
    if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
dludwig@9924
   246
        /* DXGI_ERROR_NOT_CURRENTLY_AVAILABLE gets returned by IDXGIOutput::FindClosestMatchingMode
dludwig@9924
   247
           when running under the Windows Simulator, which uses Remote Desktop (formerly known as Terminal
dludwig@9924
   248
           Services) under the hood.  According to the MSDN docs for the similar function,
dludwig@9924
   249
           IDXGIOutput::GetDisplayModeList, DXGI_ERROR_NOT_CURRENTLY_AVAILABLE is returned if and
dludwig@9924
   250
           when an app is run under a Terminal Services session, hence the assumption.
dludwig@9924
   251
dludwig@9924
   252
           In this case, just add an SDL display mode, with approximated values.
dludwig@9924
   253
        */
dludwig@9924
   254
        SDL_DisplayMode mode;
dludwig@9924
   255
        SDL_zero(mode);
dludwig@9924
   256
        display.name = "Windows Simulator / Terminal Services Display";
dludwig@9924
   257
        mode.w = (dxgiOutputDesc.DesktopCoordinates.right - dxgiOutputDesc.DesktopCoordinates.left);
dludwig@9924
   258
        mode.h = (dxgiOutputDesc.DesktopCoordinates.bottom - dxgiOutputDesc.DesktopCoordinates.top);
dludwig@9924
   259
        mode.format = DXGI_FORMAT_B8G8R8A8_UNORM;
dludwig@9924
   260
        mode.refresh_rate = 0;  /* Display mode is unknown, so just fill in zero, as specified by SDL's header files */
dludwig@9924
   261
        display.desktop_mode = mode;
dludwig@9924
   262
        display.current_mode = mode;
dludwig@9924
   263
        if ( ! SDL_AddDisplayMode(&display, &mode)) {
dludwig@9924
   264
            goto done;
dludwig@9924
   265
        }
dludwig@9924
   266
    } else if (FAILED(hr)) {
dludwig@9924
   267
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::FindClosestMatchingMode failed", hr);
dludwig@9924
   268
        goto done;
dludwig@9924
   269
    } else {
dludwig@9924
   270
        displayName = WIN_StringToUTF8(dxgiOutputDesc.DeviceName);
dludwig@9924
   271
        display.name = displayName;
dludwig@9924
   272
        WINRT_DXGIModeToSDLDisplayMode(&closestMatch, &display.desktop_mode);
dludwig@9924
   273
        display.current_mode = display.desktop_mode;
dludwig@9924
   274
dludwig@9924
   275
        hr = dxgiOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &numModes, NULL);
dludwig@9924
   276
        if (FAILED(hr)) {
dludwig@9924
   277
            if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) {
dludwig@9924
   278
                // TODO, WinRT: make sure display mode(s) are added when using Terminal Services / Windows Simulator
dludwig@9924
   279
            }
dludwig@9924
   280
            WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDisplayModeList [get mode list size] failed", hr);
dludwig@9924
   281
            goto done;
dludwig@9924
   282
        }
dludwig@8578
   283
dludwig@9924
   284
        dxgiModes = (DXGI_MODE_DESC *)SDL_calloc(numModes, sizeof(DXGI_MODE_DESC));
dludwig@9924
   285
        if ( ! dxgiModes) {
dludwig@9924
   286
            SDL_OutOfMemory();
dludwig@9924
   287
            goto done;
dludwig@9924
   288
        }
dludwig@9924
   289
dludwig@9924
   290
        hr = dxgiOutput->GetDisplayModeList(DXGI_FORMAT_B8G8R8A8_UNORM, 0, &numModes, dxgiModes);
dludwig@9924
   291
        if (FAILED(hr)) {
dludwig@9924
   292
            WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIOutput::GetDisplayModeList [get mode contents] failed", hr);
dludwig@9924
   293
            goto done;
dludwig@9924
   294
        }
dludwig@9924
   295
dludwig@9924
   296
        for (UINT i = 0; i < numModes; ++i) {
dludwig@9924
   297
            SDL_DisplayMode sdlMode;
dludwig@9924
   298
            WINRT_DXGIModeToSDLDisplayMode(&dxgiModes[i], &sdlMode);
dludwig@9924
   299
            SDL_AddDisplayMode(&display, &sdlMode);
dludwig@9924
   300
        }
dludwig@9924
   301
    }
dludwig@9924
   302
dludwig@9924
   303
    if (SDL_AddVideoDisplay(&display) < 0) {
dludwig@9924
   304
        goto done;
dludwig@9924
   305
    }
dludwig@8522
   306
dludwig@9924
   307
    functionResult = 0;     /* 0 for Success! */
dludwig@9924
   308
done:
dludwig@9924
   309
    if (dxgiModes) {
dludwig@9924
   310
        SDL_free(dxgiModes);
dludwig@9924
   311
    }
dludwig@9924
   312
    if (dxgiOutput) {
dludwig@9924
   313
        dxgiOutput->Release();
dludwig@9924
   314
    }
dludwig@9924
   315
    if (displayName) {
dludwig@9924
   316
        SDL_free(displayName);
dludwig@9924
   317
    }
dludwig@9924
   318
    return functionResult;
dludwig@9924
   319
}
dludwig@9924
   320
dludwig@9924
   321
static int
dludwig@9924
   322
WINRT_AddDisplaysForAdapter (_THIS, IDXGIFactory2 * dxgiFactory2, int adapterIndex)
dludwig@9924
   323
{
dludwig@9924
   324
    HRESULT hr;
dludwig@9924
   325
    IDXGIAdapter1 * dxgiAdapter1;
dludwig@9924
   326
dludwig@9924
   327
    hr = dxgiFactory2->EnumAdapters1(adapterIndex, &dxgiAdapter1);
dludwig@9924
   328
    if (FAILED(hr)) {
dludwig@9924
   329
        if (hr != DXGI_ERROR_NOT_FOUND) {
dludwig@9924
   330
            WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIFactory1::EnumAdapters1() failed", hr);
dludwig@9924
   331
        }
dludwig@9924
   332
        return -1;
dludwig@9924
   333
    }
dludwig@9924
   334
dludwig@9924
   335
    for (int outputIndex = 0; ; ++outputIndex) {
dludwig@9924
   336
        if (WINRT_AddDisplaysForOutput(_this, dxgiAdapter1, outputIndex) < 0) {
dludwig@9947
   337
            /* HACK: The Windows App Certification Kit 10.0 can fail, when
dludwig@9947
   338
               running the Store Apps' test, "Direct3D Feature Test".  The
dludwig@9947
   339
               certification kit's error is:
dludwig@9947
   340
dludwig@9947
   341
               "Application App was not running at the end of the test. It likely crashed or was terminated for having become unresponsive."
dludwig@9947
   342
dludwig@9947
   343
               This was caused by SDL/WinRT's DXGI failing to report any
dludwig@9947
   344
               outputs.  Attempts to get the 1st display-output from the
dludwig@9947
   345
               1st display-adapter can fail, with IDXGIAdapter::EnumOutputs
dludwig@9947
   346
               returning DXGI_ERROR_NOT_FOUND.  This could be a bug in Windows,
dludwig@9947
   347
               the Windows App Certification Kit, or possibly in SDL/WinRT's
dludwig@9947
   348
               display detection code.  Either way, try to detect when this
dludwig@9947
   349
               happens, and use a hackish means to create a reasonable-as-possible
dludwig@9947
   350
               'display mode'.  -- DavidL
dludwig@9947
   351
            */
dludwig@9947
   352
            if (adapterIndex == 0 && outputIndex == 0) {
dludwig@9947
   353
                SDL_VideoDisplay display;
dludwig@9947
   354
                SDL_DisplayMode mode;
dludwig@9952
   355
#if SDL_WINRT_USE_APPLICATIONVIEW
dludwig@9947
   356
                ApplicationView ^ appView = ApplicationView::GetForCurrentView();
dludwig@9952
   357
#endif
dludwig@9950
   358
                CoreWindow ^ coreWin = CoreWindow::GetForCurrentThread();
dludwig@9947
   359
                SDL_zero(display);
dludwig@9947
   360
                SDL_zero(mode);
dludwig@9947
   361
                display.name = "DXGI Display-detection Workaround";
dludwig@9947
   362
dludwig@9947
   363
                /* HACK: ApplicationView's VisibleBounds property, appeared, via testing, to
dludwig@9947
   364
                   give a better approximation of display-size, than did CoreWindow's
dludwig@9947
   365
                   Bounds property, insofar that ApplicationView::VisibleBounds seems like
dludwig@9947
   366
                   it will, at least some of the time, give the full display size (during the
dludwig@9950
   367
                   failing test), whereas CoreWindow might not.  -- DavidL
dludwig@9947
   368
                */
dludwig@9950
   369
dludwig@9952
   370
#if (NTDDI_VERSION >= NTDDI_WIN10) || (SDL_WINRT_USE_APPLICATIONVIEW && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
dludwig@9947
   371
                mode.w = WINRT_DIPS_TO_PHYSICAL_PIXELS(appView->VisibleBounds.Width);
dludwig@9947
   372
                mode.h = WINRT_DIPS_TO_PHYSICAL_PIXELS(appView->VisibleBounds.Height);
dludwig@9950
   373
#else
dludwig@9950
   374
                /* On platform(s) that do not support VisibleBounds, such as Windows 8.1,
dludwig@9950
   375
                   fall back to CoreWindow's Bounds property.
dludwig@9950
   376
                */
dludwig@9950
   377
                mode.w = WINRT_DIPS_TO_PHYSICAL_PIXELS(coreWin->Bounds.Width);
dludwig@9950
   378
                mode.h = WINRT_DIPS_TO_PHYSICAL_PIXELS(coreWin->Bounds.Height);
dludwig@9950
   379
#endif
dludwig@9947
   380
dludwig@9947
   381
                mode.format = DXGI_FORMAT_B8G8R8A8_UNORM;
dludwig@9947
   382
                mode.refresh_rate = 0;  /* Display mode is unknown, so just fill in zero, as specified by SDL's header files */
dludwig@9947
   383
                display.desktop_mode = mode;
dludwig@9947
   384
                display.current_mode = mode;
dludwig@9947
   385
                if ((SDL_AddDisplayMode(&display, &mode) < 0) ||
dludwig@9947
   386
                    (SDL_AddVideoDisplay(&display) < 0))
dludwig@9947
   387
                {
dludwig@9947
   388
                    return SDL_SetError("Failed to apply DXGI Display-detection workaround");
dludwig@9947
   389
                }
dludwig@9947
   390
            }
dludwig@9947
   391
dludwig@8522
   392
            break;
dludwig@8522
   393
        }
dludwig@8522
   394
    }
dludwig@8578
   395
dludwig@9924
   396
    dxgiAdapter1->Release();
dludwig@8578
   397
    return 0;
dludwig@8522
   398
}
dludwig@8503
   399
dludwig@8505
   400
int
dludwig@8374
   401
WINRT_InitModes(_THIS)
dludwig@8374
   402
{
dludwig@9924
   403
    /* HACK: Initialize a single display, for whatever screen the app's
dludwig@9924
   404
         CoreApplicationView is on.
dludwig@9924
   405
       TODO, WinRT: Try initializing multiple displays, one for each monitor.
dludwig@9924
   406
         Appropriate WinRT APIs for this seem elusive, though.  -- DavidL
dludwig@9924
   407
    */
dludwig@8522
   408
dludwig@9924
   409
    HRESULT hr;
dludwig@9924
   410
    IDXGIFactory2 * dxgiFactory2 = NULL;
dludwig@9924
   411
dludwig@9924
   412
    hr = CreateDXGIFactory1(IID_IDXGIFactory2, (void **)&dxgiFactory2);
dludwig@9924
   413
    if (FAILED(hr)) {
dludwig@9924
   414
        WIN_SetErrorFromHRESULT(__FUNCTION__ ", CreateDXGIFactory1() failed", hr);
dludwig@8522
   415
        return -1;
dludwig@8374
   416
    }
dludwig@8374
   417
dludwig@9924
   418
    for (int adapterIndex = 0; ; ++adapterIndex) {
dludwig@9924
   419
        if (WINRT_AddDisplaysForAdapter(_this, dxgiFactory2, adapterIndex) < 0) {
dludwig@9924
   420
            break;
dludwig@9924
   421
        }
dludwig@9924
   422
    }
dludwig@9924
   423
dludwig@8327
   424
    return 0;
dludwig@8327
   425
}
dludwig@8327
   426
dludwig@8327
   427
static int
dludwig@8327
   428
WINRT_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
dludwig@8327
   429
{
dludwig@8327
   430
    return 0;
dludwig@8327
   431
}
dludwig@8327
   432
dludwig@8327
   433
void
dludwig@8327
   434
WINRT_VideoQuit(_THIS)
dludwig@8327
   435
{
dludwig@10293
   436
    SDL_VideoData * driverdata = (SDL_VideoData *) _this->driverdata;
dludwig@10293
   437
    if (driverdata && driverdata->displayRequest) {
dludwig@10293
   438
        driverdata->displayRequest->Release();
dludwig@10293
   439
        driverdata->displayRequest = NULL;
dludwig@10293
   440
    }
dludwig@10222
   441
    WINRT_QuitGameBar(_this);
dludwig@8374
   442
    WINRT_QuitMouse(_this);
dludwig@8327
   443
}
dludwig@8327
   444
dludwig@9926
   445
static const Uint32 WINRT_DetectableFlags =
dludwig@9926
   446
    SDL_WINDOW_MAXIMIZED |
dludwig@9926
   447
    SDL_WINDOW_FULLSCREEN_DESKTOP |
dludwig@9926
   448
    SDL_WINDOW_SHOWN |
dludwig@9926
   449
    SDL_WINDOW_HIDDEN |
dludwig@9926
   450
    SDL_WINDOW_MOUSE_FOCUS;
dludwig@9926
   451
dludwig@9924
   452
extern "C" Uint32
dludwig@9924
   453
WINRT_DetectWindowFlags(SDL_Window * window)
dludwig@9924
   454
{
dludwig@9924
   455
    Uint32 latestFlags = 0;
dludwig@9924
   456
    SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
dludwig@9924
   457
    bool is_fullscreen = false;
dludwig@9924
   458
dludwig@9924
   459
#if SDL_WINRT_USE_APPLICATIONVIEW
dludwig@9924
   460
    if (data->appView) {
dludwig@9924
   461
        is_fullscreen = data->appView->IsFullScreen;
dludwig@9924
   462
    }
dludwig@9927
   463
#elif (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION == NTDDI_WIN8)
dludwig@9924
   464
    is_fullscreen = true;
dludwig@9924
   465
#endif
dludwig@9924
   466
dludwig@9924
   467
    if (data->coreWindow.Get()) {
dludwig@9924
   468
        if (is_fullscreen) {
dludwig@9924
   469
            SDL_VideoDisplay * display = SDL_GetDisplayForWindow(window);
dludwig@9925
   470
            int w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
dludwig@9925
   471
            int h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
dludwig@9925
   472
dludwig@9925
   473
#if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION > NTDDI_WIN8)
dludwig@9925
   474
            // On all WinRT platforms, except for WinPhone 8.0, rotate the
dludwig@9925
   475
            // window size.  This is needed to properly calculate
dludwig@9925
   476
            // fullscreen vs. maximized.
dludwig@9925
   477
            const DisplayOrientations currentOrientation = WINRT_DISPLAY_PROPERTY(CurrentOrientation);
dludwig@9925
   478
            switch (currentOrientation) {
dludwig@9925
   479
#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
dludwig@9925
   480
                case DisplayOrientations::Landscape:
dludwig@9925
   481
                case DisplayOrientations::LandscapeFlipped:
dludwig@9925
   482
#else
dludwig@9925
   483
                case DisplayOrientations::Portrait:
dludwig@9925
   484
                case DisplayOrientations::PortraitFlipped:
dludwig@9925
   485
#endif
dludwig@9925
   486
                {
dludwig@9925
   487
                    int tmp = w;
dludwig@9925
   488
                    w = h;
dludwig@9925
   489
                    h = tmp;
dludwig@9925
   490
                } break;
dludwig@9925
   491
            }
dludwig@9925
   492
#endif
dludwig@9925
   493
dludwig@9925
   494
            if (display->desktop_mode.w != w || display->desktop_mode.h != h) {
dludwig@9924
   495
                latestFlags |= SDL_WINDOW_MAXIMIZED;
dludwig@9924
   496
            } else {
dludwig@9924
   497
                latestFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
dludwig@9924
   498
            }
dludwig@9924
   499
        }
dludwig@9924
   500
dludwig@9924
   501
        if (data->coreWindow->Visible) {
dludwig@9924
   502
            latestFlags |= SDL_WINDOW_SHOWN;
dludwig@9924
   503
        } else {
dludwig@9924
   504
            latestFlags |= SDL_WINDOW_HIDDEN;
dludwig@9924
   505
        }
dludwig@9924
   506
dludwig@9924
   507
#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) && (NTDDI_VERSION < NTDDI_WINBLUE)
dludwig@9924
   508
        // data->coreWindow->PointerPosition is not supported on WinPhone 8.0
dludwig@9924
   509
        latestFlags |= SDL_WINDOW_MOUSE_FOCUS;
dludwig@9924
   510
#else
dludwig@10293
   511
        if (data->coreWindow->Visible && data->coreWindow->Bounds.Contains(data->coreWindow->PointerPosition)) {
dludwig@9924
   512
            latestFlags |= SDL_WINDOW_MOUSE_FOCUS;
dludwig@9924
   513
        }
dludwig@9924
   514
#endif
dludwig@9924
   515
    }
dludwig@9924
   516
dludwig@9924
   517
    return latestFlags;
dludwig@9924
   518
}
dludwig@9924
   519
dludwig@9993
   520
// TODO, WinRT: consider removing WINRT_UpdateWindowFlags, and just calling WINRT_DetectWindowFlags as-appropriate (with appropriate calls to SDL_SendWindowEvent)
dludwig@9924
   521
void
dludwig@9924
   522
WINRT_UpdateWindowFlags(SDL_Window * window, Uint32 mask)
dludwig@9924
   523
{
dludwig@9926
   524
    mask &= WINRT_DetectableFlags;
dludwig@9924
   525
    if (window) {
dludwig@9924
   526
        Uint32 apply = WINRT_DetectWindowFlags(window);
dludwig@9924
   527
        if ((apply & mask) & SDL_WINDOW_FULLSCREEN) {
dludwig@9924
   528
            window->last_fullscreen_flags = window->flags;  // seems necessary to programmatically un-fullscreen, via SDL APIs
dludwig@9924
   529
        }
dludwig@9924
   530
        window->flags = (window->flags & ~mask) | (apply & mask);
dludwig@9924
   531
    }
dludwig@9924
   532
}
dludwig@9924
   533
dludwig@9964
   534
static bool
dludwig@9964
   535
WINRT_IsCoreWindowActive(CoreWindow ^ coreWindow)
dludwig@9964
   536
{
dludwig@9964
   537
    /* WinRT does not appear to offer API(s) to determine window-activation state,
dludwig@9964
   538
       at least not that I am aware of in Win8 - Win10.  As such, SDL tracks this
dludwig@9964
   539
       itself, via window-activation events.
dludwig@9964
   540
       
dludwig@9964
   541
       If there *is* an API to track this, it should probably get used instead
dludwig@9964
   542
       of the following hack (that uses "SDLHelperWindowActivationState").
dludwig@9964
   543
         -- DavidL.
dludwig@9964
   544
    */
dludwig@9964
   545
    if (coreWindow->CustomProperties->HasKey("SDLHelperWindowActivationState")) {
dludwig@9964
   546
        CoreWindowActivationState activationState = \
dludwig@9964
   547
            safe_cast<CoreWindowActivationState>(coreWindow->CustomProperties->Lookup("SDLHelperWindowActivationState"));
dludwig@9964
   548
        return (activationState != CoreWindowActivationState::Deactivated);
dludwig@9964
   549
    }
dludwig@9964
   550
dludwig@9964
   551
    /* Assume that non-SDL tracked windows are active, although this should
dludwig@9964
   552
       probably be avoided, if possible.
dludwig@9964
   553
       
dludwig@9964
   554
       This might not even be possible, in normal SDL use, at least as of
dludwig@9964
   555
       this writing (Dec 22, 2015; via latest hg.libsdl.org/SDL clone)  -- DavidL
dludwig@9964
   556
    */
dludwig@9964
   557
    return true;
dludwig@9964
   558
}
dludwig@9964
   559
dludwig@8522
   560
int
dludwig@8522
   561
WINRT_CreateWindow(_THIS, SDL_Window * window)
dludwig@8522
   562
{
dludwig@8522
   563
    // Make sure that only one window gets created, at least until multimonitor
dludwig@8522
   564
    // support is added.
dludwig@8522
   565
    if (WINRT_GlobalSDLWindow != NULL) {
dludwig@8522
   566
        SDL_SetError("WinRT only supports one window");
dludwig@8522
   567
        return -1;
dludwig@8522
   568
    }
dludwig@8522
   569
dludwig@9924
   570
    SDL_WindowData *data = new SDL_WindowData;  /* use 'new' here as SDL_WindowData may use WinRT/C++ types */
dludwig@8522
   571
    if (!data) {
dludwig@8522
   572
        SDL_OutOfMemory();
dludwig@8522
   573
        return -1;
dludwig@8522
   574
    }
dludwig@8522
   575
    window->driverdata = data;
dludwig@8522
   576
    data->sdlWindow = window;
dludwig@8522
   577
dludwig@8522
   578
    /* To note, when XAML support is enabled, access to the CoreWindow will not
dludwig@8522
   579
       be possible, at least not via the SDL/XAML thread.  Attempts to access it
dludwig@8522
   580
       from there will throw exceptions.  As such, the SDL_WindowData's
dludwig@8522
   581
       'coreWindow' field will only be set (to a non-null value) if XAML isn't
dludwig@8522
   582
       enabled.
dludwig@8522
   583
    */
dludwig@8522
   584
    if (!WINRT_XAMLWasEnabled) {
dludwig@8522
   585
        data->coreWindow = CoreWindow::GetForCurrentThread();
dludwig@9924
   586
#if SDL_WINRT_USE_APPLICATIONVIEW
dludwig@9924
   587
        data->appView = ApplicationView::GetForCurrentView();
dludwig@9924
   588
#endif
dludwig@8522
   589
    }
dludwig@8522
   590
dludwig@9931
   591
    /* Make note of the requested window flags, before they start getting changed. */
dludwig@9931
   592
    const Uint32 requestedFlags = window->flags;
dludwig@9931
   593
dludwig@8541
   594
#if SDL_VIDEO_OPENGL_EGL
dludwig@8541
   595
    /* Setup the EGL surface, but only if OpenGL ES 2 was requested. */
dludwig@8541
   596
    if (!(window->flags & SDL_WINDOW_OPENGL)) {
dludwig@8541
   597
        /* OpenGL ES 2 wasn't requested.  Don't set up an EGL surface. */
dludwig@8541
   598
        data->egl_surface = EGL_NO_SURFACE;
dludwig@8541
   599
    } else {
dludwig@8541
   600
        /* OpenGL ES 2 was reuqested.  Set up an EGL surface. */
dludwig@8663
   601
        SDL_VideoData * video_data = (SDL_VideoData *)_this->driverdata;
dludwig@8572
   602
dludwig@8663
   603
        /* Call SDL_EGL_ChooseConfig and eglCreateWindowSurface directly,
dludwig@9212
   604
         * rather than via SDL_EGL_CreateSurface, as older versions of
dludwig@9212
   605
         * ANGLE/WinRT may require that a C++ object, ComPtr<IUnknown>,
dludwig@9212
   606
         * be passed into eglCreateWindowSurface.
dludwig@8572
   607
         */
dludwig@8663
   608
        if (SDL_EGL_ChooseConfig(_this) != 0) {
dludwig@8663
   609
            char buf[512];
dludwig@8663
   610
            SDL_snprintf(buf, sizeof(buf), "SDL_EGL_ChooseConfig failed: %s", SDL_GetError());
philipp@9557
   611
            return SDL_SetError("%s", buf);
dludwig@8663
   612
        }
dludwig@8572
   613
dludwig@9211
   614
        if (video_data->winrtEglWindow) {   /* ... is the 'old' version of ANGLE/WinRT being used? */
dludwig@9211
   615
            /* Attempt to create a window surface using older versions of
dludwig@9211
   616
             * ANGLE/WinRT:
dludwig@9211
   617
             */
dludwig@9211
   618
            Microsoft::WRL::ComPtr<IUnknown> cpp_winrtEglWindow = video_data->winrtEglWindow;
dludwig@9211
   619
            data->egl_surface = ((eglCreateWindowSurface_Old_Function)_this->egl_data->eglCreateWindowSurface)(
dludwig@9211
   620
                _this->egl_data->egl_display,
dludwig@9211
   621
                _this->egl_data->egl_config,
dludwig@9211
   622
                cpp_winrtEglWindow, NULL);
dludwig@9211
   623
            if (data->egl_surface == NULL) {
dludwig@10740
   624
                return SDL_EGL_SetError("unable to create EGL native-window surface", "eglCreateWindowSurface");
dludwig@9211
   625
            }
dludwig@9211
   626
        } else if (data->coreWindow.Get() != nullptr) {
dludwig@9211
   627
            /* Attempt to create a window surface using newer versions of
dludwig@9211
   628
             * ANGLE/WinRT:
dludwig@9211
   629
             */
dludwig@9211
   630
            IInspectable * coreWindowAsIInspectable = reinterpret_cast<IInspectable *>(data->coreWindow.Get());
dludwig@9211
   631
            data->egl_surface = _this->egl_data->eglCreateWindowSurface(
dludwig@9211
   632
                _this->egl_data->egl_display,
dludwig@9211
   633
                _this->egl_data->egl_config,
dludwig@9211
   634
                coreWindowAsIInspectable,
dludwig@9211
   635
                NULL);
dludwig@9211
   636
            if (data->egl_surface == NULL) {
dludwig@10740
   637
                return SDL_EGL_SetError("unable to create EGL native-window surface", "eglCreateWindowSurface");
dludwig@9211
   638
            }
dludwig@9211
   639
        } else {
dludwig@9211
   640
            return SDL_SetError("No supported means to create an EGL window surface are available");
dludwig@8541
   641
        }
dludwig@8541
   642
    }
dludwig@8541
   643
#endif
dludwig@8541
   644
dludwig@9924
   645
    /* Determine as many flags dynamically, as possible. */
dludwig@8522
   646
    window->flags =
dludwig@9928
   647
        SDL_WINDOW_BORDERLESS |
dludwig@9928
   648
        SDL_WINDOW_RESIZABLE;
dludwig@8522
   649
dludwig@8541
   650
#if SDL_VIDEO_OPENGL_EGL
dludwig@8541
   651
    if (data->egl_surface) {
dludwig@8541
   652
        window->flags |= SDL_WINDOW_OPENGL;
dludwig@8541
   653
    }
dludwig@8541
   654
#endif
dludwig@8541
   655
dludwig@9924
   656
    if (WINRT_XAMLWasEnabled) {
dludwig@9924
   657
        /* TODO, WinRT: set SDL_Window size, maybe position too, from XAML control */
dludwig@9924
   658
        window->x = 0;
dludwig@9924
   659
        window->y = 0;
dludwig@9924
   660
        window->flags |= SDL_WINDOW_SHOWN;
dludwig@9924
   661
        SDL_SetMouseFocus(NULL);        // TODO: detect this
dludwig@9924
   662
        SDL_SetKeyboardFocus(NULL);     // TODO: detect this
dludwig@9924
   663
    } else {
dludwig@9931
   664
        /* WinRT 8.x apps seem to live in an environment where the OS controls the
dludwig@9924
   665
           app's window size, with some apps being fullscreen, depending on
dludwig@9924
   666
           user choice of various things.  For now, just adapt the SDL_Window to
dludwig@9924
   667
           whatever Windows set-up as the native-window's geometry.
dludwig@9924
   668
        */
dludwig@9924
   669
        window->x = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Left);
dludwig@9924
   670
        window->y = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Top);
dludwig@9931
   671
#if NTDDI_VERSION < NTDDI_WIN10
dludwig@9931
   672
        /* On WinRT 8.x / pre-Win10, just use the size we were given. */
dludwig@9924
   673
        window->w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
dludwig@9924
   674
        window->h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
dludwig@9931
   675
#else
dludwig@9931
   676
        /* On Windows 10, we occasionally get control over window size.  For windowed
dludwig@9931
   677
           mode apps, try this.
dludwig@9931
   678
        */
dludwig@9931
   679
        bool didSetSize = false;
dludwig@9931
   680
        if (!(requestedFlags & SDL_WINDOW_FULLSCREEN)) {
dludwig@9931
   681
            const Windows::Foundation::Size size(WINRT_PHYSICAL_PIXELS_TO_DIPS(window->w),
dludwig@9931
   682
                                                 WINRT_PHYSICAL_PIXELS_TO_DIPS(window->h));
dludwig@9931
   683
            didSetSize = data->appView->TryResizeView(size);
dludwig@9931
   684
        }
dludwig@9931
   685
        if (!didSetSize) {
dludwig@9931
   686
            /* We either weren't able to set the window size, or a request for
dludwig@9931
   687
               fullscreen was made.  Get window-size info from the OS.
dludwig@9931
   688
            */
dludwig@9931
   689
            window->w = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Width);
dludwig@9931
   690
            window->h = WINRT_DIPS_TO_PHYSICAL_PIXELS(data->coreWindow->Bounds.Height);
dludwig@9931
   691
        }
dludwig@9931
   692
#endif
dludwig@8522
   693
dludwig@9924
   694
        WINRT_UpdateWindowFlags(
dludwig@9924
   695
            window,
dludwig@9924
   696
            0xffffffff      /* Update any window flag(s) that WINRT_UpdateWindow can handle */
dludwig@9924
   697
        );
dludwig@8551
   698
dludwig@9924
   699
        /* Try detecting if the window is active */
dludwig@9964
   700
        bool isWindowActive = WINRT_IsCoreWindowActive(data->coreWindow.Get());
dludwig@9924
   701
        if (isWindowActive) {
dludwig@9924
   702
            SDL_SetKeyboardFocus(window);
dludwig@9924
   703
        }
dludwig@9924
   704
    }
dludwig@8522
   705
 
dludwig@8522
   706
    /* Make sure the WinRT app's IFramworkView can post events on
dludwig@8522
   707
       behalf of SDL:
dludwig@8522
   708
    */
dludwig@8522
   709
    WINRT_GlobalSDLWindow = window;
dludwig@8522
   710
dludwig@8522
   711
    /* All done! */
dludwig@8522
   712
    return 0;
dludwig@8522
   713
}
dludwig@8522
   714
dludwig@8333
   715
void
dludwig@9931
   716
WINRT_SetWindowSize(_THIS, SDL_Window * window)
dludwig@9931
   717
{
dludwig@9931
   718
#if NTDDI_VERSION >= NTDDI_WIN10
dludwig@9931
   719
    SDL_WindowData * data = (SDL_WindowData *)window->driverdata;
dludwig@9931
   720
    const Windows::Foundation::Size size(WINRT_PHYSICAL_PIXELS_TO_DIPS(window->w),
dludwig@9931
   721
                                         WINRT_PHYSICAL_PIXELS_TO_DIPS(window->h));
dludwig@9931
   722
    data->appView->TryResizeView(size); // TODO, WinRT: return failure (to caller?) from TryResizeView()
dludwig@9931
   723
#endif
dludwig@9931
   724
}
dludwig@9931
   725
dludwig@9931
   726
void
dludwig@9931
   727
WINRT_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
dludwig@9931
   728
{
dludwig@9931
   729
#if NTDDI_VERSION >= NTDDI_WIN10
dludwig@9931
   730
    SDL_WindowData * data = (SDL_WindowData *)window->driverdata;
dludwig@9964
   731
    bool isWindowActive = WINRT_IsCoreWindowActive(data->coreWindow.Get());
dludwig@9964
   732
    if (isWindowActive) {
dludwig@9964
   733
        if (fullscreen) {
dludwig@9964
   734
            if (!data->appView->IsFullScreenMode) {
dludwig@9964
   735
                data->appView->TryEnterFullScreenMode();    // TODO, WinRT: return failure (to caller?) from TryEnterFullScreenMode()
dludwig@9964
   736
            }
dludwig@9964
   737
        } else {
dludwig@9964
   738
            if (data->appView->IsFullScreenMode) {
dludwig@9964
   739
                data->appView->ExitFullScreenMode();
dludwig@9964
   740
            }
dludwig@9931
   741
        }
dludwig@9931
   742
    }
dludwig@9931
   743
#endif
dludwig@9931
   744
}
dludwig@9931
   745
dludwig@9931
   746
dludwig@9931
   747
void
dludwig@8333
   748
WINRT_DestroyWindow(_THIS, SDL_Window * window)
dludwig@8333
   749
{
dludwig@8411
   750
    SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
dludwig@8411
   751
dludwig@8497
   752
    if (WINRT_GlobalSDLWindow == window) {
dludwig@8497
   753
        WINRT_GlobalSDLWindow = NULL;
dludwig@8424
   754
    }
dludwig@8424
   755
dludwig@8411
   756
    if (data) {
dludwig@8411
   757
        // Delete the internal window data:
dludwig@8411
   758
        delete data;
dludwig@8411
   759
        data = NULL;
dludwig@9214
   760
        window->driverdata = NULL;
dludwig@8411
   761
    }
dludwig@8333
   762
}
dludwig@8333
   763
dludwig@8522
   764
SDL_bool
dludwig@8522
   765
WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
dludwig@8522
   766
{
dludwig@8522
   767
    SDL_WindowData * data = (SDL_WindowData *) window->driverdata;
dludwig@8522
   768
dludwig@8522
   769
    if (info->version.major <= SDL_MAJOR_VERSION) {
dludwig@8522
   770
        info->subsystem = SDL_SYSWM_WINRT;
dludwig@8527
   771
        info->info.winrt.window = reinterpret_cast<IInspectable *>(data->coreWindow.Get());
dludwig@8522
   772
        return SDL_TRUE;
dludwig@8522
   773
    } else {
dludwig@8522
   774
        SDL_SetError("Application not compiled with SDL %d.%d\n",
dludwig@8522
   775
                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
dludwig@8522
   776
        return SDL_FALSE;
dludwig@8522
   777
    }
dludwig@8522
   778
    return SDL_FALSE;
dludwig@8411
   779
}
dludwig@8333
   780
dludwig@10293
   781
static ABI::Windows::System::Display::IDisplayRequest *
dludwig@10293
   782
WINRT_CreateDisplayRequest(_THIS)
dludwig@10293
   783
{
dludwig@10293
   784
    /* Setup a WinRT DisplayRequest object, usable for enabling/disabling screensaver requests */
dludwig@10293
   785
    wchar_t *wClassName = L"Windows.System.Display.DisplayRequest";
dludwig@10293
   786
    HSTRING hClassName;
dludwig@10293
   787
    IActivationFactory *pActivationFactory = NULL;
dludwig@10293
   788
    IInspectable * pDisplayRequestRaw = nullptr;
dludwig@10293
   789
    ABI::Windows::System::Display::IDisplayRequest * pDisplayRequest = nullptr;
dludwig@10293
   790
    HRESULT hr;
dludwig@10293
   791
dludwig@10293
   792
    hr = ::WindowsCreateString(wClassName, (UINT32)wcslen(wClassName), &hClassName);
dludwig@10293
   793
    if (FAILED(hr)) {
dludwig@10293
   794
        goto done;
dludwig@10293
   795
    }
dludwig@10293
   796
dludwig@10293
   797
    hr = Windows::Foundation::GetActivationFactory(hClassName, &pActivationFactory);
dludwig@10293
   798
    if (FAILED(hr)) {
dludwig@10293
   799
        goto done;
dludwig@10293
   800
    }
dludwig@10293
   801
dludwig@10293
   802
    hr = pActivationFactory->ActivateInstance(&pDisplayRequestRaw);
dludwig@10293
   803
    if (FAILED(hr)) {
dludwig@10293
   804
        goto done;
dludwig@10293
   805
    }
dludwig@10293
   806
dludwig@10293
   807
    hr = pDisplayRequestRaw->QueryInterface(IID_IDisplayRequest, (void **) &pDisplayRequest);
dludwig@10293
   808
    if (FAILED(hr)) {
dludwig@10293
   809
        goto done;
dludwig@10293
   810
    }
dludwig@10293
   811
dludwig@10293
   812
done:
dludwig@10293
   813
    if (pDisplayRequestRaw) {
dludwig@10293
   814
        pDisplayRequestRaw->Release();
dludwig@10293
   815
    }
dludwig@10293
   816
    if (pActivationFactory) {
dludwig@10293
   817
        pActivationFactory->Release();
dludwig@10293
   818
    }
dludwig@10293
   819
    if (hClassName) {
dludwig@10293
   820
        ::WindowsDeleteString(hClassName);
dludwig@10293
   821
    }
dludwig@10293
   822
dludwig@10293
   823
    return pDisplayRequest;
dludwig@10293
   824
}
dludwig@10293
   825
dludwig@10293
   826
void
dludwig@10293
   827
WINRT_SuspendScreenSaver(_THIS)
dludwig@10293
   828
{
dludwig@10293
   829
    SDL_VideoData *driverdata = (SDL_VideoData *)_this->driverdata;
dludwig@10300
   830
    if (driverdata && driverdata->displayRequest) {
dludwig@10293
   831
        ABI::Windows::System::Display::IDisplayRequest * displayRequest = (ABI::Windows::System::Display::IDisplayRequest *) driverdata->displayRequest;
dludwig@10293
   832
        if (_this->suspend_screensaver) {
dludwig@10293
   833
            displayRequest->RequestActive();
dludwig@10293
   834
        } else {
dludwig@10293
   835
            displayRequest->RequestRelease();
dludwig@10293
   836
        }
dludwig@10293
   837
    }
dludwig@10293
   838
}
dludwig@10293
   839
dludwig@8327
   840
#endif /* SDL_VIDEO_DRIVER_WINRT */
dludwig@8327
   841
dludwig@8327
   842
/* vi: set ts=4 sw=4 expandtab: */