| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reactive.Linq;
- using Avalonia.Input.Raw;
- using Avalonia.Interactivity;
- using Avalonia.Platform;
- using Avalonia.Utilities;
- using Avalonia.VisualTree;
- namespace Avalonia.Input
- {
- /// <summary>
- /// Represents a mouse device.
- /// </summary>
- public class MouseDevice : IMouseDevice, IDisposable
- {
- private int _clickCount;
- private Rect _lastClickRect;
- private ulong _lastClickTime;
- private readonly Pointer _pointer;
- private bool _disposed;
- private MouseButton _lastMouseDownButton;
- public MouseDevice(Pointer? pointer = null)
- {
- _pointer = pointer ?? new Pointer(Pointer.GetNextFreeId(), PointerType.Mouse, true);
- }
- public void ProcessRawEvent(RawInputEventArgs e)
- {
- if (!e.Handled && e is RawPointerEventArgs margs)
- ProcessRawEvent(margs);
- }
- int ButtonCount(PointerPointProperties props)
- {
- var rv = 0;
- if (props.IsLeftButtonPressed)
- rv++;
- if (props.IsMiddleButtonPressed)
- rv++;
- if (props.IsRightButtonPressed)
- rv++;
- if (props.IsXButton1Pressed)
- rv++;
- if (props.IsXButton2Pressed)
- rv++;
- return rv;
- }
- private void ProcessRawEvent(RawPointerEventArgs e)
- {
- e = e ?? throw new ArgumentNullException(nameof(e));
- var mouse = (MouseDevice)e.Device;
- if(mouse._disposed)
- return;
- var props = CreateProperties(e);
- var keyModifiers = e.InputModifiers.ToKeyModifiers();
- switch (e.Type)
- {
- case RawPointerEventType.LeaveWindow:
- case RawPointerEventType.NonClientLeftButtonDown:
- LeaveWindow();
- break;
- case RawPointerEventType.LeftButtonDown:
- case RawPointerEventType.RightButtonDown:
- case RawPointerEventType.MiddleButtonDown:
- case RawPointerEventType.XButton1Down:
- case RawPointerEventType.XButton2Down:
- if (ButtonCount(props) > 1)
- e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers, e.IntermediatePoints, e.InputHitTestResult);
- else
- e.Handled = MouseDown(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers, e.InputHitTestResult);
- break;
- case RawPointerEventType.LeftButtonUp:
- case RawPointerEventType.RightButtonUp:
- case RawPointerEventType.MiddleButtonUp:
- case RawPointerEventType.XButton1Up:
- case RawPointerEventType.XButton2Up:
- if (ButtonCount(props) != 0)
- e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers, e.IntermediatePoints, e.InputHitTestResult);
- else
- e.Handled = MouseUp(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers, e.InputHitTestResult);
- break;
- case RawPointerEventType.Move:
- e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers, e.IntermediatePoints, e.InputHitTestResult);
- break;
- case RawPointerEventType.Wheel:
- e.Handled = MouseWheel(mouse, e.Timestamp, e.Root, e.Position, props, ((RawMouseWheelEventArgs)e).Delta, keyModifiers, e.InputHitTestResult);
- break;
- case RawPointerEventType.Magnify:
- e.Handled = GestureMagnify(mouse, e.Timestamp, e.Root, e.Position, props, ((RawPointerGestureEventArgs)e).Delta, keyModifiers, e.InputHitTestResult);
- break;
- case RawPointerEventType.Rotate:
- e.Handled = GestureRotate(mouse, e.Timestamp, e.Root, e.Position, props, ((RawPointerGestureEventArgs)e).Delta, keyModifiers, e.InputHitTestResult);
- break;
- case RawPointerEventType.Swipe:
- e.Handled = GestureSwipe(mouse, e.Timestamp, e.Root, e.Position, props, ((RawPointerGestureEventArgs)e).Delta, keyModifiers, e.InputHitTestResult);
- break;
- }
- }
- private void LeaveWindow()
- {
- }
- PointerPointProperties CreateProperties(RawPointerEventArgs args)
- {
- return new PointerPointProperties(args.InputModifiers, args.Type.ToUpdateKind());
- }
- private bool MouseDown(IMouseDevice device, ulong timestamp, IInputElement root, Point p,
- PointerPointProperties properties,
- KeyModifiers inputModifiers, IInputElement? hitTest)
- {
- device = device ?? throw new ArgumentNullException(nameof(device));
- root = root ?? throw new ArgumentNullException(nameof(root));
- var source = _pointer.Captured ?? root.InputHitTest(p);
- if (source != null)
- {
- _pointer.Capture(source);
- if (source != null)
- {
- var settings = AvaloniaLocator.Current.GetRequiredService<IPlatformSettings>();
- var doubleClickTime = settings.GetDoubleTapTime(PointerType.Mouse).TotalMilliseconds;
- var doubleClickSize = settings.GetDoubleTapSize(PointerType.Mouse);
- if (!_lastClickRect.Contains(p) || timestamp - _lastClickTime > doubleClickTime)
- {
- _clickCount = 0;
- }
- ++_clickCount;
- _lastClickTime = timestamp;
- _lastClickRect = new Rect(p, new Size())
- .Inflate(new Thickness(doubleClickSize.Width / 2, doubleClickSize.Height / 2));
- _lastMouseDownButton = properties.PointerUpdateKind.GetMouseButton();
- var e = new PointerPressedEventArgs(source, _pointer, (Visual)root, p, timestamp, properties, inputModifiers, _clickCount);
- source.RaiseEvent(e);
- return e.Handled;
- }
- }
- return false;
- }
- private bool MouseMove(IMouseDevice device, ulong timestamp, IInputRoot root, Point p,
- PointerPointProperties properties, KeyModifiers inputModifiers, Lazy<IReadOnlyList<RawPointerPoint>?>? intermediatePoints,
- IInputElement? hitTest)
- {
- device = device ?? throw new ArgumentNullException(nameof(device));
- root = root ?? throw new ArgumentNullException(nameof(root));
- var source = _pointer.Captured ?? hitTest;
- if (source is object)
- {
- var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, (Visual)root,
- p, timestamp, properties, inputModifiers, intermediatePoints);
- source.RaiseEvent(e);
- return e.Handled;
- }
- return false;
- }
- private bool MouseUp(IMouseDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties props,
- KeyModifiers inputModifiers, IInputElement? hitTest)
- {
- device = device ?? throw new ArgumentNullException(nameof(device));
- root = root ?? throw new ArgumentNullException(nameof(root));
- var source = _pointer.Captured ?? hitTest;
- if (source is not null)
- {
- var e = new PointerReleasedEventArgs(source, _pointer, (Visual)root, p, timestamp, props, inputModifiers,
- _lastMouseDownButton);
- source?.RaiseEvent(e);
- _pointer.Capture(null);
- return e.Handled;
- }
- return false;
- }
- private bool MouseWheel(IMouseDevice device, ulong timestamp, IInputRoot root, Point p,
- PointerPointProperties props,
- Vector delta, KeyModifiers inputModifiers, IInputElement? hitTest)
- {
- var rawDelta = delta;
- device = device ?? throw new ArgumentNullException(nameof(device));
- root = root ?? throw new ArgumentNullException(nameof(root));
- var source = _pointer.Captured ?? hitTest;
- if (source is not null)
- {
- var e = new PointerWheelEventArgs(source, _pointer, (Visual)root, p, timestamp, props, inputModifiers, delta);
- source?.RaiseEvent(e);
- return e.Handled;
- }
- return false;
- }
-
- private bool GestureMagnify(IMouseDevice device, ulong timestamp, IInputRoot root, Point p,
- PointerPointProperties props, Vector delta, KeyModifiers inputModifiers, IInputElement? hitTest)
- {
- device = device ?? throw new ArgumentNullException(nameof(device));
- root = root ?? throw new ArgumentNullException(nameof(root));
- var source = _pointer.Captured ?? hitTest;
- if (source != null)
- {
- var e = new PointerDeltaEventArgs(Gestures.PointerTouchPadGestureMagnifyEvent, source,
- _pointer, (Visual)root, p, timestamp, props, inputModifiers, delta);
- source?.RaiseEvent(e);
- return e.Handled;
- }
- return false;
- }
-
- private bool GestureRotate(IMouseDevice device, ulong timestamp, IInputRoot root, Point p,
- PointerPointProperties props, Vector delta, KeyModifiers inputModifiers, IInputElement? hitTest)
- {
- device = device ?? throw new ArgumentNullException(nameof(device));
- root = root ?? throw new ArgumentNullException(nameof(root));
- var source = _pointer.Captured ?? hitTest;
- if (source != null)
- {
- var e = new PointerDeltaEventArgs(Gestures.PointerTouchPadGestureRotateEvent, source,
- _pointer, (Visual)root, p, timestamp, props, inputModifiers, delta);
- source?.RaiseEvent(e);
- return e.Handled;
- }
- return false;
- }
-
- private bool GestureSwipe(IMouseDevice device, ulong timestamp, IInputRoot root, Point p,
- PointerPointProperties props, Vector delta, KeyModifiers inputModifiers, IInputElement? hitTest)
- {
- device = device ?? throw new ArgumentNullException(nameof(device));
- root = root ?? throw new ArgumentNullException(nameof(root));
- var source = _pointer.Captured ?? hitTest;
- if (source != null)
- {
- var e = new PointerDeltaEventArgs(Gestures.PointerTouchPadGestureSwipeEvent, source,
- _pointer, (Visual)root, p, timestamp, props, inputModifiers, delta);
- source?.RaiseEvent(e);
- return e.Handled;
- }
- return false;
- }
- public void Dispose()
- {
- _disposed = true;
- _pointer?.Dispose();
- }
-
- public IPointer? TryGetPointer(RawPointerEventArgs ev)
- {
- return _pointer;
- }
- }
- }
|