csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
212 lines
8.0 KiB
212 lines
8.0 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using Avalonia.Input.Raw;
|
|
using Avalonia.Interactivity;
|
|
using Avalonia.Metadata;
|
|
using Avalonia.VisualTree;
|
|
|
|
namespace Avalonia.Input
|
|
{
|
|
public class PointerEventArgs : RoutedEventArgs
|
|
{
|
|
private readonly Visual? _rootVisual;
|
|
private readonly Point _rootVisualPosition;
|
|
private readonly PointerPointProperties _properties;
|
|
private readonly Lazy<IReadOnlyList<RawPointerPoint>?>? _previousPoints;
|
|
|
|
[Unstable("This constructor might be removed in 12.0. For unit testing, consider using IHeadlessWindow mouse methods.")]
|
|
public PointerEventArgs(RoutedEvent routedEvent,
|
|
object? source,
|
|
IPointer pointer,
|
|
Visual? rootVisual, Point rootVisualPosition,
|
|
ulong timestamp,
|
|
PointerPointProperties properties,
|
|
KeyModifiers modifiers)
|
|
: base(routedEvent)
|
|
{
|
|
Source = source;
|
|
_rootVisual = rootVisual;
|
|
_rootVisualPosition = rootVisualPosition;
|
|
_properties = properties;
|
|
Pointer = pointer;
|
|
Timestamp = timestamp;
|
|
KeyModifiers = modifiers;
|
|
}
|
|
|
|
internal PointerEventArgs(RoutedEvent routedEvent,
|
|
object? source,
|
|
IPointer pointer,
|
|
Visual? rootVisual, Point rootVisualPosition,
|
|
ulong timestamp,
|
|
PointerPointProperties properties,
|
|
KeyModifiers modifiers,
|
|
Lazy<IReadOnlyList<RawPointerPoint>?>? previousPoints)
|
|
#pragma warning disable CS0618
|
|
: this(routedEvent, source, pointer, rootVisual, rootVisualPosition, timestamp, properties, modifiers)
|
|
#pragma warning restore CS0618
|
|
{
|
|
_previousPoints = previousPoints;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets specific pointer generated by input device.
|
|
/// </summary>
|
|
public IPointer Pointer { get; }
|
|
|
|
/// <summary>
|
|
/// Gets the time when the input occurred.
|
|
/// </summary>
|
|
public ulong Timestamp { get; }
|
|
|
|
internal bool IsGestureRecognitionSkipped
|
|
{
|
|
get
|
|
{
|
|
return (Pointer as Pointer)?.IsGestureRecognitionSkipped ?? false;
|
|
}
|
|
private set
|
|
{
|
|
if (Pointer is Pointer pointer)
|
|
pointer.IsGestureRecognitionSkipped = true;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a value that indicates which key modifiers were active at the time that the pointer event was initiated.
|
|
/// </summary>
|
|
public KeyModifiers KeyModifiers { get; }
|
|
|
|
private Point GetPosition(Point pt, Visual? relativeTo)
|
|
{
|
|
if (_rootVisual == null)
|
|
return default;
|
|
if (relativeTo == null)
|
|
return pt;
|
|
|
|
// If the visual the user passed in, is not connected to the same visual root
|
|
// (i.e. they called it for a control inside a popup.
|
|
if (!ReferenceEquals(_rootVisual, relativeTo.VisualRoot) && relativeTo.VisualRoot is { })
|
|
{
|
|
// Convert to absolute screen coordinates.
|
|
var screenPt = _rootVisual.PointToScreen(pt);
|
|
|
|
// Convert to client co-ordinates of the visual inside the other visual root.
|
|
return relativeTo.PointToClient(screenPt);
|
|
}
|
|
|
|
return pt * _rootVisual.TransformToVisual(relativeTo) ?? default;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the pointer position relative to a control.
|
|
/// </summary>
|
|
/// <param name="relativeTo">The visual whose coordinate system to use. Pass null for toplevel coordinate system</param>
|
|
/// <returns>The pointer position in the control's coordinates.</returns>
|
|
public Point GetPosition(Visual? relativeTo) => GetPosition(_rootVisualPosition, relativeTo);
|
|
|
|
/// <summary>
|
|
/// Returns the PointerPoint associated with the current event
|
|
/// </summary>
|
|
/// <param name="relativeTo">The visual whose coordinate system to use. Pass null for toplevel coordinate system</param>
|
|
/// <returns></returns>
|
|
public PointerPoint GetCurrentPoint(Visual? relativeTo)
|
|
=> new PointerPoint(Pointer, GetPosition(relativeTo), _properties);
|
|
|
|
/// <summary>
|
|
/// Returns the PointerPoint associated with the current event
|
|
/// </summary>
|
|
/// <param name="relativeTo">The visual which coordinate system to use. Pass null for toplevel coordinate system</param>
|
|
/// <returns></returns>
|
|
public IReadOnlyList<PointerPoint> GetIntermediatePoints(Visual? relativeTo)
|
|
{
|
|
var previousPoints = _previousPoints?.Value;
|
|
if (previousPoints == null || previousPoints.Count == 0)
|
|
return new[] { GetCurrentPoint(relativeTo) };
|
|
var points = new PointerPoint[previousPoints.Count + 1];
|
|
for (var c = 0; c < previousPoints.Count; c++)
|
|
{
|
|
var pt = previousPoints[c];
|
|
var pointProperties = new PointerPointProperties(_properties, pt);
|
|
points[c] = new PointerPoint(Pointer, GetPosition(pt.Position, relativeTo), pointProperties);
|
|
}
|
|
|
|
points[points.Length - 1] = GetCurrentPoint(relativeTo);
|
|
return points;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Prevents this event from being handled by other gesture recognizers in the route
|
|
/// </summary>
|
|
public void PreventGestureRecognition()
|
|
{
|
|
IsGestureRecognitionSkipped = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the state the pointer device had when this event occurred.
|
|
/// </summary>
|
|
public PointerPointProperties Properties => _properties;
|
|
}
|
|
|
|
public enum MouseButton
|
|
{
|
|
None,
|
|
Left,
|
|
Right,
|
|
Middle,
|
|
XButton1,
|
|
XButton2
|
|
}
|
|
|
|
public class PointerPressedEventArgs : PointerEventArgs
|
|
{
|
|
[Unstable("This constructor might be removed in 12.0. For unit testing, consider using IHeadlessWindow mouse methods.")]
|
|
public PointerPressedEventArgs(
|
|
object source,
|
|
IPointer pointer,
|
|
Visual rootVisual, Point rootVisualPosition,
|
|
ulong timestamp,
|
|
PointerPointProperties properties,
|
|
KeyModifiers modifiers,
|
|
int clickCount = 1)
|
|
: base(InputElement.PointerPressedEvent, source, pointer, rootVisual, rootVisualPosition,
|
|
timestamp, properties, modifiers)
|
|
{
|
|
ClickCount = clickCount;
|
|
}
|
|
|
|
public int ClickCount { get; }
|
|
}
|
|
|
|
public class PointerReleasedEventArgs : PointerEventArgs
|
|
{
|
|
[Unstable("This constructor might be removed in 12.0. For unit testing, consider using IHeadlessWindow mouse methods.")]
|
|
public PointerReleasedEventArgs(
|
|
object source, IPointer pointer,
|
|
Visual rootVisual, Point rootVisualPosition, ulong timestamp,
|
|
PointerPointProperties properties, KeyModifiers modifiers,
|
|
MouseButton initialPressMouseButton)
|
|
: base(InputElement.PointerReleasedEvent, source, pointer, rootVisual, rootVisualPosition,
|
|
timestamp, properties, modifiers)
|
|
{
|
|
InitialPressMouseButton = initialPressMouseButton;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the mouse button that triggered the corresponding PointerPressed event
|
|
/// </summary>
|
|
public MouseButton InitialPressMouseButton { get; }
|
|
}
|
|
|
|
public class PointerCaptureLostEventArgs : RoutedEventArgs
|
|
{
|
|
public IPointer Pointer { get; }
|
|
|
|
[Unstable("This constructor might be removed in 12.0. If you need to remove capture, use stable methods on the IPointer instance.,")]
|
|
public PointerCaptureLostEventArgs(object source, IPointer pointer) : base(InputElement.PointerCaptureLostEvent)
|
|
{
|
|
Pointer = pointer;
|
|
Source = source;
|
|
}
|
|
}
|
|
}
|
|
|