Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

WinRT: added support for SDL_SetRelativeMouseMode

  • Loading branch information
DavidLudwig committed Dec 28, 2012
1 parent 0349ac1 commit e9df75e466472447dcbfb29ac876492823ff2f21
@@ -33,6 +33,7 @@ SDL_WinRTApp ^ SDL_WinRTGlobalApp = nullptr;
using namespace Windows::ApplicationModel;
using namespace Windows::ApplicationModel::Core;
using namespace Windows::ApplicationModel::Activation;
using namespace Windows::Devices::Input;
using namespace Windows::UI::Core;
using namespace Windows::System;
using namespace Windows::Foundation;
@@ -42,7 +43,8 @@ using namespace concurrency;
SDL_WinRTApp::SDL_WinRTApp() :
m_windowClosed(false),
m_windowVisible(true),
m_sdlWindowData(NULL)
m_sdlWindowData(NULL),
m_useRelativeMouseMode(false)
{
}

@@ -82,6 +84,10 @@ void SDL_WinRTApp::SetWindow(CoreWindow^ window)
window->PointerMoved +=
ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &SDL_WinRTApp::OnPointerMoved);

// Retrieves relative-only mouse movements:
Windows::Devices::Input::MouseDevice::GetForCurrentView()->MouseMoved +=
ref new TypedEventHandler<MouseDevice^, MouseEventArgs^>(this, &SDL_WinRTApp::OnMouseMoved);

window->KeyDown +=
ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &SDL_WinRTApp::OnKeyDown);

@@ -167,6 +173,68 @@ void SDL_WinRTApp::OnPointerReleased(CoreWindow^ sender, PointerEventArgs^ args)
}
}

void SDL_WinRTApp::OnMouseMoved(MouseDevice^ mouseDevice, MouseEventArgs^ args)
{
if (m_sdlWindowData && m_useRelativeMouseMode) {
// 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 Windows RT 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
// without transformation.
//
SDL_SendMouseMotion(m_sdlWindowData->sdlWindow, 1, args->MouseDelta.X, args->MouseDelta.Y);
}
}

// Applies necessary geometric transformations to raw cursor positions:
Point SDL_WinRTApp::TransformCursor(Point rawPosition)
{
@@ -182,7 +250,7 @@ Point SDL_WinRTApp::TransformCursor(Point rawPosition)

void SDL_WinRTApp::OnPointerMoved(CoreWindow^ sender, PointerEventArgs^ args)
{
if (m_sdlWindowData)
if (m_sdlWindowData && ! m_useRelativeMouseMode)
{
Point transformedPoint = TransformCursor(args->CurrentPoint->Position);
SDL_SendMouseMotion(m_sdlWindowData->sdlWindow, 0, (int)transformedPoint.X, (int)transformedPoint.Y);
@@ -456,6 +524,11 @@ bool SDL_WinRTApp::HasSDLWindowData() const
return (m_sdlWindowData != NULL);
}

void SDL_WinRTApp::SetRelativeMouseMode(bool enable)
{
m_useRelativeMouseMode = enable;
}

void SDL_WinRTApp::SetSDLWindowData(const SDL_WindowData* windowData)
{
m_sdlWindowData = windowData;
@@ -25,6 +25,7 @@ ref class SDL_WinRTApp sealed : public Windows::ApplicationModel::Core::IFramewo
void PumpEvents();
const SDL_WindowData * GetSDLWindowData() const;
bool HasSDLWindowData() const;
void SetRelativeMouseMode(bool enable);
void SetSDLWindowData(const SDL_WindowData * windowData);
void UpdateWindowFramebuffer(SDL_Surface * surface, SDL_Rect * rects, int numrects);
void ResizeMainTexture(int w, int h);
@@ -42,6 +43,7 @@ ref class SDL_WinRTApp sealed : public Windows::ApplicationModel::Core::IFramewo
void OnPointerPressed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
void OnPointerReleased(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
void OnPointerMoved(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);
void OnMouseMoved(Windows::Devices::Input::MouseDevice^ mouseDevice, Windows::Devices::Input::MouseEventArgs^ args);
void OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
void OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);

@@ -50,6 +52,7 @@ ref class SDL_WinRTApp sealed : public Windows::ApplicationModel::Core::IFramewo
bool m_windowClosed;
bool m_windowVisible;
const SDL_WindowData* m_sdlWindowData;
bool m_useRelativeMouseMode;
};

ref class Direct3DApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource
@@ -108,12 +108,12 @@ WINRT_ShowCursor(SDL_Cursor * cursor)
return 0;
}

//static int
//WINRT_SetRelativeMouseMode(SDL_bool enabled)
//{
// //return -1;
// return 0;
//}
static int
WINRT_SetRelativeMouseMode(SDL_bool enabled)
{
SDL_WinRTGlobalApp->SetRelativeMouseMode(enabled ? true : false);
return 0;
}

void
WINRT_InitMouse(_THIS)
@@ -131,7 +131,7 @@ WINRT_InitMouse(_THIS)
mouse->ShowCursor = WINRT_ShowCursor;
mouse->FreeCursor = WINRT_FreeCursor;
//mouse->WarpMouse = WINRT_WarpMouse;
//mouse->SetRelativeMouseMode = WINRT_SetRelativeMouseMode; // DLudwig: 'relative mouse mode' support is pending
mouse->SetRelativeMouseMode = WINRT_SetRelativeMouseMode;

SDL_SetDefaultCursor(WINRT_CreateDefaultCursor());
}

0 comments on commit e9df75e

Please sign in to comment.