diff --git a/Source/Toolkit/SharpDX.Toolkit.Input/PointerPlatformDesktop.cs b/Source/Toolkit/SharpDX.Toolkit.Input/PointerPlatformDesktop.cs index fc30da8f3..6f30c0372 100644 --- a/Source/Toolkit/SharpDX.Toolkit.Input/PointerPlatformDesktop.cs +++ b/Source/Toolkit/SharpDX.Toolkit.Input/PointerPlatformDesktop.cs @@ -104,17 +104,21 @@ private void HandleMouseUp(object sender, MouseEventArgs e) /// The current mouse wheel delta. private void CreateAndAddPoint(PointerEventType eventType, PointerUpdateKind pointerUpdateKind, int wheelDelta) { - var position = control.PointToClient(Control.MousePosition); + var p = control.PointToClient(Control.MousePosition); var mouseButtons = Control.MouseButtons; + var clientSize = control.ClientSize; + var position = new Vector2((float)p.X / clientSize.Width, (float)p.Y / clientSize.Height); + position.Saturate(); + var point = new PointerPoint { EventType = eventType, DeviceType = PointerDeviceType.Mouse, KeyModifiers = GetCurrentKeyModifiers(), PointerId = 0, - Position = new Vector2(position.X, position.Y), + Position = position, Timestamp = (ulong)DateTime.Now.Ticks, ContactRect = new RectangleF(position.X, position.Y, 0f, 0f), IsBarrelButtonPresset = false, diff --git a/Source/Toolkit/SharpDX.Toolkit.Input/PointerPlatformDesktopTouch.cs b/Source/Toolkit/SharpDX.Toolkit.Input/PointerPlatformDesktopTouch.cs index d9fe94f8b..6341d5fa2 100644 --- a/Source/Toolkit/SharpDX.Toolkit.Input/PointerPlatformDesktopTouch.cs +++ b/Source/Toolkit/SharpDX.Toolkit.Input/PointerPlatformDesktopTouch.cs @@ -183,7 +183,7 @@ private void DecodeAndDispatchTouchMessages(IntPtr wParam, IntPtr lParam) /// The touch point input structure. private void DecodeAndDispatchTouchPoint(TOUCHINPUT input) { - var position = control.PointToClient(new System.Drawing.Point(AdjustX(input.x), AdjustY(input.y))); + var p = control.PointToClient(new System.Drawing.Point(AdjustX(input.x), AdjustY(input.y))); var mask = input.dwMask; var flags = input.dwFlags; @@ -208,13 +208,17 @@ private void DecodeAndDispatchTouchPoint(TOUCHINPUT input) eventType = PointerEventType.Moved; } + var clientSize = control.ClientSize; + var position = new Vector2((float)p.X / clientSize.Width, (float)p.Y / clientSize.Height); + position.Saturate(); + var point = new PointerPoint { EventType = eventType, DeviceType = ((flags & User32.TOUCHEVENTF_PEN) != 0) ? PointerDeviceType.Pen : PointerDeviceType.Touch, PointerId = (uint)input.dwID, Timestamp = (ulong)input.dwTime, - Position = new Vector2(position.X, position.Y), + Position = position, KeyModifiers = GetCurrentKeyModifiers(), IsPrimary = isPrimary, IsInRange = (flags & User32.TOUCHEVENTF_INRANGE) != 0, @@ -223,7 +227,7 @@ private void DecodeAndDispatchTouchPoint(TOUCHINPUT input) }; if ((mask & User32.TOUCHINPUTMASKF_CONTACTAREA) != 0) - point.ContactRect = new RectangleF(position.X, position.Y, AdjustX(input.cxContact), AdjustY(input.cyContact)); + point.ContactRect = new RectangleF(position.X, position.Y, (float)AdjustX(input.cxContact) / clientSize.Width, (float)AdjustY(input.cyContact) / clientSize.Height); manager.AddPointerEvent(ref point); } diff --git a/Source/Toolkit/SharpDX.Toolkit.Input/PointerPlatformWP8.cs b/Source/Toolkit/SharpDX.Toolkit.Input/PointerPlatformWP8.cs index 9dd593412..f2656dc40 100644 --- a/Source/Toolkit/SharpDX.Toolkit.Input/PointerPlatformWP8.cs +++ b/Source/Toolkit/SharpDX.Toolkit.Input/PointerPlatformWP8.cs @@ -31,6 +31,8 @@ namespace SharpDX.Toolkit.Input /// Implements . internal sealed class PointerPlatformWP8 : PointerPlatform, IDrawingSurfaceManipulationHandler { + private System.Windows.FrameworkElement uiElement; + /// /// Initializes a new instace of class. /// @@ -45,10 +47,28 @@ protected override void BindWindow(object nativeWindow) { if (nativeWindow == null) throw new ArgumentNullException("nativeWindow"); + + var drawingSurface = nativeWindow as DrawingSurface; + if (drawingSurface != null) + { + uiElement = drawingSurface; + + // avoid threading issues as this is much more restrictive on WP8 + if (drawingSurface.Dispatcher.CheckAccess()) + BindManipulationEvents(drawingSurface); + else + drawingSurface.Dispatcher.BeginInvoke(() => BindManipulationEvents(drawingSurface)); + + return; + } + + // only DrawingSurfaceBackgroundGrid is supported at this time var grid = nativeWindow as DrawingSurfaceBackgroundGrid; if (grid != null) { + uiElement = grid; + // avoid threading issues as this is much more restrictive on WP8 if (grid.Dispatcher.CheckAccess()) BindManipulationEvents(grid); @@ -61,6 +81,22 @@ protected override void BindWindow(object nativeWindow) throw new ArgumentException("Should be an instance of DrawingSurfaceBackgroundGrid", "nativeWindow"); } + /// + /// Binds the corresponding event handler to the provided + /// + /// An instance of whose events needs to be bound to + /// Is thrown if is null + private void BindManipulationEvents(DrawingSurface drawingSurface) + { + if (drawingSurface == null) throw new ArgumentNullException("drawingSurface"); + + drawingSurface.SetManipulationHandler(this); + + // TODO: review if we need to unbind the handlers to avoid memory leaks + drawingSurface.Unloaded += (_, __) => drawingSurface.SetManipulationHandler(null); + Disposing += (_, __) => drawingSurface.SetManipulationHandler(null); + } + /// /// Binds the corresponding event handler to the provided /// @@ -104,9 +140,21 @@ private void CreateAndAddPoint(PointerEventType type, global::Windows.UI.Input.P { if (point == null) throw new ArgumentNullException("point"); - var position = point.Position; + // If we can't access the uiElement (this can happen here), then run this code on the ui thread + if (!uiElement.Dispatcher.CheckAccess()) + { + uiElement.Dispatcher.BeginInvoke(() => CreateAndAddPoint(type, point)); + return; + } + + var p = point.Position; var properties = point.Properties; var contactRect = properties.ContactRect; + var width = (float)uiElement.ActualWidth; + var height = (float)uiElement.ActualHeight; + + var position = new Vector2((float)p.X / width, (float)p.Y / height); + position.Saturate(); var result = new PointerPoint { @@ -114,9 +162,9 @@ private void CreateAndAddPoint(PointerEventType type, global::Windows.UI.Input.P DeviceType = PointerDeviceType.Touch, KeyModifiers = KeyModifiers.None, PointerId = point.PointerId, - Position = new Vector2((float)position.X, (float)position.Y), + Position = position, Timestamp = point.Timestamp, - ContactRect = new RectangleF((float)contactRect.X, (float)contactRect.Y, (float)contactRect.Width, (float)contactRect.Height), + ContactRect = new RectangleF((float)contactRect.X / width, (float)contactRect.Y / height, (float)contactRect.Width / width, (float)contactRect.Height / height), IsBarrelButtonPresset = properties.IsBarrelButtonPressed, IsCanceled = properties.IsCanceled, IsEraser = properties.IsEraser, diff --git a/Source/Toolkit/SharpDX.Toolkit.Input/PointerPlatformWinRT.cs b/Source/Toolkit/SharpDX.Toolkit.Input/PointerPlatformWinRT.cs index cde5e4e90..122cbabf8 100644 --- a/Source/Toolkit/SharpDX.Toolkit.Input/PointerPlatformWinRT.cs +++ b/Source/Toolkit/SharpDX.Toolkit.Input/PointerPlatformWinRT.cs @@ -40,6 +40,10 @@ internal sealed class PointerPlatformWinRT : PointerPlatform /// Is thrown when either or is null. internal PointerPlatformWinRT(object nativeWindow, PointerManager manager) : base(nativeWindow, manager) { } + private FrameworkElement uiElement; + + private Size2F windowSize; + /// /// Binds to pointer events of specified object and raises the corresponding events on . /// @@ -52,6 +56,9 @@ protected override void BindWindow(object nativeWindow) var window = nativeWindow as CoreWindow; if (window != null) { + windowSize = new Size2F((float)window.Bounds.Width, (float)window.Bounds.Height); + window.SizeChanged += window_SizeChanged; + window.PointerCaptureLost += (_, e) => CreateAndAddPoint(PointerEventType.CaptureLost, e.KeyModifiers, e.CurrentPoint); window.PointerEntered += (_, e) => CreateAndAddPoint(PointerEventType.Entered, e.KeyModifiers, e.CurrentPoint); window.PointerExited += (_, e) => CreateAndAddPoint(PointerEventType.Exited, e.KeyModifiers, e.CurrentPoint); @@ -62,22 +69,42 @@ protected override void BindWindow(object nativeWindow) return; } - var control = nativeWindow as UIElement; - if (control != null) + uiElement = nativeWindow as FrameworkElement; + if (uiElement != null) { - control.PointerCaptureLost += (_, e) => CreateAndAddPoint(PointerEventType.CaptureLost, e.KeyModifiers, e.GetCurrentPoint(control)); - control.PointerEntered += (_, e) => CreateAndAddPoint(PointerEventType.Entered, e.KeyModifiers, e.GetCurrentPoint(control)); - control.PointerExited += (_, e) => CreateAndAddPoint(PointerEventType.Exited, e.KeyModifiers, e.GetCurrentPoint(control)); - control.PointerMoved += (_, e) => CreateAndAddPoint(PointerEventType.Moved, e.KeyModifiers, e.GetCurrentPoint(control)); - control.PointerPressed += (_, e) => CreateAndAddPoint(PointerEventType.Pressed, e.KeyModifiers, e.GetCurrentPoint(control)); - control.PointerReleased += (_, e) => CreateAndAddPoint(PointerEventType.Released, e.KeyModifiers, e.GetCurrentPoint(control)); - control.PointerWheelChanged += (_, e) => CreateAndAddPoint(PointerEventType.WheelChanged, e.KeyModifiers, e.GetCurrentPoint(control)); + windowSize = new Size2F((float)uiElement.ActualWidth, (float)uiElement.ActualHeight); + uiElement.Loaded += HandleLoadedEvent; + uiElement.SizeChanged += HandleSizeChangedEvent; + + uiElement.PointerCaptureLost += (_, e) => CreateAndAddPoint(PointerEventType.CaptureLost, e.KeyModifiers, e.GetCurrentPoint(uiElement)); + uiElement.PointerEntered += (_, e) => CreateAndAddPoint(PointerEventType.Entered, e.KeyModifiers, e.GetCurrentPoint(uiElement)); + uiElement.PointerExited += (_, e) => CreateAndAddPoint(PointerEventType.Exited, e.KeyModifiers, e.GetCurrentPoint(uiElement)); + uiElement.PointerMoved += (_, e) => CreateAndAddPoint(PointerEventType.Moved, e.KeyModifiers, e.GetCurrentPoint(uiElement)); + uiElement.PointerPressed += (_, e) => CreateAndAddPoint(PointerEventType.Pressed, e.KeyModifiers, e.GetCurrentPoint(uiElement)); + uiElement.PointerReleased += (_, e) => CreateAndAddPoint(PointerEventType.Released, e.KeyModifiers, e.GetCurrentPoint(uiElement)); + uiElement.PointerWheelChanged += (_, e) => CreateAndAddPoint(PointerEventType.WheelChanged, e.KeyModifiers, e.GetCurrentPoint(uiElement)); return; } throw new ArgumentException("Should be an instance of either CoreWindow or UIElement", "nativeWindow"); } + void window_SizeChanged(CoreWindow sender, WindowSizeChangedEventArgs args) + { + windowSize = new Size2F((float)args.Size.Width, (float)args.Size.Height); + args.Handled = true; + } + + private void HandleLoadedEvent(object sender, RoutedEventArgs e) + { + windowSize = new Size2F((float)uiElement.ActualWidth, (float)uiElement.ActualHeight); + } + + private void HandleSizeChangedEvent(object sender, SizeChangedEventArgs e) + { + windowSize = new Size2F((float)e.NewSize.Width, (float)e.NewSize.Height); + } + /// /// Creates a platform-independent instance of class from WinRT-specific objects. /// @@ -99,9 +126,9 @@ private void CreateAndAddPoint(PointerEventType type, VirtualKeyModifiers modifi DeviceType = GetDeviceType(point.PointerDevice.PointerDeviceType), KeyModifiers = GetKeyModifiers(modifiers), PointerId = point.PointerId, - Position = new Vector2((float)position.X, (float)position.Y), + Position = new Vector2((float)position.X / windowSize.Width, (float)position.Y / windowSize.Height), Timestamp = point.Timestamp, - ContactRect = new RectangleF((float)contactRect.X, (float)contactRect.Y, (float)contactRect.Width, (float)contactRect.Height), + ContactRect = new RectangleF((float)contactRect.X / windowSize.Width, (float)contactRect.Y / windowSize.Height, (float)contactRect.Width / windowSize.Width, (float)contactRect.Height / windowSize.Height), IsBarrelButtonPresset = properties.IsBarrelButtonPressed, IsCanceled = properties.IsCanceled, IsEraser = properties.IsEraser,