WinRT: experimental and preliminary support for XAML-based overlays on Windows 8/RT
authorDavid Ludwig <dludwig@pobox.com>
Tue, 27 Aug 2013 21:21:09 -0400
changeset 8505 a76a3842c9eb
parent 8504 3205689d1fff
child 8506 dc013502fd78
WinRT: experimental and preliminary support for XAML-based overlays on Windows 8/RT The XAML support here is still rudimentary. Bugs do exist. You've been warned. XAML support in Windows Phone 8 is not yet available (in SDL/WinRT).
VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj
VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj.filters
include/SDL_system.h
src/core/winrt/SDL_winrtapp.cpp
src/core/winrt/SDL_winrtxaml.cpp
src/render/direct3d11/SDL_render_d3d11.cpp
src/video/winrt/SDL_winrtevents.cpp
src/video/winrt/SDL_winrtevents_c.h
src/video/winrt/SDL_winrtmouse.cpp
src/video/winrt/SDL_winrtvideo.cpp
--- a/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj	Tue Aug 27 13:03:43 2013 -0400
+++ b/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj	Tue Aug 27 21:21:09 2013 -0400
@@ -70,6 +70,14 @@
       <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</CompileAsWinRT>
       <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</CompileAsWinRT>
     </ClCompile>
+    <ClCompile Include="..\..\src\core\winrt\SDL_winrtxaml.cpp">
+      <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</CompileAsWinRT>
+      <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</CompileAsWinRT>
+      <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</CompileAsWinRT>
+      <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</CompileAsWinRT>
+      <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</CompileAsWinRT>
+      <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</CompileAsWinRT>
+    </ClCompile>
     <ClCompile Include="..\..\src\cpuinfo\SDL_cpuinfo.c" />
     <ClCompile Include="..\..\src\events\SDL_clipboardevents.c" />
     <ClCompile Include="..\..\src\events\SDL_dropevents.c" />
--- a/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj.filters	Tue Aug 27 13:03:43 2013 -0400
+++ b/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj.filters	Tue Aug 27 21:21:09 2013 -0400
@@ -270,6 +270,9 @@
     <ClCompile Include="..\..\src\joystick\winrt\SDL_xinputjoystick.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\core\winrt\SDL_winrtxaml.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\include\begin_code.h">
--- a/include/SDL_system.h	Tue Aug 27 13:03:43 2013 -0400
+++ b/include/SDL_system.h	Tue Aug 27 21:21:09 2013 -0400
@@ -155,6 +155,20 @@
  */
 extern DECLSPEC const char * SDLCALL SDL_WinRTGetFSPathUTF8(SDL_WinRT_Path pathType);
 
+#ifdef __cplusplus_winrt
+/**
+ *  \brief Initializes a WinRT and XAML based application.
+ *
+ *  \param backgroundPanel The XAML background panel to draw onto and receive
+ *      events from.
+ *  \param mainFunction The SDL app's C-style main().
+ *  \ret 0 on success, -1 on failure.  On failure, use SDL_GetError to retrieve more
+ *      information on the failure.
+ */
+/* TODO, WinRT: consider making SDL_WinRTInitXAMLApp accept a void pointer to IUnknown, rather than a C++/CX reference */
+extern DECLSPEC int SDLCALL SDL_WinRTInitXAMLApp(Platform::Object^ backgroundPanel, int (*mainFunction)(int, char **));
+
+#endif // ifdef __cplusplus_winrt
 
 #endif /* __WINRT__ */
 
