TouchDevice.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using Avalonia.Input.Raw;
  6. using Avalonia.Platform;
  7. #pragma warning disable CS0618
  8. namespace Avalonia.Input
  9. {
  10. /// <summary>
  11. /// Handles raw touch events
  12. /// </summary>
  13. /// <remarks>
  14. /// This class is supposed to be used on per-toplevel basis, don't use a shared one
  15. /// </remarks>
  16. public class TouchDevice : IPointerDevice, IDisposable
  17. {
  18. private readonly Dictionary<long, Pointer> _pointers = new Dictionary<long, Pointer>();
  19. private bool _disposed;
  20. private int _clickCount;
  21. private Rect _lastClickRect;
  22. private ulong _lastClickTime;
  23. static RawInputModifiers GetModifiers(RawInputModifiers modifiers, bool isLeftButtonDown)
  24. {
  25. var rv = modifiers &= RawInputModifiers.KeyboardMask;
  26. if (isLeftButtonDown)
  27. rv |= RawInputModifiers.LeftMouseButton;
  28. return rv;
  29. }
  30. public void ProcessRawEvent(RawInputEventArgs ev)
  31. {
  32. if (ev.Handled || _disposed)
  33. return;
  34. var args = (RawPointerEventArgs)ev;
  35. if (!_pointers.TryGetValue(args.RawPointerId, out var pointer))
  36. {
  37. if (args.Type == RawPointerEventType.TouchEnd)
  38. return;
  39. var hit = args.InputHitTestResult;
  40. _pointers[args.RawPointerId] = pointer = new Pointer(Pointer.GetNextFreeId(),
  41. PointerType.Touch, _pointers.Count == 0);
  42. pointer.Capture(hit);
  43. }
  44. var target = pointer.Captured ?? args.Root;
  45. var updateKind = args.Type.ToUpdateKind();
  46. var keyModifier = args.InputModifiers.ToKeyModifiers();
  47. if (args.Type == RawPointerEventType.TouchBegin)
  48. {
  49. if (_pointers.Count > 1)
  50. {
  51. _clickCount = 1;
  52. _lastClickTime = 0;
  53. _lastClickRect = new Rect();
  54. }
  55. else
  56. {
  57. var settings = AvaloniaLocator.Current.GetRequiredService<IPlatformSettings>();
  58. var doubleClickTime = settings.GetDoubleTapTime(PointerType.Touch).TotalMilliseconds;
  59. var doubleClickSize = settings.GetDoubleTapSize(PointerType.Touch);
  60. if (!_lastClickRect.Contains(args.Position)
  61. || ev.Timestamp - _lastClickTime > doubleClickTime)
  62. {
  63. _clickCount = 0;
  64. }
  65. ++_clickCount;
  66. _lastClickTime = ev.Timestamp;
  67. _lastClickRect = new Rect(args.Position, new Size())
  68. .Inflate(new Thickness(doubleClickSize.Width / 2, doubleClickSize.Height / 2));
  69. }
  70. target.RaiseEvent(new PointerPressedEventArgs(target, pointer,
  71. (Visual)args.Root, args.Position, ev.Timestamp,
  72. new PointerPointProperties(GetModifiers(args.InputModifiers, true), updateKind),
  73. keyModifier, _clickCount));
  74. }
  75. if (args.Type == RawPointerEventType.TouchEnd)
  76. {
  77. _pointers.Remove(args.RawPointerId);
  78. using (pointer)
  79. {
  80. target.RaiseEvent(new PointerReleasedEventArgs(target, pointer,
  81. (Visual)args.Root, args.Position, ev.Timestamp,
  82. new PointerPointProperties(GetModifiers(args.InputModifiers, false), updateKind),
  83. keyModifier, MouseButton.Left));
  84. }
  85. }
  86. if (args.Type == RawPointerEventType.TouchCancel)
  87. {
  88. _pointers.Remove(args.RawPointerId);
  89. using (pointer)
  90. pointer.Capture(null);
  91. }
  92. if (args.Type == RawPointerEventType.TouchUpdate)
  93. {
  94. target.RaiseEvent(new PointerEventArgs(InputElement.PointerMovedEvent, target, pointer, (Visual)args.Root,
  95. args.Position, ev.Timestamp,
  96. new PointerPointProperties(GetModifiers(args.InputModifiers, true), updateKind),
  97. keyModifier, args.IntermediatePoints));
  98. }
  99. }
  100. public void Dispose()
  101. {
  102. if (_disposed)
  103. return;
  104. var values = _pointers.Values.ToArray();
  105. _pointers.Clear();
  106. _disposed = true;
  107. foreach (var p in values)
  108. p.Dispose();
  109. }
  110. public IPointer? TryGetPointer(RawPointerEventArgs ev)
  111. {
  112. return _pointers.TryGetValue(ev.RawPointerId, out var pointer)
  113. ? pointer
  114. : null;
  115. }
  116. }
  117. }