Browse Source
Merge pull request #12666 from AvaloniaUI/gesture_cancel
Call CaptureLost on gestures when pointer loses capture
pull/12757/head
Max Katz
3 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with
70 additions and
3 deletions
-
src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs
-
src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs
-
src/Avalonia.Base/Input/InputElement.cs
-
src/Avalonia.Base/Input/Pointer.cs
-
tests/Avalonia.Base.UnitTests/Input/GesturesTests.cs
-
tests/Avalonia.UnitTests/TouchTestHelper.cs
|
|
|
@ -1,3 +1,4 @@ |
|
|
|
using System; |
|
|
|
using System.Collections; |
|
|
|
using System.Collections.Generic; |
|
|
|
using Avalonia.Controls; |
|
|
|
@ -59,6 +60,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) |
|
|
|
|
|
|
|
@ -1,4 +1,5 @@ |
|
|
|
using Avalonia.Input.GestureRecognizers; |
|
|
|
using System.Diagnostics; |
|
|
|
using Avalonia.Input.GestureRecognizers; |
|
|
|
|
|
|
|
namespace Avalonia.Input |
|
|
|
{ |
|
|
|
@ -110,6 +111,7 @@ namespace Avalonia.Input |
|
|
|
|
|
|
|
_secondContact = null; |
|
|
|
} |
|
|
|
|
|
|
|
Target?.RaiseEvent(new PinchEndedEventArgs()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -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) |
|
|
|
|
|
|
|
@ -91,12 +91,16 @@ namespace Avalonia.Input |
|
|
|
internal void CaptureGestureRecognizer(GestureRecognizer? gestureRecognizer) |
|
|
|
{ |
|
|
|
if (CapturedGestureRecognizer != gestureRecognizer) |
|
|
|
{ |
|
|
|
CapturedGestureRecognizer?.PointerCaptureLostInternal(this); |
|
|
|
} |
|
|
|
|
|
|
|
CapturedGestureRecognizer = gestureRecognizer; |
|
|
|
|
|
|
|
if (gestureRecognizer != null) |
|
|
|
{ |
|
|
|
Capture(null); |
|
|
|
|
|
|
|
CapturedGestureRecognizer = gestureRecognizer; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -487,6 +487,40 @@ namespace Avalonia.Base.UnitTests.Input |
|
|
|
Assert.True(raised); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public void Gestures_Should_Be_Cancelled_When_Pointer_Capture_Is_Lost() |
|
|
|
{ |
|
|
|
Border border = new Border() |
|
|
|
{ |
|
|
|
Width = 100, |
|
|
|
Height = 100, |
|
|
|
Background = new SolidColorBrush(Colors.Red) |
|
|
|
}; |
|
|
|
border.GestureRecognizers.Add(new PinchGestureRecognizer()); |
|
|
|
var root = new TestRoot |
|
|
|
{ |
|
|
|
Child = border |
|
|
|
}; |
|
|
|
var raised = false; |
|
|
|
|
|
|
|
root.AddHandler(Gestures.PinchEvent, (_, _) => raised = true); |
|
|
|
|
|
|
|
var firstPoint = new Point(5, 5); |
|
|
|
var secondPoint = new Point(10, 10); |
|
|
|
|
|
|
|
var firstTouch = new TouchTestHelper(); |
|
|
|
var secondTouch = new TouchTestHelper(); |
|
|
|
|
|
|
|
firstTouch.Down(border, position: firstPoint); |
|
|
|
|
|
|
|
firstTouch.Cancel(); |
|
|
|
|
|
|
|
secondTouch.Down(border, position: secondPoint); |
|
|
|
secondTouch.Move(border, position: new Point(20, 20)); |
|
|
|
|
|
|
|
Assert.False(raised); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public void Scrolling_Should_Start_After_Start_Distance_Is_Exceeded() |
|
|
|
{ |
|
|
|
|
|
|
|
@ -61,5 +61,11 @@ namespace Avalonia.UnitTests |
|
|
|
Down(target, source, position, modifiers); |
|
|
|
Up(target, source, position, modifiers); |
|
|
|
} |
|
|
|
|
|
|
|
public void Cancel() |
|
|
|
{ |
|
|
|
_pointer.Capture(null); |
|
|
|
_pointer.CaptureGestureRecognizer(null); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|