--- a/src/core/winrt/SDL_winrtapp.cpp	Tue Aug 27 13:03:43 2013 -0400
+++ b/src/core/winrt/SDL_winrtapp.cpp	Tue Aug 27 21:21:09 2013 -0400
@@ -361,17 +361,17 @@
 
 void SDL_WinRTApp::OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args)
 {
-    WINRT_ProcessPointerPressedEvent(WINRT_GlobalSDLWindow, args);
+    WINRT_ProcessPointerPressedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
 }
 
 void SDL_WinRTApp::OnPointerReleased(CoreWindow^ sender, PointerEventArgs^ args)
 {
-    WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args);
+    WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
 }
 
 void SDL_WinRTApp::OnPointerWheelChanged(CoreWindow^ sender, PointerEventArgs^ args)
 {
-    WINRT_ProcessPointerWheelChangedEvent(WINRT_GlobalSDLWindow, args);
+    WINRT_ProcessPointerWheelChangedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
 }
 
 void SDL_WinRTApp::OnMouseMoved(MouseDevice^ mouseDevice, MouseEventArgs^ args)
@@ -381,7 +381,7 @@
 
 void SDL_WinRTApp::OnPointerMoved(CoreWindow^ sender, PointerEventArgs^ args)
 {
-    WINRT_ProcessPointerMovedEvent(WINRT_GlobalSDLWindow, args);
+    WINRT_ProcessPointerMovedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint);
 }
 
 void SDL_WinRTApp::OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/winrt/SDL_winrtxaml.cpp	Tue Aug 27 21:21:09 2013 -0400
