Просмотр исходного кода

ensure gestures receive capture lost event

Emmanuel Hansen 2 лет назад
Родитель
Сommit
c3d524d80d

+ 1 - 0
src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs

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

+ 21 - 0
src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs

@@ -1,3 +1,4 @@
+using System;
 using System.Collections;
 using System.Collections.Generic;
 using Avalonia.Controls;
@@ -24,8 +25,14 @@ namespace Avalonia.Input.GestureRecognizers
                 _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);
             recognizer.Target = _inputElement;
+            recognizer.GestureRecognizerCollection = this;
 
             // Hacks to make bindings work
 
@@ -59,6 +66,20 @@ namespace Avalonia.Input.GestureRecognizers
             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)
         {
             if (_recognizers == null)

+ 6 - 1
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
 {
@@ -61,6 +62,7 @@ namespace Avalonia.Input
         {
             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)
                 {
                     _firstContact = e.Pointer;
@@ -110,6 +112,9 @@ namespace Avalonia.Input
 
                     _secondContact = null;
                 }
+
+                Debug.WriteLine($"Pointer with ID: {pointer.Id} removed");
+
                 Target?.RaiseEvent(new PinchEndedEventArgs());
             }
         }

+ 6 - 0
src/Avalonia.Base/Input/InputElement.cs

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

+ 7 - 2
src/Avalonia.Base/Input/Pointer.cs

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