Browse Source

ensure gestures receive capture lost event

pull/12666/head
Emmanuel Hansen 3 years ago
parent
commit
c3d524d80d
  1. 1
      src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs
  2. 21
      src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs
  3. 7
      src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs
  4. 6
      src/Avalonia.Base/Input/InputElement.cs
  5. 9
      src/Avalonia.Base/Input/Pointer.cs

1
src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs

@ -3,6 +3,7 @@
public abstract class GestureRecognizer : StyledElement public abstract class GestureRecognizer : StyledElement
{ {
protected internal IInputElement? Target { get; internal set; } protected internal IInputElement? Target { get; internal set; }
protected internal GestureRecognizerCollection? GestureRecognizerCollection { get; internal set; }
protected abstract void PointerPressed(PointerPressedEventArgs e); protected abstract void PointerPressed(PointerPressedEventArgs e);
protected abstract void PointerReleased(PointerReleasedEventArgs e); protected abstract void PointerReleased(PointerReleasedEventArgs e);

21
src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs

@ -1,3 +1,4 @@
using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using Avalonia.Controls; using Avalonia.Controls;
@ -24,8 +25,14 @@ namespace Avalonia.Input.GestureRecognizers
_recognizers = new List<GestureRecognizer>(); _recognizers = new List<GestureRecognizer>();
} }
if(recognizer.GestureRecognizerCollection != null && recognizer.GestureRecognizerCollection != this)
{
throw new InvalidOperationException("The gesture recognizer has already been added to a gesture recognizer collection");
}
_recognizers.Add(recognizer); _recognizers.Add(recognizer);
recognizer.Target = _inputElement; recognizer.Target = _inputElement;
recognizer.GestureRecognizerCollection = this;
// Hacks to make bindings work // Hacks to make bindings work
@ -59,6 +66,20 @@ namespace Avalonia.Input.GestureRecognizers
return e.Handled; return e.Handled;
} }
internal void HandleCaptureLost(IPointer pointer)
{
if (_recognizers == null || pointer is not Pointer p)
return;
foreach (var r in _recognizers)
{
if (p.CapturedGestureRecognizer == r)
continue;
r.PointerCaptureLostInternal(pointer);
}
}
internal bool HandlePointerReleased(PointerReleasedEventArgs e) internal bool HandlePointerReleased(PointerReleasedEventArgs e)
{ {
if (_recognizers == null) if (_recognizers == null)

7
src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs

@ -1,4 +1,5 @@
using Avalonia.Input.GestureRecognizers; using System.Diagnostics;
using Avalonia.Input.GestureRecognizers;
namespace Avalonia.Input namespace Avalonia.Input
{ {
@ -61,6 +62,7 @@ namespace Avalonia.Input
{ {
if (Target != null && Target is Visual visual && (e.Pointer.Type == PointerType.Touch || e.Pointer.Type == PointerType.Pen)) if (Target != null && Target is Visual visual && (e.Pointer.Type == PointerType.Touch || e.Pointer.Type == PointerType.Pen))
{ {
Debug.WriteLine($"Pointer with ID: {e.Pointer.Id} pressed");
if (_firstContact == null) if (_firstContact == null)
{ {
_firstContact = e.Pointer; _firstContact = e.Pointer;
@ -110,6 +112,9 @@ namespace Avalonia.Input
_secondContact = null; _secondContact = null;
} }
Debug.WriteLine($"Pointer with ID: {pointer.Id} removed");
Target?.RaiseEvent(new PinchEndedEventArgs()); Target?.RaiseEvent(new PinchEndedEventArgs());
} }
} }

6
src/Avalonia.Base/Input/InputElement.cs

@ -230,6 +230,7 @@ namespace Avalonia.Input
PointerMovedEvent.AddClassHandler<InputElement>((x, e) => x.OnGesturePointerMoved(e), handledEventsToo: true); PointerMovedEvent.AddClassHandler<InputElement>((x, e) => x.OnGesturePointerMoved(e), handledEventsToo: true);
PointerPressedEvent.AddClassHandler<InputElement>((x, e) => x.OnGesturePointerPressed(e), handledEventsToo: true); PointerPressedEvent.AddClassHandler<InputElement>((x, e) => x.OnGesturePointerPressed(e), handledEventsToo: true);
PointerReleasedEvent.AddClassHandler<InputElement>((x, e) => x.OnGesturePointerReleased(e), handledEventsToo: true); PointerReleasedEvent.AddClassHandler<InputElement>((x, e) => x.OnGesturePointerReleased(e), handledEventsToo: true);
PointerCaptureLostEvent.AddClassHandler<InputElement>((x, e) => x.OnGesturePointerCaptureLost(e), handledEventsToo: true);
} }
public InputElement() public InputElement()
@ -615,6 +616,11 @@ namespace Avalonia.Input
} }
} }
private void OnGesturePointerCaptureLost(PointerCaptureLostEventArgs e)
{
_gestureRecognizers?.HandleCaptureLost(e.Pointer);
}
private void OnGesturePointerPressed(PointerPressedEventArgs e) private void OnGesturePointerPressed(PointerPressedEventArgs e)
{ {
if (!e.IsGestureRecognitionSkipped) if (!e.IsGestureRecognitionSkipped)

9
src/Avalonia.Base/Input/Pointer.cs

@ -91,12 +91,17 @@ namespace Avalonia.Input
internal void CaptureGestureRecognizer(GestureRecognizer? gestureRecognizer) internal void CaptureGestureRecognizer(GestureRecognizer? gestureRecognizer)
{ {
if (CapturedGestureRecognizer != gestureRecognizer) if (CapturedGestureRecognizer != gestureRecognizer)
{
CapturedGestureRecognizer?.PointerCaptureLostInternal(this); CapturedGestureRecognizer?.PointerCaptureLostInternal(this);
}
CapturedGestureRecognizer = gestureRecognizer;
if (gestureRecognizer != null) if (gestureRecognizer != null)
{
gestureRecognizer.GestureRecognizerCollection?.HandleCaptureLost(this);
Capture(null); Capture(null);
}
CapturedGestureRecognizer = gestureRecognizer;
} }
} }
} }

Loading…
Cancel
Save