Skip to content
This repository has been archived by the owner on Mar 30, 2019. It is now read-only.

Commit

Permalink
[Toolkit.Input] Change behavior of PointerManager to return position …
Browse files Browse the repository at this point in the history
…independent window size in the range [0,1]
  • Loading branch information
xoofx committed Mar 21, 2013
1 parent d75d2a5 commit 52182b4
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 19 deletions.
Expand Up @@ -104,17 +104,21 @@ private void HandleMouseUp(object sender, MouseEventArgs e)
/// <param name="wheelDelta">The current mouse wheel delta.</param>
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,
Expand Down
Expand Up @@ -183,7 +183,7 @@ private void DecodeAndDispatchTouchMessages(IntPtr wParam, IntPtr lParam)
/// <param name="input">The touch point input structure.</param>
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;
Expand All @@ -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,
Expand All @@ -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);
}
Expand Down
54 changes: 51 additions & 3 deletions Source/Toolkit/SharpDX.Toolkit.Input/PointerPlatformWP8.cs
Expand Up @@ -31,6 +31,8 @@ namespace SharpDX.Toolkit.Input
/// <remarks>Implements <see cref="IDrawingSurfaceManipulationHandler"/>.</remarks>
internal sealed class PointerPlatformWP8 : PointerPlatform, IDrawingSurfaceManipulationHandler
{
private System.Windows.FrameworkElement uiElement;

/// <summary>
/// Initializes a new instace of <see cref="PointerPlatformWP8"/> class.
/// </summary>
Expand All @@ -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);
Expand All @@ -61,6 +81,22 @@ protected override void BindWindow(object nativeWindow)
throw new ArgumentException("Should be an instance of DrawingSurfaceBackgroundGrid", "nativeWindow");
}

/// <summary>
/// Binds the corresponding event handler to the provided <see cref="DrawingSurfaceBackgroundGrid"/>
/// </summary>
/// <param name="drawingSurface">An instance of <see cref="DrawingSurfaceBackgroundGrid"/> whose events needs to be bound to</param>
/// <exception cref="ArgumentNullException">Is thrown if <paramref name="drawingSurface"/> is null</exception>
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);
}

/// <summary>
/// Binds the corresponding event handler to the provided <see cref="DrawingSurfaceBackgroundGrid"/>
/// </summary>
Expand Down Expand Up @@ -104,19 +140,31 @@ 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
{
EventType = type,
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,
Expand Down
49 changes: 38 additions & 11 deletions Source/Toolkit/SharpDX.Toolkit.Input/PointerPlatformWinRT.cs
Expand Up @@ -40,6 +40,10 @@ internal sealed class PointerPlatformWinRT : PointerPlatform
/// <exception cref="ArgumentNullException">Is thrown when either <paramref name="nativeWindow"/> or <paramref name="manager"/> is null.</exception>
internal PointerPlatformWinRT(object nativeWindow, PointerManager manager) : base(nativeWindow, manager) { }

private FrameworkElement uiElement;

private Size2F windowSize;

/// <summary>
/// Binds to pointer events of specified <paramref name="nativeWindow"/> object and raises the corresponding events on <paramref name="manager"/>.
/// </summary>
Expand All @@ -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);
Expand All @@ -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);
}

/// <summary>
/// Creates a platform-independent instance of <see cref="PointerPoint"/> class from WinRT-specific objects.
/// </summary>
Expand All @@ -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,
Expand Down

0 comments on commit 52182b4

Please sign in to comment.