From d78b26ed69b906ba4904869c38999ae7d5526be1 Mon Sep 17 00:00:00 2001 From: David Ludwig Date: Mon, 26 Aug 2013 17:17:53 -0400 Subject: [PATCH] WinRT: moved most platform-specific keyboard and mouse code to shared locations --- .../SDL/SDL_VS2012-WinPhone.vcxproj | 1 + .../SDL/SDL_VS2012-WinPhone.vcxproj.filters | 3 + VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj | 8 + .../SDL/SDL_VS2012-WinRT.vcxproj.filters | 3 + src/core/winrt/SDL_winrtapp.cpp | 475 +----------------- src/core/winrt/SDL_winrtapp.h | 2 - src/video/winrt/SDL_winrtevents_c.h | 32 +- src/video/winrt/SDL_winrtkeyboard.cpp | 300 +++++++++++ src/video/winrt/SDL_winrtmouse.cpp | 260 +++++++++- 9 files changed, 617 insertions(+), 467 deletions(-) create mode 100644 src/video/winrt/SDL_winrtkeyboard.cpp diff --git a/VisualC-WinPhone/SDL/SDL_VS2012-WinPhone.vcxproj b/VisualC-WinPhone/SDL/SDL_VS2012-WinPhone.vcxproj index 90a89b389..e2459fa0f 100644 --- a/VisualC-WinPhone/SDL/SDL_VS2012-WinPhone.vcxproj +++ b/VisualC-WinPhone/SDL/SDL_VS2012-WinPhone.vcxproj @@ -363,6 +363,7 @@ 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 e3c9237f1..bd2128a3b 100644 --- a/VisualC-WinPhone/SDL/SDL_VS2012-WinPhone.vcxproj.filters +++ b/VisualC-WinPhone/SDL/SDL_VS2012-WinPhone.vcxproj.filters @@ -593,6 +593,9 @@ Source Files + + Source Files + diff --git a/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj b/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj index 1956f6399..200b6d58b 100644 --- a/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj +++ b/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj @@ -152,6 +152,14 @@ true true + + true + true + true + true + true + true + true true diff --git a/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj.filters b/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj.filters index d6a0cbee5..9a0961341 100644 --- a/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj.filters +++ b/VisualC-WinRT/SDL/SDL_VS2012-WinRT.vcxproj.filters @@ -267,6 +267,9 @@ Source Files + + Source Files + diff --git a/src/core/winrt/SDL_winrtapp.cpp b/src/core/winrt/SDL_winrtapp.cpp index 2cb2048b2..557c3a1ec 100644 --- a/src/core/winrt/SDL_winrtapp.cpp +++ b/src/core/winrt/SDL_winrtapp.cpp @@ -1,6 +1,6 @@  +#include #include -#include #include #include "ppltasks.h" @@ -15,13 +15,12 @@ extern "C" { #include "SDL_render.h" #include "../../video/SDL_sysvideo.h" //#include "../../SDL_hints_c.h" -#include "../../events/scancodes_windows.h" #include "../../events/SDL_mouse_c.h" -#include "../../events/SDL_keyboard_c.h" #include "../../events/SDL_windowevents_c.h" #include "../../render/SDL_sysrender.h" } +#include "../../video/winrt/SDL_winrtevents_c.h" #include "../../video/winrt/SDL_winrtvideo.h" #include "SDL_winrtapp.h" @@ -142,8 +141,7 @@ SDL_WinRTApp::SDL_WinRTApp() : m_windowClosed(false), m_windowVisible(true), m_sdlWindowData(NULL), - m_sdlVideoDevice(NULL), - m_useRelativeMouseMode(false) + m_sdlVideoDevice(NULL) { } @@ -387,482 +385,44 @@ void SDL_WinRTApp::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) m_windowClosed = true; } -static Uint8 -WINRT_GetSDLButtonForPointerPoint(PointerPoint ^ pt) -{ - 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; - } - - return 0; -} - -static const char * -WINRT_ConvertPointerUpdateKindToString(PointerUpdateKind kind) -{ - 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 void -WINRT_LogPointerEvent(const string & header, PointerEventArgs ^ args, Point transformedPoint) -{ - PointerPoint ^ pt = args->CurrentPoint; - SDL_Log("%s: Position={%f,%f}, Transformed Pos={%f, %f}, MouseWheelDelta=%d, FrameId=%d, PointerId=%d, PointerUpdateKind=%s\n", - header.c_str(), - pt->Position.X, pt->Position.Y, - transformedPoint.X, transformedPoint.Y, - pt->Properties->MouseWheelDelta, - pt->FrameId, - pt->PointerId, - WINRT_ConvertPointerUpdateKindToString(args->CurrentPoint->Properties->PointerUpdateKind)); -} - void SDL_WinRTApp::OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args) { -#if LOG_POINTER_EVENTS - WINRT_LogPointerEvent("mouse down", args, TransformCursor(args->CurrentPoint->Position)); -#endif - - if (m_sdlWindowData) { - Uint8 button = WINRT_GetSDLButtonForPointerPoint(args->CurrentPoint); - if (button) { - SDL_SendMouseButton(m_sdlWindowData->sdlWindow, 0, SDL_PRESSED, button); - } - } + SDL_Window * window = (m_sdlWindowData ? m_sdlWindowData->sdlWindow : nullptr); + WINRT_ProcessPointerPressedEvent(window, args); } void SDL_WinRTApp::OnPointerReleased(CoreWindow^ sender, PointerEventArgs^ args) { -#if LOG_POINTER_EVENTS - WINRT_LogPointerEvent("mouse up", args, TransformCursor(args->CurrentPoint->Position)); -#endif - - if (m_sdlWindowData) { - Uint8 button = WINRT_GetSDLButtonForPointerPoint(args->CurrentPoint); - if (button) { - SDL_SendMouseButton(m_sdlWindowData->sdlWindow, 0, SDL_RELEASED, button); - } - } + SDL_Window * window = (m_sdlWindowData ? m_sdlWindowData->sdlWindow : nullptr); + WINRT_ProcessPointerReleasedEvent(window, args); } void SDL_WinRTApp::OnPointerWheelChanged(CoreWindow^ sender, PointerEventArgs^ args) { -#if LOG_POINTER_EVENTS - WINRT_LogPointerEvent("wheel changed", args, TransformCursor(args->CurrentPoint->Position)); -#endif - - if (m_sdlWindowData) { - // FIXME: This may need to accumulate deltas up to WHEEL_DELTA - short motion = args->CurrentPoint->Properties->MouseWheelDelta / WHEEL_DELTA; - SDL_SendMouseWheel(m_sdlWindowData->sdlWindow, 0, 0, motion); - } -} - -static inline int _lround(float arg) { - if (arg >= 0.0f) { - return (int)floor(arg + 0.5f); - } else { - return (int)ceil(arg - 0.5f); - } + SDL_Window * window = (m_sdlWindowData ? m_sdlWindowData->sdlWindow : nullptr); + WINRT_ProcessPointerWheelChangedEvent(window, 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 - // to SDL with minimal transformation: from native screen coordinates (in DIPs) - // to SDL window coordinates. - // - const Point mouseDeltaInDIPs((float)args->MouseDelta.X, (float)args->MouseDelta.Y); - const Point mouseDeltaInSDLWindowCoords = TransformCursor(mouseDeltaInDIPs); - SDL_SendMouseMotion( - m_sdlWindowData->sdlWindow, - 0, - 1, - _lround(mouseDeltaInSDLWindowCoords.X), - _lround(mouseDeltaInSDLWindowCoords.Y)); - } -} - -// Applies necessary geometric transformations to raw cursor positions: -Point SDL_WinRTApp::TransformCursor(Point rawPosition) -{ - if ( ! m_sdlWindowData || ! m_sdlWindowData->sdlWindow ) { - return rawPosition; - } - CoreWindow ^ nativeWindow = CoreWindow::GetForCurrentThread(); - Point outputPosition; - outputPosition.X = rawPosition.X * (((float32)m_sdlWindowData->sdlWindow->w) / nativeWindow->Bounds.Width); - outputPosition.Y = rawPosition.Y * (((float32)m_sdlWindowData->sdlWindow->h) / nativeWindow->Bounds.Height); - return outputPosition; + SDL_Window * window = (m_sdlWindowData ? m_sdlWindowData->sdlWindow : nullptr); + WINRT_ProcessMouseMovedEvent(window, args); } void SDL_WinRTApp::OnPointerMoved(CoreWindow^ sender, PointerEventArgs^ args) { -#if LOG_POINTER_EVENTS - WINRT_LogPointerEvent("pointer moved", args, TransformCursor(args->CurrentPoint->Position)); -#endif - - if (m_sdlWindowData && ! m_useRelativeMouseMode) - { - Point transformedPoint = TransformCursor(args->CurrentPoint->Position); - SDL_SendMouseMotion(m_sdlWindowData->sdlWindow, 0, 0, (int)transformedPoint.X, (int)transformedPoint.Y); - } -} - -static SDL_Scancode WinRT_Official_Keycodes[] = { - SDL_SCANCODE_UNKNOWN, // VirtualKey.None -- 0 - SDL_SCANCODE_UNKNOWN, // VirtualKey.LeftButton -- 1 - SDL_SCANCODE_UNKNOWN, // VirtualKey.RightButton -- 2 - SDL_SCANCODE_CANCEL, // VirtualKey.Cancel -- 3 - SDL_SCANCODE_UNKNOWN, // VirtualKey.MiddleButton -- 4 - SDL_SCANCODE_UNKNOWN, // VirtualKey.XButton1 -- 5 - SDL_SCANCODE_UNKNOWN, // VirtualKey.XButton2 -- 6 - SDL_SCANCODE_UNKNOWN, // -- 7 - SDL_SCANCODE_BACKSPACE, // VirtualKey.Back -- 8 - SDL_SCANCODE_TAB, // VirtualKey.Tab -- 9 - SDL_SCANCODE_UNKNOWN, // -- 10 - SDL_SCANCODE_UNKNOWN, // -- 11 - SDL_SCANCODE_CLEAR, // VirtualKey.Clear -- 12 - SDL_SCANCODE_RETURN, // VirtualKey.Enter -- 13 - SDL_SCANCODE_UNKNOWN, // -- 14 - SDL_SCANCODE_UNKNOWN, // -- 15 - SDL_SCANCODE_LSHIFT, // VirtualKey.Shift -- 16 - SDL_SCANCODE_LCTRL, // VirtualKey.Control -- 17 - SDL_SCANCODE_MENU, // VirtualKey.Menu -- 18 - SDL_SCANCODE_PAUSE, // VirtualKey.Pause -- 19 - SDL_SCANCODE_CAPSLOCK, // VirtualKey.CapitalLock -- 20 - SDL_SCANCODE_UNKNOWN, // VirtualKey.Kana or VirtualKey.Hangul -- 21 - SDL_SCANCODE_UNKNOWN, // -- 22 - SDL_SCANCODE_UNKNOWN, // VirtualKey.Junja -- 23 - SDL_SCANCODE_UNKNOWN, // VirtualKey.Final -- 24 - SDL_SCANCODE_UNKNOWN, // VirtualKey.Hanja or VirtualKey.Kanji -- 25 - SDL_SCANCODE_UNKNOWN, // -- 26 - SDL_SCANCODE_ESCAPE, // VirtualKey.Escape -- 27 - SDL_SCANCODE_UNKNOWN, // VirtualKey.Convert -- 28 - SDL_SCANCODE_UNKNOWN, // VirtualKey.NonConvert -- 29 - SDL_SCANCODE_UNKNOWN, // VirtualKey.Accept -- 30 - SDL_SCANCODE_UNKNOWN, // VirtualKey.ModeChange -- 31 (maybe SDL_SCANCODE_MODE ?) - SDL_SCANCODE_SPACE, // VirtualKey.Space -- 32 - SDL_SCANCODE_PAGEUP, // VirtualKey.PageUp -- 33 - SDL_SCANCODE_PAGEDOWN, // VirtualKey.PageDown -- 34 - SDL_SCANCODE_END, // VirtualKey.End -- 35 - SDL_SCANCODE_HOME, // VirtualKey.Home -- 36 - SDL_SCANCODE_LEFT, // VirtualKey.Left -- 37 - SDL_SCANCODE_UP, // VirtualKey.Up -- 38 - SDL_SCANCODE_RIGHT, // VirtualKey.Right -- 39 - SDL_SCANCODE_DOWN, // VirtualKey.Down -- 40 - SDL_SCANCODE_SELECT, // VirtualKey.Select -- 41 - SDL_SCANCODE_UNKNOWN, // VirtualKey.Print -- 42 (maybe SDL_SCANCODE_PRINTSCREEN ?) - SDL_SCANCODE_EXECUTE, // VirtualKey.Execute -- 43 - SDL_SCANCODE_UNKNOWN, // VirtualKey.Snapshot -- 44 - SDL_SCANCODE_INSERT, // VirtualKey.Insert -- 45 - SDL_SCANCODE_DELETE, // VirtualKey.Delete -- 46 - SDL_SCANCODE_HELP, // VirtualKey.Help -- 47 - SDL_SCANCODE_0, // VirtualKey.Number0 -- 48 - SDL_SCANCODE_1, // VirtualKey.Number1 -- 49 - SDL_SCANCODE_2, // VirtualKey.Number2 -- 50 - SDL_SCANCODE_3, // VirtualKey.Number3 -- 51 - SDL_SCANCODE_4, // VirtualKey.Number4 -- 52 - SDL_SCANCODE_5, // VirtualKey.Number5 -- 53 - SDL_SCANCODE_6, // VirtualKey.Number6 -- 54 - SDL_SCANCODE_7, // VirtualKey.Number7 -- 55 - SDL_SCANCODE_8, // VirtualKey.Number8 -- 56 - SDL_SCANCODE_9, // VirtualKey.Number9 -- 57 - SDL_SCANCODE_UNKNOWN, // -- 58 - SDL_SCANCODE_UNKNOWN, // -- 59 - SDL_SCANCODE_UNKNOWN, // -- 60 - SDL_SCANCODE_UNKNOWN, // -- 61 - SDL_SCANCODE_UNKNOWN, // -- 62 - SDL_SCANCODE_UNKNOWN, // -- 63 - SDL_SCANCODE_UNKNOWN, // -- 64 - SDL_SCANCODE_A, // VirtualKey.A -- 65 - SDL_SCANCODE_B, // VirtualKey.B -- 66 - SDL_SCANCODE_C, // VirtualKey.C -- 67 - SDL_SCANCODE_D, // VirtualKey.D -- 68 - SDL_SCANCODE_E, // VirtualKey.E -- 69 - SDL_SCANCODE_F, // VirtualKey.F -- 70 - SDL_SCANCODE_G, // VirtualKey.G -- 71 - SDL_SCANCODE_H, // VirtualKey.H -- 72 - SDL_SCANCODE_I, // VirtualKey.I -- 73 - SDL_SCANCODE_J, // VirtualKey.J -- 74 - SDL_SCANCODE_K, // VirtualKey.K -- 75 - SDL_SCANCODE_L, // VirtualKey.L -- 76 - SDL_SCANCODE_M, // VirtualKey.M -- 77 - SDL_SCANCODE_N, // VirtualKey.N -- 78 - SDL_SCANCODE_O, // VirtualKey.O -- 79 - SDL_SCANCODE_P, // VirtualKey.P -- 80 - SDL_SCANCODE_Q, // VirtualKey.Q -- 81 - SDL_SCANCODE_R, // VirtualKey.R -- 82 - SDL_SCANCODE_S, // VirtualKey.S -- 83 - SDL_SCANCODE_T, // VirtualKey.T -- 84 - SDL_SCANCODE_U, // VirtualKey.U -- 85 - SDL_SCANCODE_V, // VirtualKey.V -- 86 - SDL_SCANCODE_W, // VirtualKey.W -- 87 - SDL_SCANCODE_X, // VirtualKey.X -- 88 - SDL_SCANCODE_Y, // VirtualKey.Y -- 89 - SDL_SCANCODE_Z, // VirtualKey.Z -- 90 - SDL_SCANCODE_UNKNOWN, // VirtualKey.LeftWindows -- 91 (maybe SDL_SCANCODE_APPLICATION or SDL_SCANCODE_LGUI ?) - SDL_SCANCODE_UNKNOWN, // VirtualKey.RightWindows -- 92 (maybe SDL_SCANCODE_APPLICATION or SDL_SCANCODE_RGUI ?) - SDL_SCANCODE_APPLICATION, // VirtualKey.Application -- 93 - SDL_SCANCODE_UNKNOWN, // -- 94 - SDL_SCANCODE_SLEEP, // VirtualKey.Sleep -- 95 - SDL_SCANCODE_KP_0, // VirtualKey.NumberPad0 -- 96 - SDL_SCANCODE_KP_1, // VirtualKey.NumberPad1 -- 97 - SDL_SCANCODE_KP_2, // VirtualKey.NumberPad2 -- 98 - SDL_SCANCODE_KP_3, // VirtualKey.NumberPad3 -- 99 - SDL_SCANCODE_KP_4, // VirtualKey.NumberPad4 -- 100 - SDL_SCANCODE_KP_5, // VirtualKey.NumberPad5 -- 101 - SDL_SCANCODE_KP_6, // VirtualKey.NumberPad6 -- 102 - SDL_SCANCODE_KP_7, // VirtualKey.NumberPad7 -- 103 - SDL_SCANCODE_KP_8, // VirtualKey.NumberPad8 -- 104 - SDL_SCANCODE_KP_9, // VirtualKey.NumberPad9 -- 105 - SDL_SCANCODE_KP_MULTIPLY, // VirtualKey.Multiply -- 106 - SDL_SCANCODE_KP_PLUS, // VirtualKey.Add -- 107 - SDL_SCANCODE_UNKNOWN, // VirtualKey.Separator -- 108 - SDL_SCANCODE_KP_MINUS, // VirtualKey.Subtract -- 109 - SDL_SCANCODE_UNKNOWN, // VirtualKey.Decimal -- 110 (maybe SDL_SCANCODE_DECIMALSEPARATOR, SDL_SCANCODE_KP_DECIMAL, or SDL_SCANCODE_KP_PERIOD ?) - SDL_SCANCODE_KP_DIVIDE, // VirtualKey.Divide -- 111 - SDL_SCANCODE_F1, // VirtualKey.F1 -- 112 - SDL_SCANCODE_F2, // VirtualKey.F2 -- 113 - SDL_SCANCODE_F3, // VirtualKey.F3 -- 114 - SDL_SCANCODE_F4, // VirtualKey.F4 -- 115 - SDL_SCANCODE_F5, // VirtualKey.F5 -- 116 - SDL_SCANCODE_F6, // VirtualKey.F6 -- 117 - SDL_SCANCODE_F7, // VirtualKey.F7 -- 118 - SDL_SCANCODE_F8, // VirtualKey.F8 -- 119 - SDL_SCANCODE_F9, // VirtualKey.F9 -- 120 - SDL_SCANCODE_F10, // VirtualKey.F10 -- 121 - SDL_SCANCODE_F11, // VirtualKey.F11 -- 122 - SDL_SCANCODE_F12, // VirtualKey.F12 -- 123 - SDL_SCANCODE_F13, // VirtualKey.F13 -- 124 - SDL_SCANCODE_F14, // VirtualKey.F14 -- 125 - SDL_SCANCODE_F15, // VirtualKey.F15 -- 126 - SDL_SCANCODE_F16, // VirtualKey.F16 -- 127 - SDL_SCANCODE_F17, // VirtualKey.F17 -- 128 - SDL_SCANCODE_F18, // VirtualKey.F18 -- 129 - SDL_SCANCODE_F19, // VirtualKey.F19 -- 130 - SDL_SCANCODE_F20, // VirtualKey.F20 -- 131 - SDL_SCANCODE_F21, // VirtualKey.F21 -- 132 - SDL_SCANCODE_F22, // VirtualKey.F22 -- 133 - SDL_SCANCODE_F23, // VirtualKey.F23 -- 134 - SDL_SCANCODE_F24, // VirtualKey.F24 -- 135 - SDL_SCANCODE_UNKNOWN, // -- 136 - SDL_SCANCODE_UNKNOWN, // -- 137 - SDL_SCANCODE_UNKNOWN, // -- 138 - SDL_SCANCODE_UNKNOWN, // -- 139 - SDL_SCANCODE_UNKNOWN, // -- 140 - SDL_SCANCODE_UNKNOWN, // -- 141 - SDL_SCANCODE_UNKNOWN, // -- 142 - SDL_SCANCODE_UNKNOWN, // -- 143 - SDL_SCANCODE_NUMLOCKCLEAR, // VirtualKey.NumberKeyLock -- 144 - SDL_SCANCODE_SCROLLLOCK, // VirtualKey.Scroll -- 145 - SDL_SCANCODE_UNKNOWN, // -- 146 - SDL_SCANCODE_UNKNOWN, // -- 147 - SDL_SCANCODE_UNKNOWN, // -- 148 - SDL_SCANCODE_UNKNOWN, // -- 149 - SDL_SCANCODE_UNKNOWN, // -- 150 - SDL_SCANCODE_UNKNOWN, // -- 151 - SDL_SCANCODE_UNKNOWN, // -- 152 - SDL_SCANCODE_UNKNOWN, // -- 153 - SDL_SCANCODE_UNKNOWN, // -- 154 - SDL_SCANCODE_UNKNOWN, // -- 155 - SDL_SCANCODE_UNKNOWN, // -- 156 - SDL_SCANCODE_UNKNOWN, // -- 157 - SDL_SCANCODE_UNKNOWN, // -- 158 - SDL_SCANCODE_UNKNOWN, // -- 159 - SDL_SCANCODE_LSHIFT, // VirtualKey.LeftShift -- 160 - SDL_SCANCODE_RSHIFT, // VirtualKey.RightShift -- 161 - SDL_SCANCODE_LCTRL, // VirtualKey.LeftControl -- 162 - SDL_SCANCODE_RCTRL, // VirtualKey.RightControl -- 163 - SDL_SCANCODE_MENU, // VirtualKey.LeftMenu -- 164 - SDL_SCANCODE_MENU, // VirtualKey.RightMenu -- 165 -}; - -static std::unordered_map WinRT_Unofficial_Keycodes; - -static SDL_Scancode -TranslateKeycode(int keycode) -{ - if (WinRT_Unofficial_Keycodes.empty()) { - /* Set up a table of undocumented (by Microsoft), WinRT-specific, - key codes: */ - // TODO, WinRT: move content declarations of WinRT_Unofficial_Keycodes into a C++11 initializer list, when possible - WinRT_Unofficial_Keycodes[220] = SDL_SCANCODE_GRAVE; - WinRT_Unofficial_Keycodes[222] = SDL_SCANCODE_BACKSLASH; - } - - /* Try to get a documented, WinRT, 'VirtualKey' first (as documented at - http://msdn.microsoft.com/en-us/library/windows/apps/windows.system.virtualkey.aspx ). - If that fails, fall back to a Win32 virtual key. - */ - // TODO, WinRT: try filling out the WinRT keycode table as much as possible, using the Win32 table for interpretation hints - //SDL_Log("WinRT TranslateKeycode, keycode=%d\n", (int)keycode); - SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN; - if (keycode < SDL_arraysize(WinRT_Official_Keycodes)) { - scancode = WinRT_Official_Keycodes[keycode]; - } - if (scancode == SDL_SCANCODE_UNKNOWN) { - if (WinRT_Unofficial_Keycodes.find(keycode) != WinRT_Unofficial_Keycodes.end()) { - scancode = WinRT_Unofficial_Keycodes[keycode]; - } - } - if (scancode == SDL_SCANCODE_UNKNOWN) { - if (keycode < SDL_arraysize(windows_scancode_table)) { - scancode = windows_scancode_table[keycode]; - } - } - if (scancode == SDL_SCANCODE_UNKNOWN) { - SDL_Log("WinRT TranslateKeycode, unknown keycode=%d\n", (int)keycode); - } - return scancode; + SDL_Window * window = (m_sdlWindowData ? m_sdlWindowData->sdlWindow : nullptr); + WINRT_ProcessPointerMovedEvent(window, args); } void SDL_WinRTApp::OnKeyDown(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args) { - SDL_Scancode sdlScancode = TranslateKeycode((int)args->VirtualKey); -#if 0 - SDL_Keycode keycode = SDL_GetKeyFromScancode(sdlScancode); - SDL_Log("key down, handled=%s, ext?=%s, released?=%s, menu key down?=%s, repeat count=%d, native scan code=%d, was down?=%s, vkey=%d, sdl scan code=%d (%s), sdl key code=%d (%s)\n", - (args->Handled ? "1" : "0"), - (args->KeyStatus.IsExtendedKey ? "1" : "0"), - (args->KeyStatus.IsKeyReleased ? "1" : "0"), - (args->KeyStatus.IsMenuKeyDown ? "1" : "0"), - args->KeyStatus.RepeatCount, - args->KeyStatus.ScanCode, - (args->KeyStatus.WasKeyDown ? "1" : "0"), - args->VirtualKey, - sdlScancode, - SDL_GetScancodeName(sdlScancode), - keycode, - SDL_GetKeyName(keycode)); - //args->Handled = true; - //VirtualKey vkey = args->VirtualKey; -#endif - SDL_SendKeyboardKey(SDL_PRESSED, sdlScancode); + WINRT_ProcessKeyDownEvent(args); } void SDL_WinRTApp::OnKeyUp(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args) { - SDL_Scancode sdlScancode = TranslateKeycode((int)args->VirtualKey); -#if 0 - SDL_Keycode keycode = SDL_GetKeyFromScancode(sdlScancode); - SDL_Log("key up, handled=%s, ext?=%s, released?=%s, menu key down?=%s, repeat count=%d, native scan code=%d, was down?=%s, vkey=%d, sdl scan code=%d (%s), sdl key code=%d (%s)\n", - (args->Handled ? "1" : "0"), - (args->KeyStatus.IsExtendedKey ? "1" : "0"), - (args->KeyStatus.IsKeyReleased ? "1" : "0"), - (args->KeyStatus.IsMenuKeyDown ? "1" : "0"), - args->KeyStatus.RepeatCount, - args->KeyStatus.ScanCode, - (args->KeyStatus.WasKeyDown ? "1" : "0"), - args->VirtualKey, - sdlScancode, - SDL_GetScancodeName(sdlScancode), - keycode, - SDL_GetKeyName(keycode)); - //args->Handled = true; -#endif - SDL_SendKeyboardKey(SDL_RELEASED, sdlScancode); + WINRT_ProcessKeyUpEvent(args); } void SDL_WinRTApp::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) @@ -970,11 +530,6 @@ 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; diff --git a/src/core/winrt/SDL_winrtapp.h b/src/core/winrt/SDL_winrtapp.h index cd0c379fc..053a0dfd7 100644 --- a/src/core/winrt/SDL_winrtapp.h +++ b/src/core/winrt/SDL_winrtapp.h @@ -20,7 +20,6 @@ internal: void PumpEvents(); const SDL_WindowData * GetSDLWindowData() const; bool HasSDLWindowData() const; - void SetRelativeMouseMode(bool enable); void SetSDLWindowData(const SDL_WindowData * windowData); void SetSDLVideoDevice(const SDL_VideoDevice * videoDevice); Windows::Foundation::Point TransformCursor(Windows::Foundation::Point rawPosition); @@ -48,5 +47,4 @@ private: bool m_windowVisible; const SDL_WindowData* m_sdlWindowData; const SDL_VideoDevice* m_sdlVideoDevice; - bool m_useRelativeMouseMode; }; diff --git a/src/video/winrt/SDL_winrtevents_c.h b/src/video/winrt/SDL_winrtevents_c.h index afbd6862c..f4b179e62 100644 --- a/src/video/winrt/SDL_winrtevents_c.h +++ b/src/video/winrt/SDL_winrtevents_c.h @@ -19,9 +19,39 @@ 3. This notice may not be removed or altered from any source distribution. */ #include "SDL_config.h" - #include "SDL_winrtvideo.h" +/* + * Internal-use, C-style functions: + */ + +#ifdef __cplusplus +extern "C" { +#endif + extern void WINRT_PumpEvents(_THIS); +#ifdef __cplusplus +} +#endif + + +/* + * Internal-use, C++/CX functions: + */ +#ifdef __cplusplus_winrt + +/* Keyboard */ +extern void WINRT_ProcessKeyDownEvent(Windows::UI::Core::KeyEventArgs ^args); +extern void WINRT_ProcessKeyUpEvent(Windows::UI::Core::KeyEventArgs ^args); + +/* 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); + +#endif + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/winrt/SDL_winrtkeyboard.cpp b/src/video/winrt/SDL_winrtkeyboard.cpp new file mode 100644 index 000000000..52b8c2a39 --- /dev/null +++ b/src/video/winrt/SDL_winrtkeyboard.cpp @@ -0,0 +1,300 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2013 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 + +// Standard C++11 headers: +#include + + +// Windows-specific headers: +#include + + +// SDL-specific headers: +#include +#include "SDL_winrtevents_c.h" + +extern "C" { +#include "../../events/scancodes_windows.h" +#include "../../events/SDL_keyboard_c.h" +} + + +static SDL_Scancode WinRT_Official_Keycodes[] = { + SDL_SCANCODE_UNKNOWN, // VirtualKey.None -- 0 + SDL_SCANCODE_UNKNOWN, // VirtualKey.LeftButton -- 1 + SDL_SCANCODE_UNKNOWN, // VirtualKey.RightButton -- 2 + SDL_SCANCODE_CANCEL, // VirtualKey.Cancel -- 3 + SDL_SCANCODE_UNKNOWN, // VirtualKey.MiddleButton -- 4 + SDL_SCANCODE_UNKNOWN, // VirtualKey.XButton1 -- 5 + SDL_SCANCODE_UNKNOWN, // VirtualKey.XButton2 -- 6 + SDL_SCANCODE_UNKNOWN, // -- 7 + SDL_SCANCODE_BACKSPACE, // VirtualKey.Back -- 8 + SDL_SCANCODE_TAB, // VirtualKey.Tab -- 9 + SDL_SCANCODE_UNKNOWN, // -- 10 + SDL_SCANCODE_UNKNOWN, // -- 11 + SDL_SCANCODE_CLEAR, // VirtualKey.Clear -- 12 + SDL_SCANCODE_RETURN, // VirtualKey.Enter -- 13 + SDL_SCANCODE_UNKNOWN, // -- 14 + SDL_SCANCODE_UNKNOWN, // -- 15 + SDL_SCANCODE_LSHIFT, // VirtualKey.Shift -- 16 + SDL_SCANCODE_LCTRL, // VirtualKey.Control -- 17 + SDL_SCANCODE_MENU, // VirtualKey.Menu -- 18 + SDL_SCANCODE_PAUSE, // VirtualKey.Pause -- 19 + SDL_SCANCODE_CAPSLOCK, // VirtualKey.CapitalLock -- 20 + SDL_SCANCODE_UNKNOWN, // VirtualKey.Kana or VirtualKey.Hangul -- 21 + SDL_SCANCODE_UNKNOWN, // -- 22 + SDL_SCANCODE_UNKNOWN, // VirtualKey.Junja -- 23 + SDL_SCANCODE_UNKNOWN, // VirtualKey.Final -- 24 + SDL_SCANCODE_UNKNOWN, // VirtualKey.Hanja or VirtualKey.Kanji -- 25 + SDL_SCANCODE_UNKNOWN, // -- 26 + SDL_SCANCODE_ESCAPE, // VirtualKey.Escape -- 27 + SDL_SCANCODE_UNKNOWN, // VirtualKey.Convert -- 28 + SDL_SCANCODE_UNKNOWN, // VirtualKey.NonConvert -- 29 + SDL_SCANCODE_UNKNOWN, // VirtualKey.Accept -- 30 + SDL_SCANCODE_UNKNOWN, // VirtualKey.ModeChange -- 31 (maybe SDL_SCANCODE_MODE ?) + SDL_SCANCODE_SPACE, // VirtualKey.Space -- 32 + SDL_SCANCODE_PAGEUP, // VirtualKey.PageUp -- 33 + SDL_SCANCODE_PAGEDOWN, // VirtualKey.PageDown -- 34 + SDL_SCANCODE_END, // VirtualKey.End -- 35 + SDL_SCANCODE_HOME, // VirtualKey.Home -- 36 + SDL_SCANCODE_LEFT, // VirtualKey.Left -- 37 + SDL_SCANCODE_UP, // VirtualKey.Up -- 38 + SDL_SCANCODE_RIGHT, // VirtualKey.Right -- 39 + SDL_SCANCODE_DOWN, // VirtualKey.Down -- 40 + SDL_SCANCODE_SELECT, // VirtualKey.Select -- 41 + SDL_SCANCODE_UNKNOWN, // VirtualKey.Print -- 42 (maybe SDL_SCANCODE_PRINTSCREEN ?) + SDL_SCANCODE_EXECUTE, // VirtualKey.Execute -- 43 + SDL_SCANCODE_UNKNOWN, // VirtualKey.Snapshot -- 44 + SDL_SCANCODE_INSERT, // VirtualKey.Insert -- 45 + SDL_SCANCODE_DELETE, // VirtualKey.Delete -- 46 + SDL_SCANCODE_HELP, // VirtualKey.Help -- 47 + SDL_SCANCODE_0, // VirtualKey.Number0 -- 48 + SDL_SCANCODE_1, // VirtualKey.Number1 -- 49 + SDL_SCANCODE_2, // VirtualKey.Number2 -- 50 + SDL_SCANCODE_3, // VirtualKey.Number3 -- 51 + SDL_SCANCODE_4, // VirtualKey.Number4 -- 52 + SDL_SCANCODE_5, // VirtualKey.Number5 -- 53 + SDL_SCANCODE_6, // VirtualKey.Number6 -- 54 + SDL_SCANCODE_7, // VirtualKey.Number7 -- 55 + SDL_SCANCODE_8, // VirtualKey.Number8 -- 56 + SDL_SCANCODE_9, // VirtualKey.Number9 -- 57 + SDL_SCANCODE_UNKNOWN, // -- 58 + SDL_SCANCODE_UNKNOWN, // -- 59 + SDL_SCANCODE_UNKNOWN, // -- 60 + SDL_SCANCODE_UNKNOWN, // -- 61 + SDL_SCANCODE_UNKNOWN, // -- 62 + SDL_SCANCODE_UNKNOWN, // -- 63 + SDL_SCANCODE_UNKNOWN, // -- 64 + SDL_SCANCODE_A, // VirtualKey.A -- 65 + SDL_SCANCODE_B, // VirtualKey.B -- 66 + SDL_SCANCODE_C, // VirtualKey.C -- 67 + SDL_SCANCODE_D, // VirtualKey.D -- 68 + SDL_SCANCODE_E, // VirtualKey.E -- 69 + SDL_SCANCODE_F, // VirtualKey.F -- 70 + SDL_SCANCODE_G, // VirtualKey.G -- 71 + SDL_SCANCODE_H, // VirtualKey.H -- 72 + SDL_SCANCODE_I, // VirtualKey.I -- 73 + SDL_SCANCODE_J, // VirtualKey.J -- 74 + SDL_SCANCODE_K, // VirtualKey.K -- 75 + SDL_SCANCODE_L, // VirtualKey.L -- 76 + SDL_SCANCODE_M, // VirtualKey.M -- 77 + SDL_SCANCODE_N, // VirtualKey.N -- 78 + SDL_SCANCODE_O, // VirtualKey.O -- 79 + SDL_SCANCODE_P, // VirtualKey.P -- 80 + SDL_SCANCODE_Q, // VirtualKey.Q -- 81 + SDL_SCANCODE_R, // VirtualKey.R -- 82 + SDL_SCANCODE_S, // VirtualKey.S -- 83 + SDL_SCANCODE_T, // VirtualKey.T -- 84 + SDL_SCANCODE_U, // VirtualKey.U -- 85 + SDL_SCANCODE_V, // VirtualKey.V -- 86 + SDL_SCANCODE_W, // VirtualKey.W -- 87 + SDL_SCANCODE_X, // VirtualKey.X -- 88 + SDL_SCANCODE_Y, // VirtualKey.Y -- 89 + SDL_SCANCODE_Z, // VirtualKey.Z -- 90 + SDL_SCANCODE_UNKNOWN, // VirtualKey.LeftWindows -- 91 (maybe SDL_SCANCODE_APPLICATION or SDL_SCANCODE_LGUI ?) + SDL_SCANCODE_UNKNOWN, // VirtualKey.RightWindows -- 92 (maybe SDL_SCANCODE_APPLICATION or SDL_SCANCODE_RGUI ?) + SDL_SCANCODE_APPLICATION, // VirtualKey.Application -- 93 + SDL_SCANCODE_UNKNOWN, // -- 94 + SDL_SCANCODE_SLEEP, // VirtualKey.Sleep -- 95 + SDL_SCANCODE_KP_0, // VirtualKey.NumberPad0 -- 96 + SDL_SCANCODE_KP_1, // VirtualKey.NumberPad1 -- 97 + SDL_SCANCODE_KP_2, // VirtualKey.NumberPad2 -- 98 + SDL_SCANCODE_KP_3, // VirtualKey.NumberPad3 -- 99 + SDL_SCANCODE_KP_4, // VirtualKey.NumberPad4 -- 100 + SDL_SCANCODE_KP_5, // VirtualKey.NumberPad5 -- 101 + SDL_SCANCODE_KP_6, // VirtualKey.NumberPad6 -- 102 + SDL_SCANCODE_KP_7, // VirtualKey.NumberPad7 -- 103 + SDL_SCANCODE_KP_8, // VirtualKey.NumberPad8 -- 104 + SDL_SCANCODE_KP_9, // VirtualKey.NumberPad9 -- 105 + SDL_SCANCODE_KP_MULTIPLY, // VirtualKey.Multiply -- 106 + SDL_SCANCODE_KP_PLUS, // VirtualKey.Add -- 107 + SDL_SCANCODE_UNKNOWN, // VirtualKey.Separator -- 108 + SDL_SCANCODE_KP_MINUS, // VirtualKey.Subtract -- 109 + SDL_SCANCODE_UNKNOWN, // VirtualKey.Decimal -- 110 (maybe SDL_SCANCODE_DECIMALSEPARATOR, SDL_SCANCODE_KP_DECIMAL, or SDL_SCANCODE_KP_PERIOD ?) + SDL_SCANCODE_KP_DIVIDE, // VirtualKey.Divide -- 111 + SDL_SCANCODE_F1, // VirtualKey.F1 -- 112 + SDL_SCANCODE_F2, // VirtualKey.F2 -- 113 + SDL_SCANCODE_F3, // VirtualKey.F3 -- 114 + SDL_SCANCODE_F4, // VirtualKey.F4 -- 115 + SDL_SCANCODE_F5, // VirtualKey.F5 -- 116 + SDL_SCANCODE_F6, // VirtualKey.F6 -- 117 + SDL_SCANCODE_F7, // VirtualKey.F7 -- 118 + SDL_SCANCODE_F8, // VirtualKey.F8 -- 119 + SDL_SCANCODE_F9, // VirtualKey.F9 -- 120 + SDL_SCANCODE_F10, // VirtualKey.F10 -- 121 + SDL_SCANCODE_F11, // VirtualKey.F11 -- 122 + SDL_SCANCODE_F12, // VirtualKey.F12 -- 123 + SDL_SCANCODE_F13, // VirtualKey.F13 -- 124 + SDL_SCANCODE_F14, // VirtualKey.F14 -- 125 + SDL_SCANCODE_F15, // VirtualKey.F15 -- 126 + SDL_SCANCODE_F16, // VirtualKey.F16 -- 127 + SDL_SCANCODE_F17, // VirtualKey.F17 -- 128 + SDL_SCANCODE_F18, // VirtualKey.F18 -- 129 + SDL_SCANCODE_F19, // VirtualKey.F19 -- 130 + SDL_SCANCODE_F20, // VirtualKey.F20 -- 131 + SDL_SCANCODE_F21, // VirtualKey.F21 -- 132 + SDL_SCANCODE_F22, // VirtualKey.F22 -- 133 + SDL_SCANCODE_F23, // VirtualKey.F23 -- 134 + SDL_SCANCODE_F24, // VirtualKey.F24 -- 135 + SDL_SCANCODE_UNKNOWN, // -- 136 + SDL_SCANCODE_UNKNOWN, // -- 137 + SDL_SCANCODE_UNKNOWN, // -- 138 + SDL_SCANCODE_UNKNOWN, // -- 139 + SDL_SCANCODE_UNKNOWN, // -- 140 + SDL_SCANCODE_UNKNOWN, // -- 141 + SDL_SCANCODE_UNKNOWN, // -- 142 + SDL_SCANCODE_UNKNOWN, // -- 143 + SDL_SCANCODE_NUMLOCKCLEAR, // VirtualKey.NumberKeyLock -- 144 + SDL_SCANCODE_SCROLLLOCK, // VirtualKey.Scroll -- 145 + SDL_SCANCODE_UNKNOWN, // -- 146 + SDL_SCANCODE_UNKNOWN, // -- 147 + SDL_SCANCODE_UNKNOWN, // -- 148 + SDL_SCANCODE_UNKNOWN, // -- 149 + SDL_SCANCODE_UNKNOWN, // -- 150 + SDL_SCANCODE_UNKNOWN, // -- 151 + SDL_SCANCODE_UNKNOWN, // -- 152 + SDL_SCANCODE_UNKNOWN, // -- 153 + SDL_SCANCODE_UNKNOWN, // -- 154 + SDL_SCANCODE_UNKNOWN, // -- 155 + SDL_SCANCODE_UNKNOWN, // -- 156 + SDL_SCANCODE_UNKNOWN, // -- 157 + SDL_SCANCODE_UNKNOWN, // -- 158 + SDL_SCANCODE_UNKNOWN, // -- 159 + SDL_SCANCODE_LSHIFT, // VirtualKey.LeftShift -- 160 + SDL_SCANCODE_RSHIFT, // VirtualKey.RightShift -- 161 + SDL_SCANCODE_LCTRL, // VirtualKey.LeftControl -- 162 + SDL_SCANCODE_RCTRL, // VirtualKey.RightControl -- 163 + SDL_SCANCODE_MENU, // VirtualKey.LeftMenu -- 164 + SDL_SCANCODE_MENU, // VirtualKey.RightMenu -- 165 +}; + +static std::unordered_map WinRT_Unofficial_Keycodes; + +static SDL_Scancode +TranslateKeycode(int keycode) +{ + if (WinRT_Unofficial_Keycodes.empty()) { + /* Set up a table of undocumented (by Microsoft), WinRT-specific, + key codes: */ + // TODO, WinRT: move content declarations of WinRT_Unofficial_Keycodes into a C++11 initializer list, when possible + WinRT_Unofficial_Keycodes[220] = SDL_SCANCODE_GRAVE; + WinRT_Unofficial_Keycodes[222] = SDL_SCANCODE_BACKSLASH; + } + + /* Try to get a documented, WinRT, 'VirtualKey' first (as documented at + http://msdn.microsoft.com/en-us/library/windows/apps/windows.system.virtualkey.aspx ). + If that fails, fall back to a Win32 virtual key. + */ + // TODO, WinRT: try filling out the WinRT keycode table as much as possible, using the Win32 table for interpretation hints + //SDL_Log("WinRT TranslateKeycode, keycode=%d\n", (int)keycode); + SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN; + if (keycode < SDL_arraysize(WinRT_Official_Keycodes)) { + scancode = WinRT_Official_Keycodes[keycode]; + } + if (scancode == SDL_SCANCODE_UNKNOWN) { + if (WinRT_Unofficial_Keycodes.find(keycode) != WinRT_Unofficial_Keycodes.end()) { + scancode = WinRT_Unofficial_Keycodes[keycode]; + } + } + if (scancode == SDL_SCANCODE_UNKNOWN) { + if (keycode < SDL_arraysize(windows_scancode_table)) { + scancode = windows_scancode_table[keycode]; + } + } + if (scancode == SDL_SCANCODE_UNKNOWN) { + SDL_Log("WinRT TranslateKeycode, unknown keycode=%d\n", (int)keycode); + } + return scancode; +} + +void +WINRT_ProcessKeyDownEvent(Windows::UI::Core::KeyEventArgs ^args) +{ + SDL_Scancode sdlScancode = TranslateKeycode((int)args->VirtualKey); +#if 0 + SDL_Keycode keycode = SDL_GetKeyFromScancode(sdlScancode); + SDL_Log("key down, handled=%s, ext?=%s, released?=%s, menu key down?=%s, repeat count=%d, native scan code=%d, was down?=%s, vkey=%d, sdl scan code=%d (%s), sdl key code=%d (%s)\n", + (args->Handled ? "1" : "0"), + (args->KeyStatus.IsExtendedKey ? "1" : "0"), + (args->KeyStatus.IsKeyReleased ? "1" : "0"), + (args->KeyStatus.IsMenuKeyDown ? "1" : "0"), + args->KeyStatus.RepeatCount, + args->KeyStatus.ScanCode, + (args->KeyStatus.WasKeyDown ? "1" : "0"), + args->VirtualKey, + sdlScancode, + SDL_GetScancodeName(sdlScancode), + keycode, + SDL_GetKeyName(keycode)); + //args->Handled = true; + //VirtualKey vkey = args->VirtualKey; +#endif + SDL_SendKeyboardKey(SDL_PRESSED, sdlScancode); +} + +void +WINRT_ProcessKeyUpEvent(Windows::UI::Core::KeyEventArgs ^args) +{ + SDL_Scancode sdlScancode = TranslateKeycode((int)args->VirtualKey); +#if 0 + SDL_Keycode keycode = SDL_GetKeyFromScancode(sdlScancode); + SDL_Log("key up, handled=%s, ext?=%s, released?=%s, menu key down?=%s, repeat count=%d, native scan code=%d, was down?=%s, vkey=%d, sdl scan code=%d (%s), sdl key code=%d (%s)\n", + (args->Handled ? "1" : "0"), + (args->KeyStatus.IsExtendedKey ? "1" : "0"), + (args->KeyStatus.IsKeyReleased ? "1" : "0"), + (args->KeyStatus.IsMenuKeyDown ? "1" : "0"), + args->KeyStatus.RepeatCount, + args->KeyStatus.ScanCode, + (args->KeyStatus.WasKeyDown ? "1" : "0"), + args->VirtualKey, + sdlScancode, + SDL_GetScancodeName(sdlScancode), + keycode, + SDL_GetKeyName(keycode)); + //args->Handled = true; +#endif + SDL_SendKeyboardKey(SDL_RELEASED, sdlScancode); +} + +#endif // SDL_VIDEO_DRIVER_WINRT diff --git a/src/video/winrt/SDL_winrtmouse.cpp b/src/video/winrt/SDL_winrtmouse.cpp index 12c97d064..ec32a2ab2 100644 --- a/src/video/winrt/SDL_winrtmouse.cpp +++ b/src/video/winrt/SDL_winrtmouse.cpp @@ -23,19 +23,29 @@ #if SDL_VIDEO_DRIVER_WINRT +/* + * Windows includes: + */ +#include +using namespace Windows::UI::Core; +using Windows::UI::Core::CoreCursor; + +/* + * SDL includes: + */ extern "C" { #include "SDL_assert.h" #include "../../events/SDL_mouse_c.h" #include "../SDL_sysvideo.h" +#include "SDL_events.h" +#include "SDL_log.h" } #include "../../core/winrt/SDL_winrtapp.h" #include "SDL_winrtmouse.h" -using namespace Windows::UI::Core; -using Windows::UI::Core::CoreCursor; -extern SDL_WinRTApp ^ SDL_WinRTGlobalApp; +static SDL_bool WINRT_UseRelativeMouseMode = SDL_FALSE; static SDL_Cursor * @@ -112,7 +122,7 @@ WINRT_ShowCursor(SDL_Cursor * cursor) static int WINRT_SetRelativeMouseMode(SDL_bool enabled) { - SDL_WinRTGlobalApp->SetRelativeMouseMode(enabled ? true : false); + WINRT_UseRelativeMouseMode = enabled; return 0; } @@ -144,6 +154,248 @@ WINRT_QuitMouse(_THIS) { } +// Applies necessary geometric transformations to raw cursor positions: +static Windows::Foundation::Point +TransformCursor(SDL_Window * window, Windows::Foundation::Point rawPosition) +{ + if (!window) { + return rawPosition; + } + CoreWindow ^ nativeWindow = CoreWindow::GetForCurrentThread(); + Windows::Foundation::Point outputPosition; + outputPosition.X = rawPosition.X * (((float32)window->w) / nativeWindow->Bounds.Width); + outputPosition.Y = rawPosition.Y * (((float32)window->h) / nativeWindow->Bounds.Height); + 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 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 + // 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 = TransformCursor(window, mouseDeltaInDIPs); + SDL_SendMouseMotion( + window, + 0, + 1, + _lround(mouseDeltaInSDLWindowCoords.X), + _lround(mouseDeltaInSDLWindowCoords.Y)); +} + +static Uint8 +WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt) +{ + using namespace Windows::UI::Input; + + 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; + } + + return 0; +} + +static 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 void +WINRT_LogPointerEvent(const char * header, 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, PointerUpdateKind=%s\n", + header, + pt->Position.X, pt->Position.Y, + transformedPoint.X, transformedPoint.Y, + pt->Properties->MouseWheelDelta, + pt->FrameId, + pt->PointerId, + WINRT_ConvertPointerUpdateKindToString(args->CurrentPoint->Properties->PointerUpdateKind)); +} + +void +WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args) +{ +#if LOG_POINTER_EVENTS + WINRT_LogPointerEvent("pointer moved", args, TransformCursor(args->CurrentPoint->Position)); +#endif + + if (!window || WINRT_UseRelativeMouseMode) { + return; + } + + Windows::Foundation::Point transformedPoint = TransformCursor(window, args->CurrentPoint->Position); + SDL_SendMouseMotion(window, 0, 0, (int)transformedPoint.X, (int)transformedPoint.Y); +} + +void +WINRT_ProcessPointerWheelChangedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args) +{ +#if LOG_POINTER_EVENTS + WINRT_LogPointerEvent("wheel changed", args, TransformCursor(args->CurrentPoint->Position)); +#endif + + if (!window) { + return; + } + + // FIXME: This may need to accumulate deltas up to WHEEL_DELTA + short motion = args->CurrentPoint->Properties->MouseWheelDelta / WHEEL_DELTA; + SDL_SendMouseWheel(window, 0, 0, motion); +} + +void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args) +{ +#if LOG_POINTER_EVENTS + WINRT_LogPointerEvent("mouse up", args, TransformCursor(args->CurrentPoint->Position)); +#endif + + if (!window) { + return; + } + + Uint8 button = WINRT_GetSDLButtonForPointerPoint(args->CurrentPoint); + if (button) { + SDL_SendMouseButton(window, 0, SDL_RELEASED, button); + } +} + +void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Core::PointerEventArgs ^args) +{ +#if LOG_POINTER_EVENTS + WINRT_LogPointerEvent("mouse down", args, TransformCursor(args->CurrentPoint->Position)); +#endif + + if (!window) { + return; + } + + Uint8 button = WINRT_GetSDLButtonForPointerPoint(args->CurrentPoint); + if (button) { + SDL_SendMouseButton(window, 0, SDL_PRESSED, button); + } +} + #endif /* SDL_VIDEO_DRIVER_WINRT */ /* vi: set ts=4 sw=4 expandtab: */