src/video/winrt/SDL_winrtpointerinput.cpp
changeset 8521 cefdaf414ead
parent 8516 f3e0e381bdcd
child 8534 50177f518fdb
     1.1 --- a/src/video/winrt/SDL_winrtpointerinput.cpp	Fri Sep 06 19:23:42 2013 -0400
     1.2 +++ b/src/video/winrt/SDL_winrtpointerinput.cpp	Fri Sep 06 21:00:52 2013 -0400
     1.3 @@ -47,7 +47,6 @@
     1.4      SDL_AddTouch(WINRT_TouchID, "");
     1.5  }
     1.6  
     1.7 -
     1.8  // Applies necessary geometric transformations to raw cursor positions:
     1.9  Windows::Foundation::Point
    1.10  WINRT_TransformCursorPosition(SDL_Window * window, Windows::Foundation::Point rawPosition)
    1.11 @@ -114,79 +113,6 @@
    1.12      }
    1.13  }
    1.14  
    1.15 -void
    1.16 -WINRT_ProcessMouseMovedEvent(SDL_Window * window, Windows::Devices::Input::MouseEventArgs ^args)
    1.17 -{
    1.18 -    if (!window || !WINRT_UsingRelativeMouseMode) {
    1.19 -        return;
    1.20 -    }
    1.21 -
    1.22 -    // DLudwig, 2012-12-28: On some systems, namely Visual Studio's Windows
    1.23 -    // Simulator, as well as Windows 8 in a Parallels 8 VM, MouseEventArgs'
    1.24 -    // MouseDelta field often reports very large values.  More information
    1.25 -    // on this can be found at the following pages on MSDN:
    1.26 -    //  - http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/a3c789fa-f1c5-49c4-9c0a-7db88d0f90f8
    1.27 -    //  - https://connect.microsoft.com/VisualStudio/Feedback/details/756515
    1.28 -    //
    1.29 -    // The values do not appear to be as large when running on some systems,
    1.30 -    // most notably a Surface RT.  Furthermore, the values returned by
    1.31 -    // CoreWindow's PointerMoved event, and sent to this class' OnPointerMoved
    1.32 -    // method, do not ever appear to be large, even when MouseEventArgs'
    1.33 -    // MouseDelta is reporting to the contrary.
    1.34 -    //
    1.35 -    // On systems with the large-values behavior, it appears that the values
    1.36 -    // get reported as if the screen's size is 65536 units in both the X and Y
    1.37 -    // dimensions.  This can be viewed by using Windows' now-private, "Raw Input"
    1.38 -    // APIs.  (GetRawInputData, RegisterRawInputDevices, WM_INPUT, etc.)
    1.39 -    //
    1.40 -    // MSDN's documentation on MouseEventArgs' MouseDelta field (at
    1.41 -    // http://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.input.mouseeventargs.mousedelta ),
    1.42 -    // does not seem to indicate (to me) that its values should be so large.  It
    1.43 -    // says that its values should be a "change in screen location".  I could
    1.44 -    // be misinterpreting this, however a post on MSDN from a Microsoft engineer (see: 
    1.45 -    // http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/09a9868e-95bb-4858-ba1a-cb4d2c298d62 ),
    1.46 -    // indicates that these values are in DIPs, which is the same unit used
    1.47 -    // by CoreWindow's PointerMoved events (via the Position field in its CurrentPoint
    1.48 -    // property.  See http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.input.pointerpoint.position.aspx
    1.49 -    // for details.)
    1.50 -    //
    1.51 -    // To note, PointerMoved events are sent a 'RawPosition' value (via the
    1.52 -    // CurrentPoint property in MouseEventArgs), however these do not seem
    1.53 -    // to exhibit the same large-value behavior.
    1.54 -    //
    1.55 -    // The values passed via PointerMoved events can't always be used for relative
    1.56 -    // mouse motion, unfortunately.  Its values are bound to the cursor's position,
    1.57 -    // which stops when it hits one of the screen's edges.  This can be a problem in
    1.58 -    // first person shooters, whereby it is normal for mouse motion to travel far
    1.59 -    // along any one axis for a period of time.  MouseMoved events do not have the
    1.60 -    // screen-bounding limitation, and can be used regardless of where the system's
    1.61 -    // cursor is.
    1.62 -    //
    1.63 -    // One possible workaround would be to programmatically set the cursor's
    1.64 -    // position to the screen's center (when SDL's relative mouse mode is enabled),
    1.65 -    // however WinRT does not yet seem to have the ability to set the cursor's
    1.66 -    // position via a public API.  Win32 did this via an API call, SetCursorPos,
    1.67 -    // however WinRT makes this function be private.  Apps that use it won't get
    1.68 -    // approved for distribution in the Windows Store.  I've yet to be able to find
    1.69 -    // a suitable, store-friendly counterpart for WinRT.
    1.70 -    //
    1.71 -    // There may be some room for a workaround whereby OnPointerMoved's values
    1.72 -    // are compared to the values from OnMouseMoved in order to detect
    1.73 -    // when this bug is active.  A suitable transformation could then be made to
    1.74 -    // OnMouseMoved's values.  For now, however, the system-reported values are sent
    1.75 -    // to SDL with minimal transformation: from native screen coordinates (in DIPs)
    1.76 -    // to SDL window coordinates.
    1.77 -    //
    1.78 -    const Windows::Foundation::Point mouseDeltaInDIPs((float)args->MouseDelta.X, (float)args->MouseDelta.Y);
    1.79 -    const Windows::Foundation::Point mouseDeltaInSDLWindowCoords = WINRT_TransformCursorPosition(window, mouseDeltaInDIPs);
    1.80 -    SDL_SendMouseMotion(
    1.81 -        window,
    1.82 -        0,
    1.83 -        1,
    1.84 -        _lround(mouseDeltaInSDLWindowCoords.X),
    1.85 -        _lround(mouseDeltaInSDLWindowCoords.Y));
    1.86 -}
    1.87 -
    1.88  Uint8
    1.89  WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt)
    1.90  {
    1.91 @@ -276,68 +202,6 @@
    1.92  #endif
    1.93  }
    1.94  
    1.95 -void
    1.96 -WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
    1.97 -{
    1.98 -    if (!window || WINRT_UsingRelativeMouseMode) {
    1.99 -        return;
   1.100 -    }
   1.101 -
   1.102 -    Windows::Foundation::Point transformedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position);
   1.103 -
   1.104 -    if (pointerPoint->PointerId == WINRT_LeftFingerDown) {
   1.105 -        SDL_SendMouseMotion(window, 0, 0, (int)transformedPoint.X, (int)transformedPoint.Y);
   1.106 -    }
   1.107 -
   1.108 -    if (WINRT_IsTouchEvent(pointerPoint)) {
   1.109 -        SDL_SendTouchMotion(
   1.110 -            WINRT_TouchID,
   1.111 -            (SDL_FingerID) pointerPoint->PointerId,
   1.112 -            transformedPoint.X,
   1.113 -            transformedPoint.Y,
   1.114 -            pointerPoint->Properties->Pressure);
   1.115 -    }
   1.116 -}
   1.117 -
   1.118 -void
   1.119 -WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
   1.120 -{
   1.121 -    if (!window) {
   1.122 -        return;
   1.123 -    }
   1.124 -
   1.125 -    // FIXME: This may need to accumulate deltas up to WHEEL_DELTA
   1.126 -    short motion = pointerPoint->Properties->MouseWheelDelta / WHEEL_DELTA;
   1.127 -    SDL_SendMouseWheel(window, 0, 0, motion);
   1.128 -}
   1.129 -
   1.130 -void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
   1.131 -{
   1.132 -    if (!window) {
   1.133 -        return;
   1.134 -    }
   1.135 -
   1.136 -    Windows::Foundation::Point transformedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position);
   1.137 -
   1.138 -    if (WINRT_LeftFingerDown == pointerPoint->PointerId) {
   1.139 -        Uint8 button = WINRT_GetSDLButtonForPointerPoint(pointerPoint);
   1.140 -        if (button) {
   1.141 -            SDL_SendMouseButton(window, 0, SDL_RELEASED, button);
   1.142 -        }
   1.143 -        WINRT_LeftFingerDown = 0;
   1.144 -    }
   1.145 -
   1.146 -    if (WINRT_IsTouchEvent(pointerPoint)) {
   1.147 -        SDL_SendTouch(
   1.148 -            WINRT_TouchID,
   1.149 -            (SDL_FingerID) pointerPoint->PointerId,
   1.150 -            SDL_FALSE,
   1.151 -            transformedPoint.X,
   1.152 -            transformedPoint.Y,
   1.153 -            pointerPoint->Properties->Pressure);
   1.154 -    }
   1.155 -}
   1.156 -
   1.157  void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
   1.158  {
   1.159      if (!window) {
   1.160 @@ -368,5 +232,140 @@
   1.161              pointerPoint->Properties->Pressure);
   1.162      }
   1.163  }
   1.164 +
   1.165 +void
   1.166 +WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
   1.167 +{
   1.168 +    if (!window || WINRT_UsingRelativeMouseMode) {
   1.169 +        return;
   1.170 +    }
   1.171 +
   1.172 +    Windows::Foundation::Point transformedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position);
   1.173 +
   1.174 +    if (pointerPoint->PointerId == WINRT_LeftFingerDown) {
   1.175 +        SDL_SendMouseMotion(window, 0, 0, (int)transformedPoint.X, (int)transformedPoint.Y);
   1.176 +    }
   1.177 +
   1.178 +    if (WINRT_IsTouchEvent(pointerPoint)) {
   1.179 +        SDL_SendTouchMotion(
   1.180 +            WINRT_TouchID,
   1.181 +            (SDL_FingerID) pointerPoint->PointerId,
   1.182 +            transformedPoint.X,
   1.183 +            transformedPoint.Y,
   1.184 +            pointerPoint->Properties->Pressure);
   1.185 +    }
   1.186 +}
   1.187 +
   1.188 +void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
   1.189 +{
   1.190 +    if (!window) {
   1.191 +        return;
   1.192 +    }
   1.193 +
   1.194 +    Windows::Foundation::Point transformedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position);
   1.195 +
   1.196 +    if (WINRT_LeftFingerDown == pointerPoint->PointerId) {
   1.197 +        Uint8 button = WINRT_GetSDLButtonForPointerPoint(pointerPoint);
   1.198 +        if (button) {
   1.199 +            SDL_SendMouseButton(window, 0, SDL_RELEASED, button);
   1.200 +        }
   1.201 +        WINRT_LeftFingerDown = 0;
   1.202 +    }
   1.203 +
   1.204 +    if (WINRT_IsTouchEvent(pointerPoint)) {
   1.205 +        SDL_SendTouch(
   1.206 +            WINRT_TouchID,
   1.207 +            (SDL_FingerID) pointerPoint->PointerId,
   1.208 +            SDL_FALSE,
   1.209 +            transformedPoint.X,
   1.210 +            transformedPoint.Y,
   1.211 +            pointerPoint->Properties->Pressure);
   1.212 +    }
   1.213 +}
   1.214 +
   1.215 +void
   1.216 +WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint)
   1.217 +{
   1.218 +    if (!window) {
   1.219 +        return;
   1.220 +    }
   1.221 +
   1.222 +    // FIXME: This may need to accumulate deltas up to WHEEL_DELTA
   1.223 +    short motion = pointerPoint->Properties->MouseWheelDelta / WHEEL_DELTA;
   1.224 +    SDL_SendMouseWheel(window, 0, 0, motion);
   1.225 +}
   1.226 +
   1.227 +void
   1.228 +WINRT_ProcessMouseMovedEvent(SDL_Window * window, Windows::Devices::Input::MouseEventArgs ^args)
   1.229 +{
   1.230 +    if (!window || !WINRT_UsingRelativeMouseMode) {
   1.231 +        return;
   1.232 +    }
   1.233 +
   1.234 +    // DLudwig, 2012-12-28: On some systems, namely Visual Studio's Windows
   1.235 +    // Simulator, as well as Windows 8 in a Parallels 8 VM, MouseEventArgs'
   1.236 +    // MouseDelta field often reports very large values.  More information
   1.237 +    // on this can be found at the following pages on MSDN:
   1.238 +    //  - http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/a3c789fa-f1c5-49c4-9c0a-7db88d0f90f8
   1.239 +    //  - https://connect.microsoft.com/VisualStudio/Feedback/details/756515
   1.240 +    //
   1.241 +    // The values do not appear to be as large when running on some systems,
   1.242 +    // most notably a Surface RT.  Furthermore, the values returned by
   1.243 +    // CoreWindow's PointerMoved event, and sent to this class' OnPointerMoved
   1.244 +    // method, do not ever appear to be large, even when MouseEventArgs'
   1.245 +    // MouseDelta is reporting to the contrary.
   1.246 +    //
   1.247 +    // On systems with the large-values behavior, it appears that the values
   1.248 +    // get reported as if the screen's size is 65536 units in both the X and Y
   1.249 +    // dimensions.  This can be viewed by using Windows' now-private, "Raw Input"
   1.250 +    // APIs.  (GetRawInputData, RegisterRawInputDevices, WM_INPUT, etc.)
   1.251 +    //
   1.252 +    // MSDN's documentation on MouseEventArgs' MouseDelta field (at
   1.253 +    // http://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.input.mouseeventargs.mousedelta ),
   1.254 +    // does not seem to indicate (to me) that its values should be so large.  It
   1.255 +    // says that its values should be a "change in screen location".  I could
   1.256 +    // be misinterpreting this, however a post on MSDN from a Microsoft engineer (see: 
   1.257 +    // http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/09a9868e-95bb-4858-ba1a-cb4d2c298d62 ),
   1.258 +    // indicates that these values are in DIPs, which is the same unit used
   1.259 +    // by CoreWindow's PointerMoved events (via the Position field in its CurrentPoint
   1.260 +    // property.  See http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.input.pointerpoint.position.aspx
   1.261 +    // for details.)
   1.262 +    //
   1.263 +    // To note, PointerMoved events are sent a 'RawPosition' value (via the
   1.264 +    // CurrentPoint property in MouseEventArgs), however these do not seem
   1.265 +    // to exhibit the same large-value behavior.
   1.266 +    //
   1.267 +    // The values passed via PointerMoved events can't always be used for relative
   1.268 +    // mouse motion, unfortunately.  Its values are bound to the cursor's position,
   1.269 +    // which stops when it hits one of the screen's edges.  This can be a problem in
   1.270 +    // first person shooters, whereby it is normal for mouse motion to travel far
   1.271 +    // along any one axis for a period of time.  MouseMoved events do not have the
   1.272 +    // screen-bounding limitation, and can be used regardless of where the system's
   1.273 +    // cursor is.
   1.274 +    //
   1.275 +    // One possible workaround would be to programmatically set the cursor's
   1.276 +    // position to the screen's center (when SDL's relative mouse mode is enabled),
   1.277 +    // however WinRT does not yet seem to have the ability to set the cursor's
   1.278 +    // position via a public API.  Win32 did this via an API call, SetCursorPos,
   1.279 +    // however WinRT makes this function be private.  Apps that use it won't get
   1.280 +    // approved for distribution in the Windows Store.  I've yet to be able to find
   1.281 +    // a suitable, store-friendly counterpart for WinRT.
   1.282 +    //
   1.283 +    // There may be some room for a workaround whereby OnPointerMoved's values
   1.284 +    // are compared to the values from OnMouseMoved in order to detect
   1.285 +    // when this bug is active.  A suitable transformation could then be made to
   1.286 +    // OnMouseMoved's values.  For now, however, the system-reported values are sent
   1.287 +    // to SDL with minimal transformation: from native screen coordinates (in DIPs)
   1.288 +    // to SDL window coordinates.
   1.289 +    //
   1.290 +    const Windows::Foundation::Point mouseDeltaInDIPs((float)args->MouseDelta.X, (float)args->MouseDelta.Y);
   1.291 +    const Windows::Foundation::Point mouseDeltaInSDLWindowCoords = WINRT_TransformCursorPosition(window, mouseDeltaInDIPs);
   1.292 +    SDL_SendMouseMotion(
   1.293 +        window,
   1.294 +        0,
   1.295 +        1,
   1.296 +        _lround(mouseDeltaInSDLWindowCoords.X),
   1.297 +        _lround(mouseDeltaInSDLWindowCoords.Y));
   1.298 +}
   1.299  
   1.300  #endif // SDL_VIDEO_DRIVER_WINRT