2015-06-21 17:33:46 +02: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"
/* Standard C++11 includes */
# include <functional>
# include <string>
# include <sstream>
using namespace std ;
/* Windows includes */
# include "ppltasks.h"
using namespace concurrency ;
using namespace Windows : : ApplicationModel ;
using namespace Windows : : ApplicationModel : : Core ;
using namespace Windows : : ApplicationModel : : Activation ;
using namespace Windows : : Devices : : Input ;
using namespace Windows : : Graphics : : Display ;
using namespace Windows : : Foundation ;
using namespace Windows : : System ;
using namespace Windows : : UI : : Core ;
using namespace Windows : : UI : : Input ;
# if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
using namespace Windows : : Phone : : UI : : Input ;
# endif
/* SDL includes */
extern " C " {
# include "../../SDL_internal.h"
# include "SDL_assert.h"
# include "SDL_events.h"
# include "SDL_hints.h"
# include "SDL_log.h"
# include "SDL_main.h"
# include "SDL_stdinc.h"
# include "SDL_render.h"
# include "../../video/SDL_sysvideo.h"
//#include "../../SDL_hints_c.h"
# include "../../events/SDL_events_c.h"
# include "../../events/SDL_keyboard_c.h"
# include "../../events/SDL_mouse_c.h"
# include "../../events/SDL_windowevents_c.h"
# include "../../render/SDL_sysrender.h"
# include "../windows/SDL_windows.h"
}
# include "../../video/winrt/SDL_winrtevents_c.h"
# include "../../video/winrt/SDL_winrtvideo_cpp.h"
# include "SDL_winrtapp_common.h"
# include "SDL_winrtapp_direct3d.h"
# if SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED
/* Calling IDXGIDevice3::Trim on the active Direct3D 11.x device is necessary
* when Windows 8.1 apps are about to get suspended .
*/
extern " C " void D3D11_Trim ( SDL_Renderer * ) ;
# endif
// Compile-time debugging options:
// To enable, uncomment; to disable, comment them out.
//#define LOG_POINTER_EVENTS 1
//#define LOG_WINDOW_EVENTS 1
//#define LOG_ORIENTATION_EVENTS 1
// HACK, DLudwig: record a reference to the global, WinRT 'app'/view.
// SDL/WinRT will use this throughout its code.
//
// TODO, WinRT: consider replacing SDL_WinRTGlobalApp with something
// non-global, such as something created inside
// SDL_InitSubSystem(SDL_INIT_VIDEO), or something inside
// SDL_CreateWindow().
SDL_WinRTApp ^ SDL_WinRTGlobalApp = nullptr ;
ref class SDLApplicationSource sealed : Windows : : ApplicationModel : : Core : : IFrameworkViewSource
{
public :
virtual Windows : : ApplicationModel : : Core : : IFrameworkView ^ CreateView ( ) ;
} ;
IFrameworkView ^ SDLApplicationSource : : CreateView ( )
{
// TODO, WinRT: see if this function (CreateView) can ever get called
// more than once. For now, just prevent it from ever assigning
// SDL_WinRTGlobalApp more than once.
SDL_assert ( ! SDL_WinRTGlobalApp ) ;
SDL_WinRTApp ^ app = ref new SDL_WinRTApp ( ) ;
if ( ! SDL_WinRTGlobalApp )
{
SDL_WinRTGlobalApp = app ;
}
return app ;
}
int SDL_WinRTInitNonXAMLApp ( int ( * mainFunction ) ( int , char * * ) )
{
WINRT_SDLAppEntryPoint = mainFunction ;
auto direct3DApplicationSource = ref new SDLApplicationSource ( ) ;
CoreApplication : : Run ( direct3DApplicationSource ) ;
return 0 ;
}
static void WINRT_SetDisplayOrientationsPreference ( void * userdata , const char * name , const char * oldValue , const char * newValue )
{
SDL_assert ( SDL_strcmp ( name , SDL_HINT_ORIENTATIONS ) = = 0 ) ;
/* HACK: prevent SDL from altering an app's .appxmanifest-set orientation
* from being changed on startup , by detecting when SDL_HINT_ORIENTATIONS
* is getting registered .
*
* TODO , WinRT : consider reading in an app ' s . appxmanifest file , and apply its orientation when ' newValue = = NULL ' .
*/
if ( ( oldValue = = NULL ) & & ( newValue = = NULL ) ) {
return ;
}
// Start with no orientation flags, then add each in as they're parsed
// from newValue.
unsigned int orientationFlags = 0 ;
if ( newValue ) {
std : : istringstream tokenizer ( newValue ) ;
while ( ! tokenizer . eof ( ) ) {
std : : string orientationName ;
std : : getline ( tokenizer , orientationName , ' ' ) ;
if ( orientationName = = " LandscapeLeft " ) {
orientationFlags | = ( unsigned int ) DisplayOrientations : : LandscapeFlipped ;
} else if ( orientationName = = " LandscapeRight " ) {
orientationFlags | = ( unsigned int ) DisplayOrientations : : Landscape ;
} else if ( orientationName = = " Portrait " ) {
orientationFlags | = ( unsigned int ) DisplayOrientations : : Portrait ;
} else if ( orientationName = = " PortraitUpsideDown " ) {
orientationFlags | = ( unsigned int ) DisplayOrientations : : PortraitFlipped ;
}
}
}
// If no valid orientation flags were specified, use a reasonable set of defaults:
if ( ! orientationFlags ) {
// TODO, WinRT: consider seeing if an app's default orientation flags can be found out via some API call(s).
orientationFlags = ( unsigned int ) ( \
DisplayOrientations : : Landscape |
DisplayOrientations : : LandscapeFlipped |
DisplayOrientations : : Portrait |
DisplayOrientations : : PortraitFlipped ) ;
}
// Set the orientation/rotation preferences. Please note that this does
// not constitute a 100%-certain lock of a given set of possible
// orientations. According to Microsoft's documentation on WinRT [1]
// when a device is not capable of being rotated, Windows may ignore
// the orientation preferences, and stick to what the device is capable of
// displaying.
//
// [1] Documentation on the 'InitialRotationPreference' setting for a
// Windows app's manifest file describes how some orientation/rotation
// preferences may be ignored. See
// http://msdn.microsoft.com/en-us/library/windows/apps/hh700343.aspx
// for details. Microsoft's "Display orientation sample" also gives an
// outline of how Windows treats device rotation
// (http://code.msdn.microsoft.com/Display-Orientation-Sample-19a58e93).
WINRT_DISPLAY_PROPERTY ( AutoRotationPreferences ) = ( DisplayOrientations ) orientationFlags ;
}
static void
2015-11-26 00:41:39 -05:00
WINRT_ProcessWindowSizeChange ( ) // TODO: Pass an SDL_Window-identifying thing into WINRT_ProcessWindowSizeChange()
2015-06-21 17:33:46 +02:00
{
2015-11-26 00:41:39 -05:00
CoreWindow ^ coreWindow = CoreWindow : : GetForCurrentThread ( ) ;
if ( coreWindow ) {
if ( WINRT_GlobalSDLWindow ) {
SDL_Window * window = WINRT_GlobalSDLWindow ;
SDL_WindowData * data = ( SDL_WindowData * ) window - > driverdata ;
int x = WINRT_DIPS_TO_PHYSICAL_PIXELS ( data - > coreWindow - > Bounds . Left ) ;
int y = WINRT_DIPS_TO_PHYSICAL_PIXELS ( data - > coreWindow - > Bounds . Top ) ;
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)
/* WinPhone 8.0 always keeps its native window size in portrait,
regardless of orientation . This changes in WinPhone 8.1 ,
in which the native window ' s size changes along with
orientation .
Attempt to emulate WinPhone 8.1 ' s behavior on WinPhone 8.0 , with
regards to window size . This fixes a rendering bug that occurs
when a WinPhone 8.0 app is rotated to either 90 or 270 degrees .
*/
const DisplayOrientations currentOrientation = WINRT_DISPLAY_PROPERTY ( CurrentOrientation ) ;
switch ( currentOrientation ) {
case DisplayOrientations : : Landscape :
case DisplayOrientations : : LandscapeFlipped : {
int tmp = w ;
w = h ;
h = tmp ;
} break ;
2015-06-21 17:33:46 +02:00
}
# endif
2015-11-26 00:41:39 -05:00
WINRT_UpdateWindowFlags ( window , SDL_WINDOW_MAXIMIZED | SDL_WINDOW_FULLSCREEN_DESKTOP ) ;
/* The window can move during a resize event, such as when maximizing
or resizing from a corner */
SDL_SendWindowEvent ( window , SDL_WINDOWEVENT_MOVED , x , y ) ;
SDL_SendWindowEvent ( window , SDL_WINDOWEVENT_RESIZED , w , h ) ;
2015-06-21 17:33:46 +02:00
}
}
}
SDL_WinRTApp : : SDL_WinRTApp ( ) :
m_windowClosed ( false ) ,
m_windowVisible ( true )
{
}
void SDL_WinRTApp : : Initialize ( CoreApplicationView ^ applicationView )
{
applicationView - > Activated + =
2015-11-26 00:41:39 -05:00
ref new TypedEventHandler < CoreApplicationView ^ , IActivatedEventArgs ^ > ( this , & SDL_WinRTApp : : OnAppActivated ) ;
2015-06-21 17:33:46 +02:00
CoreApplication : : Suspending + =
ref new EventHandler < SuspendingEventArgs ^ > ( this , & SDL_WinRTApp : : OnSuspending ) ;
CoreApplication : : Resuming + =
ref new EventHandler < Platform : : Object ^ > ( this , & SDL_WinRTApp : : OnResuming ) ;
CoreApplication : : Exiting + =
ref new EventHandler < Platform : : Object ^ > ( this , & SDL_WinRTApp : : OnExiting ) ;
}
# if NTDDI_VERSION > NTDDI_WIN8
void SDL_WinRTApp : : OnOrientationChanged ( DisplayInformation ^ sender , Object ^ args )
# else
void SDL_WinRTApp : : OnOrientationChanged ( Object ^ sender )
# endif
{
# if LOG_ORIENTATION_EVENTS==1
2015-11-26 00:41:39 -05:00
{
CoreWindow ^ window = CoreWindow : : GetForCurrentThread ( ) ;
if ( window ) {
SDL_Log ( " %s, current orientation=%d, native orientation=%d, auto rot. pref=%d, CoreWindow Bounds={%f,%f,%f,%f} \n " ,
__FUNCTION__ ,
WINRT_DISPLAY_PROPERTY ( CurrentOrientation ) ,
WINRT_DISPLAY_PROPERTY ( NativeOrientation ) ,
WINRT_DISPLAY_PROPERTY ( AutoRotationPreferences ) ,
window - > Bounds . X ,
window - > Bounds . Y ,
window - > Bounds . Width ,
window - > Bounds . Height ) ;
} else {
SDL_Log ( " %s, current orientation=%d, native orientation=%d, auto rot. pref=%d \n " ,
__FUNCTION__ ,
WINRT_DISPLAY_PROPERTY ( CurrentOrientation ) ,
WINRT_DISPLAY_PROPERTY ( NativeOrientation ) ,
WINRT_DISPLAY_PROPERTY ( AutoRotationPreferences ) ) ;
}
2015-06-21 17:33:46 +02:00
}
# endif
WINRT_ProcessWindowSizeChange ( ) ;
2015-11-26 00:41:39 -05:00
# if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
// HACK: Make sure that orientation changes
// lead to the Direct3D renderer's viewport getting updated:
//
// For some reason, this doesn't seem to need to be done on Windows 8.x,
// even when going from Landscape to LandscapeFlipped. It only seems to
// be needed on Windows Phone, at least when I tested on my devices.
// I'm not currently sure why this is, but it seems to work fine. -- David L.
//
// TODO, WinRT: do more extensive research into why orientation changes on Win 8.x don't need D3D changes, or if they might, in some cases
SDL_Window * window = WINRT_GlobalSDLWindow ;
if ( window ) {
SDL_WindowData * data = ( SDL_WindowData * ) window - > driverdata ;
int w = WINRT_DIPS_TO_PHYSICAL_PIXELS ( data - > coreWindow - > Bounds . Width ) ;
int h = WINRT_DIPS_TO_PHYSICAL_PIXELS ( data - > coreWindow - > Bounds . Height ) ;
SDL_SendWindowEvent ( WINRT_GlobalSDLWindow , SDL_WINDOWEVENT_SIZE_CHANGED , w , h ) ;
}
# endif
2015-06-21 17:33:46 +02:00
}
void SDL_WinRTApp : : SetWindow ( CoreWindow ^ window )
{
# if LOG_WINDOW_EVENTS==1
2015-11-26 00:41:39 -05:00
SDL_Log ( " %s, current orientation=%d, native orientation=%d, auto rot. pref=%d, window bounds={%f, %f, %f,%f} \n " ,
2015-06-21 17:33:46 +02:00
__FUNCTION__ ,
WINRT_DISPLAY_PROPERTY ( CurrentOrientation ) ,
WINRT_DISPLAY_PROPERTY ( NativeOrientation ) ,
WINRT_DISPLAY_PROPERTY ( AutoRotationPreferences ) ,
2015-11-26 00:41:39 -05:00
window - > Bounds . X ,
window - > Bounds . Y ,
2015-06-21 17:33:46 +02:00
window - > Bounds . Width ,
window - > Bounds . Height ) ;
# endif
window - > SizeChanged + =
ref new TypedEventHandler < CoreWindow ^ , WindowSizeChangedEventArgs ^ > ( this , & SDL_WinRTApp : : OnWindowSizeChanged ) ;
window - > VisibilityChanged + =
ref new TypedEventHandler < CoreWindow ^ , VisibilityChangedEventArgs ^ > ( this , & SDL_WinRTApp : : OnVisibilityChanged ) ;
2015-11-26 00:41:39 -05:00
window - > Activated + =
ref new TypedEventHandler < CoreWindow ^ , WindowActivatedEventArgs ^ > ( this , & SDL_WinRTApp : : OnWindowActivated ) ;
2015-06-21 17:33:46 +02:00
window - > Closed + =
ref new TypedEventHandler < CoreWindow ^ , CoreWindowEventArgs ^ > ( this , & SDL_WinRTApp : : OnWindowClosed ) ;
# if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
window - > PointerCursor = ref new CoreCursor ( CoreCursorType : : Arrow , 0 ) ;
# endif
window - > PointerPressed + =
ref new TypedEventHandler < CoreWindow ^ , PointerEventArgs ^ > ( this , & SDL_WinRTApp : : OnPointerPressed ) ;
window - > PointerMoved + =
ref new TypedEventHandler < CoreWindow ^ , PointerEventArgs ^ > ( this , & SDL_WinRTApp : : OnPointerMoved ) ;
window - > PointerReleased + =
ref new TypedEventHandler < CoreWindow ^ , PointerEventArgs ^ > ( this , & SDL_WinRTApp : : OnPointerReleased ) ;
2015-11-26 00:41:39 -05:00
window - > PointerEntered + =
ref new TypedEventHandler < CoreWindow ^ , PointerEventArgs ^ > ( this , & SDL_WinRTApp : : OnPointerEntered ) ;
window - > PointerExited + =
ref new TypedEventHandler < CoreWindow ^ , PointerEventArgs ^ > ( this , & SDL_WinRTApp : : OnPointerExited ) ;
2015-06-21 17:33:46 +02:00
window - > PointerWheelChanged + =
ref new TypedEventHandler < CoreWindow ^ , PointerEventArgs ^ > ( this , & SDL_WinRTApp : : OnPointerWheelChanged ) ;
# if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
// Retrieves relative-only mouse movements:
Windows : : Devices : : Input : : MouseDevice : : GetForCurrentView ( ) - > MouseMoved + =
ref new TypedEventHandler < MouseDevice ^ , MouseEventArgs ^ > ( this , & SDL_WinRTApp : : OnMouseMoved ) ;
# endif
window - > KeyDown + =
ref new TypedEventHandler < CoreWindow ^ , KeyEventArgs ^ > ( this , & SDL_WinRTApp : : OnKeyDown ) ;
window - > KeyUp + =
ref new TypedEventHandler < CoreWindow ^ , KeyEventArgs ^ > ( this , & SDL_WinRTApp : : OnKeyUp ) ;
window - > CharacterReceived + =
ref new TypedEventHandler < CoreWindow ^ , CharacterReceivedEventArgs ^ > ( this , & SDL_WinRTApp : : OnCharacterReceived ) ;
2015-12-09 21:34:56 -05:00
# if NTDDI_VERSION >= NTDDI_WIN10
Windows : : UI : : Core : : SystemNavigationManager : : GetForCurrentView ( ) - > BackRequested + =
ref new EventHandler < BackRequestedEventArgs ^ > ( this , & SDL_WinRTApp : : OnBackButtonPressed ) ;
# elif WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
2015-06-21 17:33:46 +02:00
HardwareButtons : : BackPressed + =
ref new EventHandler < BackPressedEventArgs ^ > ( this , & SDL_WinRTApp : : OnBackButtonPressed ) ;
# endif
# if NTDDI_VERSION > NTDDI_WIN8
DisplayInformation : : GetForCurrentView ( ) - > OrientationChanged + =
ref new TypedEventHandler < Windows : : Graphics : : Display : : DisplayInformation ^ , Object ^ > ( this , & SDL_WinRTApp : : OnOrientationChanged ) ;
# else
DisplayProperties : : OrientationChanged + =
ref new DisplayPropertiesEventHandler ( this , & SDL_WinRTApp : : OnOrientationChanged ) ;
# endif
// Register the hint, SDL_HINT_ORIENTATIONS, with SDL.
// TODO, WinRT: see if an app's default orientation can be found out via WinRT API(s), then set the initial value of SDL_HINT_ORIENTATIONS accordingly.
SDL_AddHintCallback ( SDL_HINT_ORIENTATIONS , WINRT_SetDisplayOrientationsPreference , NULL ) ;
2015-11-29 19:33:11 -05:00
# if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10) // for Windows 8/8.1/RT apps... (and not Phone apps)
2015-06-21 17:33:46 +02:00
// Make sure we know when a user has opened the app's settings pane.
// This is needed in order to display a privacy policy, which needs
// to be done for network-enabled apps, as per Windows Store requirements.
using namespace Windows : : UI : : ApplicationSettings ;
SettingsPane : : GetForCurrentView ( ) - > CommandsRequested + =
ref new TypedEventHandler < SettingsPane ^ , SettingsPaneCommandsRequestedEventArgs ^ >
( this , & SDL_WinRTApp : : OnSettingsPaneCommandsRequested ) ;
# endif
}
void SDL_WinRTApp : : Load ( Platform : : String ^ entryPoint )
{
}
void SDL_WinRTApp : : Run ( )
{
SDL_SetMainReady ( ) ;
if ( WINRT_SDLAppEntryPoint )
{
// TODO, WinRT: pass the C-style main() a reasonably realistic
// representation of command line arguments.
int argc = 0 ;
char * * argv = NULL ;
WINRT_SDLAppEntryPoint ( argc , argv ) ;
}
}
static bool IsSDLWindowEventPending ( SDL_WindowEventID windowEventID )
{
SDL_Event events [ 128 ] ;
const int count = SDL_PeepEvents ( events , sizeof ( events ) / sizeof ( SDL_Event ) , SDL_PEEKEVENT , SDL_WINDOWEVENT , SDL_WINDOWEVENT ) ;
for ( int i = 0 ; i < count ; + + i ) {
if ( events [ i ] . window . event = = windowEventID ) {
return true ;
}
}
return false ;
}
bool SDL_WinRTApp : : ShouldWaitForAppResumeEvents ( )
{
/* Don't wait if the app is visible: */
if ( m_windowVisible ) {
return false ;
}
/* Don't wait until the window-hide events finish processing.
* Do note that if an app - suspend event is sent ( as indicated
* by SDL_APP_WILLENTERBACKGROUND and SDL_APP_DIDENTERBACKGROUND
* events ) , then this code may be a moot point , as WinRT ' s
* own event pump ( aka ProcessEvents ( ) ) will pause regardless
* of what we do here . This happens on Windows Phone 8 , to note .
* Windows 8. x apps , on the other hand , may get a chance to run
* these .
*/
if ( IsSDLWindowEventPending ( SDL_WINDOWEVENT_HIDDEN ) ) {
return false ;
} else if ( IsSDLWindowEventPending ( SDL_WINDOWEVENT_FOCUS_LOST ) ) {
return false ;
} else if ( IsSDLWindowEventPending ( SDL_WINDOWEVENT_MINIMIZED ) ) {
return false ;
}
return true ;
}
void SDL_WinRTApp : : PumpEvents ( )
{
if ( ! m_windowClosed ) {
if ( ! ShouldWaitForAppResumeEvents ( ) ) {
/* This is the normal way in which events should be pumped.
* ' ProcessAllIfPresent ' will make ProcessEvents ( ) process anywhere
* from zero to N events , and will then return .
*/
CoreWindow : : GetForCurrentThread ( ) - > Dispatcher - > ProcessEvents ( CoreProcessEventsOption : : ProcessAllIfPresent ) ;
} else {
/* This style of event-pumping, with 'ProcessOneAndAllPending',
* will cause anywhere from one to N events to be processed . If
* at least one event is processed , the call will return . If
* no events are pending , then the call will wait until one is
* available , and will not return ( to the caller ) until this
* happens ! This should only occur when the app is hidden .
*/
CoreWindow : : GetForCurrentThread ( ) - > Dispatcher - > ProcessEvents ( CoreProcessEventsOption : : ProcessOneAndAllPending ) ;
}
}
}
void SDL_WinRTApp : : Uninitialize ( )
{
}
2015-11-29 19:33:11 -05:00
# if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10)
2015-06-21 17:33:46 +02:00
void SDL_WinRTApp : : OnSettingsPaneCommandsRequested (
Windows : : UI : : ApplicationSettings : : SettingsPane ^ p ,
Windows : : UI : : ApplicationSettings : : SettingsPaneCommandsRequestedEventArgs ^ args )
{
using namespace Platform ;
using namespace Windows : : UI : : ApplicationSettings ;
using namespace Windows : : UI : : Popups ;
String ^ privacyPolicyURL = nullptr ; // a URL to an app's Privacy Policy
String ^ privacyPolicyLabel = nullptr ; // label/link text
const char * tmpHintValue = NULL ; // SDL_GetHint-retrieved value, used immediately
wchar_t * tmpStr = NULL ; // used for UTF8 to UCS2 conversion
// Setup a 'Privacy Policy' link, if one is available (via SDL_GetHint):
tmpHintValue = SDL_GetHint ( SDL_HINT_WINRT_PRIVACY_POLICY_URL ) ;
if ( tmpHintValue & & tmpHintValue [ 0 ] ! = ' \0 ' ) {
// Convert the privacy policy's URL to UCS2:
tmpStr = WIN_UTF8ToString ( tmpHintValue ) ;
privacyPolicyURL = ref new String ( tmpStr ) ;
SDL_free ( tmpStr ) ;
// Optionally retrieve custom label-text for the link. If this isn't
// available, a default value will be used instead.
tmpHintValue = SDL_GetHint ( SDL_HINT_WINRT_PRIVACY_POLICY_LABEL ) ;
if ( tmpHintValue & & tmpHintValue [ 0 ] ! = ' \0 ' ) {
tmpStr = WIN_UTF8ToString ( tmpHintValue ) ;
privacyPolicyLabel = ref new String ( tmpStr ) ;
SDL_free ( tmpStr ) ;
} else {
privacyPolicyLabel = ref new String ( L " Privacy Policy " ) ;
}
// Register the link, along with a handler to be called if and when it is
// clicked:
auto cmd = ref new SettingsCommand ( L " privacyPolicy " , privacyPolicyLabel ,
ref new UICommandInvokedHandler ( [ = ] ( IUICommand ^ ) {
Windows : : System : : Launcher : : LaunchUriAsync ( ref new Uri ( privacyPolicyURL ) ) ;
} ) ) ;
args - > Request - > ApplicationCommands - > Append ( cmd ) ;
}
}
2015-11-29 19:33:11 -05:00
# endif // if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10)
2015-06-21 17:33:46 +02:00
void SDL_WinRTApp : : OnWindowSizeChanged ( CoreWindow ^ sender , WindowSizeChangedEventArgs ^ args )
{
# if LOG_WINDOW_EVENTS==1
2015-11-26 00:41:39 -05:00
SDL_Log ( " %s, size={%f,%f}, bounds={%f,%f,%f,%f}, current orientation=%d, native orientation=%d, auto rot. pref=%d, WINRT_GlobalSDLWindow?=%s \n " ,
2015-06-21 17:33:46 +02:00
__FUNCTION__ ,
args - > Size . Width , args - > Size . Height ,
2015-11-26 00:41:39 -05:00
sender - > Bounds . X , sender - > Bounds . Y , sender - > Bounds . Width , sender - > Bounds . Height ,
2015-06-21 17:33:46 +02:00
WINRT_DISPLAY_PROPERTY ( CurrentOrientation ) ,
WINRT_DISPLAY_PROPERTY ( NativeOrientation ) ,
WINRT_DISPLAY_PROPERTY ( AutoRotationPreferences ) ,
( WINRT_GlobalSDLWindow ? " yes " : " no " ) ) ;
# endif
WINRT_ProcessWindowSizeChange ( ) ;
}
void SDL_WinRTApp : : OnVisibilityChanged ( CoreWindow ^ sender , VisibilityChangedEventArgs ^ args )
{
# if LOG_WINDOW_EVENTS==1
2015-11-26 00:41:39 -05:00
SDL_Log ( " %s, visible?=%s, bounds={%f,%f,%f,%f}, WINRT_GlobalSDLWindow?=%s \n " ,
2015-06-21 17:33:46 +02:00
__FUNCTION__ ,
( args - > Visible ? " yes " : " no " ) ,
2015-11-26 00:41:39 -05:00
sender - > Bounds . X , sender - > Bounds . Y ,
sender - > Bounds . Width , sender - > Bounds . Height ,
2015-06-21 17:33:46 +02:00
( WINRT_GlobalSDLWindow ? " yes " : " no " ) ) ;
# endif
m_windowVisible = args - > Visible ;
if ( WINRT_GlobalSDLWindow ) {
SDL_bool wasSDLWindowSurfaceValid = WINRT_GlobalSDLWindow - > surface_valid ;
2015-11-26 00:41:39 -05:00
Uint32 latestWindowFlags = WINRT_DetectWindowFlags ( WINRT_GlobalSDLWindow ) ;
2015-06-21 17:33:46 +02:00
if ( args - > Visible ) {
SDL_SendWindowEvent ( WINRT_GlobalSDLWindow , SDL_WINDOWEVENT_SHOWN , 0 , 0 ) ;
SDL_SendWindowEvent ( WINRT_GlobalSDLWindow , SDL_WINDOWEVENT_FOCUS_GAINED , 0 , 0 ) ;
2015-11-26 00:41:39 -05:00
if ( latestWindowFlags & SDL_WINDOW_MAXIMIZED ) {
SDL_SendWindowEvent ( WINRT_GlobalSDLWindow , SDL_WINDOWEVENT_MAXIMIZED , 0 , 0 ) ;
} else {
SDL_SendWindowEvent ( WINRT_GlobalSDLWindow , SDL_WINDOWEVENT_RESTORED , 0 , 0 ) ;
}
2015-06-21 17:33:46 +02:00
} else {
SDL_SendWindowEvent ( WINRT_GlobalSDLWindow , SDL_WINDOWEVENT_HIDDEN , 0 , 0 ) ;
SDL_SendWindowEvent ( WINRT_GlobalSDLWindow , SDL_WINDOWEVENT_FOCUS_LOST , 0 , 0 ) ;
SDL_SendWindowEvent ( WINRT_GlobalSDLWindow , SDL_WINDOWEVENT_MINIMIZED , 0 , 0 ) ;
}
// HACK: Prevent SDL's window-hide handling code, which currently
// triggers a fake window resize (possibly erronously), from
// marking the SDL window's surface as invalid.
//
// A better solution to this probably involves figuring out if the
// fake window resize can be prevented.
WINRT_GlobalSDLWindow - > surface_valid = wasSDLWindowSurfaceValid ;
}
}
2015-11-26 00:41:39 -05:00
void SDL_WinRTApp : : OnWindowActivated ( CoreWindow ^ sender , WindowActivatedEventArgs ^ args )
{
# if LOG_WINDOW_EVENTS==1
SDL_Log ( " %s, WINRT_GlobalSDLWindow?=%s \n \n " ,
__FUNCTION__ ,
( WINRT_GlobalSDLWindow ? " yes " : " no " ) ) ;
# endif
/* There's no property in Win 8.x to tell whether a window is active or
not . [ De ] activation events are , however , sent to the app . We ' ll just
record those , in case the CoreWindow gets wrapped by an SDL_Window at
some future time .
*/
sender - > CustomProperties - > Insert ( " SDLHelperWindowActivationState " , args - > WindowActivationState ) ;
SDL_Window * window = WINRT_GlobalSDLWindow ;
if ( window ) {
if ( args - > WindowActivationState ! = CoreWindowActivationState : : Deactivated ) {
SDL_SendWindowEvent ( window , SDL_WINDOWEVENT_SHOWN , 0 , 0 ) ;
if ( SDL_GetKeyboardFocus ( ) ! = window ) {
SDL_SetKeyboardFocus ( window ) ;
}
/* Send a mouse-motion event as appropriate.
This doesn ' t work when called from OnPointerEntered , at least
not in WinRT CoreWindow apps ( as OnPointerEntered doesn ' t
appear to be called after window - reactivation , at least not
in Windows 10 , Build 10586.3 ( November 2015 update , non - beta ) .
Don ' t do it on WinPhone 8.0 though , as CoreWindow ' s ' PointerPosition '
property isn ' t available .
*/
# if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) || (NTDDI_VERSION >= NTDDI_WINBLUE)
Point cursorPos = WINRT_TransformCursorPosition ( window , sender - > PointerPosition , TransformToSDLWindowSize ) ;
SDL_SendMouseMotion ( window , 0 , 0 , ( int ) cursorPos . X , ( int ) cursorPos . Y ) ;
# endif
/* TODO, WinRT: see if the Win32 bugfix from https://hg.libsdl.org/SDL/rev/d278747da408 needs to be applied (on window activation) */
//WIN_CheckAsyncMouseRelease(data);
/* TODO, WinRT: implement clipboard support, if possible */
///*
// * FIXME: Update keyboard state
// */
//WIN_CheckClipboardUpdate(data->videodata);
} else {
if ( SDL_GetKeyboardFocus ( ) = = window ) {
SDL_SetKeyboardFocus ( NULL ) ;
}
}
}
}
2015-06-21 17:33:46 +02:00
void SDL_WinRTApp : : OnWindowClosed ( CoreWindow ^ sender , CoreWindowEventArgs ^ args )
{
# if LOG_WINDOW_EVENTS==1
SDL_Log ( " %s \n " , __FUNCTION__ ) ;
# endif
m_windowClosed = true ;
}
2015-11-26 00:41:39 -05:00
void SDL_WinRTApp : : OnAppActivated ( CoreApplicationView ^ applicationView , IActivatedEventArgs ^ args )
2015-06-21 17:33:46 +02:00
{
CoreWindow : : GetForCurrentThread ( ) - > Activate ( ) ;
}
void SDL_WinRTApp : : OnSuspending ( Platform : : Object ^ sender , SuspendingEventArgs ^ args )
{
// Save app state asynchronously after requesting a deferral. Holding a deferral
// indicates that the application is busy performing suspending operations. Be
// aware that a deferral may not be held indefinitely. After about five seconds,
// the app will be forced to exit.
// ... but first, let the app know it's about to go to the background.
// The separation of events may be important, given that the deferral
// runs in a separate thread. This'll make SDL_APP_WILLENTERBACKGROUND
// the only event among the two that runs in the main thread. Given
// that a few WinRT operations can only be done from the main thread
// (things that access the WinRT CoreWindow are one example of this),
// this could be important.
SDL_SendAppEvent ( SDL_APP_WILLENTERBACKGROUND ) ;
SuspendingDeferral ^ deferral = args - > SuspendingOperation - > GetDeferral ( ) ;
create_task ( [ this , deferral ] ( )
{
// Send an app did-enter-background event immediately to observers.
// CoreDispatcher::ProcessEvents, which is the backbone on which
// SDL_WinRTApp::PumpEvents is built, will not return to its caller
// once it sends out a suspend event. Any events posted to SDL's
// event queue won't get received until the WinRT app is resumed.
// SDL_AddEventWatch() may be used to receive app-suspend events on
// WinRT.
SDL_SendAppEvent ( SDL_APP_DIDENTERBACKGROUND ) ;
// Let the Direct3D 11 renderer prepare for the app to be backgrounded.
// This is necessary for Windows 8.1, possibly elsewhere in the future.
// More details at: http://msdn.microsoft.com/en-us/library/windows/apps/Hh994929.aspx
# if SDL_VIDEO_RENDER_D3D11 && !SDL_RENDER_DISABLED
if ( WINRT_GlobalSDLWindow ) {
SDL_Renderer * renderer = SDL_GetRenderer ( WINRT_GlobalSDLWindow ) ;
if ( renderer & & ( SDL_strcmp ( renderer - > info . name , " direct3d11 " ) = = 0 ) ) {
D3D11_Trim ( renderer ) ;
}
}
# endif
deferral - > Complete ( ) ;
} ) ;
}
void SDL_WinRTApp : : OnResuming ( Platform : : Object ^ sender , Platform : : Object ^ args )
{
// Restore any data or state that was unloaded on suspend. By default, data
// and state are persisted when resuming from suspend. Note that these events
// do not occur if the app was previously terminated.
SDL_SendAppEvent ( SDL_APP_WILLENTERFOREGROUND ) ;
SDL_SendAppEvent ( SDL_APP_DIDENTERFOREGROUND ) ;
}
void SDL_WinRTApp : : OnExiting ( Platform : : Object ^ sender , Platform : : Object ^ args )
{
SDL_SendAppEvent ( SDL_APP_TERMINATING ) ;
}
static void
WINRT_LogPointerEvent ( const char * header , Windows : : UI : : Core : : PointerEventArgs ^ args , Windows : : Foundation : : Point transformedPoint )
{
Windows : : UI : : Input : : PointerPoint ^ pt = args - > CurrentPoint ;
SDL_Log ( " %s: Position={%f,%f}, Transformed Pos={%f, %f}, MouseWheelDelta=%d, FrameId=%d, PointerId=%d, SDL button=%d \n " ,
header ,
pt - > Position . X , pt - > Position . Y ,
transformedPoint . X , transformedPoint . Y ,
pt - > Properties - > MouseWheelDelta ,
pt - > FrameId ,
pt - > PointerId ,
WINRT_GetSDLButtonForPointerPoint ( pt ) ) ;
}
void SDL_WinRTApp : : OnPointerPressed ( CoreWindow ^ sender , PointerEventArgs ^ args )
{
# if LOG_POINTER_EVENTS
WINRT_LogPointerEvent ( " pointer pressed " , args , WINRT_TransformCursorPosition ( WINRT_GlobalSDLWindow , args - > CurrentPoint - > Position , TransformToSDLWindowSize ) ) ;
# endif
WINRT_ProcessPointerPressedEvent ( WINRT_GlobalSDLWindow , args - > CurrentPoint ) ;
}
void SDL_WinRTApp : : OnPointerMoved ( CoreWindow ^ sender , PointerEventArgs ^ args )
{
# if LOG_POINTER_EVENTS
WINRT_LogPointerEvent ( " pointer moved " , args , WINRT_TransformCursorPosition ( WINRT_GlobalSDLWindow , args - > CurrentPoint - > Position , TransformToSDLWindowSize ) ) ;
# endif
WINRT_ProcessPointerMovedEvent ( WINRT_GlobalSDLWindow , args - > CurrentPoint ) ;
}
void SDL_WinRTApp : : OnPointerReleased ( CoreWindow ^ sender , PointerEventArgs ^ args )
{
# if LOG_POINTER_EVENTS
WINRT_LogPointerEvent ( " pointer released " , args , WINRT_TransformCursorPosition ( WINRT_GlobalSDLWindow , args - > CurrentPoint - > Position , TransformToSDLWindowSize ) ) ;
# endif
2015-11-26 00:41:39 -05:00
2015-06-21 17:33:46 +02:00
WINRT_ProcessPointerReleasedEvent ( WINRT_GlobalSDLWindow , args - > CurrentPoint ) ;
}
2015-11-26 00:41:39 -05:00
void SDL_WinRTApp : : OnPointerEntered ( CoreWindow ^ sender , PointerEventArgs ^ args )
{
# if LOG_POINTER_EVENTS
WINRT_LogPointerEvent ( " pointer entered " , args , WINRT_TransformCursorPosition ( WINRT_GlobalSDLWindow , args - > CurrentPoint - > Position , TransformToSDLWindowSize ) ) ;
# endif
WINRT_ProcessPointerEnteredEvent ( WINRT_GlobalSDLWindow , args - > CurrentPoint ) ;
}
void SDL_WinRTApp : : OnPointerExited ( CoreWindow ^ sender , PointerEventArgs ^ args )
{
# if LOG_POINTER_EVENTS
WINRT_LogPointerEvent ( " pointer exited " , args , WINRT_TransformCursorPosition ( WINRT_GlobalSDLWindow , args - > CurrentPoint - > Position , TransformToSDLWindowSize ) ) ;
# endif
WINRT_ProcessPointerExitedEvent ( WINRT_GlobalSDLWindow , args - > CurrentPoint ) ;
}
2015-06-21 17:33:46 +02:00
void SDL_WinRTApp : : OnPointerWheelChanged ( CoreWindow ^ sender , PointerEventArgs ^ args )
{
# if LOG_POINTER_EVENTS
WINRT_LogPointerEvent ( " pointer wheel changed " , args , WINRT_TransformCursorPosition ( WINRT_GlobalSDLWindow , args - > CurrentPoint - > Position , TransformToSDLWindowSize ) ) ;
# endif
WINRT_ProcessPointerWheelChangedEvent ( WINRT_GlobalSDLWindow , args - > CurrentPoint ) ;
}
void SDL_WinRTApp : : OnMouseMoved ( MouseDevice ^ mouseDevice , MouseEventArgs ^ args )
{
WINRT_ProcessMouseMovedEvent ( WINRT_GlobalSDLWindow , args ) ;
}
void SDL_WinRTApp : : OnKeyDown ( Windows : : UI : : Core : : CoreWindow ^ sender , Windows : : UI : : Core : : KeyEventArgs ^ args )
{
WINRT_ProcessKeyDownEvent ( args ) ;
}
void SDL_WinRTApp : : OnKeyUp ( Windows : : UI : : Core : : CoreWindow ^ sender , Windows : : UI : : Core : : KeyEventArgs ^ args )
{
WINRT_ProcessKeyUpEvent ( args ) ;
}
void SDL_WinRTApp : : OnCharacterReceived ( Windows : : UI : : Core : : CoreWindow ^ sender , Windows : : UI : : Core : : CharacterReceivedEventArgs ^ args )
{
WINRT_ProcessCharacterReceivedEvent ( args ) ;
}
2015-12-09 21:34:56 -05:00
template < typename BackButtonEventArgs >
static void WINRT_OnBackButtonPressed ( BackButtonEventArgs ^ args )
2015-06-21 17:33:46 +02:00
{
SDL_SendKeyboardKey ( SDL_PRESSED , SDL_SCANCODE_AC_BACK ) ;
SDL_SendKeyboardKey ( SDL_RELEASED , SDL_SCANCODE_AC_BACK ) ;
const char * hint = SDL_GetHint ( SDL_HINT_WINRT_HANDLE_BACK_BUTTON ) ;
if ( hint ) {
if ( * hint = = ' 1 ' ) {
args - > Handled = true ;
}
}
}
2015-12-09 21:34:56 -05:00
# if NTDDI_VERSION == NTDDI_WIN10
void SDL_WinRTApp : : OnBackButtonPressed ( Platform : : Object ^ sender , Windows : : UI : : Core : : BackRequestedEventArgs ^ args )
{
WINRT_OnBackButtonPressed ( args ) ;
}
# elif WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
void SDL_WinRTApp : : OnBackButtonPressed ( Platform : : Object ^ sender , Windows : : Phone : : UI : : Input : : BackPressedEventArgs ^ args )
{
WINRT_OnBackButtonPressed ( args ) ;
}
2015-06-21 17:33:46 +02:00
# endif