@@ -0,0 +1,162 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 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.
+*/
+
+/* Windows includes */
+#include <agile.h>
+#include <Windows.h>
+
+#if WINAPI_FAMILY == WINAPI_FAMILY_APP
+#include <windows.ui.xaml.media.dxinterop.h>
+#endif
+
+
+/* SDL includes */
+#include "SDL.h"
+//#include "SDL_error.h"
+//#include "SDL_log.h"
+//#include "SDL_main.h"
+//#include "SDL_system.h"
+#include "../../video/winrt/SDL_winrtevents_c.h"
+
+
+/* External globals: */
+extern SDL_Window * WINRT_GlobalSDLWindow;
+
+
+/* Internal globals: */
+SDL_bool WINRT_XAMLWasEnabled = SDL_FALSE;
+int (*WINRT_XAMLAppMainFunction)(int, char **) = NULL;
+
+#if WINAPI_FAMILY == WINAPI_FAMILY_APP
+ISwapChainBackgroundPanelNative * WINRT_GlobalSwapChainBackgroundPanelNative = NULL;
+static Windows::Foundation::EventRegistrationToken	WINRT_XAMLAppEventToken;
+#endif
+
+
+/*
+ * Input event handlers (XAML)
+ */
+#if WINAPI_FAMILY == WINAPI_FAMILY_APP
+
+static void
+WINRT_OnPointerPressedViaXAML(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ args)
+{
+    WINRT_ProcessPointerPressedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr));
+}
+
+static void
+WINRT_OnPointerReleasedViaXAML(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ args)
+{
+    WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr));
+}
+
+static void
+WINRT_OnPointerWheelChangedViaXAML(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ args)
+{
+    WINRT_ProcessPointerWheelChangedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr));
+}
+
+static void
+WINRT_OnPointerMovedViaXAML(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ args)
+{
+    WINRT_ProcessPointerMovedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr));
+}
+
+#endif // WINAPI_FAMILY == WINAPI_FAMILY_APP
+
+
+/*
+ * XAML-to-SDL Rendering Callback
+ */
+#if WINAPI_FAMILY == WINAPI_FAMILY_APP
+
+static void
+WINRT_OnRenderViaXAML(_In_ Platform::Object^ sender, _In_ Platform::Object^ args)
+{
+    WINRT_CycleXAMLThread();
+}
+
+#endif // WINAPI_FAMILY == WINAPI_FAMILY_APP
+
+
+/*
+ * SDL + XAML Initialization
+ */
+
+extern "C" int
+SDL_WinRTInitXAMLApp(Platform::Object ^backgroundPanel, int (*mainFunction)(int, char **))
+{
+#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
+    return SDL_SetError("XAML support is not yet available in Windows Phone.");
+#else
+    // Declare C++/CX namespaces:
+    using namespace Platform;
+    using namespace Windows::Foundation;
+    using namespace Windows::UI::Core;
+    using namespace Windows::UI::Xaml;
+    using namespace Windows::UI::Xaml::Controls;
+    using namespace Windows::UI::Xaml::Input;
+    using namespace Windows::UI::Xaml::Media;
+
+    // Make sure we have a valid XAML element (to draw onto):
+    if ( ! backgroundPanel) {
+        return SDL_SetError("'backgroundPanel' can't be NULL");
+    }
+
+    SwapChainBackgroundPanel ^swapChainBackgroundPanel = dynamic_cast<SwapChainBackgroundPanel ^>(backgroundPanel);
+    if ( ! swapChainBackgroundPanel) {
+        return SDL_SetError("An unknown or unsupported type of XAML control was specified.");
+    }
+
+    // Setup event handlers:
+    swapChainBackgroundPanel->PointerPressed += ref new PointerEventHandler(WINRT_OnPointerPressedViaXAML);
+    swapChainBackgroundPanel->PointerReleased += ref new PointerEventHandler(WINRT_OnPointerReleasedViaXAML);
+    swapChainBackgroundPanel->PointerWheelChanged += ref new PointerEventHandler(WINRT_OnPointerWheelChangedViaXAML);
+    swapChainBackgroundPanel->PointerMoved += ref new PointerEventHandler(WINRT_OnPointerMovedViaXAML);
+
+    // Setup for rendering:
+    IInspectable *panelInspectable = (IInspectable*) reinterpret_cast<IInspectable*>(swapChainBackgroundPanel);
+    panelInspectable->QueryInterface(__uuidof(ISwapChainBackgroundPanelNative), (void **)&WINRT_GlobalSwapChainBackgroundPanelNative);
+
+    WINRT_XAMLAppEventToken = CompositionTarget::Rendering::add(ref new EventHandler<Object^>(WINRT_OnRenderViaXAML));
+
+    // Make sure the app is ready to call the SDL-centric main() function:
+    WINRT_XAMLAppMainFunction = mainFunction;
+    SDL_SetMainReady();
+
+    // Make sure video-init knows that we're initializing XAML:
+    SDL_bool oldXAMLWasEnabledValue = WINRT_XAMLWasEnabled;
+    WINRT_XAMLWasEnabled = SDL_TRUE;
+
+    // Make sure video modes are detected now, while we still have access to the WinRT
+    // CoreWindow.  WinRT will not allow the app's CoreWindow to be accessed via the
+    // SDL/WinRT thread.
+    if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
+        // SDL_InitSubSystem will, on error, set the SDL error.  Let that propogate to
+        // the caller to here:
+        WINRT_XAMLWasEnabled = oldXAMLWasEnabledValue;
+        return -1;
+    }
+
+    // All done, for now.
+    return 0;
+#endif // WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP  /  else
+}
--- a/src/render/direct3d11/SDL_render_d3d11.cpp	Tue Aug 27 13:03:43 2013 -0400
+++ b/src/render/direct3d11/SDL_render_d3d11.cpp	Tue Aug 27 21:21:09 2013 -0400
@@ -26,6 +26,11 @@
 #ifdef __WINRT__
 #include <windows.ui.core.h>
 #include <windows.foundation.h>
+
+#if WINAPI_FAMILY == WINAPI_FAMILY_APP
+#include <windows.ui.xaml.media.dxinterop.h>
+#endif
+
 #endif
 
 extern "C" {
@@ -608,6 +613,13 @@
 }
 #endif
 
+
+#if WINAPI_FAMILY == WINAPI_FAMILY_APP
+// TODO, WinRT, XAML: get the ISwapChainBackgroundPanelNative from something other than a global var
+extern ISwapChainBackgroundPanelNative * WINRT_GlobalSwapChainBackgroundPanelNative;
+#endif
+
+
 // Initialize all resources that change when the window's size changes.
 // TODO, WinRT: get D3D11_CreateWindowSizeDependentResources working on Win32
 HRESULT
