TouchDevice.cs 4.6 KB

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