diff --git a/VisualC-WinPhone/SDL/SDL_VS2012-WinPhone.vcxproj b/VisualC-WinPhone/SDL/SDL_VS2012-WinPhone.vcxproj
index 1db16b019..231f4afe8 100644
--- a/VisualC-WinPhone/SDL/SDL_VS2012-WinPhone.vcxproj
+++ b/VisualC-WinPhone/SDL/SDL_VS2012-WinPhone.vcxproj
@@ -198,6 +198,7 @@
+
@@ -381,6 +382,12 @@
true
true
+
+ true
+ true
+ true
+ true
+
true
true
diff --git a/VisualC-WinPhone/SDL/SDL_VS2012-WinPhone.vcxproj.filters b/VisualC-WinPhone/SDL/SDL_VS2012-WinPhone.vcxproj.filters
index 4c726d7a3..0f039415e 100644
--- a/VisualC-WinPhone/SDL/SDL_VS2012-WinPhone.vcxproj.filters
+++ b/VisualC-WinPhone/SDL/SDL_VS2012-WinPhone.vcxproj.filters
@@ -336,6 +336,9 @@
Source Files
+
+ Source Files
+
@@ -599,6 +602,9 @@
Source Files
+
+ Source Files
+
diff --git a/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj b/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj
index 97286011f..613775e9f 100644
--- a/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj
+++ b/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj
@@ -176,6 +176,14 @@
true
true
+
+ true
+ true
+ true
+ true
+ true
+ true
+
true
true
@@ -244,6 +252,7 @@
+
diff --git a/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj.filters b/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj.filters
index 847d900e0..927ce6c73 100644
--- a/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj.filters
+++ b/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj.filters
@@ -270,6 +270,9 @@
Source Files
+
+ Source Files
+
Source Files
@@ -602,6 +605,9 @@
Source Files
+
+ Source Files
+
diff --git a/src/core/winrt/SDL_winrtapp.cpp b/src/core/winrt/SDL_winrtapp.cpp
index aecab9a62..6b4de54b1 100644
--- a/src/core/winrt/SDL_winrtapp.cpp
+++ b/src/core/winrt/SDL_winrtapp.cpp
@@ -37,12 +37,9 @@ extern "C" {
}
#include "../../video/winrt/SDL_winrtevents_c.h"
+#include "../../video/winrt/SDL_winrtvideo_cpp.h"
#include "SDL_winrtapp.h"
-extern SDL_Window * WINRT_GlobalSDLWindow;
-extern SDL_VideoDevice * WINRT_GlobalSDLVideoDevice;
-extern SDL_DisplayMode WINRT_CalcDisplayModeUsingNativeWindow();
-
// Compile-time debugging options:
// To enable, uncomment; to disable, comment them out.
diff --git a/src/core/winrt/SDL_winrtapp.h b/src/core/winrt/SDL_winrtapp.h
index 93fd61ade..d9cf33e9e 100644
--- a/src/core/winrt/SDL_winrtapp.h
+++ b/src/core/winrt/SDL_winrtapp.h
@@ -38,3 +38,5 @@ private:
bool m_windowClosed;
bool m_windowVisible;
};
+
+extern SDL_WinRTApp ^ SDL_WinRTGlobalApp;
diff --git a/src/core/winrt/SDL_winrtxaml.cpp b/src/core/winrt/SDL_winrtxaml.cpp
index 811f332d4..8b78a1f18 100644
--- a/src/core/winrt/SDL_winrtxaml.cpp
+++ b/src/core/winrt/SDL_winrtxaml.cpp
@@ -30,18 +30,13 @@
/* 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"
+#include "../../video/winrt/SDL_winrtvideo_cpp.h"
+#include "SDL_winrtxaml_cpp.h"
-/* External globals: */
-extern SDL_Window * WINRT_GlobalSDLWindow;
-
-/* Internal globals: */
+/* SDL-internal globals: */
SDL_bool WINRT_XAMLWasEnabled = SDL_FALSE;
int (*WINRT_XAMLAppMainFunction)(int, char **) = NULL;
diff --git a/src/core/winrt/SDL_winrtxaml_cpp.h b/src/core/winrt/SDL_winrtxaml_cpp.h
new file mode 100644
index 000000000..e0997becc
--- /dev/null
+++ b/src/core/winrt/SDL_winrtxaml_cpp.h
@@ -0,0 +1,33 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2012 Sam Lantinga
+
+ 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_config.h"
+
+#ifndef _SDL_winrtxaml_h
+#define _SDL_winrtxaml_h
+
+#include "SDL_types.h"
+
+#ifdef __cplusplus
+extern SDL_bool WINRT_XAMLWasEnabled;
+extern int (*WINRT_XAMLAppMainFunction)(int, char **);
+#endif // ifdef __cplusplus
+
+#endif // ifndef _SDL_winrtxaml_h
diff --git a/src/video/winrt/SDL_winrtevents.cpp b/src/video/winrt/SDL_winrtevents.cpp
index 10f4137af..94d71590a 100644
--- a/src/video/winrt/SDL_winrtevents.cpp
+++ b/src/video/winrt/SDL_winrtevents.cpp
@@ -22,9 +22,19 @@
#if SDL_VIDEO_DRIVER_WINRT
-/* SDL includes */
+/*
+ * Windows includes:
+ */
+#include
+using namespace Windows::UI::Core;
+using Windows::UI::Core::CoreCursor;
+
+/*
+ * SDL includes:
+ */
#include "SDL_winrtevents_c.h"
#include "../../core/winrt/SDL_winrtapp.h"
+#include "../../core/winrt/SDL_winrtxaml_cpp.h"
#include "SDL_assert.h"
#include "SDL_system.h"
@@ -34,10 +44,8 @@ extern "C" {
}
-/* Forward declarations and globals */
-extern SDL_WinRTApp ^ SDL_WinRTGlobalApp;
-extern int (*WINRT_XAMLAppMainFunction)(int, char **);
-extern void WINRT_YieldXAMLThread();
+/* Forward declarations */
+static void WINRT_YieldXAMLThread();
/* Global event management */
@@ -135,7 +143,6 @@ WINRT_CycleXAMLThread()
}
}
-
#endif /* SDL_VIDEO_DRIVER_WINRT */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/winrt/SDL_winrtevents_c.h b/src/video/winrt/SDL_winrtevents_c.h
index b8f132fd5..4d9ae6d4d 100644
--- a/src/video/winrt/SDL_winrtevents_c.h
+++ b/src/video/winrt/SDL_winrtevents_c.h
@@ -32,6 +32,7 @@ extern "C" {
extern "C" {
#endif
+extern void WINRT_InitTouch(_THIS);
extern void WINRT_PumpEvents(_THIS);
#ifdef __cplusplus
@@ -60,6 +61,6 @@ extern Windows::Foundation::Point WINRT_TransformCursorPosition(SDL_Window * win
/* XAML Thread Management */
extern void WINRT_CycleXAMLThread();
-#endif
+#endif // ifdef __cplusplus_winrt
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/winrt/SDL_winrtmouse.cpp b/src/video/winrt/SDL_winrtmouse.cpp
index d639210a5..6f385bab0 100644
--- a/src/video/winrt/SDL_winrtmouse.cpp
+++ b/src/video/winrt/SDL_winrtmouse.cpp
@@ -47,9 +47,7 @@ extern "C" {
#include "SDL_winrtmouse.h"
-static SDL_bool WINRT_UseRelativeMouseMode = SDL_FALSE;
-static SDL_TouchID WINRT_TouchID = 1;
-static unsigned int WINRT_LeftFingerDown = 0;
+extern "C" SDL_bool WINRT_UsingRelativeMouseMode = SDL_FALSE;
static SDL_Cursor *
@@ -131,7 +129,7 @@ WINRT_ShowCursor(SDL_Cursor * cursor)
static int
WINRT_SetRelativeMouseMode(SDL_bool enabled)
{
- WINRT_UseRelativeMouseMode = enabled;
+ WINRT_UsingRelativeMouseMode = enabled;
return 0;
}
@@ -156,9 +154,6 @@ WINRT_InitMouse(_THIS)
SDL_SetDefaultCursor(WINRT_CreateDefaultCursor());
#endif
-
- /* Init touch: */
- SDL_AddTouch(WINRT_TouchID, "");
}
void
@@ -166,326 +161,6 @@ WINRT_QuitMouse(_THIS)
{
}
-// Applies necessary geometric transformations to raw cursor positions:
-Windows::Foundation::Point
-WINRT_TransformCursorPosition(SDL_Window * window, Windows::Foundation::Point rawPosition)
-{
- using namespace Windows::Graphics::Display;
-
- if (!window) {
- return rawPosition;
- }
-
- SDL_WindowData * windowData = (SDL_WindowData *) window->driverdata;
- if (windowData->coreWindow == nullptr) {
- // For some reason, the window isn't associated with a CoreWindow.
- // This might end up being the case as XAML support is extended.
- // For now, if there's no CoreWindow attached to the SDL_Window,
- // don't do any transforms.
- return rawPosition;
- }
-
- // The CoreWindow can only be accessed on certain thread(s).
- SDL_assert(CoreWindow::GetForCurrentThread() != nullptr);
-
- CoreWindow ^ nativeWindow = windowData->coreWindow.Get();
- Windows::Foundation::Point outputPosition;
-
-#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
- outputPosition.X = rawPosition.X * (((float32)window->w) / nativeWindow->Bounds.Width);
- outputPosition.Y = rawPosition.Y * (((float32)window->h) / nativeWindow->Bounds.Height);
-#else
- switch (DisplayProperties::CurrentOrientation)
- {
- case DisplayOrientations::Portrait:
- outputPosition.X = rawPosition.X * (((float32)window->w) / nativeWindow->Bounds.Width);
- outputPosition.Y = rawPosition.Y * (((float32)window->h) / nativeWindow->Bounds.Height);
- break;
- case DisplayOrientations::PortraitFlipped:
- outputPosition.X = (float32)window->w - rawPosition.X * (((float32)window->w) / nativeWindow->Bounds.Width);
- outputPosition.Y = (float32)window->h - rawPosition.Y * (((float32)window->h) / nativeWindow->Bounds.Height);
- break;
- case DisplayOrientations::Landscape:
- outputPosition.X = rawPosition.Y * (((float32)window->w) / nativeWindow->Bounds.Height);
- outputPosition.Y = (float32)window->h - rawPosition.X * (((float32)window->h) / nativeWindow->Bounds.Width);
- break;
- case DisplayOrientations::LandscapeFlipped:
- outputPosition.X = (float32)window->w - rawPosition.Y * (((float32)window->w) / nativeWindow->Bounds.Height);
- outputPosition.Y = rawPosition.X * (((float32)window->h) / nativeWindow->Bounds.Width);
- break;
- default:
- break;
- }
-#endif
-
- return outputPosition;
-}
-
-static inline int
-_lround(float arg)
-{
- if (arg >= 0.0f) {
- return (int)floor(arg + 0.5f);
- } else {
- return (int)ceil(arg - 0.5f);
- }
-}
-
-void
-WINRT_ProcessMouseMovedEvent(SDL_Window * window, Windows::Devices::Input::MouseEventArgs ^args)
-{
- if (!window || !WINRT_UseRelativeMouseMode) {
- return;
- }
-
- // DLudwig, 2012-12-28: On some systems, namely Visual Studio's Windows
- // Simulator, as well as Windows 8 in a Parallels 8 VM, MouseEventArgs'
- // MouseDelta field often reports very large values. More information
- // on this can be found at the following pages on MSDN:
- // - http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/a3c789fa-f1c5-49c4-9c0a-7db88d0f90f8
- // - https://connect.microsoft.com/VisualStudio/Feedback/details/756515
- //
- // The values do not appear to be as large when running on some systems,
- // most notably a Surface RT. Furthermore, the values returned by
- // CoreWindow's PointerMoved event, and sent to this class' OnPointerMoved
- // method, do not ever appear to be large, even when MouseEventArgs'
- // MouseDelta is reporting to the contrary.
- //
- // On systems with the large-values behavior, it appears that the values
- // get reported as if the screen's size is 65536 units in both the X and Y
- // dimensions. This can be viewed by using Windows' now-private, "Raw Input"
- // APIs. (GetRawInputData, RegisterRawInputDevices, WM_INPUT, etc.)
- //
- // MSDN's documentation on MouseEventArgs' MouseDelta field (at
- // http://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.input.mouseeventargs.mousedelta ),
- // does not seem to indicate (to me) that its values should be so large. It
- // says that its values should be a "change in screen location". I could
- // be misinterpreting this, however a post on MSDN from a Microsoft engineer (see:
- // http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/09a9868e-95bb-4858-ba1a-cb4d2c298d62 ),
- // indicates that these values are in DIPs, which is the same unit used
- // by CoreWindow's PointerMoved events (via the Position field in its CurrentPoint
- // property. See http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.input.pointerpoint.position.aspx
- // for details.)
- //
- // To note, PointerMoved events are sent a 'RawPosition' value (via the
- // CurrentPoint property in MouseEventArgs), however these do not seem
- // to exhibit the same large-value behavior.
- //
- // The values passed via PointerMoved events can't always be used for relative
- // mouse motion, unfortunately. Its values are bound to the cursor's position,
- // which stops when it hits one of the screen's edges. This can be a problem in
- // first person shooters, whereby it is normal for mouse motion to travel far
- // along any one axis for a period of time. MouseMoved events do not have the
- // screen-bounding limitation, and can be used regardless of where the system's
- // cursor is.
- //
- // One possible workaround would be to programmatically set the cursor's
- // position to the screen's center (when SDL's relative mouse mode is enabled),
- // however WinRT does not yet seem to have the ability to set the cursor's
- // position via a public API. Win32 did this via an API call, SetCursorPos,
- // however WinRT makes this function be private. Apps that use it won't get
- // approved for distribution in the Windows Store. I've yet to be able to find
- // a suitable, store-friendly counterpart for WinRT.
- //
- // There may be some room for a workaround whereby OnPointerMoved's values
- // are compared to the values from OnMouseMoved in order to detect
- // when this bug is active. A suitable transformation could then be made to
- // OnMouseMoved's values. For now, however, the system-reported values are sent
- // to SDL with minimal transformation: from native screen coordinates (in DIPs)
- // to SDL window coordinates.
- //
- const Windows::Foundation::Point mouseDeltaInDIPs((float)args->MouseDelta.X, (float)args->MouseDelta.Y);
- const Windows::Foundation::Point mouseDeltaInSDLWindowCoords = WINRT_TransformCursorPosition(window, mouseDeltaInDIPs);
- SDL_SendMouseMotion(
- window,
- 0,
- 1,
- _lround(mouseDeltaInSDLWindowCoords.X),
- _lround(mouseDeltaInSDLWindowCoords.Y));
-}
-
-Uint8
-WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt)
-{
- using namespace Windows::UI::Input;
-
-#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
- return SDL_BUTTON_LEFT;
-#else
- switch (pt->Properties->PointerUpdateKind)
- {
- case PointerUpdateKind::LeftButtonPressed:
- case PointerUpdateKind::LeftButtonReleased:
- return SDL_BUTTON_LEFT;
-
- case PointerUpdateKind::RightButtonPressed:
- case PointerUpdateKind::RightButtonReleased:
- return SDL_BUTTON_RIGHT;
-
- case PointerUpdateKind::MiddleButtonPressed:
- case PointerUpdateKind::MiddleButtonReleased:
- return SDL_BUTTON_MIDDLE;
-
- case PointerUpdateKind::XButton1Pressed:
- case PointerUpdateKind::XButton1Released:
- return SDL_BUTTON_X1;
-
- case PointerUpdateKind::XButton2Pressed:
- case PointerUpdateKind::XButton2Released:
- return SDL_BUTTON_X2;
-
- default:
- break;
- }
-#endif
-
- return 0;
-}
-
-//const char *
-//WINRT_ConvertPointerUpdateKindToString(Windows::UI::Input::PointerUpdateKind kind)
-//{
-// using namespace Windows::UI::Input;
-//
-// switch (kind)
-// {
-// case PointerUpdateKind::Other:
-// return "Other";
-// case PointerUpdateKind::LeftButtonPressed:
-// return "LeftButtonPressed";
-// case PointerUpdateKind::LeftButtonReleased:
-// return "LeftButtonReleased";
-// case PointerUpdateKind::RightButtonPressed:
-// return "RightButtonPressed";
-// case PointerUpdateKind::RightButtonReleased:
-// return "RightButtonReleased";
-// case PointerUpdateKind::MiddleButtonPressed:
-// return "MiddleButtonPressed";
-// case PointerUpdateKind::MiddleButtonReleased:
-// return "MiddleButtonReleased";
-// case PointerUpdateKind::XButton1Pressed:
-// return "XButton1Pressed";
-// case PointerUpdateKind::XButton1Released:
-// return "XButton1Released";
-// case PointerUpdateKind::XButton2Pressed:
-// return "XButton2Pressed";
-// case PointerUpdateKind::XButton2Released:
-// return "XButton2Released";
-// }
-//
-// return "";
-//}
-
-static bool
-WINRT_IsTouchEvent(Windows::UI::Input::PointerPoint ^pointerPoint)
-{
-#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
- return true;
-#else
- using namespace Windows::Devices::Input;
- switch (pointerPoint->PointerDevice->PointerDeviceType) {
- case PointerDeviceType::Touch:
- case PointerDeviceType::Pen:
- return true;
- default:
- return false;
- }
-#endif
-}
-
-void
-WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
-{
- if (!window || WINRT_UseRelativeMouseMode) {
- return;
- }
-
- Windows::Foundation::Point transformedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position);
-
- if (pointerPoint->PointerId == WINRT_LeftFingerDown) {
- SDL_SendMouseMotion(window, 0, 0, (int)transformedPoint.X, (int)transformedPoint.Y);
- }
-
- if (WINRT_IsTouchEvent(pointerPoint)) {
- SDL_SendTouchMotion(
- WINRT_TouchID,
- (SDL_FingerID) pointerPoint->PointerId,
- transformedPoint.X,
- transformedPoint.Y,
- pointerPoint->Properties->Pressure);
- }
-}
-
-void
-WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
-{
- if (!window) {
- return;
- }
-
- // FIXME: This may need to accumulate deltas up to WHEEL_DELTA
- short motion = pointerPoint->Properties->MouseWheelDelta / WHEEL_DELTA;
- SDL_SendMouseWheel(window, 0, 0, motion);
-}
-
-void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
-{
- if (!window) {
- return;
- }
-
- Windows::Foundation::Point transformedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position);
-
- if (WINRT_LeftFingerDown == pointerPoint->PointerId) {
- Uint8 button = WINRT_GetSDLButtonForPointerPoint(pointerPoint);
- if (button) {
- SDL_SendMouseButton(window, 0, SDL_RELEASED, button);
- }
- WINRT_LeftFingerDown = 0;
- }
-
- if (WINRT_IsTouchEvent(pointerPoint)) {
- SDL_SendTouch(
- WINRT_TouchID,
- (SDL_FingerID) pointerPoint->PointerId,
- SDL_FALSE,
- transformedPoint.X,
- transformedPoint.Y,
- pointerPoint->Properties->Pressure);
- }
-}
-
-void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
-{
- if (!window) {
- return;
- }
-
- Windows::Foundation::Point transformedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position);
-
- if (!WINRT_LeftFingerDown) {
- Uint8 button = WINRT_GetSDLButtonForPointerPoint(pointerPoint);
- if (button) {
-#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
- SDL_SendMouseMotion(window, 0, 0, (int)transformedPoint.X, (int)transformedPoint.Y);
-#endif
- SDL_SendMouseButton(window, 0, SDL_PRESSED, button);
- }
-
- WINRT_LeftFingerDown = pointerPoint->PointerId;
- }
-
- if (WINRT_IsTouchEvent(pointerPoint)) {
- SDL_SendTouch(
- WINRT_TouchID,
- (SDL_FingerID) pointerPoint->PointerId,
- SDL_TRUE,
- transformedPoint.X,
- transformedPoint.Y,
- pointerPoint->Properties->Pressure);
- }
-}
-
#endif /* SDL_VIDEO_DRIVER_WINRT */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/winrt/SDL_winrtmouse.h b/src/video/winrt/SDL_winrtmouse.h
index 50bdbe24d..24c6e015e 100644
--- a/src/video/winrt/SDL_winrtmouse.h
+++ b/src/video/winrt/SDL_winrtmouse.h
@@ -20,11 +20,20 @@
*/
#include "SDL_config.h"
-#ifndef _SDL_windowsmouse_h
-#define _SDL_windowsmouse_h
+#ifndef _SDL_winrtmouse_h
+#define _SDL_winrtmouse_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
extern void WINRT_InitMouse(_THIS);
extern void WINRT_QuitMouse(_THIS);
+extern SDL_bool WINRT_UsingRelativeMouseMode;
+
+#ifdef __cplusplus
+}
+#endif
#endif /* _SDL_windowsmouse_h */
diff --git a/src/video/winrt/SDL_winrtpointerinput.cpp b/src/video/winrt/SDL_winrtpointerinput.cpp
new file mode 100644
index 000000000..ee1dc80e5
--- /dev/null
+++ b/src/video/winrt/SDL_winrtpointerinput.cpp
@@ -0,0 +1,372 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2012 Sam Lantinga
+
+ 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_config.h"
+
+#if SDL_VIDEO_DRIVER_WINRT
+
+/* SDL includes */
+#include "SDL_winrtevents_c.h"
+#include "SDL_winrtmouse.h"
+#include "SDL_winrtvideo_cpp.h"
+#include "SDL_assert.h"
+#include "SDL_system.h"
+
+extern "C" {
+#include "../SDL_sysvideo.h"
+#include "../../events/SDL_events_c.h"
+#include "../../events/SDL_mouse_c.h"
+#include "../../events/SDL_touch_c.h"
+}
+
+/* File-specific globals: */
+static SDL_TouchID WINRT_TouchID = 1;
+static unsigned int WINRT_LeftFingerDown = 0;
+
+
+void
+WINRT_InitTouch(_THIS)
+{
+ SDL_AddTouch(WINRT_TouchID, "");
+}
+
+
+// Applies necessary geometric transformations to raw cursor positions:
+Windows::Foundation::Point
+WINRT_TransformCursorPosition(SDL_Window * window, Windows::Foundation::Point rawPosition)
+{
+ using namespace Windows::UI::Core;
+ using namespace Windows::Graphics::Display;
+
+ if (!window) {
+ return rawPosition;
+ }
+
+ SDL_WindowData * windowData = (SDL_WindowData *) window->driverdata;
+ if (windowData->coreWindow == nullptr) {
+ // For some reason, the window isn't associated with a CoreWindow.
+ // This might end up being the case as XAML support is extended.
+ // For now, if there's no CoreWindow attached to the SDL_Window,
+ // don't do any transforms.
+ return rawPosition;
+ }
+
+ // The CoreWindow can only be accessed on certain thread(s).
+ SDL_assert(CoreWindow::GetForCurrentThread() != nullptr);
+
+ CoreWindow ^ nativeWindow = windowData->coreWindow.Get();
+ Windows::Foundation::Point outputPosition;
+
+#if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
+ outputPosition.X = rawPosition.X * (((float32)window->w) / nativeWindow->Bounds.Width);
+ outputPosition.Y = rawPosition.Y * (((float32)window->h) / nativeWindow->Bounds.Height);
+#else
+ switch (DisplayProperties::CurrentOrientation)
+ {
+ case DisplayOrientations::Portrait:
+ outputPosition.X = rawPosition.X * (((float32)window->w) / nativeWindow->Bounds.Width);
+ outputPosition.Y = rawPosition.Y * (((float32)window->h) / nativeWindow->Bounds.Height);
+ break;
+ case DisplayOrientations::PortraitFlipped:
+ outputPosition.X = (float32)window->w - rawPosition.X * (((float32)window->w) / nativeWindow->Bounds.Width);
+ outputPosition.Y = (float32)window->h - rawPosition.Y * (((float32)window->h) / nativeWindow->Bounds.Height);
+ break;
+ case DisplayOrientations::Landscape:
+ outputPosition.X = rawPosition.Y * (((float32)window->w) / nativeWindow->Bounds.Height);
+ outputPosition.Y = (float32)window->h - rawPosition.X * (((float32)window->h) / nativeWindow->Bounds.Width);
+ break;
+ case DisplayOrientations::LandscapeFlipped:
+ outputPosition.X = (float32)window->w - rawPosition.Y * (((float32)window->w) / nativeWindow->Bounds.Height);
+ outputPosition.Y = rawPosition.X * (((float32)window->h) / nativeWindow->Bounds.Width);
+ break;
+ default:
+ break;
+ }
+#endif
+
+ return outputPosition;
+}
+
+static inline int
+_lround(float arg)
+{
+ if (arg >= 0.0f) {
+ return (int)floor(arg + 0.5f);
+ } else {
+ return (int)ceil(arg - 0.5f);
+ }
+}
+
+void
+WINRT_ProcessMouseMovedEvent(SDL_Window * window, Windows::Devices::Input::MouseEventArgs ^args)
+{
+ if (!window || !WINRT_UsingRelativeMouseMode) {
+ return;
+ }
+
+ // DLudwig, 2012-12-28: On some systems, namely Visual Studio's Windows
+ // Simulator, as well as Windows 8 in a Parallels 8 VM, MouseEventArgs'
+ // MouseDelta field often reports very large values. More information
+ // on this can be found at the following pages on MSDN:
+ // - http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/a3c789fa-f1c5-49c4-9c0a-7db88d0f90f8
+ // - https://connect.microsoft.com/VisualStudio/Feedback/details/756515
+ //
+ // The values do not appear to be as large when running on some systems,
+ // most notably a Surface RT. Furthermore, the values returned by
+ // CoreWindow's PointerMoved event, and sent to this class' OnPointerMoved
+ // method, do not ever appear to be large, even when MouseEventArgs'
+ // MouseDelta is reporting to the contrary.
+ //
+ // On systems with the large-values behavior, it appears that the values
+ // get reported as if the screen's size is 65536 units in both the X and Y
+ // dimensions. This can be viewed by using Windows' now-private, "Raw Input"
+ // APIs. (GetRawInputData, RegisterRawInputDevices, WM_INPUT, etc.)
+ //
+ // MSDN's documentation on MouseEventArgs' MouseDelta field (at
+ // http://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.input.mouseeventargs.mousedelta ),
+ // does not seem to indicate (to me) that its values should be so large. It
+ // says that its values should be a "change in screen location". I could
+ // be misinterpreting this, however a post on MSDN from a Microsoft engineer (see:
+ // http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/09a9868e-95bb-4858-ba1a-cb4d2c298d62 ),
+ // indicates that these values are in DIPs, which is the same unit used
+ // by CoreWindow's PointerMoved events (via the Position field in its CurrentPoint
+ // property. See http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.input.pointerpoint.position.aspx
+ // for details.)
+ //
+ // To note, PointerMoved events are sent a 'RawPosition' value (via the
+ // CurrentPoint property in MouseEventArgs), however these do not seem
+ // to exhibit the same large-value behavior.
+ //
+ // The values passed via PointerMoved events can't always be used for relative
+ // mouse motion, unfortunately. Its values are bound to the cursor's position,
+ // which stops when it hits one of the screen's edges. This can be a problem in
+ // first person shooters, whereby it is normal for mouse motion to travel far
+ // along any one axis for a period of time. MouseMoved events do not have the
+ // screen-bounding limitation, and can be used regardless of where the system's
+ // cursor is.
+ //
+ // One possible workaround would be to programmatically set the cursor's
+ // position to the screen's center (when SDL's relative mouse mode is enabled),
+ // however WinRT does not yet seem to have the ability to set the cursor's
+ // position via a public API. Win32 did this via an API call, SetCursorPos,
+ // however WinRT makes this function be private. Apps that use it won't get
+ // approved for distribution in the Windows Store. I've yet to be able to find
+ // a suitable, store-friendly counterpart for WinRT.
+ //
+ // There may be some room for a workaround whereby OnPointerMoved's values
+ // are compared to the values from OnMouseMoved in order to detect
+ // when this bug is active. A suitable transformation could then be made to
+ // OnMouseMoved's values. For now, however, the system-reported values are sent
+ // to SDL with minimal transformation: from native screen coordinates (in DIPs)
+ // to SDL window coordinates.
+ //
+ const Windows::Foundation::Point mouseDeltaInDIPs((float)args->MouseDelta.X, (float)args->MouseDelta.Y);
+ const Windows::Foundation::Point mouseDeltaInSDLWindowCoords = WINRT_TransformCursorPosition(window, mouseDeltaInDIPs);
+ SDL_SendMouseMotion(
+ window,
+ 0,
+ 1,
+ _lround(mouseDeltaInSDLWindowCoords.X),
+ _lround(mouseDeltaInSDLWindowCoords.Y));
+}
+
+Uint8
+WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt)
+{
+ using namespace Windows::UI::Input;
+
+#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
+ return SDL_BUTTON_LEFT;
+#else
+ switch (pt->Properties->PointerUpdateKind)
+ {
+ case PointerUpdateKind::LeftButtonPressed:
+ case PointerUpdateKind::LeftButtonReleased:
+ return SDL_BUTTON_LEFT;
+
+ case PointerUpdateKind::RightButtonPressed:
+ case PointerUpdateKind::RightButtonReleased:
+ return SDL_BUTTON_RIGHT;
+
+ case PointerUpdateKind::MiddleButtonPressed:
+ case PointerUpdateKind::MiddleButtonReleased:
+ return SDL_BUTTON_MIDDLE;
+
+ case PointerUpdateKind::XButton1Pressed:
+ case PointerUpdateKind::XButton1Released:
+ return SDL_BUTTON_X1;
+
+ case PointerUpdateKind::XButton2Pressed:
+ case PointerUpdateKind::XButton2Released:
+ return SDL_BUTTON_X2;
+
+ default:
+ break;
+ }
+#endif
+
+ return 0;
+}
+
+//const char *
+//WINRT_ConvertPointerUpdateKindToString(Windows::UI::Input::PointerUpdateKind kind)
+//{
+// using namespace Windows::UI::Input;
+//
+// switch (kind)
+// {
+// case PointerUpdateKind::Other:
+// return "Other";
+// case PointerUpdateKind::LeftButtonPressed:
+// return "LeftButtonPressed";
+// case PointerUpdateKind::LeftButtonReleased:
+// return "LeftButtonReleased";
+// case PointerUpdateKind::RightButtonPressed:
+// return "RightButtonPressed";
+// case PointerUpdateKind::RightButtonReleased:
+// return "RightButtonReleased";
+// case PointerUpdateKind::MiddleButtonPressed:
+// return "MiddleButtonPressed";
+// case PointerUpdateKind::MiddleButtonReleased:
+// return "MiddleButtonReleased";
+// case PointerUpdateKind::XButton1Pressed:
+// return "XButton1Pressed";
+// case PointerUpdateKind::XButton1Released:
+// return "XButton1Released";
+// case PointerUpdateKind::XButton2Pressed:
+// return "XButton2Pressed";
+// case PointerUpdateKind::XButton2Released:
+// return "XButton2Released";
+// }
+//
+// return "";
+//}
+
+static bool
+WINRT_IsTouchEvent(Windows::UI::Input::PointerPoint ^pointerPoint)
+{
+#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
+ return true;
+#else
+ using namespace Windows::Devices::Input;
+ switch (pointerPoint->PointerDevice->PointerDeviceType) {
+ case PointerDeviceType::Touch:
+ case PointerDeviceType::Pen:
+ return true;
+ default:
+ return false;
+ }
+#endif
+}
+
+void
+WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
+{
+ if (!window || WINRT_UsingRelativeMouseMode) {
+ return;
+ }
+
+ Windows::Foundation::Point transformedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position);
+
+ if (pointerPoint->PointerId == WINRT_LeftFingerDown) {
+ SDL_SendMouseMotion(window, 0, 0, (int)transformedPoint.X, (int)transformedPoint.Y);
+ }
+
+ if (WINRT_IsTouchEvent(pointerPoint)) {
+ SDL_SendTouchMotion(
+ WINRT_TouchID,
+ (SDL_FingerID) pointerPoint->PointerId,
+ transformedPoint.X,
+ transformedPoint.Y,
+ pointerPoint->Properties->Pressure);
+ }
+}
+
+void
+WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
+{
+ if (!window) {
+ return;
+ }
+
+ // FIXME: This may need to accumulate deltas up to WHEEL_DELTA
+ short motion = pointerPoint->Properties->MouseWheelDelta / WHEEL_DELTA;
+ SDL_SendMouseWheel(window, 0, 0, motion);
+}
+
+void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
+{
+ if (!window) {
+ return;
+ }
+
+ Windows::Foundation::Point transformedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position);
+
+ if (WINRT_LeftFingerDown == pointerPoint->PointerId) {
+ Uint8 button = WINRT_GetSDLButtonForPointerPoint(pointerPoint);
+ if (button) {
+ SDL_SendMouseButton(window, 0, SDL_RELEASED, button);
+ }
+ WINRT_LeftFingerDown = 0;
+ }
+
+ if (WINRT_IsTouchEvent(pointerPoint)) {
+ SDL_SendTouch(
+ WINRT_TouchID,
+ (SDL_FingerID) pointerPoint->PointerId,
+ SDL_FALSE,
+ transformedPoint.X,
+ transformedPoint.Y,
+ pointerPoint->Properties->Pressure);
+ }
+}
+
+void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
+{
+ if (!window) {
+ return;
+ }
+
+ Windows::Foundation::Point transformedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position);
+
+ if (!WINRT_LeftFingerDown) {
+ Uint8 button = WINRT_GetSDLButtonForPointerPoint(pointerPoint);
+ if (button) {
+#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
+ SDL_SendMouseMotion(window, 0, 0, (int)transformedPoint.X, (int)transformedPoint.Y);
+#endif
+ SDL_SendMouseButton(window, 0, SDL_PRESSED, button);
+ }
+
+ WINRT_LeftFingerDown = pointerPoint->PointerId;
+ }
+
+ if (WINRT_IsTouchEvent(pointerPoint)) {
+ SDL_SendTouch(
+ WINRT_TouchID,
+ (SDL_FingerID) pointerPoint->PointerId,
+ SDL_TRUE,
+ transformedPoint.X,
+ transformedPoint.Y,
+ pointerPoint->Properties->Pressure);
+ }
+}
+
+#endif // SDL_VIDEO_DRIVER_WINRT
diff --git a/src/video/winrt/SDL_winrtvideo.cpp b/src/video/winrt/SDL_winrtvideo.cpp
index 621b2edaa..5e5c75e2b 100644
--- a/src/video/winrt/SDL_winrtvideo.cpp
+++ b/src/video/winrt/SDL_winrtvideo.cpp
@@ -45,15 +45,13 @@ extern "C" {
}
#include "../../core/winrt/SDL_winrtapp.h"
+#include "../../core/winrt/SDL_winrtxaml_cpp.h"
#include "SDL_winrtvideo_cpp.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 */
static int WINRT_VideoInit(_THIS);
@@ -68,19 +66,11 @@ static void WINRT_DestroyWindow(_THIS, SDL_Window * window);
static SDL_bool WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info);
-/* The global, WinRT, SDL Window.
- For now, SDL/WinRT only supports one window (due to platform limitations of
- WinRT.
-*/
+/* SDL-internal globals: */
SDL_Window * WINRT_GlobalSDLWindow = NULL;
-
-
-/* The global, WinRT, video device.
-*/
SDL_VideoDevice * WINRT_GlobalSDLVideoDevice = NULL;
-
/* WinRT driver bootstrap functions */
static int
@@ -140,6 +130,7 @@ WINRT_VideoInit(_THIS)
return -1;
}
WINRT_InitMouse(_this);
+ WINRT_InitTouch(_this);
return 0;
}
diff --git a/src/video/winrt/SDL_winrtvideo_cpp.h b/src/video/winrt/SDL_winrtvideo_cpp.h
index eb4d788fa..a36cc308d 100644
--- a/src/video/winrt/SDL_winrtvideo_cpp.h
+++ b/src/video/winrt/SDL_winrtvideo_cpp.h
@@ -29,6 +29,19 @@
#include "SDL_events.h"
+/* The global, WinRT, SDL Window.
+ For now, SDL/WinRT only supports one window (due to platform limitations of
+ WinRT.
+*/
+extern SDL_Window * WINRT_GlobalSDLWindow;
+
+/* The global, WinRT, video device. */
+extern SDL_VideoDevice * WINRT_GlobalSDLVideoDevice;
+
+/* Computes the current display mode for Plain Direct3D (non-XAML) apps */
+extern SDL_DisplayMode WINRT_CalcDisplayModeUsingNativeWindow();
+
+
#ifdef __cplusplus_winrt
/* Internal window data */