@@ -619,15 +631,28 @@
 
     // Store the window bounds so the next time we get a SizeChanged event we can
     // avoid rebuilding everything if the size is identical.
-    ABI::Windows::Foundation::Rect coreWindowBounds;
-    result = coreWindow->get_Bounds(&coreWindowBounds);
-    if (FAILED(result)) {
-        WIN_SetErrorFromHRESULT(__FUNCTION__", Get Window Bounds", result);
-        return result;
+    ABI::Windows::Foundation::Rect nativeWindowBounds;
+    if (coreWindow) {
+        result = coreWindow->get_Bounds(&nativeWindowBounds);
+        if (FAILED(result)) {
+            WIN_SetErrorFromHRESULT(__FUNCTION__", Get Window Bounds", result);
+            return result;
+        }
+    } else {
+        // TODO, WinRT, XAML: clean up window-bounds code in D3D11_CreateWindowSizeDependentResources
+        SDL_DisplayMode displayMode;
+        if (SDL_GetDesktopDisplayMode(0, &displayMode) < 0) {
+            SDL_SetError(__FUNCTION__", Get Window Bounds (XAML): Unable to retrieve the native window's size");
+            return E_FAIL;
+        }
+
+        nativeWindowBounds.Width = (FLOAT) displayMode.w;
+        nativeWindowBounds.Height = (FLOAT) displayMode.h;
     }
 
-    data->windowSizeInDIPs.x = coreWindowBounds.Width;
-    data->windowSizeInDIPs.y = coreWindowBounds.Height;
+    // TODO, WinRT, XAML: see if window/control sizes are in DIPs, or something else.  If something else, then adjust renderer size tracking accordingly.
+    data->windowSizeInDIPs.x = nativeWindowBounds.Width;
+    data->windowSizeInDIPs.y = nativeWindowBounds.Height;
 
     // Calculate the necessary swap chain and render target size in pixels.
     float windowWidth = D3D11_ConvertDipsToPixels(data->windowSizeInDIPs.x);
@@ -660,6 +685,8 @@
     }
     else
     {
+        const bool usingXAML = (coreWindow == nullptr);
+
         // Otherwise, create a new one using the same adapter as the existing Direct3D device.
         DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
         swapChainDesc.Width = static_cast<UINT>(data->renderTargetSize.x); // Match the size of the window.
@@ -674,7 +701,11 @@
         swapChainDesc.Scaling = DXGI_SCALING_STRETCH; // On phone, only stretch and aspect-ratio stretch scaling are allowed.
         swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; // On phone, no swap effects are supported.
 #else
-        swapChainDesc.Scaling = DXGI_SCALING_NONE;
+        if (usingXAML) {
+            swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
+        } else {
+            swapChainDesc.Scaling = DXGI_SCALING_NONE;
+        }
         swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use this SwapEffect.
 #endif
         swapChainDesc.Flags = 0;
@@ -703,25 +734,48 @@
             return result;
         }
 
