30 private readonly Control _control;
31 private readonly
bool _emulateMouse;
32 private readonly Dictionary<int, TouchPoint> _activeTouches =
new();
34 private readonly ConcurrentQueue<TouchPoint> _pendingBegins =
new();
35 private readonly ConcurrentQueue<TouchPoint> _pendingEnds =
new();
36 private bool _isDisposed;
39 public IReadOnlyList<TouchPoint>
ActiveTouches => _activeTouchesSnapshot;
58 _control = control ??
throw new ArgumentNullException(nameof(control));
59 _emulateMouse = emulateMouse;
61 _control.PointerPressed += OnPointerPressed;
62 _control.PointerMoved += OnPointerMoved;
63 _control.PointerReleased += OnPointerReleased;
64 _control.PointerCaptureLost += OnPointerCaptureLost;
66 Engine.
Logger.LogInformation(
"AvaloniaTouchInputAdapter initialized.");
69 private void OnPointerPressed(
object? sender, PointerPressedEventArgs e)
71 if (e.Pointer.Type == PointerType.Mouse && !_emulateMouse)
76 if (e.Pointer.Type == PointerType.Mouse &&
77 !e.GetCurrentPoint(sender as Control).Properties.IsLeftButtonPressed)
80 var
id = GetTouchId(e.Pointer);
81 var pos = GetPosition(e, sender as Control);
84 _activeTouches[id] = point;
86 _pendingBegins.Enqueue(point);
89 private void OnPointerMoved(
object? sender, PointerEventArgs e)
91 if (e.Pointer.Type == PointerType.Mouse && !_emulateMouse)
94 var
id = GetTouchId(e.Pointer);
98 if (!_activeTouches.ContainsKey(
id))
101 var pos = GetPosition(e, sender as Control);
104 _activeTouches[id] = point;
108 private void OnPointerReleased(
object? sender, PointerReleasedEventArgs e)
110 if (e.Pointer.Type == PointerType.Mouse && !_emulateMouse)
113 var
id = GetTouchId(e.Pointer);
115 if (!_activeTouches.ContainsKey(
id))
118 var pos = GetPosition(e, sender as Control);
121 _activeTouches.Remove(
id);
123 _pendingEnds.Enqueue(point);
126 private void OnPointerCaptureLost(
object? sender, PointerCaptureLostEventArgs e)
128 if (e.Pointer.Type == PointerType.Mouse && !_emulateMouse)
132 var
id = GetTouchId(e.Pointer);
134 if (!_activeTouches.TryGetValue(
id, out var existing))
138 _activeTouches.Remove(
id);
140 _pendingEnds.Enqueue(point);
146 if (_pendingBegins.IsEmpty)
149 var snapshot =
new List<TouchPoint>(_pendingBegins.Count);
150 while (_pendingBegins.TryDequeue(out var point))
158 if (_pendingEnds.IsEmpty)
161 var snapshot =
new List<TouchPoint>(_pendingEnds.Count);
162 while (_pendingEnds.TryDequeue(out var point))
167 private void RebuildSnapshot()
169 _activeTouchesSnapshot = _activeTouches.Values.ToArray();
179 private static int GetTouchId(IPointer pointer)
180 => pointer.Type == PointerType.Mouse ? 0 : (int)pointer.Id;
182 private static Point GetPosition(PointerEventArgs e, Control? relativeTo)
184 var pos = e.GetPosition(relativeTo);
185 return PointerCoordinates.ToScreenPx(relativeTo,
new PointF((
float)pos.X, (
float)pos.Y));
194 if (_isDisposed)
return;
197 _control.PointerPressed -= OnPointerPressed;
198 _control.PointerMoved -= OnPointerMoved;
199 _control.PointerReleased -= OnPointerReleased;
200 _control.PointerCaptureLost -= OnPointerCaptureLost;
202 Engine.
Logger.LogInformation(
"AvaloniaTouchInputAdapter disposed.");