From 42fccd1af633a8c840e7aaeea13e62c7c1f3b6ec Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen Date: Thu, 25 May 2023 11:58:11 +0000 Subject: [PATCH 1/8] track currently active gesture in the pointer --- .../GestureRecognizerCollection.cs | 6 +++++ src/Avalonia.Base/Input/IPointer.cs | 1 + src/Avalonia.Base/Input/Pointer.cs | 25 ++++++++++++++++++- .../PullToRefresh/RefreshVisualizer.cs | 3 --- .../DefaultMenuInteractionHandlerTests.cs | 1 + 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs index 3b9b2d0de6..8101e79af9 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs @@ -114,7 +114,13 @@ namespace Avalonia.Input.GestureRecognizers void IGestureRecognizerActionsDispatcher.Capture(IPointer pointer, IGestureRecognizer recognizer) { + var p = pointer as Pointer; + if (p != null && p.CapturedGestureRecognizer != null && recognizer != p.CapturedGestureRecognizer) + return; + pointer.Capture(_inputElement); + p?.CaptureGestureRecognizer(recognizer); + _pointerGrabs![pointer] = recognizer; foreach (var r in _recognizers!) { diff --git a/src/Avalonia.Base/Input/IPointer.cs b/src/Avalonia.Base/Input/IPointer.cs index 52605bb6ae..050adbabaa 100644 --- a/src/Avalonia.Base/Input/IPointer.cs +++ b/src/Avalonia.Base/Input/IPointer.cs @@ -1,3 +1,4 @@ +using Avalonia.Input.GestureRecognizers; using Avalonia.Metadata; namespace Avalonia.Input diff --git a/src/Avalonia.Base/Input/Pointer.cs b/src/Avalonia.Base/Input/Pointer.cs index 4713364f00..a600624276 100644 --- a/src/Avalonia.Base/Input/Pointer.cs +++ b/src/Avalonia.Base/Input/Pointer.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Avalonia.Input.GestureRecognizers; using Avalonia.VisualTree; namespace Avalonia.Input @@ -52,6 +53,9 @@ namespace Avalonia.Input if (Captured is Visual v3) v3.DetachedFromVisualTree += OnCaptureDetached; + + if (Captured == null) + CaptureGestureRecognizer(null); } static IInputElement? GetNextCapture(Visual parent) @@ -69,6 +73,25 @@ namespace Avalonia.Input public PointerType Type { get; } public bool IsPrimary { get; } - public void Dispose() => Capture(null); + + /// + /// Gets the gesture recognizer that is currently capturing by the pointer, if any. + /// + internal IGestureRecognizer? CapturedGestureRecognizer { get; private set; } + + public void Dispose() + { + Capture(null); + } + + /// + /// Captures pointer input to the specified gesture recognizer. + /// + /// The gesture recognizer. + /// + internal void CaptureGestureRecognizer(IGestureRecognizer? gestureRecognizer) + { + CapturedGestureRecognizer = gestureRecognizer; + } } } diff --git a/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs b/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs index 5c7071a161..39ff8e3a92 100644 --- a/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs +++ b/src/Avalonia.Controls/PullToRefresh/RefreshVisualizer.cs @@ -238,7 +238,6 @@ namespace Avalonia.Controls visualizerVisual.Offset = IsPullDirectionVertical ? new Vector3(visualizerVisual.Offset.X, 0, 0) : new Vector3(0, visualizerVisual.Offset.Y, 0); - visual.Offset = default; _content.InvalidateMeasure(); break; case RefreshVisualizerState.Interacting: @@ -452,8 +451,6 @@ namespace Avalonia.Controls _interactionRatioSubscription = RefreshInfoProvider.GetObservable(RefreshInfoProvider.InteractionRatioProperty) .Subscribe(InteractionRatioObserver); - var visual = RefreshInfoProvider.Visual; - _executingRatio = RefreshInfoProvider.ExecutionRatio; } else diff --git a/tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs b/tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs index 506a62525c..3259ec1a4c 100644 --- a/tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs @@ -2,6 +2,7 @@ using Avalonia.Controls.Platform; using Avalonia.Controls.Primitives; using Avalonia.Input; +using Avalonia.Input.GestureRecognizers; using Avalonia.Interactivity; using Avalonia.VisualTree; using Moq; From 250959acc863124dd978729d1fb55b141932ac0d Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen Date: Thu, 25 May 2023 15:15:39 +0000 Subject: [PATCH 2/8] notify current gesture recognizer that it's lost capture --- src/Avalonia.Base/Input/Pointer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Avalonia.Base/Input/Pointer.cs b/src/Avalonia.Base/Input/Pointer.cs index a600624276..30c32ae48c 100644 --- a/src/Avalonia.Base/Input/Pointer.cs +++ b/src/Avalonia.Base/Input/Pointer.cs @@ -91,6 +91,9 @@ namespace Avalonia.Input /// internal void CaptureGestureRecognizer(IGestureRecognizer? gestureRecognizer) { + if (CapturedGestureRecognizer != gestureRecognizer) + CapturedGestureRecognizer?.PointerCaptureLost(this); + CapturedGestureRecognizer = gestureRecognizer; } } From 8c0dfbaf08f84e1c810d1870aca47ae6e387b298 Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen Date: Fri, 26 May 2023 11:32:57 +0000 Subject: [PATCH 3/8] rework gesture routing #11522 --- .../GestureRecognizerCollection.cs | 50 +++++-------------- .../GestureRecognizers/IGestureRecognizer.cs | 1 + .../PinchGestureRecognizer.cs | 4 +- .../PullGestureRecognizer.cs | 6 ++- .../ScrollGestureRecognizer.cs | 6 ++- src/Avalonia.Base/Input/InputElement.cs | 46 ++++++++++++----- src/Avalonia.Base/Input/MouseDevice.cs | 36 ++++++++++++- src/Avalonia.Base/Input/PenDevice.cs | 35 ++++++++++++- src/Avalonia.Base/Input/Pointer.cs | 5 +- src/Avalonia.Base/Input/PointerEventArgs.cs | 10 ++++ src/Avalonia.Base/Input/TouchDevice.cs | 35 ++++++++++--- src/Avalonia.Controls/Primitives/Thumb.cs | 2 + 12 files changed, 171 insertions(+), 65 deletions(-) diff --git a/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs index 8101e79af9..8ec9cb7301 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs @@ -10,8 +10,6 @@ namespace Avalonia.Input.GestureRecognizers { private readonly IInputElement _inputElement; private List? _recognizers; - private Dictionary? _pointerGrabs; - public GestureRecognizerCollection(IInputElement inputElement) { @@ -24,7 +22,6 @@ namespace Avalonia.Input.GestureRecognizers { // We initialize the collection when the first recognizer is added _recognizers = new List(); - _pointerGrabs = new Dictionary(); } _recognizers.Add(recognizer); @@ -57,8 +54,6 @@ namespace Avalonia.Input.GestureRecognizers return false; foreach (var r in _recognizers) { - if (e.Handled) - break; r.PointerPressed(e); } @@ -69,17 +64,15 @@ namespace Avalonia.Input.GestureRecognizers { if (_recognizers == null) return false; - if (_pointerGrabs!.TryGetValue(e.Pointer, out var capture)) + var pointer = e.Pointer as Pointer; + + foreach (var r in _recognizers) { - capture.PointerReleased(e); + if (pointer?.CapturedGestureRecognizer != null) + break; + + r.PointerReleased(e); } - else - foreach (var r in _recognizers) - { - if (e.Handled) - break; - r.PointerReleased(e); - } return e.Handled; } @@ -87,41 +80,24 @@ namespace Avalonia.Input.GestureRecognizers { if (_recognizers == null) return false; - if (_pointerGrabs!.TryGetValue(e.Pointer, out var capture)) - { - capture.PointerMoved(e); - } - else - foreach (var r in _recognizers) - { - if (e.Handled) - break; - r.PointerMoved(e); - } - return e.Handled; - } + var pointer = e.Pointer as Pointer; - internal void HandlePointerCaptureLost(PointerCaptureLostEventArgs e) - { - if (_recognizers == null) - return; - _pointerGrabs!.Remove(e.Pointer); foreach (var r in _recognizers) { - r.PointerCaptureLost(e.Pointer); + if (pointer?.CapturedGestureRecognizer != null) + break; + + r.PointerMoved(e); } + return e.Handled; } void IGestureRecognizerActionsDispatcher.Capture(IPointer pointer, IGestureRecognizer recognizer) { var p = pointer as Pointer; - if (p != null && p.CapturedGestureRecognizer != null && recognizer != p.CapturedGestureRecognizer) - return; - pointer.Capture(_inputElement); p?.CaptureGestureRecognizer(recognizer); - _pointerGrabs![pointer] = recognizer; foreach (var r in _recognizers!) { if (r != recognizer) diff --git a/src/Avalonia.Base/Input/GestureRecognizers/IGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/IGestureRecognizer.cs index c1d9ae5304..51c36a93de 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/IGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/IGestureRecognizer.cs @@ -2,6 +2,7 @@ namespace Avalonia.Input.GestureRecognizers { public interface IGestureRecognizer { + IInputElement? Target { get; } void Initialize(IInputElement target, IGestureRecognizerActionsDispatcher actions); void PointerPressed(PointerPressedEventArgs e); void PointerReleased(PointerReleasedEventArgs e); diff --git a/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs index 3b83d0cb87..4390167e98 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs @@ -2,7 +2,7 @@ namespace Avalonia.Input { - public class PinchGestureRecognizer : StyledElement, IGestureRecognizer + public class PinchGestureRecognizer : AvaloniaObject, IGestureRecognizer { private IInputElement? _target; private IGestureRecognizerActionsDispatcher? _actions; @@ -13,6 +13,8 @@ namespace Avalonia.Input private Point _secondPoint; private Point _origin; + public IInputElement? Target => _target; + public void Initialize(IInputElement target, IGestureRecognizerActionsDispatcher actions) { _target = target; diff --git a/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs index 6784677520..7391cdbaca 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs @@ -1,10 +1,9 @@ using System; -using System.Diagnostics; using Avalonia.Input.GestureRecognizers; namespace Avalonia.Input { - public class PullGestureRecognizer : StyledElement, IGestureRecognizer + public class PullGestureRecognizer : AvaloniaObject, IGestureRecognizer { internal static int MinPullDetectionSize = 50; @@ -27,6 +26,8 @@ namespace Avalonia.Input set => SetValue(PullDirectionProperty, value); } + public IInputElement? Target => _target; + public PullGestureRecognizer(PullDirection pullDirection) { PullDirection = pullDirection; @@ -54,6 +55,7 @@ namespace Avalonia.Input { var currentPosition = e.GetPosition(visual); _actions!.Capture(e.Pointer, this); + e.PreventGestureRecognition(); Vector delta = default; switch (PullDirection) diff --git a/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs index b510d44e63..3206c3903a 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs @@ -91,7 +91,9 @@ namespace Avalonia.Input.GestureRecognizers { get => _scrollStartDistance; set => SetAndRaise(ScrollStartDistanceProperty, ref _scrollStartDistance, value); - } + } + + public IInputElement? Target => _target; public void Initialize(IInputElement target, IGestureRecognizerActionsDispatcher actions) { @@ -132,6 +134,8 @@ namespace Avalonia.Input.GestureRecognizers _trackedRootPoint.Y - (_trackedRootPoint.Y >= rootPoint.Y ? ScrollStartDistance : -ScrollStartDistance)); _actions!.Capture(e.Pointer, this); + + e.PreventGestureRecognition(); } } diff --git a/src/Avalonia.Base/Input/InputElement.cs b/src/Avalonia.Base/Input/InputElement.cs index 68131e5bf7..46f543d25b 100644 --- a/src/Avalonia.Base/Input/InputElement.cs +++ b/src/Avalonia.Base/Input/InputElement.cs @@ -225,6 +225,11 @@ namespace Avalonia.Input PointerReleasedEvent.AddClassHandler((x, e) => x.OnPointerReleased(e)); PointerCaptureLostEvent.AddClassHandler((x, e) => x.OnPointerCaptureLost(e)); PointerWheelChangedEvent.AddClassHandler((x, e) => x.OnPointerWheelChanged(e)); + + // Gesture only handlers + PointerMovedEvent.AddClassHandler((x, e) => x.OnGesturePointerMoved(e), handledEventsToo: true); + PointerPressedEvent.AddClassHandler((x, e) => x.OnGesturePointerPressed(e), handledEventsToo: true); + PointerReleasedEvent.AddClassHandler((x, e) => x.OnGesturePointerReleased(e), handledEventsToo: true); } public InputElement() @@ -583,10 +588,6 @@ namespace Avalonia.Input /// The event args. protected virtual void OnPointerMoved(PointerEventArgs e) { - if (_gestureRecognizers?.HandlePointerMoved(e) == true) - { - e.Handled = true; - } } /// @@ -595,10 +596,6 @@ namespace Avalonia.Input /// The event args. protected virtual void OnPointerPressed(PointerPressedEventArgs e) { - if (_gestureRecognizers?.HandlePointerPressed(e) == true) - { - e.Handled = true; - } } /// @@ -607,10 +604,33 @@ namespace Avalonia.Input /// The event args. protected virtual void OnPointerReleased(PointerReleasedEventArgs e) { - if (_gestureRecognizers?.HandlePointerReleased(e) == true) - { - e.Handled = true; - } + } + + private void OnGesturePointerReleased(PointerReleasedEventArgs e) + { + if (!e.IsGestureRecognitionSkipped) + if (_gestureRecognizers?.HandlePointerReleased(e) == true) + { + e.Handled = true; + } + } + + private void OnGesturePointerPressed(PointerPressedEventArgs e) + { + if (!e.IsGestureRecognitionSkipped) + if (_gestureRecognizers?.HandlePointerPressed(e) == true) + { + e.Handled = true; + } + } + + private void OnGesturePointerMoved(PointerEventArgs e) + { + if (!e.IsGestureRecognitionSkipped) + if (_gestureRecognizers?.HandlePointerMoved(e) == true) + { + e.Handled = true; + } } /// @@ -619,7 +639,7 @@ namespace Avalonia.Input /// The event args. protected virtual void OnPointerCaptureLost(PointerCaptureLostEventArgs e) { - _gestureRecognizers?.HandlePointerCaptureLost(e); + } /// diff --git a/src/Avalonia.Base/Input/MouseDevice.cs b/src/Avalonia.Base/Input/MouseDevice.cs index 69c7a83900..bb8313106f 100644 --- a/src/Avalonia.Base/Input/MouseDevice.cs +++ b/src/Avalonia.Base/Input/MouseDevice.cs @@ -163,7 +163,22 @@ namespace Avalonia.Input device = device ?? throw new ArgumentNullException(nameof(device)); root = root ?? throw new ArgumentNullException(nameof(root)); - var source = _pointer.Captured ?? hitTest; + IInputElement source; + if (_pointer.CapturedGestureRecognizer is { } gestureRecognizer) + { + source = gestureRecognizer.Target ?? hitTest; + + if(source != null) + { + var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, (Visual)root, + p, timestamp, properties, inputModifiers, intermediatePoints); + gestureRecognizer.PointerMoved(e); + + return e.Handled; + } + } + + source = _pointer.Captured ?? hitTest; if (source is object) { @@ -174,6 +189,7 @@ namespace Avalonia.Input return e.Handled; } + return false; } @@ -183,7 +199,22 @@ namespace Avalonia.Input device = device ?? throw new ArgumentNullException(nameof(device)); root = root ?? throw new ArgumentNullException(nameof(root)); - var source = _pointer.Captured ?? hitTest; + IInputElement source; + if (_pointer.CapturedGestureRecognizer is { } gestureRecognizer) + { + source = gestureRecognizer.Target ?? hitTest; + + if (source != null) + { + var e = new PointerReleasedEventArgs(source, _pointer, (Visual)root, p, timestamp, props, inputModifiers, + _lastMouseDownButton); + gestureRecognizer.PointerReleased(e); + + return e.Handled; + } + } + + source = _pointer.Captured ?? hitTest; if (source is not null) { @@ -192,6 +223,7 @@ namespace Avalonia.Input source?.RaiseEvent(e); _pointer.Capture(null); + _pointer.CaptureGestureRecognizer(null); _lastMouseDownButton = default; return e.Handled; } diff --git a/src/Avalonia.Base/Input/PenDevice.cs b/src/Avalonia.Base/Input/PenDevice.cs index d5ccfdb18d..fcf7d31e03 100644 --- a/src/Avalonia.Base/Input/PenDevice.cs +++ b/src/Avalonia.Base/Input/PenDevice.cs @@ -114,7 +114,22 @@ namespace Avalonia.Input KeyModifiers inputModifiers, IInputElement? hitTest, Lazy?>? intermediatePoints) { - var source = pointer.Captured ?? hitTest; + IInputElement source; + if (pointer.CapturedGestureRecognizer is { } gestureRecognizer) + { + source = gestureRecognizer.Target ?? hitTest; + + if (source != null) + { + var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, pointer, (Visual)root, + p, timestamp, properties, inputModifiers, intermediatePoints); + gestureRecognizer.PointerMoved(e); + + return e.Handled; + } + } + + source = pointer.Captured ?? hitTest; if (source is not null) { @@ -132,7 +147,22 @@ namespace Avalonia.Input IInputElement root, Point p, PointerPointProperties properties, KeyModifiers inputModifiers, IInputElement? hitTest) { - var source = pointer.Captured ?? hitTest; + IInputElement source; + if (pointer.CapturedGestureRecognizer is { } gestureRecognizer) + { + source = gestureRecognizer.Target ?? hitTest; + + if (source != null) + { + var e = new PointerReleasedEventArgs(source, pointer, (Visual)root, p, timestamp, properties, inputModifiers, + _lastMouseDownButton); + gestureRecognizer.PointerReleased(e); + + return e.Handled; + } + } + + source = pointer.Captured ?? hitTest; if (source is not null) { @@ -141,6 +171,7 @@ namespace Avalonia.Input source.RaiseEvent(e); pointer.Capture(null); + pointer.CaptureGestureRecognizer(null); _lastMouseDownButton = default; return e.Handled; } diff --git a/src/Avalonia.Base/Input/Pointer.cs b/src/Avalonia.Base/Input/Pointer.cs index 30c32ae48c..3abda3637e 100644 --- a/src/Avalonia.Base/Input/Pointer.cs +++ b/src/Avalonia.Base/Input/Pointer.cs @@ -54,7 +54,7 @@ namespace Avalonia.Input if (Captured is Visual v3) v3.DetachedFromVisualTree += OnCaptureDetached; - if (Captured == null) + if (Captured != null) CaptureGestureRecognizer(null); } @@ -94,6 +94,9 @@ namespace Avalonia.Input if (CapturedGestureRecognizer != gestureRecognizer) CapturedGestureRecognizer?.PointerCaptureLost(this); + if (gestureRecognizer != null) + Capture(null); + CapturedGestureRecognizer = gestureRecognizer; } } diff --git a/src/Avalonia.Base/Input/PointerEventArgs.cs b/src/Avalonia.Base/Input/PointerEventArgs.cs index 9c24e5c314..cd742cc4e4 100644 --- a/src/Avalonia.Base/Input/PointerEventArgs.cs +++ b/src/Avalonia.Base/Input/PointerEventArgs.cs @@ -58,6 +58,8 @@ namespace Avalonia.Input /// public ulong Timestamp { get; } + internal bool IsGestureRecognitionSkipped { get; private set; } + /// /// Gets a value that indicates which key modifiers were active at the time that the pointer event was initiated. /// @@ -121,6 +123,14 @@ namespace Avalonia.Input return points; } + /// + /// Prevents this event from being handled by other gesture recognizers in the route + /// + public void PreventGestureRecognition() + { + IsGestureRecognitionSkipped = true; + } + /// /// Returns the current pointer point properties /// diff --git a/src/Avalonia.Base/Input/TouchDevice.cs b/src/Avalonia.Base/Input/TouchDevice.cs index 74c5837b84..c5b372defa 100644 --- a/src/Avalonia.Base/Input/TouchDevice.cs +++ b/src/Avalonia.Base/Input/TouchDevice.cs @@ -52,6 +52,7 @@ namespace Avalonia.Input } var target = pointer.Captured ?? args.Root; + var gestureTarget = pointer.CapturedGestureRecognizer?.Target; var updateKind = args.Type.ToUpdateKind(); var keyModifier = args.InputModifiers.ToKeyModifiers(); @@ -95,10 +96,19 @@ namespace Avalonia.Input _pointers.Remove(args.RawPointerId); using (pointer) { - target.RaiseEvent(new PointerReleasedEventArgs(target, pointer, - (Visual)args.Root, args.Position, ev.Timestamp, - new PointerPointProperties(GetModifiers(args.InputModifiers, false), updateKind), - keyModifier, MouseButton.Left)); + target = gestureTarget ?? target; + var e = new PointerReleasedEventArgs(target, pointer, + (Visual)args.Root, args.Position, ev.Timestamp, + new PointerPointProperties(GetModifiers(args.InputModifiers, false), updateKind), + keyModifier, MouseButton.Left); + if (gestureTarget != null) + { + pointer?.CapturedGestureRecognizer?.PointerReleased(e); + } + else + { + target.RaiseEvent(e); + } } } @@ -106,15 +116,28 @@ namespace Avalonia.Input { _pointers.Remove(args.RawPointerId); using (pointer) + { pointer.Capture(null); + pointer.CaptureGestureRecognizer(null); + } } if (args.Type == RawPointerEventType.TouchUpdate) { - target.RaiseEvent(new PointerEventArgs(InputElement.PointerMovedEvent, target, pointer, (Visual)args.Root, + target = gestureTarget ?? target; + var e = new PointerEventArgs(InputElement.PointerMovedEvent, target, pointer, (Visual)args.Root, args.Position, ev.Timestamp, new PointerPointProperties(GetModifiers(args.InputModifiers, true), updateKind), - keyModifier, args.IntermediatePoints)); + keyModifier, args.IntermediatePoints); + + if (gestureTarget != null) + { + pointer?.CapturedGestureRecognizer?.PointerMoved(e); + } + else + { + target.RaiseEvent(e); + } } } diff --git a/src/Avalonia.Controls/Primitives/Thumb.cs b/src/Avalonia.Controls/Primitives/Thumb.cs index c5d73dc00f..7299300cc7 100644 --- a/src/Avalonia.Controls/Primitives/Thumb.cs +++ b/src/Avalonia.Controls/Primitives/Thumb.cs @@ -113,6 +113,8 @@ namespace Avalonia.Controls.Primitives PseudoClasses.Add(":pressed"); + e.PreventGestureRecognition(); + RaiseEvent(ev); } From 5ad9e4ea4ed478875ff46d4669b29800018a15da Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen Date: Fri, 26 May 2023 12:16:17 +0000 Subject: [PATCH 4/8] fix tests --- src/Avalonia.Base/Input/MouseDevice.cs | 10 +++++----- src/Avalonia.Base/Input/PenDevice.cs | 9 +++++---- src/Avalonia.Base/Input/TouchDevice.cs | 6 +++--- tests/Avalonia.UnitTests/TouchTestHelper.cs | 20 ++++++++++++++++---- 4 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/Avalonia.Base/Input/MouseDevice.cs b/src/Avalonia.Base/Input/MouseDevice.cs index bb8313106f..328d5e945f 100644 --- a/src/Avalonia.Base/Input/MouseDevice.cs +++ b/src/Avalonia.Base/Input/MouseDevice.cs @@ -7,7 +7,7 @@ using Avalonia.Metadata; using Avalonia.Platform; using Avalonia.Utilities; using Avalonia.VisualTree; - +using Avalonia.Input.GestureRecognizers; #pragma warning disable CS0618 namespace Avalonia.Input @@ -163,8 +163,8 @@ namespace Avalonia.Input device = device ?? throw new ArgumentNullException(nameof(device)); root = root ?? throw new ArgumentNullException(nameof(root)); - IInputElement source; - if (_pointer.CapturedGestureRecognizer is { } gestureRecognizer) + IInputElement? source; + if (_pointer.CapturedGestureRecognizer is IGestureRecognizer gestureRecognizer) { source = gestureRecognizer.Target ?? hitTest; @@ -199,8 +199,8 @@ namespace Avalonia.Input device = device ?? throw new ArgumentNullException(nameof(device)); root = root ?? throw new ArgumentNullException(nameof(root)); - IInputElement source; - if (_pointer.CapturedGestureRecognizer is { } gestureRecognizer) + IInputElement? source; + if (_pointer.CapturedGestureRecognizer is IGestureRecognizer gestureRecognizer) { source = gestureRecognizer.Target ?? hitTest; diff --git a/src/Avalonia.Base/Input/PenDevice.cs b/src/Avalonia.Base/Input/PenDevice.cs index fcf7d31e03..a183dbbaf8 100644 --- a/src/Avalonia.Base/Input/PenDevice.cs +++ b/src/Avalonia.Base/Input/PenDevice.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; +using Avalonia.Input.GestureRecognizers; using Avalonia.Input.Raw; using Avalonia.Interactivity; using Avalonia.Metadata; @@ -114,8 +115,8 @@ namespace Avalonia.Input KeyModifiers inputModifiers, IInputElement? hitTest, Lazy?>? intermediatePoints) { - IInputElement source; - if (pointer.CapturedGestureRecognizer is { } gestureRecognizer) + IInputElement? source; + if (pointer.CapturedGestureRecognizer is IGestureRecognizer gestureRecognizer) { source = gestureRecognizer.Target ?? hitTest; @@ -147,8 +148,8 @@ namespace Avalonia.Input IInputElement root, Point p, PointerPointProperties properties, KeyModifiers inputModifiers, IInputElement? hitTest) { - IInputElement source; - if (pointer.CapturedGestureRecognizer is { } gestureRecognizer) + IInputElement? source; + if (pointer.CapturedGestureRecognizer is IGestureRecognizer gestureRecognizer) { source = gestureRecognizer.Target ?? hitTest; diff --git a/src/Avalonia.Base/Input/TouchDevice.cs b/src/Avalonia.Base/Input/TouchDevice.cs index c5b372defa..02f3479e95 100644 --- a/src/Avalonia.Base/Input/TouchDevice.cs +++ b/src/Avalonia.Base/Input/TouchDevice.cs @@ -117,15 +117,15 @@ namespace Avalonia.Input _pointers.Remove(args.RawPointerId); using (pointer) { - pointer.Capture(null); - pointer.CaptureGestureRecognizer(null); + pointer?.Capture(null); + pointer?.CaptureGestureRecognizer(null); } } if (args.Type == RawPointerEventType.TouchUpdate) { target = gestureTarget ?? target; - var e = new PointerEventArgs(InputElement.PointerMovedEvent, target, pointer, (Visual)args.Root, + var e = new PointerEventArgs(InputElement.PointerMovedEvent, target, pointer!, (Visual)args.Root, args.Position, ev.Timestamp, new PointerPointProperties(GetModifiers(args.InputModifiers, true), updateKind), keyModifier, args.IntermediatePoints); diff --git a/tests/Avalonia.UnitTests/TouchTestHelper.cs b/tests/Avalonia.UnitTests/TouchTestHelper.cs index db70f570a2..703cb45b96 100644 --- a/tests/Avalonia.UnitTests/TouchTestHelper.cs +++ b/tests/Avalonia.UnitTests/TouchTestHelper.cs @@ -27,8 +27,13 @@ namespace Avalonia.UnitTests public void Move(Interactive target, Interactive source, in Point position, KeyModifiers modifiers = default) { - target.RaiseEvent(new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, (Visual)target, position, - Timestamp(), PointerPointProperties.None, modifiers)); + var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, (Visual)target, position, + Timestamp(), PointerPointProperties.None, modifiers); + if (_pointer.CapturedGestureRecognizer != null) + _pointer.CapturedGestureRecognizer.PointerMoved(e); + else + target.RaiseEvent(e); + } public void Up(Interactive target, Point position = default, KeyModifiers modifiers = default) @@ -36,9 +41,16 @@ namespace Avalonia.UnitTests public void Up(Interactive target, Interactive source, Point position = default, KeyModifiers modifiers = default) { - source.RaiseEvent(new PointerReleasedEventArgs(source, _pointer, (Visual)target, position, Timestamp(), PointerPointProperties.None, - modifiers, MouseButton.None)); + var e = new PointerReleasedEventArgs(source, _pointer, (Visual)target, position, Timestamp(), PointerPointProperties.None, + modifiers, MouseButton.None); + + if (_pointer.CapturedGestureRecognizer != null) + _pointer.CapturedGestureRecognizer.PointerReleased(e); + else + source.RaiseEvent(e); + _pointer.Capture(null); + _pointer.CaptureGestureRecognizer(null); } public void Tap(Interactive target, Point position = default, KeyModifiers modifiers = default) From 0042c19121f185a0895f1e3f6572b2706b72fca5 Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen Date: Mon, 29 May 2023 15:48:48 +0000 Subject: [PATCH 5/8] replace IGestureRecognizer with abstrac GestureRecognizer. remove related obsolete interfaces. --- .../GestureRecognizers/GestureRecognizer.cs | 23 +++++++++++++++ .../GestureRecognizerCollection.cs | 29 +++++-------------- .../GestureRecognizers/IGestureRecognizer.cs | 24 --------------- .../PinchGestureRecognizer.cs | 20 ++++++------- .../PullGestureRecognizer.cs | 18 +++++------- .../ScrollGestureRecognizer.cs | 20 ++++++------- src/Avalonia.Base/Input/MouseDevice.cs | 24 ++++++--------- src/Avalonia.Base/Input/PenDevice.cs | 22 +++++--------- src/Avalonia.Base/Input/Pointer.cs | 4 +-- 9 files changed, 75 insertions(+), 109 deletions(-) create mode 100644 src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs delete mode 100644 src/Avalonia.Base/Input/GestureRecognizers/IGestureRecognizer.cs diff --git a/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs new file mode 100644 index 0000000000..fd6748dee7 --- /dev/null +++ b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Avalonia.Input.GestureRecognizers +{ + public abstract class GestureRecognizer : StyledElement + { + public abstract IInputElement? Target { get; } + public abstract void Initialize(IInputElement target); + public abstract void PointerPressed(PointerPressedEventArgs e); + public abstract void PointerReleased(PointerReleasedEventArgs e); + public abstract void PointerMoved(PointerEventArgs e); + public abstract void PointerCaptureLost(IPointer pointer); + + protected void Capture(IPointer pointer) + { + (pointer as Pointer)?.CaptureGestureRecognizer(this); + } + } +} diff --git a/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs index 8ec9cb7301..e7c6513c43 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs @@ -6,26 +6,26 @@ using Avalonia.Reactive; namespace Avalonia.Input.GestureRecognizers { - public class GestureRecognizerCollection : IReadOnlyCollection, IGestureRecognizerActionsDispatcher + public class GestureRecognizerCollection : IReadOnlyCollection { private readonly IInputElement _inputElement; - private List? _recognizers; + private List? _recognizers; public GestureRecognizerCollection(IInputElement inputElement) { _inputElement = inputElement; } - public void Add(IGestureRecognizer recognizer) + public void Add(GestureRecognizer recognizer) { if (_recognizers == null) { // We initialize the collection when the first recognizer is added - _recognizers = new List(); + _recognizers = new List(); } _recognizers.Add(recognizer); - recognizer.Initialize(_inputElement, this); + recognizer.Initialize(_inputElement); // Hacks to make bindings work @@ -38,16 +38,15 @@ namespace Avalonia.Input.GestureRecognizers } } - static readonly List s_Empty = new List(); + static readonly List s_Empty = new List(); - public IEnumerator GetEnumerator() + public IEnumerator GetEnumerator() => _recognizers?.GetEnumerator() ?? s_Empty.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); public int Count => _recognizers?.Count ?? 0; - internal bool HandlePointerPressed(PointerPressedEventArgs e) { if (_recognizers == null) @@ -91,19 +90,5 @@ namespace Avalonia.Input.GestureRecognizers } return e.Handled; } - - void IGestureRecognizerActionsDispatcher.Capture(IPointer pointer, IGestureRecognizer recognizer) - { - var p = pointer as Pointer; - - p?.CaptureGestureRecognizer(recognizer); - - foreach (var r in _recognizers!) - { - if (r != recognizer) - r.PointerCaptureLost(pointer); - } - } - } } diff --git a/src/Avalonia.Base/Input/GestureRecognizers/IGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/IGestureRecognizer.cs deleted file mode 100644 index 51c36a93de..0000000000 --- a/src/Avalonia.Base/Input/GestureRecognizers/IGestureRecognizer.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Avalonia.Input.GestureRecognizers -{ - public interface IGestureRecognizer - { - IInputElement? Target { get; } - void Initialize(IInputElement target, IGestureRecognizerActionsDispatcher actions); - void PointerPressed(PointerPressedEventArgs e); - void PointerReleased(PointerReleasedEventArgs e); - void PointerMoved(PointerEventArgs e); - void PointerCaptureLost(IPointer pointer); - } - - public interface IGestureRecognizerActionsDispatcher - { - void Capture(IPointer pointer, IGestureRecognizer recognizer); - } - - public enum GestureRecognizerResult - { - None, - Capture, - ReleaseCapture - } -} diff --git a/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs index 4390167e98..133fd76947 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs @@ -2,10 +2,9 @@ namespace Avalonia.Input { - public class PinchGestureRecognizer : AvaloniaObject, IGestureRecognizer + public class PinchGestureRecognizer : GestureRecognizer { private IInputElement? _target; - private IGestureRecognizerActionsDispatcher? _actions; private float _initialDistance; private IPointer? _firstContact; private Point _firstPoint; @@ -13,12 +12,11 @@ namespace Avalonia.Input private Point _secondPoint; private Point _origin; - public IInputElement? Target => _target; + public override IInputElement? Target => _target; - public void Initialize(IInputElement target, IGestureRecognizerActionsDispatcher actions) + public override void Initialize(IInputElement target) { _target = target; - _actions = actions; } private void OnPointerPressed(object? sender, PointerPressedEventArgs e) @@ -31,12 +29,12 @@ namespace Avalonia.Input PointerReleased(e); } - public void PointerCaptureLost(IPointer pointer) + public override void PointerCaptureLost(IPointer pointer) { RemoveContact(pointer); } - public void PointerMoved(PointerEventArgs e) + public override void PointerMoved(PointerEventArgs e) { if (_target != null && _target is Visual visual) { @@ -67,7 +65,7 @@ namespace Avalonia.Input } } - public void PointerPressed(PointerPressedEventArgs e) + public override void PointerPressed(PointerPressedEventArgs e) { if (_target != null && _target is Visual visual && (e.Pointer.Type == PointerType.Touch || e.Pointer.Type == PointerType.Pen)) { @@ -94,13 +92,13 @@ namespace Avalonia.Input _origin = new Point((_firstPoint.X + _secondPoint.X) / 2.0f, (_firstPoint.Y + _secondPoint.Y) / 2.0f); - _actions!.Capture(_firstContact, this); - _actions!.Capture(_secondContact, this); + Capture(_firstContact); + Capture(_secondContact); } } } - public void PointerReleased(PointerReleasedEventArgs e) + public override void PointerReleased(PointerReleasedEventArgs e) { RemoveContact(e.Pointer); } diff --git a/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs index 7391cdbaca..f6ab1c4508 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs @@ -3,12 +3,11 @@ using Avalonia.Input.GestureRecognizers; namespace Avalonia.Input { - public class PullGestureRecognizer : AvaloniaObject, IGestureRecognizer + public class PullGestureRecognizer : GestureRecognizer { internal static int MinPullDetectionSize = 50; private IInputElement? _target; - private IGestureRecognizerActionsDispatcher? _actions; private Point _initialPosition; private int _gestureId; private IPointer? _tracking; @@ -26,7 +25,7 @@ namespace Avalonia.Input set => SetValue(PullDirectionProperty, value); } - public IInputElement? Target => _target; + public override IInputElement? Target => _target; public PullGestureRecognizer(PullDirection pullDirection) { @@ -35,13 +34,12 @@ namespace Avalonia.Input public PullGestureRecognizer() { } - public void Initialize(IInputElement target, IGestureRecognizerActionsDispatcher actions) + public override void Initialize(IInputElement target) { _target = target; - _actions = actions; } - public void PointerCaptureLost(IPointer pointer) + public override void PointerCaptureLost(IPointer pointer) { if (_tracking == pointer) { @@ -49,12 +47,12 @@ namespace Avalonia.Input } } - public void PointerMoved(PointerEventArgs e) + public override void PointerMoved(PointerEventArgs e) { if (_tracking == e.Pointer && _target is Visual visual) { var currentPosition = e.GetPosition(visual); - _actions!.Capture(e.Pointer, this); + Capture(e.Pointer); e.PreventGestureRecognition(); Vector delta = default; @@ -94,7 +92,7 @@ namespace Avalonia.Input } } - public void PointerPressed(PointerPressedEventArgs e) + public override void PointerPressed(PointerPressedEventArgs e) { if (_target != null && _target is Visual visual && (e.Pointer.Type == PointerType.Touch || e.Pointer.Type == PointerType.Pen)) { @@ -129,7 +127,7 @@ namespace Avalonia.Input } } - public void PointerReleased(PointerReleasedEventArgs e) + public override void PointerReleased(PointerReleasedEventArgs e) { if (_tracking == e.Pointer && _pullInProgress) { diff --git a/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs index 3206c3903a..ecc72c8f60 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs @@ -4,7 +4,7 @@ using Avalonia.Threading; namespace Avalonia.Input.GestureRecognizers { - public class ScrollGestureRecognizer : AvaloniaObject, IGestureRecognizer + public class ScrollGestureRecognizer : GestureRecognizer { // Pixels per second speed that is considered to be the stop of inertial scroll internal const double InertialScrollSpeedEnd = 5; @@ -19,7 +19,6 @@ namespace Avalonia.Input.GestureRecognizers private Point _trackedRootPoint; private IPointer? _tracking; private IInputElement? _target; - private IGestureRecognizerActionsDispatcher? _actions; private int _gestureId; private Point _pointerPressedPoint; private VelocityTracker? _velocityTracker; @@ -93,15 +92,14 @@ namespace Avalonia.Input.GestureRecognizers set => SetAndRaise(ScrollStartDistanceProperty, ref _scrollStartDistance, value); } - public IInputElement? Target => _target; + public override IInputElement? Target => _target; - public void Initialize(IInputElement target, IGestureRecognizerActionsDispatcher actions) + public override void Initialize(IInputElement target) { _target = target; - _actions = actions; } - public void PointerPressed(PointerPressedEventArgs e) + public override void PointerPressed(PointerPressedEventArgs e) { if (e.Pointer.IsPrimary && (e.Pointer.Type == PointerType.Touch || e.Pointer.Type == PointerType.Pen)) @@ -112,8 +110,8 @@ namespace Avalonia.Input.GestureRecognizers _trackedRootPoint = _pointerPressedPoint = e.GetPosition((Visual?)_target); } } - - public void PointerMoved(PointerEventArgs e) + + public override void PointerMoved(PointerEventArgs e) { if (e.Pointer == _tracking) { @@ -133,7 +131,7 @@ namespace Avalonia.Input.GestureRecognizers _trackedRootPoint.X - (_trackedRootPoint.X >= rootPoint.X ? ScrollStartDistance : -ScrollStartDistance), _trackedRootPoint.Y - (_trackedRootPoint.Y >= rootPoint.Y ? ScrollStartDistance : -ScrollStartDistance)); - _actions!.Capture(e.Pointer, this); + Capture(e.Pointer); e.PreventGestureRecognition(); } @@ -153,7 +151,7 @@ namespace Avalonia.Input.GestureRecognizers } } - public void PointerCaptureLost(IPointer pointer) + public override void PointerCaptureLost(IPointer pointer) { if (pointer == _tracking) EndGesture(); } @@ -173,7 +171,7 @@ namespace Avalonia.Input.GestureRecognizers } - public void PointerReleased(PointerReleasedEventArgs e) + public override void PointerReleased(PointerReleasedEventArgs e) { if (e.Pointer == _tracking && _scrolling) { diff --git a/src/Avalonia.Base/Input/MouseDevice.cs b/src/Avalonia.Base/Input/MouseDevice.cs index 328d5e945f..4da8062897 100644 --- a/src/Avalonia.Base/Input/MouseDevice.cs +++ b/src/Avalonia.Base/Input/MouseDevice.cs @@ -163,14 +163,11 @@ namespace Avalonia.Input device = device ?? throw new ArgumentNullException(nameof(device)); root = root ?? throw new ArgumentNullException(nameof(root)); - IInputElement? source; - if (_pointer.CapturedGestureRecognizer is IGestureRecognizer gestureRecognizer) + if (_pointer.CapturedGestureRecognizer is GestureRecognizer gestureRecognizer) { - source = gestureRecognizer.Target ?? hitTest; - - if(source != null) + if(gestureRecognizer.Target != null) { - var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, (Visual)root, + var e = new PointerEventArgs(InputElement.PointerMovedEvent, gestureRecognizer.Target, _pointer, (Visual)root, p, timestamp, properties, inputModifiers, intermediatePoints); gestureRecognizer.PointerMoved(e); @@ -178,7 +175,7 @@ namespace Avalonia.Input } } - source = _pointer.Captured ?? hitTest; + var source = _pointer.Captured ?? hitTest; if (source is object) { @@ -198,15 +195,12 @@ namespace Avalonia.Input { device = device ?? throw new ArgumentNullException(nameof(device)); root = root ?? throw new ArgumentNullException(nameof(root)); - - IInputElement? source; - if (_pointer.CapturedGestureRecognizer is IGestureRecognizer gestureRecognizer) + + if (_pointer.CapturedGestureRecognizer is GestureRecognizer gestureRecognizer) { - source = gestureRecognizer.Target ?? hitTest; - - if (source != null) + if (gestureRecognizer.Target != null) { - var e = new PointerReleasedEventArgs(source, _pointer, (Visual)root, p, timestamp, props, inputModifiers, + var e = new PointerReleasedEventArgs(gestureRecognizer.Target, _pointer, (Visual)root, p, timestamp, props, inputModifiers, _lastMouseDownButton); gestureRecognizer.PointerReleased(e); @@ -214,7 +208,7 @@ namespace Avalonia.Input } } - source = _pointer.Captured ?? hitTest; + var source = _pointer.Captured ?? hitTest; if (source is not null) { diff --git a/src/Avalonia.Base/Input/PenDevice.cs b/src/Avalonia.Base/Input/PenDevice.cs index a183dbbaf8..fab0f1320c 100644 --- a/src/Avalonia.Base/Input/PenDevice.cs +++ b/src/Avalonia.Base/Input/PenDevice.cs @@ -115,14 +115,11 @@ namespace Avalonia.Input KeyModifiers inputModifiers, IInputElement? hitTest, Lazy?>? intermediatePoints) { - IInputElement? source; - if (pointer.CapturedGestureRecognizer is IGestureRecognizer gestureRecognizer) + if (pointer.CapturedGestureRecognizer is GestureRecognizer gestureRecognizer) { - source = gestureRecognizer.Target ?? hitTest; - - if (source != null) + if (gestureRecognizer.Target != null) { - var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, pointer, (Visual)root, + var e = new PointerEventArgs(InputElement.PointerMovedEvent, gestureRecognizer.Target, pointer, (Visual)root, p, timestamp, properties, inputModifiers, intermediatePoints); gestureRecognizer.PointerMoved(e); @@ -130,7 +127,7 @@ namespace Avalonia.Input } } - source = pointer.Captured ?? hitTest; + var source = pointer.Captured ?? hitTest; if (source is not null) { @@ -148,14 +145,11 @@ namespace Avalonia.Input IInputElement root, Point p, PointerPointProperties properties, KeyModifiers inputModifiers, IInputElement? hitTest) { - IInputElement? source; - if (pointer.CapturedGestureRecognizer is IGestureRecognizer gestureRecognizer) + if (pointer.CapturedGestureRecognizer is GestureRecognizer gestureRecognizer) { - source = gestureRecognizer.Target ?? hitTest; - - if (source != null) + if (gestureRecognizer.Target != null) { - var e = new PointerReleasedEventArgs(source, pointer, (Visual)root, p, timestamp, properties, inputModifiers, + var e = new PointerReleasedEventArgs(gestureRecognizer.Target, pointer, (Visual)root, p, timestamp, properties, inputModifiers, _lastMouseDownButton); gestureRecognizer.PointerReleased(e); @@ -163,7 +157,7 @@ namespace Avalonia.Input } } - source = pointer.Captured ?? hitTest; + var source = pointer.Captured ?? hitTest; if (source is not null) { diff --git a/src/Avalonia.Base/Input/Pointer.cs b/src/Avalonia.Base/Input/Pointer.cs index 3abda3637e..65c0d7f538 100644 --- a/src/Avalonia.Base/Input/Pointer.cs +++ b/src/Avalonia.Base/Input/Pointer.cs @@ -77,7 +77,7 @@ namespace Avalonia.Input /// /// Gets the gesture recognizer that is currently capturing by the pointer, if any. /// - internal IGestureRecognizer? CapturedGestureRecognizer { get; private set; } + internal GestureRecognizer? CapturedGestureRecognizer { get; private set; } public void Dispose() { @@ -89,7 +89,7 @@ namespace Avalonia.Input /// /// The gesture recognizer. /// - internal void CaptureGestureRecognizer(IGestureRecognizer? gestureRecognizer) + internal void CaptureGestureRecognizer(GestureRecognizer? gestureRecognizer) { if (CapturedGestureRecognizer != gestureRecognizer) CapturedGestureRecognizer?.PointerCaptureLost(this); From 0ac73d1a734bd4b63dbf2bf80265af3d5d80c58d Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen Date: Tue, 30 May 2023 09:11:09 +0000 Subject: [PATCH 6/8] remove GestureRecognizer.Initialize --- .../GestureRecognizers/GestureRecognizer.cs | 12 +++-------- .../GestureRecognizerCollection.cs | 2 +- .../PinchGestureRecognizer.cs | 16 ++++----------- .../PullGestureRecognizer.cs | 17 ++++------------ .../ScrollGestureRecognizer.cs | 20 ++++++------------- 5 files changed, 18 insertions(+), 49 deletions(-) diff --git a/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs index fd6748dee7..c7f40b4468 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs @@ -1,15 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Avalonia.Input.GestureRecognizers +namespace Avalonia.Input.GestureRecognizers { public abstract class GestureRecognizer : StyledElement { - public abstract IInputElement? Target { get; } - public abstract void Initialize(IInputElement target); + protected internal IInputElement? Target { get; internal set; } + public abstract void PointerPressed(PointerPressedEventArgs e); public abstract void PointerReleased(PointerReleasedEventArgs e); public abstract void PointerMoved(PointerEventArgs e); diff --git a/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs index e7c6513c43..d8c2d5a21b 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs @@ -25,7 +25,7 @@ namespace Avalonia.Input.GestureRecognizers } _recognizers.Add(recognizer); - recognizer.Initialize(_inputElement); + recognizer.Target = _inputElement; // Hacks to make bindings work diff --git a/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs index 133fd76947..b5342ae180 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs @@ -4,7 +4,6 @@ namespace Avalonia.Input { public class PinchGestureRecognizer : GestureRecognizer { - private IInputElement? _target; private float _initialDistance; private IPointer? _firstContact; private Point _firstPoint; @@ -12,13 +11,6 @@ namespace Avalonia.Input private Point _secondPoint; private Point _origin; - public override IInputElement? Target => _target; - - public override void Initialize(IInputElement target) - { - _target = target; - } - private void OnPointerPressed(object? sender, PointerPressedEventArgs e) { PointerPressed(e); @@ -36,7 +28,7 @@ namespace Avalonia.Input public override void PointerMoved(PointerEventArgs e) { - if (_target != null && _target is Visual visual) + if (Target != null && Target is Visual visual) { if(_firstContact == e.Pointer) { @@ -58,7 +50,7 @@ namespace Avalonia.Input var scale = distance / _initialDistance; var pinchEventArgs = new PinchEventArgs(scale, _origin); - _target?.RaiseEvent(pinchEventArgs); + Target?.RaiseEvent(pinchEventArgs); e.Handled = pinchEventArgs.Handled; } @@ -67,7 +59,7 @@ namespace Avalonia.Input public override void PointerPressed(PointerPressedEventArgs e) { - 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)) { if (_firstContact == null) { @@ -118,7 +110,7 @@ namespace Avalonia.Input _secondContact = null; } - _target?.RaiseEvent(new PinchEndedEventArgs()); + Target?.RaiseEvent(new PinchEndedEventArgs()); } } diff --git a/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs index f6ab1c4508..4d463203e6 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs @@ -6,8 +6,6 @@ namespace Avalonia.Input public class PullGestureRecognizer : GestureRecognizer { internal static int MinPullDetectionSize = 50; - - private IInputElement? _target; private Point _initialPosition; private int _gestureId; private IPointer? _tracking; @@ -25,8 +23,6 @@ namespace Avalonia.Input set => SetValue(PullDirectionProperty, value); } - public override IInputElement? Target => _target; - public PullGestureRecognizer(PullDirection pullDirection) { PullDirection = pullDirection; @@ -34,11 +30,6 @@ namespace Avalonia.Input public PullGestureRecognizer() { } - public override void Initialize(IInputElement target) - { - _target = target; - } - public override void PointerCaptureLost(IPointer pointer) { if (_tracking == pointer) @@ -49,7 +40,7 @@ namespace Avalonia.Input public override void PointerMoved(PointerEventArgs e) { - if (_tracking == e.Pointer && _target is Visual visual) + if (_tracking == e.Pointer && Target is Visual visual) { var currentPosition = e.GetPosition(visual); Capture(e.Pointer); @@ -86,7 +77,7 @@ namespace Avalonia.Input _pullInProgress = true; var pullEventArgs = new PullGestureEventArgs(_gestureId, delta, PullDirection); - _target?.RaiseEvent(pullEventArgs); + Target?.RaiseEvent(pullEventArgs); e.Handled = pullEventArgs.Handled; } @@ -94,7 +85,7 @@ namespace Avalonia.Input public override void PointerPressed(PointerPressedEventArgs e) { - 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)) { var position = e.GetPosition(visual); @@ -141,7 +132,7 @@ namespace Avalonia.Input _initialPosition = default; _pullInProgress = false; - _target?.RaiseEvent(new PullGestureEndedEventArgs(_gestureId, PullDirection)); + Target?.RaiseEvent(new PullGestureEndedEventArgs(_gestureId, PullDirection)); } } } diff --git a/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs index ecc72c8f60..2f2afd5289 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs @@ -18,7 +18,6 @@ namespace Avalonia.Input.GestureRecognizers private bool _scrolling; private Point _trackedRootPoint; private IPointer? _tracking; - private IInputElement? _target; private int _gestureId; private Point _pointerPressedPoint; private VelocityTracker? _velocityTracker; @@ -91,13 +90,6 @@ namespace Avalonia.Input.GestureRecognizers get => _scrollStartDistance; set => SetAndRaise(ScrollStartDistanceProperty, ref _scrollStartDistance, value); } - - public override IInputElement? Target => _target; - - public override void Initialize(IInputElement target) - { - _target = target; - } public override void PointerPressed(PointerPressedEventArgs e) { @@ -107,7 +99,7 @@ namespace Avalonia.Input.GestureRecognizers EndGesture(); _tracking = e.Pointer; _gestureId = ScrollGestureEventArgs.GetNextFreeId(); - _trackedRootPoint = _pointerPressedPoint = e.GetPosition((Visual?)_target); + _trackedRootPoint = _pointerPressedPoint = e.GetPosition((Visual?)Target); } } @@ -115,7 +107,7 @@ namespace Avalonia.Input.GestureRecognizers { if (e.Pointer == _tracking) { - var rootPoint = e.GetPosition((Visual?)_target); + var rootPoint = e.GetPosition((Visual?)Target); if (!_scrolling) { if (CanHorizontallyScroll && Math.Abs(_trackedRootPoint.X - rootPoint.X) > ScrollStartDistance) @@ -145,7 +137,7 @@ namespace Avalonia.Input.GestureRecognizers _lastMoveTimestamp = e.Timestamp; _trackedRootPoint = rootPoint; - _target!.RaiseEvent(new ScrollGestureEventArgs(_gestureId, vector)); + Target!.RaiseEvent(new ScrollGestureEventArgs(_gestureId, vector)); e.Handled = true; } } @@ -163,7 +155,7 @@ namespace Avalonia.Input.GestureRecognizers { _inertia = default; _scrolling = false; - _target!.RaiseEvent(new ScrollGestureEndedEventArgs(_gestureId)); + Target!.RaiseEvent(new ScrollGestureEndedEventArgs(_gestureId)); _gestureId = 0; _lastMoveTimestamp = null; } @@ -190,7 +182,7 @@ namespace Avalonia.Input.GestureRecognizers var savedGestureId = _gestureId; var st = Stopwatch.StartNew(); var lastTime = TimeSpan.Zero; - _target!.RaiseEvent(new ScrollGestureInertiaStartingEventArgs(_gestureId, _inertia)); + Target!.RaiseEvent(new ScrollGestureInertiaStartingEventArgs(_gestureId, _inertia)); DispatcherTimer.Run(() => { // Another gesture has started, finish the current one @@ -205,7 +197,7 @@ namespace Avalonia.Input.GestureRecognizers var speed = _inertia * Math.Pow(InertialResistance, st.Elapsed.TotalSeconds); var distance = speed * elapsedSinceLastTick.TotalSeconds; var scrollGestureEventArgs = new ScrollGestureEventArgs(_gestureId, distance); - _target!.RaiseEvent(scrollGestureEventArgs); + Target!.RaiseEvent(scrollGestureEventArgs); if (!scrollGestureEventArgs.Handled || scrollGestureEventArgs.ShouldEndScrollGesture) { From 9b41e8e8f820fdc7c3c7c6bcb59535f0122f0a48 Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen Date: Tue, 30 May 2023 10:07:15 +0000 Subject: [PATCH 7/8] make pointer handler protected internal --- .../Input/GestureRecognizers/GestureRecognizer.cs | 8 ++++---- .../Input/GestureRecognizers/PinchGestureRecognizer.cs | 8 ++++---- .../Input/GestureRecognizers/PullGestureRecognizer.cs | 8 ++++---- .../GestureRecognizers/ScrollGestureRecognizer.cs | 10 +++++----- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs index c7f40b4468..e96c397d11 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs @@ -4,10 +4,10 @@ { protected internal IInputElement? Target { get; internal set; } - public abstract void PointerPressed(PointerPressedEventArgs e); - public abstract void PointerReleased(PointerReleasedEventArgs e); - public abstract void PointerMoved(PointerEventArgs e); - public abstract void PointerCaptureLost(IPointer pointer); + protected internal abstract void PointerPressed(PointerPressedEventArgs e); + protected internal abstract void PointerReleased(PointerReleasedEventArgs e); + protected internal abstract void PointerMoved(PointerEventArgs e); + protected internal abstract void PointerCaptureLost(IPointer pointer); protected void Capture(IPointer pointer) { diff --git a/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs index b5342ae180..b12c2cc701 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs @@ -21,12 +21,12 @@ namespace Avalonia.Input PointerReleased(e); } - public override void PointerCaptureLost(IPointer pointer) + protected internal override void PointerCaptureLost(IPointer pointer) { RemoveContact(pointer); } - public override void PointerMoved(PointerEventArgs e) + protected internal override void PointerMoved(PointerEventArgs e) { if (Target != null && Target is Visual visual) { @@ -57,7 +57,7 @@ namespace Avalonia.Input } } - public override void PointerPressed(PointerPressedEventArgs e) + protected internal override void PointerPressed(PointerPressedEventArgs e) { if (Target != null && Target is Visual visual && (e.Pointer.Type == PointerType.Touch || e.Pointer.Type == PointerType.Pen)) { @@ -90,7 +90,7 @@ namespace Avalonia.Input } } - public override void PointerReleased(PointerReleasedEventArgs e) + protected internal override void PointerReleased(PointerReleasedEventArgs e) { RemoveContact(e.Pointer); } diff --git a/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs index 4d463203e6..5358eb4cda 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs @@ -30,7 +30,7 @@ namespace Avalonia.Input public PullGestureRecognizer() { } - public override void PointerCaptureLost(IPointer pointer) + protected internal override void PointerCaptureLost(IPointer pointer) { if (_tracking == pointer) { @@ -38,7 +38,7 @@ namespace Avalonia.Input } } - public override void PointerMoved(PointerEventArgs e) + protected internal override void PointerMoved(PointerEventArgs e) { if (_tracking == e.Pointer && Target is Visual visual) { @@ -83,7 +83,7 @@ namespace Avalonia.Input } } - public override void PointerPressed(PointerPressedEventArgs e) + protected internal override void PointerPressed(PointerPressedEventArgs e) { if (Target != null && Target is Visual visual && (e.Pointer.Type == PointerType.Touch || e.Pointer.Type == PointerType.Pen)) { @@ -118,7 +118,7 @@ namespace Avalonia.Input } } - public override void PointerReleased(PointerReleasedEventArgs e) + protected internal override void PointerReleased(PointerReleasedEventArgs e) { if (_tracking == e.Pointer && _pullInProgress) { diff --git a/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs index 2f2afd5289..80c0583d90 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs @@ -90,8 +90,8 @@ namespace Avalonia.Input.GestureRecognizers get => _scrollStartDistance; set => SetAndRaise(ScrollStartDistanceProperty, ref _scrollStartDistance, value); } - - public override void PointerPressed(PointerPressedEventArgs e) + + protected internal override void PointerPressed(PointerPressedEventArgs e) { if (e.Pointer.IsPrimary && (e.Pointer.Type == PointerType.Touch || e.Pointer.Type == PointerType.Pen)) @@ -103,7 +103,7 @@ namespace Avalonia.Input.GestureRecognizers } } - public override void PointerMoved(PointerEventArgs e) + protected internal override void PointerMoved(PointerEventArgs e) { if (e.Pointer == _tracking) { @@ -143,7 +143,7 @@ namespace Avalonia.Input.GestureRecognizers } } - public override void PointerCaptureLost(IPointer pointer) + protected internal override void PointerCaptureLost(IPointer pointer) { if (pointer == _tracking) EndGesture(); } @@ -163,7 +163,7 @@ namespace Avalonia.Input.GestureRecognizers } - public override void PointerReleased(PointerReleasedEventArgs e) + protected internal override void PointerReleased(PointerReleasedEventArgs e) { if (e.Pointer == _tracking && _scrolling) { From c12fe17315dade003858ea1359704e7ff64b9bfb Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen Date: Wed, 31 May 2023 12:50:03 +0000 Subject: [PATCH 8/8] Added internal helpers for protected gesture events --- .../GestureRecognizers/GestureRecognizer.cs | 28 ++++++++++++-- .../GestureRecognizerCollection.cs | 6 +-- .../PinchGestureRecognizer.cs | 8 ++-- .../PullGestureRecognizer.cs | 8 ++-- .../ScrollGestureRecognizer.cs | 8 ++-- src/Avalonia.Base/Input/MouseDevice.cs | 38 +++++-------------- src/Avalonia.Base/Input/PenDevice.cs | 38 +++++-------------- src/Avalonia.Base/Input/Pointer.cs | 2 +- src/Avalonia.Base/Input/TouchDevice.cs | 4 +- tests/Avalonia.UnitTests/TouchTestHelper.cs | 4 +- 10 files changed, 64 insertions(+), 80 deletions(-) diff --git a/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs index e96c397d11..2cb97b4707 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizer.cs @@ -4,10 +4,30 @@ { protected internal IInputElement? Target { get; internal set; } - protected internal abstract void PointerPressed(PointerPressedEventArgs e); - protected internal abstract void PointerReleased(PointerReleasedEventArgs e); - protected internal abstract void PointerMoved(PointerEventArgs e); - protected internal abstract void PointerCaptureLost(IPointer pointer); + protected abstract void PointerPressed(PointerPressedEventArgs e); + protected abstract void PointerReleased(PointerReleasedEventArgs e); + protected abstract void PointerMoved(PointerEventArgs e); + protected abstract void PointerCaptureLost(IPointer pointer); + + internal void PointerPressedInternal(PointerPressedEventArgs e) + { + PointerPressed(e); + } + + internal void PointerReleasedInternal(PointerReleasedEventArgs e) + { + PointerReleased(e); + } + + internal void PointerMovedInternal(PointerEventArgs e) + { + PointerMoved(e); + } + + internal void PointerCaptureLostInternal(IPointer pointer) + { + PointerCaptureLost(pointer); + } protected void Capture(IPointer pointer) { diff --git a/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs index d8c2d5a21b..05dce8214b 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/GestureRecognizerCollection.cs @@ -53,7 +53,7 @@ namespace Avalonia.Input.GestureRecognizers return false; foreach (var r in _recognizers) { - r.PointerPressed(e); + r.PointerPressedInternal(e); } return e.Handled; @@ -70,7 +70,7 @@ namespace Avalonia.Input.GestureRecognizers if (pointer?.CapturedGestureRecognizer != null) break; - r.PointerReleased(e); + r.PointerReleasedInternal(e); } return e.Handled; } @@ -86,7 +86,7 @@ namespace Avalonia.Input.GestureRecognizers if (pointer?.CapturedGestureRecognizer != null) break; - r.PointerMoved(e); + r.PointerMovedInternal(e); } return e.Handled; } diff --git a/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs index b12c2cc701..b02c82a066 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs @@ -21,12 +21,12 @@ namespace Avalonia.Input PointerReleased(e); } - protected internal override void PointerCaptureLost(IPointer pointer) + protected override void PointerCaptureLost(IPointer pointer) { RemoveContact(pointer); } - protected internal override void PointerMoved(PointerEventArgs e) + protected override void PointerMoved(PointerEventArgs e) { if (Target != null && Target is Visual visual) { @@ -57,7 +57,7 @@ namespace Avalonia.Input } } - protected internal override void PointerPressed(PointerPressedEventArgs e) + protected override void PointerPressed(PointerPressedEventArgs e) { if (Target != null && Target is Visual visual && (e.Pointer.Type == PointerType.Touch || e.Pointer.Type == PointerType.Pen)) { @@ -90,7 +90,7 @@ namespace Avalonia.Input } } - protected internal override void PointerReleased(PointerReleasedEventArgs e) + protected override void PointerReleased(PointerReleasedEventArgs e) { RemoveContact(e.Pointer); } diff --git a/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs index 5358eb4cda..57faf5bfd8 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/PullGestureRecognizer.cs @@ -30,7 +30,7 @@ namespace Avalonia.Input public PullGestureRecognizer() { } - protected internal override void PointerCaptureLost(IPointer pointer) + protected override void PointerCaptureLost(IPointer pointer) { if (_tracking == pointer) { @@ -38,7 +38,7 @@ namespace Avalonia.Input } } - protected internal override void PointerMoved(PointerEventArgs e) + protected override void PointerMoved(PointerEventArgs e) { if (_tracking == e.Pointer && Target is Visual visual) { @@ -83,7 +83,7 @@ namespace Avalonia.Input } } - protected internal override void PointerPressed(PointerPressedEventArgs e) + protected override void PointerPressed(PointerPressedEventArgs e) { if (Target != null && Target is Visual visual && (e.Pointer.Type == PointerType.Touch || e.Pointer.Type == PointerType.Pen)) { @@ -118,7 +118,7 @@ namespace Avalonia.Input } } - protected internal override void PointerReleased(PointerReleasedEventArgs e) + protected override void PointerReleased(PointerReleasedEventArgs e) { if (_tracking == e.Pointer && _pullInProgress) { diff --git a/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs index 80c0583d90..beecfcc3ce 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs @@ -91,7 +91,7 @@ namespace Avalonia.Input.GestureRecognizers set => SetAndRaise(ScrollStartDistanceProperty, ref _scrollStartDistance, value); } - protected internal override void PointerPressed(PointerPressedEventArgs e) + protected override void PointerPressed(PointerPressedEventArgs e) { if (e.Pointer.IsPrimary && (e.Pointer.Type == PointerType.Touch || e.Pointer.Type == PointerType.Pen)) @@ -103,7 +103,7 @@ namespace Avalonia.Input.GestureRecognizers } } - protected internal override void PointerMoved(PointerEventArgs e) + protected override void PointerMoved(PointerEventArgs e) { if (e.Pointer == _tracking) { @@ -143,7 +143,7 @@ namespace Avalonia.Input.GestureRecognizers } } - protected internal override void PointerCaptureLost(IPointer pointer) + protected override void PointerCaptureLost(IPointer pointer) { if (pointer == _tracking) EndGesture(); } @@ -163,7 +163,7 @@ namespace Avalonia.Input.GestureRecognizers } - protected internal override void PointerReleased(PointerReleasedEventArgs e) + protected override void PointerReleased(PointerReleasedEventArgs e) { if (e.Pointer == _tracking && _scrolling) { diff --git a/src/Avalonia.Base/Input/MouseDevice.cs b/src/Avalonia.Base/Input/MouseDevice.cs index 4da8062897..db333dbd8b 100644 --- a/src/Avalonia.Base/Input/MouseDevice.cs +++ b/src/Avalonia.Base/Input/MouseDevice.cs @@ -163,26 +163,17 @@ namespace Avalonia.Input device = device ?? throw new ArgumentNullException(nameof(device)); root = root ?? throw new ArgumentNullException(nameof(root)); - if (_pointer.CapturedGestureRecognizer is GestureRecognizer gestureRecognizer) - { - if(gestureRecognizer.Target != null) - { - var e = new PointerEventArgs(InputElement.PointerMovedEvent, gestureRecognizer.Target, _pointer, (Visual)root, - p, timestamp, properties, inputModifiers, intermediatePoints); - gestureRecognizer.PointerMoved(e); - - return e.Handled; - } - } - - var source = _pointer.Captured ?? hitTest; + var source = _pointer.CapturedGestureRecognizer?.Target ?? _pointer.Captured ?? hitTest; if (source is object) { var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, (Visual)root, p, timestamp, properties, inputModifiers, intermediatePoints); - source.RaiseEvent(e); + if (_pointer.CapturedGestureRecognizer is GestureRecognizer gestureRecognizer) + gestureRecognizer.PointerMovedInternal(e); + else + source.RaiseEvent(e); return e.Handled; } @@ -195,27 +186,18 @@ namespace Avalonia.Input { device = device ?? throw new ArgumentNullException(nameof(device)); root = root ?? throw new ArgumentNullException(nameof(root)); - - if (_pointer.CapturedGestureRecognizer is GestureRecognizer gestureRecognizer) - { - if (gestureRecognizer.Target != null) - { - var e = new PointerReleasedEventArgs(gestureRecognizer.Target, _pointer, (Visual)root, p, timestamp, props, inputModifiers, - _lastMouseDownButton); - gestureRecognizer.PointerReleased(e); - - return e.Handled; - } - } - var source = _pointer.Captured ?? hitTest; + var source = _pointer.CapturedGestureRecognizer?.Target ?? _pointer.Captured ?? hitTest; if (source is not null) { var e = new PointerReleasedEventArgs(source, _pointer, (Visual)root, p, timestamp, props, inputModifiers, _lastMouseDownButton); - source?.RaiseEvent(e); + if (_pointer.CapturedGestureRecognizer is GestureRecognizer gestureRecognizer) + gestureRecognizer.PointerReleasedInternal(e); + else + source?.RaiseEvent(e); _pointer.Capture(null); _pointer.CaptureGestureRecognizer(null); _lastMouseDownButton = default; diff --git a/src/Avalonia.Base/Input/PenDevice.cs b/src/Avalonia.Base/Input/PenDevice.cs index fab0f1320c..09bf18d3fd 100644 --- a/src/Avalonia.Base/Input/PenDevice.cs +++ b/src/Avalonia.Base/Input/PenDevice.cs @@ -115,26 +115,17 @@ namespace Avalonia.Input KeyModifiers inputModifiers, IInputElement? hitTest, Lazy?>? intermediatePoints) { - if (pointer.CapturedGestureRecognizer is GestureRecognizer gestureRecognizer) - { - if (gestureRecognizer.Target != null) - { - var e = new PointerEventArgs(InputElement.PointerMovedEvent, gestureRecognizer.Target, pointer, (Visual)root, - p, timestamp, properties, inputModifiers, intermediatePoints); - gestureRecognizer.PointerMoved(e); - - return e.Handled; - } - } - - var source = pointer.Captured ?? hitTest; + var source = pointer.CapturedGestureRecognizer?.Target ?? pointer.Captured ?? hitTest; if (source is not null) { var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, pointer, (Visual)root, p, timestamp, properties, inputModifiers, intermediatePoints); - source.RaiseEvent(e); + if (pointer.CapturedGestureRecognizer is GestureRecognizer gestureRecognizer) + gestureRecognizer.PointerMovedInternal(e); + else + source.RaiseEvent(e); return e.Handled; } @@ -145,26 +136,17 @@ namespace Avalonia.Input IInputElement root, Point p, PointerPointProperties properties, KeyModifiers inputModifiers, IInputElement? hitTest) { - if (pointer.CapturedGestureRecognizer is GestureRecognizer gestureRecognizer) - { - if (gestureRecognizer.Target != null) - { - var e = new PointerReleasedEventArgs(gestureRecognizer.Target, pointer, (Visual)root, p, timestamp, properties, inputModifiers, - _lastMouseDownButton); - gestureRecognizer.PointerReleased(e); - - return e.Handled; - } - } - - var source = pointer.Captured ?? hitTest; + var source = pointer.CapturedGestureRecognizer?.Target ?? pointer.Captured ?? hitTest; if (source is not null) { var e = new PointerReleasedEventArgs(source, pointer, (Visual)root, p, timestamp, properties, inputModifiers, _lastMouseDownButton); - source.RaiseEvent(e); + if (pointer.CapturedGestureRecognizer is GestureRecognizer gestureRecognizer) + gestureRecognizer.PointerReleasedInternal(e); + else + source.RaiseEvent(e); pointer.Capture(null); pointer.CaptureGestureRecognizer(null); _lastMouseDownButton = default; diff --git a/src/Avalonia.Base/Input/Pointer.cs b/src/Avalonia.Base/Input/Pointer.cs index 65c0d7f538..91358712a0 100644 --- a/src/Avalonia.Base/Input/Pointer.cs +++ b/src/Avalonia.Base/Input/Pointer.cs @@ -92,7 +92,7 @@ namespace Avalonia.Input internal void CaptureGestureRecognizer(GestureRecognizer? gestureRecognizer) { if (CapturedGestureRecognizer != gestureRecognizer) - CapturedGestureRecognizer?.PointerCaptureLost(this); + CapturedGestureRecognizer?.PointerCaptureLostInternal(this); if (gestureRecognizer != null) Capture(null); diff --git a/src/Avalonia.Base/Input/TouchDevice.cs b/src/Avalonia.Base/Input/TouchDevice.cs index 02f3479e95..8868e966f0 100644 --- a/src/Avalonia.Base/Input/TouchDevice.cs +++ b/src/Avalonia.Base/Input/TouchDevice.cs @@ -103,7 +103,7 @@ namespace Avalonia.Input keyModifier, MouseButton.Left); if (gestureTarget != null) { - pointer?.CapturedGestureRecognizer?.PointerReleased(e); + pointer?.CapturedGestureRecognizer?.PointerReleasedInternal(e); } else { @@ -132,7 +132,7 @@ namespace Avalonia.Input if (gestureTarget != null) { - pointer?.CapturedGestureRecognizer?.PointerMoved(e); + pointer?.CapturedGestureRecognizer?.PointerMovedInternal(e); } else { diff --git a/tests/Avalonia.UnitTests/TouchTestHelper.cs b/tests/Avalonia.UnitTests/TouchTestHelper.cs index 703cb45b96..574599d1ad 100644 --- a/tests/Avalonia.UnitTests/TouchTestHelper.cs +++ b/tests/Avalonia.UnitTests/TouchTestHelper.cs @@ -30,7 +30,7 @@ namespace Avalonia.UnitTests var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, (Visual)target, position, Timestamp(), PointerPointProperties.None, modifiers); if (_pointer.CapturedGestureRecognizer != null) - _pointer.CapturedGestureRecognizer.PointerMoved(e); + _pointer.CapturedGestureRecognizer.PointerMovedInternal(e); else target.RaiseEvent(e); @@ -45,7 +45,7 @@ namespace Avalonia.UnitTests modifiers, MouseButton.None); if (_pointer.CapturedGestureRecognizer != null) - _pointer.CapturedGestureRecognizer.PointerReleased(e); + _pointer.CapturedGestureRecognizer.PointerReleasedInternal(e); else source.RaiseEvent(e);