-        IUnknown * coreWindowAsIUnknown = nullptr;
-        result = coreWindow->QueryInterface(&coreWindowAsIUnknown);
-        if (FAILED(result)) {
-            WIN_SetErrorFromHRESULT(__FUNCTION__ ", CoreWindow to IUnknown", result);
-            return result;
-        }
+        if (usingXAML) {
+            result = dxgiFactory->CreateSwapChainForComposition(
+                data->d3dDevice.Get(),
+                &swapChainDesc,
+                nullptr,
+                &data->swapChain);
+            if (FAILED(result)) {
+                WIN_SetErrorFromHRESULT(__FUNCTION__ ", CreateSwapChainForComposition", result);
+                return result;
+            }
 
-        result = dxgiFactory->CreateSwapChainForCoreWindow(
-            data->d3dDevice.Get(),
-            coreWindowAsIUnknown,
-            &swapChainDesc,
-            nullptr, // Allow on all displays.
-            &data->swapChain
-            );
-        if (FAILED(result)) {
-            WIN_SetErrorFromHRESULT(__FUNCTION__, result);
-            return result;
+#if WINAPI_FAMILY == WINAPI_FAMILY_APP
+            result = WINRT_GlobalSwapChainBackgroundPanelNative->SetSwapChain(data->swapChain.Get());
+            if (FAILED(result)) {
+                WIN_SetErrorFromHRESULT(__FUNCTION__ ", ISwapChainBackgroundPanelNative::SetSwapChain", result);
+                return result;
+            }
+#else
+            SDL_SetError(__FUNCTION__ ", XAML support is not yet available for Windows Phone");
+            return E_FAIL;
+#endif
+        } else {
+            IUnknown * coreWindowAsIUnknown = nullptr;
+            result = coreWindow->QueryInterface(&coreWindowAsIUnknown);
+            if (FAILED(result)) {
+                WIN_SetErrorFromHRESULT(__FUNCTION__ ", CoreWindow to IUnknown", result);
+                return result;
+            }
+
+            result = dxgiFactory->CreateSwapChainForCoreWindow(
+                data->d3dDevice.Get(),
+                coreWindowAsIUnknown,
+                &swapChainDesc,
+                nullptr, // Allow on all displays.
+                &data->swapChain
+                );
+            if (FAILED(result)) {
+                WIN_SetErrorFromHRESULT(__FUNCTION__, result);
+                return result;
+            }
         }
-            
+        
         // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
         // ensures that the application will only render after each VSync, minimizing power consumption.
         result = dxgiDevice->SetMaximumFrameLatency(1);
--- a/src/video/winrt/SDL_winrtevents.cpp	Tue Aug 27 13:03:43 2013 -0400
+++ b/src/video/winrt/SDL_winrtevents.cpp	Tue Aug 27 21:21:09 2013 -0400
@@ -25,23 +25,117 @@
 /* SDL includes */
 #include "SDL_winrtevents_c.h"
 #include "../../core/winrt/SDL_winrtapp.h"
+#include "SDL_assert.h"
+#include "SDL_system.h"
 
 extern "C" {
 #include "../SDL_sysvideo.h"
 #include "../../events/SDL_events_c.h"
 }
 
+
+/* Forward declarations and globals */
 extern SDL_WinRTApp ^ SDL_WinRTGlobalApp;
+extern int (*WINRT_XAMLAppMainFunction)(int, char **);
+extern void WINRT_YieldXAMLThread();
 
 
-/* General event-management function(s) */
+/* Global event management */
 
 void
 WINRT_PumpEvents(_THIS)
 {
-    SDL_WinRTGlobalApp->PumpEvents();
+    if (SDL_WinRTGlobalApp) {
+        SDL_WinRTGlobalApp->PumpEvents();
+    } else if (WINRT_XAMLAppMainFunction) {
+        WINRT_YieldXAMLThread();
+    }
 }
 
+
+/* XAML Thread management */
+
+enum SDL_XAMLAppThreadState
+{
+    ThreadState_NotLaunched = 0,
+    ThreadState_Running,
+    ThreadState_Yielding
+};
+
+static SDL_XAMLAppThreadState _threadState = ThreadState_NotLaunched;
+static SDL_Thread * _XAMLThread = nullptr;
+static SDL_mutex * _mutex = nullptr;
+static SDL_cond * _cond = nullptr;
+
+static void
+WINRT_YieldXAMLThread()
+{
+    SDL_LockMutex(_mutex);
+    SDL_assert(_threadState == ThreadState_Running);
+    _threadState = ThreadState_Yielding;
+    SDL_UnlockMutex(_mutex);
+
+    SDL_CondSignal(_cond);
+
+    SDL_LockMutex(_mutex);
+    while (_threadState != ThreadState_Running) {
+        SDL_CondWait(_cond, _mutex);
+    }
+    SDL_UnlockMutex(_mutex);
+}
+
+static int
+WINRT_XAMLThreadMain(void * userdata)
+{
+    return WINRT_XAMLAppMainFunction(0, NULL);
+}
+
+void
+WINRT_CycleXAMLThread()
+{
+    switch (_threadState) {
+        case ThreadState_NotLaunched:
+        {
+            _cond = SDL_CreateCond();
+
+            _mutex = SDL_CreateMutex();
+            _threadState = ThreadState_Running;
+            _XAMLThread = SDL_CreateThread(WINRT_XAMLThreadMain, "SDL/XAML App Thread", nullptr);
+
+            SDL_LockMutex(_mutex);
+            while (_threadState != ThreadState_Yielding) {
+                SDL_CondWait(_cond, _mutex);
+            }
+            SDL_UnlockMutex(_mutex);
+
+            break;
+        }
+
+        case ThreadState_Running:
+        {
+            SDL_assert(false);
+            break;
+        }
+
+        case ThreadState_Yielding:
+        {
+            SDL_LockMutex(_mutex);
+            SDL_assert(_threadState == ThreadState_Yielding);
+            _threadState = ThreadState_Running;
+            SDL_UnlockMutex(_mutex);
+
+            SDL_CondSignal(_cond);
+
+            SDL_LockMutex(_mutex);
+            while (_threadState != ThreadState_Yielding) {
+                SDL_CondWait(_cond, _mutex);
+            }
+            SDL_UnlockMutex(_mutex);
+        }
+    }
+}
+
+
 #endif /* SDL_VIDEO_DRIVER_WINRT */
 
 /* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/winrt/SDL_winrtevents_c.h	Tue Aug 27 13:03:43 2013 -0400
+++ b/src/video/winrt/SDL_winrtevents_c.h	Tue Aug 27 21:21:09 2013 -0400
@@ -50,10 +50,13 @@
 
 /* Pointers (Mice, Touch, etc.) */
 extern void WINRT_ProcessMouseMovedEvent(SDL_Window * window, Windows::Devices::Input::MouseEventArgs ^args);
-extern void WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args);
-extern void WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args);
-extern void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args);
-extern void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args);
+extern void WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
+extern void WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
+extern void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
+extern void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint);
+
+/* XAML Thread Management */
+extern void WINRT_CycleXAMLThread();
 
 #endif
 
