2015-06-21 15:33:46 +00:00
/*
Simple DirectMedia Layer
Copyright ( C ) 1997 - 2015 Sam Lantinga < slouken @ libsdl . org >
This software is provided ' as - is ' , without any express or implied
warranty . In no event will the authors be held liable for any damages
arising from the use of this software .
Permission is granted to anyone to use this software for any purpose ,
including commercial applications , and to alter it and redistribute it
freely , subject to the following restrictions :
1. The origin of this software must not be misrepresented ; you must not
claim that you wrote the original software . If you use this software
in a product , an acknowledgment in the product documentation would be
appreciated but is not required .
2. Altered source versions must be plainly marked as such , and must not be
misrepresented as being the original software .
3. This notice may not be removed or altered from any source distribution .
*/
# include "../../SDL_internal.h"
# if SDL_VIDEO_DRIVER_WINRT
/* WinRT SDL video driver implementation
Initial work on this was done by David Ludwig ( dludwig @ pobox . com ) , and
was based off of SDL ' s " dummy " video driver .
*/
/* Windows includes */
# include <agile.h>
2015-11-26 05:41:39 +00:00
# include <windows.graphics.display.h>
# include <dxgi.h>
# include <dxgi1_2.h>
using namespace Windows : : ApplicationModel : : Core ;
using namespace Windows : : Foundation ;
2015-11-26 06:36:36 +00:00
using namespace Windows : : Graphics : : Display ;
2015-06-21 15:33:46 +00:00
using namespace Windows : : UI : : Core ;
2015-11-26 05:41:39 +00:00
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 } } ;
2015-06-21 15:33:46 +00:00
/* SDL includes */
extern " C " {
# include "SDL_video.h"
# include "SDL_mouse.h"
# include "../SDL_sysvideo.h"
# include "../SDL_pixels_c.h"
# include "../../events/SDL_events_c.h"
# include "../../render/SDL_sysrender.h"
# include "SDL_syswm.h"
# include "SDL_winrtopengles.h"
2015-11-26 05:41:39 +00:00
# include "../../core/windows/SDL_windows.h"
2015-06-21 15:33:46 +00:00
}
# include "../../core/winrt/SDL_winrtapp_direct3d.h"
# include "../../core/winrt/SDL_winrtapp_xaml.h"
# include "SDL_winrtvideo_cpp.h"
# include "SDL_winrtevents_c.h"
# include "SDL_winrtmouse_c.h"
# include "SDL_main.h"
# include "SDL_system.h"
//#include "SDL_log.h"
/* Initialization/Query functions */
static int WINRT_VideoInit ( _THIS ) ;
static int WINRT_InitModes ( _THIS ) ;
static int WINRT_SetDisplayMode ( _THIS , SDL_VideoDisplay * display , SDL_DisplayMode * mode ) ;
static void WINRT_VideoQuit ( _THIS ) ;
/* Window functions */
static int WINRT_CreateWindow ( _THIS , SDL_Window * window ) ;
2015-11-30 00:33:11 +00:00
static void WINRT_SetWindowSize ( _THIS , SDL_Window * window ) ;
static void WINRT_SetWindowFullscreen ( _THIS , SDL_Window * window , SDL_VideoDisplay * display , SDL_bool fullscreen ) ;
2015-06-21 15:33:46 +00:00
static void WINRT_DestroyWindow ( _THIS , SDL_Window * window ) ;
static SDL_bool WINRT_GetWindowWMInfo ( _THIS , SDL_Window * window , SDL_SysWMinfo * info ) ;
/* SDL-internal globals: */
SDL_Window * WINRT_GlobalSDLWindow = NULL ;
/* WinRT driver bootstrap functions */
static int
WINRT_Available ( void )
{
return ( 1 ) ;
}
static void
WINRT_DeleteDevice ( SDL_VideoDevice * device )
{
if ( device - > driverdata ) {
SDL_VideoData * video_data = ( SDL_VideoData * ) device - > driverdata ;
if ( video_data - > winrtEglWindow ) {
video_data - > winrtEglWindow - > Release ( ) ;
}
SDL_free ( video_data ) ;
}
SDL_free ( device ) ;
}
static SDL_VideoDevice *
WINRT_CreateDevice ( int devindex )
{
SDL_VideoDevice * device ;
SDL_VideoData * data ;
/* Initialize all variables that we clean on shutdown */
device = ( SDL_VideoDevice * ) SDL_calloc ( 1 , sizeof ( SDL_VideoDevice ) ) ;
if ( ! device ) {
SDL_OutOfMemory ( ) ;
if ( device ) {
SDL_free ( device ) ;
}
return ( 0 ) ;
}
data = ( SDL_VideoData * ) SDL_calloc ( 1 , sizeof ( SDL_VideoData ) ) ;
if ( ! data ) {
SDL_OutOfMemory ( ) ;
return ( 0 ) ;
}
SDL_zerop ( data ) ;
device - > driverdata = data ;
/* Set the function pointers */
device - > VideoInit = WINRT_VideoInit ;
device - > VideoQuit = WINRT_VideoQuit ;
device - > CreateWindow = WINRT_CreateWindow ;
2015-11-30 00:33:11 +00:00
device - > SetWindowSize = WINRT_SetWindowSize ;
device - > SetWindowFullscreen = WINRT_SetWindowFullscreen ;
2015-06-21 15:33:46 +00:00
device - > DestroyWindow = WINRT_DestroyWindow ;
device - > SetDisplayMode = WINRT_SetDisplayMode ;
device - > PumpEvents = WINRT_PumpEvents ;
device - > GetWindowWMInfo = WINRT_GetWindowWMInfo ;
# ifdef SDL_VIDEO_OPENGL_EGL
device - > GL_LoadLibrary = WINRT_GLES_LoadLibrary ;
device - > GL_GetProcAddress = WINRT_GLES_GetProcAddress ;
device - > GL_UnloadLibrary = WINRT_GLES_UnloadLibrary ;
device - > GL_CreateContext = WINRT_GLES_CreateContext ;
device - > GL_MakeCurrent = WINRT_GLES_MakeCurrent ;
device - > GL_SetSwapInterval = WINRT_GLES_SetSwapInterval ;
device - > GL_GetSwapInterval = WINRT_GLES_GetSwapInterval ;
device - > GL_SwapWindow = WINRT_GLES_SwapWindow ;
device - > GL_DeleteContext = WINRT_GLES_DeleteContext ;
# endif
device - > free = WINRT_DeleteDevice ;
return device ;
}
# define WINRTVID_DRIVER_NAME "winrt"
VideoBootStrap WINRT_bootstrap = {
WINRTVID_DRIVER_NAME , " SDL WinRT video driver " ,
WINRT_Available , WINRT_CreateDevice
} ;
int
WINRT_VideoInit ( _THIS )
{
if ( WINRT_InitModes ( _this ) < 0 ) {
return - 1 ;
}
WINRT_InitMouse ( _this ) ;
WINRT_InitTouch ( _this ) ;
return 0 ;
}
2015-11-26 05:41:39 +00:00
extern " C "
Uint32 D3D11_DXGIFormatToSDLPixelFormat ( DXGI_FORMAT dxgiFormat ) ;
2015-06-21 15:33:46 +00:00
2015-11-26 05:41:39 +00:00
static void
WINRT_DXGIModeToSDLDisplayMode ( const DXGI_MODE_DESC * dxgiMode , SDL_DisplayMode * sdlMode )
{
SDL_zerop ( sdlMode ) ;
sdlMode - > w = dxgiMode - > Width ;
sdlMode - > h = dxgiMode - > Height ;
sdlMode - > refresh_rate = dxgiMode - > RefreshRate . Numerator / dxgiMode - > RefreshRate . Denominator ;
sdlMode - > format = D3D11_DXGIFormatToSDLPixelFormat ( dxgiMode - > Format ) ;
}
2015-06-21 15:33:46 +00:00
2015-11-26 05:41:39 +00:00
static int
WINRT_AddDisplaysForOutput ( _THIS , IDXGIAdapter1 * dxgiAdapter1 , int outputIndex )
{
HRESULT hr ;
IDXGIOutput * dxgiOutput = NULL ;
DXGI_OUTPUT_DESC dxgiOutputDesc ;
SDL_VideoDisplay display ;
char * displayName = NULL ;
UINT numModes ;
DXGI_MODE_DESC * dxgiModes = NULL ;
int functionResult = - 1 ; /* -1 for failure, 0 for success */
DXGI_MODE_DESC modeToMatch , closestMatch ;
SDL_zero ( display ) ;
hr = dxgiAdapter1 - > EnumOutputs ( outputIndex , & dxgiOutput ) ;
if ( FAILED ( hr ) ) {
if ( hr ! = DXGI_ERROR_NOT_FOUND ) {
WIN_SetErrorFromHRESULT ( __FUNCTION__ " , IDXGIAdapter1::EnumOutputs failed " , hr ) ;
}
goto done ;
2015-06-21 15:33:46 +00:00
}
2015-11-26 05:41:39 +00:00
hr = dxgiOutput - > GetDesc ( & dxgiOutputDesc ) ;
if ( FAILED ( hr ) ) {
WIN_SetErrorFromHRESULT ( __FUNCTION__ " , IDXGIOutput::GetDesc failed " , hr ) ;
goto done ;
2015-06-21 15:33:46 +00:00
}
2015-11-26 05:41:39 +00:00
SDL_zero ( modeToMatch ) ;
modeToMatch . Format = DXGI_FORMAT_B8G8R8A8_UNORM ;
modeToMatch . Width = ( dxgiOutputDesc . DesktopCoordinates . right - dxgiOutputDesc . DesktopCoordinates . left ) ;
modeToMatch . Height = ( dxgiOutputDesc . DesktopCoordinates . bottom - dxgiOutputDesc . DesktopCoordinates . top ) ;
hr = dxgiOutput - > FindClosestMatchingMode ( & modeToMatch , & closestMatch , NULL ) ;
if ( hr = = DXGI_ERROR_NOT_CURRENTLY_AVAILABLE ) {
/* DXGI_ERROR_NOT_CURRENTLY_AVAILABLE gets returned by IDXGIOutput::FindClosestMatchingMode
when running under the Windows Simulator , which uses Remote Desktop ( formerly known as Terminal
Services ) under the hood . According to the MSDN docs for the similar function ,
IDXGIOutput : : GetDisplayModeList , DXGI_ERROR_NOT_CURRENTLY_AVAILABLE is returned if and
when an app is run under a Terminal Services session , hence the assumption .
In this case , just add an SDL display mode , with approximated values .
*/
SDL_DisplayMode mode ;
SDL_zero ( mode ) ;
display . name = " Windows Simulator / Terminal Services Display " ;
mode . w = ( dxgiOutputDesc . DesktopCoordinates . right - dxgiOutputDesc . DesktopCoordinates . left ) ;
mode . h = ( dxgiOutputDesc . DesktopCoordinates . bottom - dxgiOutputDesc . DesktopCoordinates . top ) ;
mode . format = DXGI_FORMAT_B8G8R8A8_UNORM ;
mode . refresh_rate = 0 ; /* Display mode is unknown, so just fill in zero, as specified by SDL's header files */
display . desktop_mode = mode ;
display . current_mode = mode ;
if ( ! SDL_AddDisplayMode ( & display , & mode ) ) {
goto done ;
}
} else if ( FAILED ( hr ) ) {
WIN_SetErrorFromHRESULT ( __FUNCTION__ " , IDXGIOutput::FindClosestMatchingMode failed " , hr ) ;
goto done ;
} else {
displayName = WIN_StringToUTF8 ( dxgiOutputDesc . DeviceName ) ;
display . name = displayName ;
WINRT_DXGIModeToSDLDisplayMode ( & closestMatch , & display . desktop_mode ) ;
display . current_mode = display . desktop_mode ;
hr = dxgiOutput - > GetDisplayModeList ( DXGI_FORMAT_B8G8R8A8_UNORM , 0 , & numModes , NULL ) ;
if ( FAILED ( hr ) ) {
if ( hr = = DXGI_ERROR_NOT_CURRENTLY_AVAILABLE ) {
// TODO, WinRT: make sure display mode(s) are added when using Terminal Services / Windows Simulator
}
WIN_SetErrorFromHRESULT ( __FUNCTION__ " , IDXGIOutput::GetDisplayModeList [get mode list size] failed " , hr ) ;
goto done ;
2015-06-21 15:33:46 +00:00
}
2015-11-26 05:41:39 +00:00
dxgiModes = ( DXGI_MODE_DESC * ) SDL_calloc ( numModes , sizeof ( DXGI_MODE_DESC ) ) ;
if ( ! dxgiModes ) {
SDL_OutOfMemory ( ) ;
goto done ;
}
hr = dxgiOutput - > GetDisplayModeList ( DXGI_FORMAT_B8G8R8A8_UNORM , 0 , & numModes , dxgiModes ) ;
if ( FAILED ( hr ) ) {
WIN_SetErrorFromHRESULT ( __FUNCTION__ " , IDXGIOutput::GetDisplayModeList [get mode contents] failed " , hr ) ;
goto done ;
}
for ( UINT i = 0 ; i < numModes ; + + i ) {
SDL_DisplayMode sdlMode ;
WINRT_DXGIModeToSDLDisplayMode ( & dxgiModes [ i ] , & sdlMode ) ;
SDL_AddDisplayMode ( & display , & sdlMode ) ;
}
2015-06-21 15:33:46 +00:00
}
2015-11-26 05:41:39 +00:00
if ( SDL_AddVideoDisplay ( & display ) < 0 ) {
goto done ;
}
functionResult = 0 ; /* 0 for Success! */
done :
if ( dxgiModes ) {
SDL_free ( dxgiModes ) ;
}
if ( dxgiOutput ) {
dxgiOutput - > Release ( ) ;
}
if ( displayName ) {
SDL_free ( displayName ) ;
}
return functionResult ;
2015-06-21 15:33:46 +00:00
}
2015-11-26 05:41:39 +00:00
static int
WINRT_AddDisplaysForAdapter ( _THIS , IDXGIFactory2 * dxgiFactory2 , int adapterIndex )
2015-06-21 15:33:46 +00:00
{
2015-11-26 05:41:39 +00:00
HRESULT hr ;
IDXGIAdapter1 * dxgiAdapter1 ;
hr = dxgiFactory2 - > EnumAdapters1 ( adapterIndex , & dxgiAdapter1 ) ;
if ( FAILED ( hr ) ) {
if ( hr ! = DXGI_ERROR_NOT_FOUND ) {
WIN_SetErrorFromHRESULT ( __FUNCTION__ " , IDXGIFactory1::EnumAdapters1() failed " , hr ) ;
}
return - 1 ;
2015-06-21 15:33:46 +00:00
}
2015-11-26 05:41:39 +00:00
for ( int outputIndex = 0 ; ; + + outputIndex ) {
if ( WINRT_AddDisplaysForOutput ( _this , dxgiAdapter1 , outputIndex ) < 0 ) {
2015-12-06 22:06:40 +00:00
/* HACK: The Windows App Certification Kit 10.0 can fail, when
running the Store Apps ' test , " Direct3D Feature Test " . The
certification kit ' s error is :
" Application App was not running at the end of the test. It likely crashed or was terminated for having become unresponsive. "
This was caused by SDL / WinRT ' s DXGI failing to report any
outputs . Attempts to get the 1 st display - output from the
1 st display - adapter can fail , with IDXGIAdapter : : EnumOutputs
returning DXGI_ERROR_NOT_FOUND . This could be a bug in Windows ,
the Windows App Certification Kit , or possibly in SDL / WinRT ' s
display detection code . Either way , try to detect when this
happens , and use a hackish means to create a reasonable - as - possible
' display mode ' . - - DavidL
*/
if ( adapterIndex = = 0 & & outputIndex = = 0 ) {
SDL_VideoDisplay display ;
SDL_DisplayMode mode ;
2015-12-06 23:48:46 +00:00
# if SDL_WINRT_USE_APPLICATIONVIEW
2015-12-06 22:06:40 +00:00
ApplicationView ^ appView = ApplicationView : : GetForCurrentView ( ) ;
2015-12-06 23:42:30 +00:00
# endif
2015-12-06 23:48:46 +00:00
CoreWindow ^ coreWin = CoreWindow : : GetForCurrentThread ( ) ;
2015-12-06 22:06:40 +00:00
SDL_zero ( display ) ;
SDL_zero ( mode ) ;
display . name = " DXGI Display-detection Workaround " ;
/* HACK: ApplicationView's VisibleBounds property, appeared, via testing, to
give a better approximation of display - size , than did CoreWindow ' s
Bounds property , insofar that ApplicationView : : VisibleBounds seems like
it will , at least some of the time , give the full display size ( during the
2015-12-06 23:33:43 +00:00
failing test ) , whereas CoreWindow might not . - - DavidL
2015-12-06 22:06:40 +00:00
*/
2015-12-06 23:33:43 +00:00
2015-12-06 23:48:46 +00:00
# if (NTDDI_VERSION >= NTDDI_WIN10) || (SDL_WINRT_USE_APPLICATIONVIEW && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
2015-12-06 22:06:40 +00:00
mode . w = WINRT_DIPS_TO_PHYSICAL_PIXELS ( appView - > VisibleBounds . Width ) ;
mode . h = WINRT_DIPS_TO_PHYSICAL_PIXELS ( appView - > VisibleBounds . Height ) ;
2015-12-06 23:33:43 +00:00
# else
/* On platform(s) that do not support VisibleBounds, such as Windows 8.1,
fall back to CoreWindow ' s Bounds property .
*/
mode . w = WINRT_DIPS_TO_PHYSICAL_PIXELS ( coreWin - > Bounds . Width ) ;
mode . h = WINRT_DIPS_TO_PHYSICAL_PIXELS ( coreWin - > Bounds . Height ) ;
# endif
2015-12-06 22:06:40 +00:00
mode . format = DXGI_FORMAT_B8G8R8A8_UNORM ;
mode . refresh_rate = 0 ; /* Display mode is unknown, so just fill in zero, as specified by SDL's header files */
display . desktop_mode = mode ;
display . current_mode = mode ;
if ( ( SDL_AddDisplayMode ( & display , & mode ) < 0 ) | |
( SDL_AddVideoDisplay ( & display ) < 0 ) )
{
return SDL_SetError ( " Failed to apply DXGI Display-detection workaround " ) ;
}
}
2015-11-26 05:41:39 +00:00
break ;
}
}
dxgiAdapter1 - > Release ( ) ;
2015-06-21 15:33:46 +00:00
return 0 ;
}
int
WINRT_InitModes ( _THIS )
{
2015-11-26 05:41:39 +00:00
/* HACK: Initialize a single display, for whatever screen the app's
CoreApplicationView is on .
TODO , WinRT : Try initializing multiple displays , one for each monitor .
Appropriate WinRT APIs for this seem elusive , though . - - DavidL
*/
HRESULT hr ;
IDXGIFactory2 * dxgiFactory2 = NULL ;
2015-06-21 15:33:46 +00:00
2015-11-26 05:41:39 +00:00
hr = CreateDXGIFactory1 ( IID_IDXGIFactory2 , ( void * * ) & dxgiFactory2 ) ;
if ( FAILED ( hr ) ) {
WIN_SetErrorFromHRESULT ( __FUNCTION__ " , CreateDXGIFactory1() failed " , hr ) ;
2015-06-21 15:33:46 +00:00
return - 1 ;
}
2015-11-26 05:41:39 +00:00
for ( int adapterIndex = 0 ; ; + + adapterIndex ) {
if ( WINRT_AddDisplaysForAdapter ( _this , dxgiFactory2 , adapterIndex ) < 0 ) {
break ;
}
2015-06-21 15:33:46 +00:00
}
return 0 ;
}
static int
WINRT_SetDisplayMode ( _THIS , SDL_VideoDisplay * display , SDL_DisplayMode * mode )
{
return 0 ;
}
void
WINRT_VideoQuit ( _THIS )
{
WINRT_QuitMouse ( _this ) ;
}
2015-11-26 07:13:15 +00:00
static const Uint32 WINRT_DetectableFlags =
SDL_WINDOW_MAXIMIZED |
SDL_WINDOW_FULLSCREEN_DESKTOP |
SDL_WINDOW_SHOWN |
SDL_WINDOW_HIDDEN |
SDL_WINDOW_MOUSE_FOCUS ;
2015-11-26 05:41:39 +00:00
extern " C " Uint32
WINRT_DetectWindowFlags ( SDL_Window * window )
{
Uint32 latestFlags = 0 ;
SDL_WindowData * data = ( SDL_WindowData * ) window - > driverdata ;
bool is_fullscreen = false ;
# if SDL_WINRT_USE_APPLICATIONVIEW
if ( data - > appView ) {
is_fullscreen = data - > appView - > IsFullScreen ;
}
2015-11-26 07:37:51 +00:00
# elif (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION == NTDDI_WIN8)
2015-11-26 05:41:39 +00:00
is_fullscreen = true ;
# endif
if ( data - > coreWindow . Get ( ) ) {
if ( is_fullscreen ) {
SDL_VideoDisplay * display = SDL_GetDisplayForWindow ( window ) ;
2015-11-26 06:36:36 +00:00
int w = WINRT_DIPS_TO_PHYSICAL_PIXELS ( data - > coreWindow - > Bounds . Width ) ;
int h = WINRT_DIPS_TO_PHYSICAL_PIXELS ( data - > coreWindow - > Bounds . Height ) ;
# if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION > NTDDI_WIN8)
// On all WinRT platforms, except for WinPhone 8.0, rotate the
// window size. This is needed to properly calculate
// fullscreen vs. maximized.
const DisplayOrientations currentOrientation = WINRT_DISPLAY_PROPERTY ( CurrentOrientation ) ;
switch ( currentOrientation ) {
# if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
case DisplayOrientations : : Landscape :
case DisplayOrientations : : LandscapeFlipped :
# else
case DisplayOrientations : : Portrait :
case DisplayOrientations : : PortraitFlipped :
# endif
{
int tmp = w ;
w = h ;
h = tmp ;
} break ;
}
# endif
if ( display - > desktop_mode . w ! = w | | display - > desktop_mode . h ! = h ) {
2015-11-26 05:41:39 +00:00
latestFlags | = SDL_WINDOW_MAXIMIZED ;
} else {
latestFlags | = SDL_WINDOW_FULLSCREEN_DESKTOP ;
}
}
if ( data - > coreWindow - > Visible ) {
latestFlags | = SDL_WINDOW_SHOWN ;
} else {
latestFlags | = SDL_WINDOW_HIDDEN ;
}
# if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) && (NTDDI_VERSION < NTDDI_WINBLUE)
// data->coreWindow->PointerPosition is not supported on WinPhone 8.0
latestFlags | = SDL_WINDOW_MOUSE_FOCUS ;
# else
if ( data - > coreWindow - > Bounds . Contains ( data - > coreWindow - > PointerPosition ) ) {
latestFlags | = SDL_WINDOW_MOUSE_FOCUS ;
}
# endif
}
return latestFlags ;
}
2015-12-31 06:54:11 +00:00
// TODO, WinRT: consider removing WINRT_UpdateWindowFlags, and just calling WINRT_DetectWindowFlags as-appropriate (with appropriate calls to SDL_SendWindowEvent)
2015-11-26 05:41:39 +00:00
void
WINRT_UpdateWindowFlags ( SDL_Window * window , Uint32 mask )
{
2015-11-26 07:13:15 +00:00
mask & = WINRT_DetectableFlags ;
2015-11-26 05:41:39 +00:00
if ( window ) {
Uint32 apply = WINRT_DetectWindowFlags ( window ) ;
if ( ( apply & mask ) & SDL_WINDOW_FULLSCREEN ) {
window - > last_fullscreen_flags = window - > flags ; // seems necessary to programmatically un-fullscreen, via SDL APIs
}
window - > flags = ( window - > flags & ~ mask ) | ( apply & mask ) ;
}
}
2015-12-22 05:58:47 +00:00
static bool
WINRT_IsCoreWindowActive ( CoreWindow ^ coreWindow )
{
/* WinRT does not appear to offer API(s) to determine window-activation state,
at least not that I am aware of in Win8 - Win10 . As such , SDL tracks this
itself , via window - activation events .
If there * is * an API to track this , it should probably get used instead
of the following hack ( that uses " SDLHelperWindowActivationState " ) .
- - DavidL .
*/
if ( coreWindow - > CustomProperties - > HasKey ( " SDLHelperWindowActivationState " ) ) {
CoreWindowActivationState activationState = \
safe_cast < CoreWindowActivationState > ( coreWindow - > CustomProperties - > Lookup ( " SDLHelperWindowActivationState " ) ) ;
return ( activationState ! = CoreWindowActivationState : : Deactivated ) ;
}
/* Assume that non-SDL tracked windows are active, although this should
probably be avoided , if possible .
This might not even be possible , in normal SDL use , at least as of
this writing ( Dec 22 , 2015 ; via latest hg . libsdl . org / SDL clone ) - - DavidL
*/
return true ;
}
2015-06-21 15:33:46 +00:00
int
WINRT_CreateWindow ( _THIS , SDL_Window * window )
{
// Make sure that only one window gets created, at least until multimonitor
// support is added.
if ( WINRT_GlobalSDLWindow ! = NULL ) {
SDL_SetError ( " WinRT only supports one window " ) ;
return - 1 ;
}
2015-11-26 05:41:39 +00:00
SDL_WindowData * data = new SDL_WindowData ; /* use 'new' here as SDL_WindowData may use WinRT/C++ types */
2015-06-21 15:33:46 +00:00
if ( ! data ) {
SDL_OutOfMemory ( ) ;
return - 1 ;
}
window - > driverdata = data ;
data - > sdlWindow = window ;
/* To note, when XAML support is enabled, access to the CoreWindow will not
be possible , at least not via the SDL / XAML thread . Attempts to access it
from there will throw exceptions . As such , the SDL_WindowData ' s
' coreWindow ' field will only be set ( to a non - null value ) if XAML isn ' t
enabled .
*/
if ( ! WINRT_XAMLWasEnabled ) {
data - > coreWindow = CoreWindow : : GetForCurrentThread ( ) ;
2015-11-26 05:41:39 +00:00
# if SDL_WINRT_USE_APPLICATIONVIEW
data - > appView = ApplicationView : : GetForCurrentView ( ) ;
# endif
2015-06-21 15:33:46 +00:00
}
2015-11-30 00:33:11 +00:00
/* Make note of the requested window flags, before they start getting changed. */
const Uint32 requestedFlags = window - > flags ;
2015-06-21 15:33:46 +00:00
# if SDL_VIDEO_OPENGL_EGL
/* Setup the EGL surface, but only if OpenGL ES 2 was requested. */
if ( ! ( window - > flags & SDL_WINDOW_OPENGL ) ) {
/* OpenGL ES 2 wasn't requested. Don't set up an EGL surface. */
data - > egl_surface = EGL_NO_SURFACE ;
} else {
/* OpenGL ES 2 was reuqested. Set up an EGL surface. */
SDL_VideoData * video_data = ( SDL_VideoData * ) _this - > driverdata ;
/* Call SDL_EGL_ChooseConfig and eglCreateWindowSurface directly,
* rather than via SDL_EGL_CreateSurface , as older versions of
* ANGLE / WinRT may require that a C + + object , ComPtr < IUnknown > ,
* be passed into eglCreateWindowSurface .
*/
if ( SDL_EGL_ChooseConfig ( _this ) ! = 0 ) {
char buf [ 512 ] ;
SDL_snprintf ( buf , sizeof ( buf ) , " SDL_EGL_ChooseConfig failed: %s " , SDL_GetError ( ) ) ;
return SDL_SetError ( " %s " , buf ) ;
}
if ( video_data - > winrtEglWindow ) { /* ... is the 'old' version of ANGLE/WinRT being used? */
/* Attempt to create a window surface using older versions of
* ANGLE / WinRT :
*/
Microsoft : : WRL : : ComPtr < IUnknown > cpp_winrtEglWindow = video_data - > winrtEglWindow ;
data - > egl_surface = ( ( eglCreateWindowSurface_Old_Function ) _this - > egl_data - > eglCreateWindowSurface ) (
_this - > egl_data - > egl_display ,
_this - > egl_data - > egl_config ,
cpp_winrtEglWindow , NULL ) ;
if ( data - > egl_surface = = NULL ) {
return SDL_SetError ( " eglCreateWindowSurface failed " ) ;
}
} else if ( data - > coreWindow . Get ( ) ! = nullptr ) {
/* Attempt to create a window surface using newer versions of
* ANGLE / WinRT :
*/
IInspectable * coreWindowAsIInspectable = reinterpret_cast < IInspectable * > ( data - > coreWindow . Get ( ) ) ;
data - > egl_surface = _this - > egl_data - > eglCreateWindowSurface (
_this - > egl_data - > egl_display ,
_this - > egl_data - > egl_config ,
coreWindowAsIInspectable ,
NULL ) ;
if ( data - > egl_surface = = NULL ) {
return SDL_SetError ( " eglCreateWindowSurface failed " ) ;
}
} else {
return SDL_SetError ( " No supported means to create an EGL window surface are available " ) ;
}
}
# endif
2015-11-26 05:41:39 +00:00
/* Determine as many flags dynamically, as possible. */
window - > flags =
2015-11-26 16:09:50 +00:00
SDL_WINDOW_BORDERLESS |
SDL_WINDOW_RESIZABLE ;
2015-06-21 15:33:46 +00:00
# if SDL_VIDEO_OPENGL_EGL
if ( data - > egl_surface ) {
window - > flags | = SDL_WINDOW_OPENGL ;
}
# endif
2015-11-26 05:41:39 +00:00
if ( WINRT_XAMLWasEnabled ) {
/* TODO, WinRT: set SDL_Window size, maybe position too, from XAML control */
window - > x = 0 ;
window - > y = 0 ;
window - > flags | = SDL_WINDOW_SHOWN ;
SDL_SetMouseFocus ( NULL ) ; // TODO: detect this
SDL_SetKeyboardFocus ( NULL ) ; // TODO: detect this
} else {
2015-11-30 00:33:11 +00:00
/* WinRT 8.x apps seem to live in an environment where the OS controls the
2015-11-26 05:41:39 +00:00
app ' s window size , with some apps being fullscreen , depending on
user choice of various things . For now , just adapt the SDL_Window to
whatever Windows set - up as the native - window ' s geometry .
*/
window - > x = WINRT_DIPS_TO_PHYSICAL_PIXELS ( data - > coreWindow - > Bounds . Left ) ;
window - > y = WINRT_DIPS_TO_PHYSICAL_PIXELS ( data - > coreWindow - > Bounds . Top ) ;
2015-11-30 00:33:11 +00:00
# if NTDDI_VERSION < NTDDI_WIN10
/* On WinRT 8.x / pre-Win10, just use the size we were given. */
2015-11-26 05:41:39 +00:00
window - > w = WINRT_DIPS_TO_PHYSICAL_PIXELS ( data - > coreWindow - > Bounds . Width ) ;
window - > h = WINRT_DIPS_TO_PHYSICAL_PIXELS ( data - > coreWindow - > Bounds . Height ) ;
2015-11-30 00:33:11 +00:00
# else
/* On Windows 10, we occasionally get control over window size. For windowed
mode apps , try this .
*/
bool didSetSize = false ;
if ( ! ( requestedFlags & SDL_WINDOW_FULLSCREEN ) ) {
const Windows : : Foundation : : Size size ( WINRT_PHYSICAL_PIXELS_TO_DIPS ( window - > w ) ,
WINRT_PHYSICAL_PIXELS_TO_DIPS ( window - > h ) ) ;
didSetSize = data - > appView - > TryResizeView ( size ) ;
}
if ( ! didSetSize ) {
/* We either weren't able to set the window size, or a request for
fullscreen was made . Get window - size info from the OS .
*/
window - > w = WINRT_DIPS_TO_PHYSICAL_PIXELS ( data - > coreWindow - > Bounds . Width ) ;
window - > h = WINRT_DIPS_TO_PHYSICAL_PIXELS ( data - > coreWindow - > Bounds . Height ) ;
}
# endif
2015-11-26 05:41:39 +00:00
WINRT_UpdateWindowFlags (
window ,
0xffffffff /* Update any window flag(s) that WINRT_UpdateWindow can handle */
) ;
/* Try detecting if the window is active */
2015-12-22 05:58:47 +00:00
bool isWindowActive = WINRT_IsCoreWindowActive ( data - > coreWindow . Get ( ) ) ;
2015-11-26 05:41:39 +00:00
if ( isWindowActive ) {
SDL_SetKeyboardFocus ( window ) ;
}
}
2015-06-21 15:33:46 +00:00
/* Make sure the WinRT app's IFramworkView can post events on
behalf of SDL :
*/
WINRT_GlobalSDLWindow = window ;
/* All done! */
return 0 ;
}
2015-11-30 00:33:11 +00:00
void
WINRT_SetWindowSize ( _THIS , SDL_Window * window )
{
# if NTDDI_VERSION >= NTDDI_WIN10
SDL_WindowData * data = ( SDL_WindowData * ) window - > driverdata ;
const Windows : : Foundation : : Size size ( WINRT_PHYSICAL_PIXELS_TO_DIPS ( window - > w ) ,
WINRT_PHYSICAL_PIXELS_TO_DIPS ( window - > h ) ) ;
data - > appView - > TryResizeView ( size ) ; // TODO, WinRT: return failure (to caller?) from TryResizeView()
# endif
}
void
WINRT_SetWindowFullscreen ( _THIS , SDL_Window * window , SDL_VideoDisplay * display , SDL_bool fullscreen )
{
# if NTDDI_VERSION >= NTDDI_WIN10
SDL_WindowData * data = ( SDL_WindowData * ) window - > driverdata ;
2015-12-22 05:58:47 +00:00
bool isWindowActive = WINRT_IsCoreWindowActive ( data - > coreWindow . Get ( ) ) ;
if ( isWindowActive ) {
if ( fullscreen ) {
if ( ! data - > appView - > IsFullScreenMode ) {
data - > appView - > TryEnterFullScreenMode ( ) ; // TODO, WinRT: return failure (to caller?) from TryEnterFullScreenMode()
}
} else {
if ( data - > appView - > IsFullScreenMode ) {
data - > appView - > ExitFullScreenMode ( ) ;
}
2015-11-30 00:33:11 +00:00
}
}
# endif
}
2015-06-21 15:33:46 +00:00
void
WINRT_DestroyWindow ( _THIS , SDL_Window * window )
{
SDL_WindowData * data = ( SDL_WindowData * ) window - > driverdata ;
if ( WINRT_GlobalSDLWindow = = window ) {
WINRT_GlobalSDLWindow = NULL ;
}
if ( data ) {
// Delete the internal window data:
delete data ;
data = NULL ;
window - > driverdata = NULL ;
}
}
SDL_bool
WINRT_GetWindowWMInfo ( _THIS , SDL_Window * window , SDL_SysWMinfo * info )
{
SDL_WindowData * data = ( SDL_WindowData * ) window - > driverdata ;
if ( info - > version . major < = SDL_MAJOR_VERSION ) {
info - > subsystem = SDL_SYSWM_WINRT ;
info - > info . winrt . window = reinterpret_cast < IInspectable * > ( data - > coreWindow . Get ( ) ) ;
return SDL_TRUE ;
} else {
SDL_SetError ( " Application not compiled with SDL %d.%d \n " ,
SDL_MAJOR_VERSION , SDL_MINOR_VERSION ) ;
return SDL_FALSE ;
}
return SDL_FALSE ;
}
# endif /* SDL_VIDEO_DRIVER_WINRT */
/* vi: set ts=4 sw=4 expandtab: */