--- a/src/video/winrt/SDL_winrtmouse.cpp	Tue Aug 27 13:03:43 2013 -0400
+++ b/src/video/winrt/SDL_winrtmouse.cpp	Tue Aug 27 21:21:09 2013 -0400
@@ -110,6 +110,11 @@
 static int
 WINRT_ShowCursor(SDL_Cursor * cursor)
 {
+    // TODO, WinRT, XAML: make WINRT_ShowCursor work when XAML support is enabled.
+    if ( ! CoreWindow::GetForCurrentThread()) {
+        return 0;
+    }
+
     if (cursor) {
         CoreCursor ^* theCursor = (CoreCursor ^*) cursor->driverdata;
         CoreWindow::GetForCurrentThread()->PointerCursor = *theCursor;
@@ -334,25 +339,25 @@
 }
 
 void
-WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args)
+WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
 {
 #if LOG_POINTER_EVENTS
-    WINRT_LogPointerEvent("pointer moved", args, TransformCursor(args->CurrentPoint->Position));
+    WINRT_LogPointerEvent("pointer moved", args, TransformCursor(pointerPoint->Position));
 #endif
 
     if (!window || WINRT_UseRelativeMouseMode) {
         return;
     }
 
-    Windows::Foundation::Point transformedPoint = TransformCursor(window, args->CurrentPoint->Position);
+    Windows::Foundation::Point transformedPoint = TransformCursor(window, pointerPoint->Position);
     SDL_SendMouseMotion(window, 0, 0, (int)transformedPoint.X, (int)transformedPoint.Y);
 }
 
 void
-WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args)
+WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
 {
 #if LOG_POINTER_EVENTS
-    WINRT_LogPointerEvent("wheel changed", args, TransformCursor(args->CurrentPoint->Position));
+    WINRT_LogPointerEvent("wheel changed", args, TransformCursor(pointerPoint->Position));
 #endif
 
     if (!window) {
@@ -360,11 +365,11 @@
     }
 
     // FIXME: This may need to accumulate deltas up to WHEEL_DELTA
-    short motion = args->CurrentPoint->Properties->MouseWheelDelta / WHEEL_DELTA;
+    short motion = pointerPoint->Properties->MouseWheelDelta / WHEEL_DELTA;
     SDL_SendMouseWheel(window, 0, 0, motion);
 }
 
-void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args)
+void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
 {
 #if LOG_POINTER_EVENTS
     WINRT_LogPointerEvent("mouse up", args, TransformCursor(args->CurrentPoint->Position));
@@ -374,13 +379,13 @@
         return;
     }
 
-    Uint8 button = WINRT_GetSDLButtonForPointerPoint(args->CurrentPoint);
+    Uint8 button = WINRT_GetSDLButtonForPointerPoint(pointerPoint);
     if (button) {
         SDL_SendMouseButton(window, 0, SDL_RELEASED, button);
     }
 }
 
-void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args)
+void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
 {
 #if LOG_POINTER_EVENTS
     WINRT_LogPointerEvent("mouse down", args, TransformCursor(args->CurrentPoint->Position));
@@ -390,7 +395,7 @@
         return;
     }
 
-    Uint8 button = WINRT_GetSDLButtonForPointerPoint(args->CurrentPoint);
+    Uint8 button = WINRT_GetSDLButtonForPointerPoint(pointerPoint);
     if (button) {
         SDL_SendMouseButton(window, 0, SDL_PRESSED, button);
     }
--- a/src/video/winrt/SDL_winrtvideo.cpp	Tue Aug 27 13:03:43 2013 -0400
+++ b/src/video/winrt/SDL_winrtvideo.cpp	Tue Aug 27 21:21:09 2013 -0400
@@ -47,8 +47,11 @@
 #include "../../core/winrt/SDL_winrtapp.h"
 #include "SDL_winrtevents_c.h"
 #include "SDL_winrtmouse.h"
+#include "SDL_main.h"
+#include "SDL_system.h"
 
 extern SDL_WinRTApp ^ SDL_WinRTGlobalApp;
+extern SDL_bool WINRT_XAMLWasEnabled;
 
 
 /* Initialization/Query functions */
@@ -84,6 +87,7 @@
 SDL_VideoDevice * WINRT_GlobalSDLVideoDevice = NULL;
 
 
+
 /* WinRT driver bootstrap functions */
 
 static int
@@ -154,6 +158,13 @@
     SDL_DisplayMode mode;
     SDL_zero(mode);
 
+    // Go no further if a native window cannot be accessed.  This can happen,
+    // for example, if this function is called from certain threads, such as
+    // the SDL/XAML thread.
+    if (!CoreWindow::GetForCurrentThread()) {
+        return mode;
+    }
+
     // Fill in most fields:
     mode.format = SDL_PIXELFORMAT_RGB888;
     mode.refresh_rate = 0;  // TODO, WinRT: see if refresh rate data is available, or relevant (for WinRT apps)
@@ -169,11 +180,15 @@
     return mode;
 }
 
-
-static int
+int
 WINRT_InitModes(_THIS)
 {
+    // Retrieve the display mode:
     SDL_DisplayMode mode = WINRT_CalcDisplayModeUsingNativeWindow();
+    if (mode.w == 0 || mode.h == 0) {
+        return SDL_SetError("Unable to calculate the WinRT window/display's size");
+    }
+
     if (SDL_AddBasicVideoDisplay(&mode) < 0) {
         return -1;
     }
@@ -211,7 +226,16 @@
     }
     window->driverdata = data;
     data->sdlWindow = window;
-    data->coreWindow = CoreWindow::GetForCurrentThread();
+
+    /* 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();
+    }
 
     /* Make sure the window is considered to be positioned at {0,0},
        and is considered fullscreen, shown, and the like.