diff --git a/api/Avalonia.nupkg.xml b/api/Avalonia.nupkg.xml
index fbf4000a79..a1656e6527 100644
--- a/api/Avalonia.nupkg.xml
+++ b/api/Avalonia.nupkg.xml
@@ -103,6 +103,12 @@
baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
+ CP0001
+ T:Avalonia.Input.Gestures
+ baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
+ current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
CP0001
T:Avalonia.Input.IDataObject
@@ -247,6 +253,12 @@
baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll
current/Avalonia/lib/net10.0/Avalonia.Controls.dll
+
+ CP0001
+ T:Avalonia.Controls.ContextRequestedEventArgs
+ baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll
+ current/Avalonia/lib/net10.0/Avalonia.Controls.dll
+
CP0001
T:Avalonia.Controls.Diagnostics.IPopupHostProvider
@@ -499,6 +511,12 @@
baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
+ CP0001
+ T:Avalonia.Input.Gestures
+ baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
+ current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
CP0001
T:Avalonia.Input.IDataObject
@@ -643,6 +661,12 @@
baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll
current/Avalonia/lib/net8.0/Avalonia.Controls.dll
+
+ CP0001
+ T:Avalonia.Controls.ContextRequestedEventArgs
+ baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll
+ current/Avalonia/lib/net8.0/Avalonia.Controls.dll
+
CP0001
T:Avalonia.Controls.Diagnostics.IPopupHostProvider
@@ -823,6 +847,12 @@
baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
+ CP0002
+ F:Avalonia.Input.HoldingState.Cancelled
+ baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
+ current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
CP0002
F:Avalonia.Media.DrawingImage.ViewboxProperty
@@ -865,6 +895,24 @@
baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
+ CP0002
+ M:Avalonia.Data.CompiledBindingPathBuilder.StreamObservable
+ baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
+ current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
+
+ CP0002
+ M:Avalonia.Data.CompiledBindingPathBuilder.StreamTask
+ baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
+ current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
+
+ CP0002
+ M:Avalonia.Data.CompiledBindingPathBuilder.TypeCast(System.Type)
+ baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
+ current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
CP0002
M:Avalonia.Data.ReflectionBinding.#ctor(System.String,Avalonia.Data.BindingMode)
@@ -913,6 +961,12 @@
baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
+ CP0002
+ M:Avalonia.Input.HoldingRoutedEventArgs.#ctor(Avalonia.Input.HoldingState,Avalonia.Point,Avalonia.Input.PointerType)
+ baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
+ current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
CP0002
M:Avalonia.Input.IInputRoot.get_KeyboardNavigationHandler
@@ -1321,6 +1375,12 @@
baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll
current/Avalonia/lib/net10.0/Avalonia.Controls.dll
+
+ CP0002
+ F:Avalonia.Controls.Control.ContextRequestedEvent
+ baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll
+ current/Avalonia/lib/net10.0/Avalonia.Controls.dll
+
CP0002
F:Avalonia.Controls.Documents.Inline.TextDecorationsProperty
@@ -1939,6 +1999,12 @@
baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
+ CP0002
+ F:Avalonia.Input.HoldingState.Cancelled
+ baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
+ current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
CP0002
F:Avalonia.Media.DrawingImage.ViewboxProperty
@@ -1981,6 +2047,24 @@
baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
+ CP0002
+ M:Avalonia.Data.CompiledBindingPathBuilder.StreamObservable
+ baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
+ current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
+
+ CP0002
+ M:Avalonia.Data.CompiledBindingPathBuilder.StreamTask
+ baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
+ current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
+
+ CP0002
+ M:Avalonia.Data.CompiledBindingPathBuilder.TypeCast(System.Type)
+ baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
+ current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
CP0002
M:Avalonia.Data.ReflectionBinding.#ctor(System.String,Avalonia.Data.BindingMode)
@@ -2029,6 +2113,12 @@
baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
+ CP0002
+ M:Avalonia.Input.HoldingRoutedEventArgs.#ctor(Avalonia.Input.HoldingState,Avalonia.Point,Avalonia.Input.PointerType)
+ baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
+ current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
CP0002
M:Avalonia.Input.IInputRoot.get_KeyboardNavigationHandler
@@ -2437,6 +2527,12 @@
baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll
current/Avalonia/lib/net8.0/Avalonia.Controls.dll
+
+ CP0002
+ F:Avalonia.Controls.Control.ContextRequestedEvent
+ baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll
+ current/Avalonia/lib/net8.0/Avalonia.Controls.dll
+
CP0002
F:Avalonia.Controls.Documents.Inline.TextDecorationsProperty
@@ -3817,6 +3913,12 @@
baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
+ CP0009
+ T:Avalonia.Input.HoldingRoutedEventArgs
+ baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
+ current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
CP0009
T:Avalonia.Controls.Primitives.AdornerLayer
@@ -3853,6 +3955,12 @@
baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
+ CP0009
+ T:Avalonia.Input.HoldingRoutedEventArgs
+ baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
+ current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
CP0009
T:Avalonia.Controls.Primitives.AdornerLayer
diff --git a/samples/ControlCatalog/Pages/ContextFlyoutPage.xaml.cs b/samples/ControlCatalog/Pages/ContextFlyoutPage.xaml.cs
index d033956664..bef2c8212d 100644
--- a/samples/ControlCatalog/Pages/ContextFlyoutPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/ContextFlyoutPage.xaml.cs
@@ -1,6 +1,7 @@
using System;
using System.ComponentModel;
using Avalonia.Controls;
+using Avalonia.Input;
using Avalonia.Interactivity;
using ControlCatalog.ViewModels;
diff --git a/samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs b/samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs
index 8c36f81fcd..a71398181c 100644
--- a/samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/ContextMenuPage.xaml.cs
@@ -1,6 +1,7 @@
using System;
using System.ComponentModel;
using Avalonia.Controls;
+using Avalonia.Input;
using ControlCatalog.ViewModels;
namespace ControlCatalog.Pages
diff --git a/samples/ControlCatalog/Pages/GesturePage.cs b/samples/ControlCatalog/Pages/GesturePage.cs
index 7bc3b96c49..2906091daa 100644
--- a/samples/ControlCatalog/Pages/GesturePage.cs
+++ b/samples/ControlCatalog/Pages/GesturePage.cs
@@ -52,7 +52,7 @@ namespace ControlCatalog.Pages
}
};
- RotationGesture.AddHandler(Gestures.PinchEvent, (s, e) =>
+ RotationGesture.AddHandler(InputElement.PinchEvent, (s, e) =>
{
AngleSlider.Value = e.Angle;
});
@@ -94,7 +94,7 @@ namespace ControlCatalog.Pages
}
};
- control.AddHandler(Gestures.PinchEvent, (s, e) =>
+ control.AddHandler(InputElement.PinchEvent, (s, e) =>
{
InitComposition(control!);
@@ -114,7 +114,7 @@ namespace ControlCatalog.Pages
}
});
- control.AddHandler(Gestures.PinchEndedEvent, (s, e) =>
+ control.AddHandler(InputElement.PinchEndedEvent, (s, e) =>
{
InitComposition(control!);
@@ -124,7 +124,7 @@ namespace ControlCatalog.Pages
}
});
- control.AddHandler(Gestures.ScrollGestureEvent, (s, e) =>
+ control.AddHandler(InputElement.ScrollGestureEvent, (s, e) =>
{
InitComposition(control!);
@@ -171,7 +171,7 @@ namespace ControlCatalog.Pages
}
};
- control.AddHandler(Gestures.PullGestureEvent, (s, e) =>
+ control.AddHandler(InputElement.PullGestureEvent, (s, e) =>
{
Vector3D center = new((float)control.Bounds.Center.X, (float)control.Bounds.Center.Y, 0);
InitComposition(ball!);
@@ -183,7 +183,7 @@ namespace ControlCatalog.Pages
}
});
- control.AddHandler(Gestures.PullGestureEndedEvent, (s, e) =>
+ control.AddHandler(InputElement.PullGestureEndedEvent, (s, e) =>
{
InitComposition(ball!);
if (ballCompositionVisual != null)
diff --git a/samples/IntegrationTestApp/Pages/GesturesPage.axaml b/samples/IntegrationTestApp/Pages/GesturesPage.axaml
index eb028e226f..e171cc62f9 100644
--- a/samples/IntegrationTestApp/Pages/GesturesPage.axaml
+++ b/samples/IntegrationTestApp/Pages/GesturesPage.axaml
@@ -19,7 +19,7 @@
AutomationProperties.ControlTypeOverride="Image"
Tapped="GestureBorder_Tapped"
DoubleTapped="GestureBorder_DoubleTapped"
- Gestures.RightTapped="GestureBorder_RightTapped"/>
+ RightTapped="GestureBorder_RightTapped"/>
/// Provides event data for the ContextRequested event.
@@ -14,7 +13,7 @@ namespace Avalonia.Controls
/// Initializes a new instance of the ContextRequestedEventArgs class.
///
public ContextRequestedEventArgs()
- : base(Control.ContextRequestedEvent)
+ : base(InputElement.ContextRequestedEvent)
{
}
@@ -34,10 +33,10 @@ namespace Avalonia.Controls
}
///
- /// Gets the x- and y-coordinates of the pointer position, optionally evaluated against a coordinate origin of a supplied .
+ /// Gets the x- and y-coordinates of the pointer position, optionally evaluated against a coordinate origin of a supplied .
///
///
- /// Any -derived object that is connected to the same object tree.
+ /// Any -derived object that is connected to the same object tree.
/// To specify the object relative to the overall coordinate system, use a relativeTo value of null.
///
///
@@ -48,7 +47,7 @@ namespace Avalonia.Controls
///
/// true if the context request was initiated by a pointer device; otherwise, false.
///
- public bool TryGetPosition(Control? relativeTo, out Point point)
+ public bool TryGetPosition(InputElement? relativeTo, out Point point)
{
if (_pointerEventArgs is null)
{
diff --git a/src/Avalonia.Base/Input/Gestures.cs b/src/Avalonia.Base/Input/Gestures.cs
index 4929cd0ea6..3ae504a77f 100644
--- a/src/Avalonia.Base/Input/Gestures.cs
+++ b/src/Avalonia.Base/Input/Gestures.cs
@@ -1,15 +1,23 @@
using System;
using System.Threading;
using Avalonia.Interactivity;
-using Avalonia.Platform;
-using Avalonia.Threading;
using Avalonia.Reactive;
+using Avalonia.Threading;
using Avalonia.VisualTree;
namespace Avalonia.Input
{
- public static class Gestures
+ internal static class Gestures
{
+ // These events are only used internally and not propagated through a route.
+ // They have routed event args as their target type because their args generated from
+ // PointerEventArgs. In order to prevent having identical classes with just their base class
+ // being different, these events use routed args.
+ public static event EventHandler? Holding;
+ public static event EventHandler? Tapped;
+ public static event EventHandler? RightTapped;
+ public static event EventHandler? DoubleTapped;
+
private record struct GestureState(GestureStateType Type, IPointer Pointer);
private enum GestureStateType
{
@@ -23,98 +31,6 @@ namespace Avalonia.Input
private static Point s_lastPressPoint;
private static CancellationTokenSource? s_holdCancellationToken;
- ///
- /// Defines the IsHoldingEnabled attached property.
- ///
- public static readonly AttachedProperty IsHoldingEnabledProperty =
- AvaloniaProperty.RegisterAttached("IsHoldingEnabled", typeof(Gestures), true);
-
- ///
- /// Defines the IsHoldWithMouseEnabled attached property.
- ///
- public static readonly AttachedProperty IsHoldWithMouseEnabledProperty =
- AvaloniaProperty.RegisterAttached("IsHoldWithMouseEnabled", typeof(Gestures), false);
-
- public static readonly RoutedEvent TappedEvent = RoutedEvent.Register(
- "Tapped",
- RoutingStrategies.Bubble,
- typeof(Gestures));
-
- public static readonly RoutedEvent DoubleTappedEvent = RoutedEvent.Register(
- "DoubleTapped",
- RoutingStrategies.Bubble,
- typeof(Gestures));
-
- public static readonly RoutedEvent RightTappedEvent = RoutedEvent.Register(
- "RightTapped",
- RoutingStrategies.Bubble,
- typeof(Gestures));
-
- public static readonly RoutedEvent ScrollGestureEvent =
- RoutedEvent.Register(
- "ScrollGesture", RoutingStrategies.Bubble, typeof(Gestures));
-
- public static readonly RoutedEvent ScrollGestureInertiaStartingEvent =
- RoutedEvent.Register(
- "ScrollGestureInertiaStarting", RoutingStrategies.Bubble, typeof(Gestures));
-
- public static readonly RoutedEvent ScrollGestureEndedEvent =
- RoutedEvent.Register(
- "ScrollGestureEnded", RoutingStrategies.Bubble, typeof(Gestures));
-
- public static readonly RoutedEvent PointerTouchPadGestureMagnifyEvent =
- RoutedEvent.Register(
- "PointerTouchPadGestureMagnify", RoutingStrategies.Bubble, typeof(Gestures));
-
- public static readonly RoutedEvent PointerTouchPadGestureRotateEvent =
- RoutedEvent.Register(
- "PointerTouchPadGestureRotate", RoutingStrategies.Bubble, typeof(Gestures));
-
- public static readonly RoutedEvent PointerTouchPadGestureSwipeEvent =
- RoutedEvent.Register(
- "PointerTouchPadGestureSwipe", RoutingStrategies.Bubble, typeof(Gestures));
-
- public static readonly RoutedEvent PinchEvent =
- RoutedEvent.Register(
- "Pinch", RoutingStrategies.Bubble, typeof(Gestures));
-
- public static readonly RoutedEvent PinchEndedEvent =
- RoutedEvent.Register(
- "PinchEnded", RoutingStrategies.Bubble, typeof(Gestures));
-
- public static readonly RoutedEvent PullGestureEvent =
- RoutedEvent.Register(
- "PullGesture", RoutingStrategies.Bubble, typeof(Gestures));
-
- ///
- /// Occurs when a user performs a press and hold gesture (with a single touch, mouse, or pen/stylus contact).
- ///
- public static readonly RoutedEvent HoldingEvent =
- RoutedEvent.Register(
- "Holding", RoutingStrategies.Bubble, typeof(Gestures));
-
- public static readonly RoutedEvent PullGestureEndedEvent =
- RoutedEvent.Register(
- "PullGestureEnded", RoutingStrategies.Bubble, typeof(Gestures));
-
- public static bool GetIsHoldingEnabled(StyledElement element)
- {
- return element.GetValue(IsHoldingEnabledProperty);
- }
- public static void SetIsHoldingEnabled(StyledElement element, bool value)
- {
- element.SetValue(IsHoldingEnabledProperty, value);
- }
-
- public static bool GetIsHoldWithMouseEnabled(StyledElement element)
- {
- return element.GetValue(IsHoldWithMouseEnabledProperty);
- }
- public static void SetIsHoldWithMouseEnabled(StyledElement element, bool value)
- {
- element.SetValue(IsHoldWithMouseEnabledProperty, value);
- }
-
static Gestures()
{
InputElement.PointerPressedEvent.RouteFinished.Subscribe(PointerPressed);
@@ -122,102 +38,6 @@ namespace Avalonia.Input
InputElement.PointerMovedEvent.RouteFinished.Subscribe(PointerMoved);
}
- public static void AddTappedHandler(Interactive element, EventHandler handler)
- {
- element.AddHandler(TappedEvent, handler);
- }
-
- public static void AddDoubleTappedHandler(Interactive element, EventHandler handler)
- {
- element.AddHandler(DoubleTappedEvent, handler);
- }
-
- public static void AddRightTappedHandler(Interactive element, EventHandler handler)
- {
- element.AddHandler(RightTappedEvent, handler);
- }
-
- public static void AddHoldingHandler(Interactive element, EventHandler handler) =>
- element.AddHandler(HoldingEvent, handler);
-
- public static void AddPinchHandler(Interactive element, EventHandler handler) =>
- element.AddHandler(PinchEvent, handler);
-
- public static void AddPinchEndedHandler(Interactive element, EventHandler handler) =>
- element.AddHandler(PinchEndedEvent, handler);
-
- public static void AddPullGestureHandler(Interactive element, EventHandler handler) =>
- element.AddHandler(PullGestureEvent, handler);
-
- public static void AddPullGestureEndedHandler(Interactive element, EventHandler handler) =>
- element.AddHandler(PullGestureEndedEvent, handler);
-
- public static void AddPointerTouchPadGestureMagnifyHandler(Interactive element, EventHandler handler) =>
- element.AddHandler(PointerTouchPadGestureMagnifyEvent, handler);
-
- public static void AddPointerTouchPadGestureRotateHandler(Interactive element, EventHandler handler) =>
- element.AddHandler(PointerTouchPadGestureRotateEvent, handler);
-
- public static void AddPointerTouchPadGestureSwipeHandler(Interactive element, EventHandler handler) =>
- element.AddHandler(PointerTouchPadGestureSwipeEvent, handler);
-
- public static void AddScrollGestureHandler(Interactive element, EventHandler handler) =>
- element.AddHandler(ScrollGestureEvent, handler);
-
- public static void AddScrollGestureEndedHandler(Interactive element, EventHandler handler) =>
- element.AddHandler(ScrollGestureEndedEvent, handler);
-
- public static void AddScrollGestureInertiaStartingHandler(Interactive element, EventHandler handler) =>
- element.AddHandler(ScrollGestureInertiaStartingEvent, handler);
-
- public static void RemoveTappedHandler(Interactive element, EventHandler handler)
- {
- element.RemoveHandler(TappedEvent, handler);
- }
-
- public static void RemoveDoubleTappedHandler(Interactive element, EventHandler handler)
- {
- element.RemoveHandler(DoubleTappedEvent, handler);
- }
-
- public static void RemoveRightTappedHandler(Interactive element, EventHandler handler)
- {
- element.RemoveHandler(RightTappedEvent, handler);
- }
-
- public static void RemoveHoldingHandler(Interactive element, EventHandler handler) =>
- element.RemoveHandler(HoldingEvent, handler);
-
- public static void RemovePinchHandler(Interactive element, EventHandler handler) =>
- element.RemoveHandler(PinchEvent, handler);
-
- public static void RemovePinchEndedHandler(Interactive element, EventHandler handler) =>
- element.RemoveHandler(PinchEndedEvent, handler);
-
- public static void RemovePullGestureHandler(Interactive element, EventHandler handler) =>
- element.RemoveHandler(PullGestureEvent, handler);
-
- public static void RemovePullGestureEndedHandler(Interactive element, EventHandler handler) =>
- element.RemoveHandler(PullGestureEndedEvent, handler);
-
- public static void RemovePointerTouchPadGestureMagnifyHandler(Interactive element, EventHandler handler) =>
- element.RemoveHandler(PointerTouchPadGestureMagnifyEvent, handler);
-
- public static void RemovePointerTouchPadGestureRotateHandler(Interactive element, EventHandler handler) =>
- element.RemoveHandler(PointerTouchPadGestureRotateEvent, handler);
-
- public static void RemovePointerTouchPadGestureSwipeHandler(Interactive element, EventHandler handler) =>
- element.RemoveHandler(PointerTouchPadGestureSwipeEvent, handler);
-
- public static void RemoveScrollGestureHandler(Interactive element, EventHandler handler) =>
- element.RemoveHandler(ScrollGestureEvent,handler);
-
- public static void RemoveScrollGestureEndedHandler(Interactive element,EventHandler handler) =>
- element.RemoveHandler(ScrollGestureEndedEvent,handler);
-
- public static void RemoveScrollGestureInertiaStartingHandler(Interactive element, EventHandler handler) =>
- element.RemoveHandler(ScrollGestureInertiaStartingEvent, handler);
-
private static object? GetCaptured(RoutedEventArgs? args)
{
if (args is not PointerEventArgs pointerEventArgs)
@@ -237,11 +57,11 @@ namespace Avalonia.Input
var e = (PointerPressedEventArgs)ev;
var visual = (Visual)source;
- if(s_gestureState != null)
+ if (s_gestureState != null)
{
- if(s_gestureState.Value.Type == GestureStateType.Holding && source is Interactive i)
+ if (s_gestureState.Value.Type == GestureStateType.Holding && source is Interactive i)
{
- i.RaiseEvent(new HoldingRoutedEventArgs(HoldingState.Cancelled, s_lastPressPoint, s_gestureState.Value.Pointer.Type, e));
+ Holding?.Invoke(i, new HoldingRoutedEventArgs(HoldingState.Canceled, s_lastPressPoint, s_gestureState.Value.Pointer.Type, e));
}
s_holdCancellationToken?.Cancel();
s_holdCancellationToken?.Dispose();
@@ -263,22 +83,23 @@ namespace Avalonia.Input
{
DispatcherTimer.RunOnce(() =>
{
- if (s_gestureState != null && !token.IsCancellationRequested && source is InputElement i && GetIsHoldingEnabled(i) && (e.Pointer.Type != PointerType.Mouse || GetIsHoldWithMouseEnabled(i)))
+ if (s_gestureState != null && !token.IsCancellationRequested && source is InputElement i && InputElement.GetIsHoldingEnabled(i) &&
+ (e.Pointer.Type != PointerType.Mouse || InputElement.GetIsHoldWithMouseEnabled(i)))
{
s_gestureState = new GestureState(GestureStateType.Holding, s_gestureState.Value.Pointer);
- i.RaiseEvent(new HoldingRoutedEventArgs(HoldingState.Started, s_lastPressPoint, s_gestureState.Value.Pointer.Type, e));
+ Holding?.Invoke(i, new HoldingRoutedEventArgs(HoldingState.Started, s_lastPressPoint, s_gestureState.Value.Pointer.Type, e));
}
}, settings.HoldWaitDuration);
}
}
else if (e.ClickCount % 2 == 0 && e.GetCurrentPoint(visual).Properties.IsLeftButtonPressed)
{
- if (s_lastPress.TryGetTarget(out var target) &&
- target == source &&
+ if (s_lastPress.TryGetTarget(out var target) &&
+ target == source &&
source is Interactive i)
{
s_gestureState = new GestureState(GestureStateType.DoubleTapped, e.Pointer);
- i.RaiseEvent(new TappedEventArgs(DoubleTappedEvent, e));
+ DoubleTapped?.Invoke(i, new TappedEventArgs(InputElement.DoubleTappedEvent, e));
}
}
}
@@ -307,17 +128,19 @@ namespace Avalonia.Input
{
if (s_gestureState?.Type == GestureStateType.Holding)
{
- i.RaiseEvent(new HoldingRoutedEventArgs(HoldingState.Completed, s_lastPressPoint, s_gestureState.Value.Pointer.Type, e));
+ Holding?.Invoke(i, new HoldingRoutedEventArgs(HoldingState.Completed, s_lastPressPoint, s_gestureState.Value.Pointer.Type, e));
+
+ RightTapped?.Invoke(i, new TappedEventArgs(InputElement.RightTappedEvent, e));
}
else if (e.InitialPressMouseButton == MouseButton.Right)
{
- i.RaiseEvent(new TappedEventArgs(RightTappedEvent, e));
+ RightTapped?.Invoke(i, new TappedEventArgs(InputElement.RightTappedEvent, e));
}
//GestureStateType.DoubleTapped needed here to prevent invoking Tapped event when DoubleTapped is called.
//This behaviour matches UWP behaviour.
else if (s_gestureState?.Type != GestureStateType.DoubleTapped)
{
- i.RaiseEvent(new TappedEventArgs(TappedEvent, e));
+ Tapped?.Invoke(i, new TappedEventArgs(InputElement.TappedEvent, e));
}
}
s_gestureState = null;
@@ -351,15 +174,15 @@ namespace Avalonia.Input
if (s_gestureState.Value.Type == GestureStateType.Holding)
{
- i.RaiseEvent(new HoldingRoutedEventArgs(HoldingState.Cancelled, s_lastPressPoint, s_gestureState.Value.Pointer.Type, e));
+ Holding?.Invoke(i, new HoldingRoutedEventArgs(HoldingState.Canceled, s_lastPressPoint, s_gestureState.Value.Pointer.Type, e));
}
+
+ s_holdCancellationToken?.Cancel();
+ s_holdCancellationToken?.Dispose();
+ s_holdCancellationToken = null;
+ s_gestureState = null;
}
}
-
- s_holdCancellationToken?.Cancel();
- s_holdCancellationToken?.Dispose();
- s_holdCancellationToken = null;
- s_gestureState = null;
}
}
}
diff --git a/src/Avalonia.Base/Input/HoldingRoutedEventArgs.cs b/src/Avalonia.Base/Input/HoldingRoutedEventArgs.cs
index efb0c01599..ffc5dfec70 100644
--- a/src/Avalonia.Base/Input/HoldingRoutedEventArgs.cs
+++ b/src/Avalonia.Base/Input/HoldingRoutedEventArgs.cs
@@ -6,7 +6,7 @@ namespace Avalonia.Input
public class HoldingRoutedEventArgs : RoutedEventArgs
{
///
- /// Gets the state of the event.
+ /// Gets the state of the event.
///
public HoldingState HoldingState { get; }
@@ -20,25 +20,18 @@ namespace Avalonia.Input
///
public PointerType PointerType { get; }
- internal PointerEventArgs? PointerEventArgs { get; }
+ internal PointerEventArgs PointerEventArgs { get; }
///
/// Initializes a new instance of the class.
///
- public HoldingRoutedEventArgs(HoldingState holdingState, Point position, PointerType pointerType) : base(Gestures.HoldingEvent)
+ internal HoldingRoutedEventArgs(HoldingState holdingState, Point position, PointerType pointerType, PointerEventArgs pointerEventArgs) : base(InputElement.HoldingEvent)
{
+ PointerEventArgs = pointerEventArgs;
HoldingState = holdingState;
Position = position;
PointerType = pointerType;
}
-
- ///
- /// Initializes a new instance of the class.
- ///
- internal HoldingRoutedEventArgs(HoldingState holdingState, Point position, PointerType pointerType, PointerEventArgs pointerEventArgs) : this(holdingState, position, pointerType)
- {
- PointerEventArgs = pointerEventArgs;
- }
}
public enum HoldingState
@@ -56,6 +49,6 @@ namespace Avalonia.Input
///
/// An additional contact is detected or a subsequent gesture (such as a slide) is detected.
///
- Cancelled,
+ Canceled,
}
}
diff --git a/src/Avalonia.Base/Input/InputElement.Gestures.cs b/src/Avalonia.Base/Input/InputElement.Gestures.cs
new file mode 100644
index 0000000000..25f6362d60
--- /dev/null
+++ b/src/Avalonia.Base/Input/InputElement.Gestures.cs
@@ -0,0 +1,241 @@
+using System;
+using Avalonia.Interactivity;
+
+namespace Avalonia.Input
+{
+ public partial class InputElement
+ {
+ private bool _isContextMenuOnHolding;
+
+ ///
+ /// Defines the IsHoldingEnabled attached property.
+ ///
+ public static readonly AttachedProperty IsHoldingEnabledProperty =
+ AvaloniaProperty.RegisterAttached("IsHoldingEnabled", typeof(InputElement), true);
+
+ ///
+ /// Defines the IsHoldWithMouseEnabled attached property.
+ ///
+ public static readonly AttachedProperty IsHoldWithMouseEnabledProperty =
+ AvaloniaProperty.RegisterAttached("IsHoldWithMouseEnabled", typeof(InputElement), false);
+
+ public static readonly RoutedEvent PinchEvent =
+ RoutedEvent.Register(
+ "Pinch", RoutingStrategies.Bubble, typeof(InputElement));
+
+ public static readonly RoutedEvent PinchEndedEvent =
+ RoutedEvent.Register(
+ "PinchEnded", RoutingStrategies.Bubble, typeof(InputElement));
+
+ public static readonly RoutedEvent PullGestureEvent =
+ RoutedEvent.Register(
+ "PullGesture", RoutingStrategies.Bubble, typeof(InputElement));
+
+ public static readonly RoutedEvent PullGestureEndedEvent =
+ RoutedEvent.Register(
+ "PullGestureEnded", RoutingStrategies.Bubble, typeof(InputElement));
+
+ public static readonly RoutedEvent ScrollGestureEvent =
+ RoutedEvent.Register(
+ "ScrollGesture", RoutingStrategies.Bubble, typeof(InputElement));
+
+ public static readonly RoutedEvent ScrollGestureInertiaStartingEvent =
+ RoutedEvent.Register(
+ "ScrollGestureInertiaStarting", RoutingStrategies.Bubble, typeof(InputElement));
+
+ public static readonly RoutedEvent ScrollGestureEndedEvent =
+ RoutedEvent.Register(
+ "ScrollGestureEnded", RoutingStrategies.Bubble, typeof(InputElement));
+
+ public static readonly RoutedEvent PointerTouchPadGestureMagnifyEvent =
+ RoutedEvent.Register(
+ "PointerTouchPadGestureMagnify", RoutingStrategies.Bubble, typeof(InputElement));
+
+ public static readonly RoutedEvent PointerTouchPadGestureRotateEvent =
+ RoutedEvent.Register(
+ "PointerTouchPadGestureRotate", RoutingStrategies.Bubble, typeof(InputElement));
+
+ public static readonly RoutedEvent PointerTouchPadGestureSwipeEvent =
+ RoutedEvent.Register(
+ "PointerTouchPadGestureSwipe", RoutingStrategies.Bubble, typeof(InputElement));
+
+ ///
+ /// Defines the event.
+ ///
+ public static readonly RoutedEvent TappedEvent =
+ RoutedEvent.Register(
+ nameof(Tapped),
+ RoutingStrategies.Bubble);
+
+ ///
+ /// Defines the event.
+ ///
+ public static readonly RoutedEvent RightTappedEvent =
+ RoutedEvent.Register(
+ nameof(RightTapped),
+ RoutingStrategies.Bubble);
+
+ ///
+ /// Defines the event.
+ ///
+ public static readonly RoutedEvent HoldingEvent =
+ RoutedEvent.Register(
+ nameof(Holding),
+ RoutingStrategies.Bubble);
+
+ ///
+ /// Defines the event.
+ ///
+ public static readonly RoutedEvent DoubleTappedEvent =
+ RoutedEvent.Register(
+ nameof(DoubleTapped),
+ RoutingStrategies.Bubble);
+
+ public static bool GetIsHoldingEnabled(StyledElement element)
+ {
+ return element.GetValue(IsHoldingEnabledProperty);
+ }
+ public static void SetIsHoldingEnabled(StyledElement element, bool value)
+ {
+ element.SetValue(IsHoldingEnabledProperty, value);
+ }
+
+ public static bool GetIsHoldWithMouseEnabled(StyledElement element)
+ {
+ return element.GetValue(IsHoldWithMouseEnabledProperty);
+ }
+ public static void SetIsHoldWithMouseEnabled(StyledElement element, bool value)
+ {
+ element.SetValue(IsHoldWithMouseEnabledProperty, value);
+ }
+
+ public static void AddPinchHandler(Interactive element, EventHandler handler) =>
+ element.AddHandler(PinchEvent, handler);
+
+ public static void AddPinchEndedHandler(Interactive element, EventHandler handler) =>
+ element.AddHandler(PinchEndedEvent, handler);
+
+ public static void AddPullGestureHandler(Interactive element, EventHandler handler) =>
+ element.AddHandler(PullGestureEvent, handler);
+
+ public static void AddPullGestureEndedHandler(Interactive element, EventHandler handler) =>
+ element.AddHandler(PullGestureEndedEvent, handler);
+
+ public static void RemovePinchHandler(Interactive element, EventHandler handler) =>
+ element.RemoveHandler(PinchEvent, handler);
+
+ public static void RemovePinchEndedHandler(Interactive element, EventHandler handler) =>
+ element.RemoveHandler(PinchEndedEvent, handler);
+
+ public static void RemovePullGestureHandler(Interactive element, EventHandler handler) =>
+ element.RemoveHandler(PullGestureEvent, handler);
+
+ public static void RemovePullGestureEndedHandler(Interactive element, EventHandler handler) =>
+ element.RemoveHandler(PullGestureEndedEvent, handler);
+
+ public static void AddPointerTouchPadGestureMagnifyHandler(Interactive element, EventHandler handler) =>
+ element.AddHandler(PointerTouchPadGestureMagnifyEvent, handler);
+
+ public static void AddPointerTouchPadGestureRotateHandler(Interactive element, EventHandler handler) =>
+ element.AddHandler(PointerTouchPadGestureRotateEvent, handler);
+
+ public static void AddPointerTouchPadGestureSwipeHandler(Interactive element, EventHandler handler) =>
+ element.AddHandler(PointerTouchPadGestureSwipeEvent, handler);
+
+ public static void AddScrollGestureHandler(Interactive element, EventHandler handler) =>
+ element.AddHandler(ScrollGestureEvent, handler);
+
+ public static void AddScrollGestureEndedHandler(Interactive element, EventHandler handler) =>
+ element.AddHandler(ScrollGestureEndedEvent, handler);
+
+ public static void AddScrollGestureInertiaStartingHandler(Interactive element, EventHandler handler) =>
+ element.AddHandler(ScrollGestureInertiaStartingEvent, handler);
+
+ public static void RemovePointerTouchPadGestureMagnifyHandler(Interactive element, EventHandler handler) =>
+ element.RemoveHandler(PointerTouchPadGestureMagnifyEvent, handler);
+
+ public static void RemovePointerTouchPadGestureRotateHandler(Interactive element, EventHandler handler) =>
+ element.RemoveHandler(PointerTouchPadGestureRotateEvent, handler);
+
+ public static void RemovePointerTouchPadGestureSwipeHandler(Interactive element, EventHandler handler) =>
+ element.RemoveHandler(PointerTouchPadGestureSwipeEvent, handler);
+
+ public static void RemoveScrollGestureHandler(Interactive element, EventHandler handler) =>
+ element.RemoveHandler(ScrollGestureEvent, handler);
+
+ public static void RemoveScrollGestureEndedHandler(Interactive element, EventHandler handler) =>
+ element.RemoveHandler(ScrollGestureEndedEvent, handler);
+
+ public static void RemoveScrollGestureInertiaStartingHandler(Interactive element, EventHandler handler) =>
+ element.RemoveHandler(ScrollGestureInertiaStartingEvent, handler);
+
+ ///
+ /// Occurs when a tap gesture occurs on the control.
+ ///
+ public event EventHandler? Tapped
+ {
+ add { AddHandler(TappedEvent, value); }
+ remove { RemoveHandler(TappedEvent, value); }
+ }
+
+ ///
+ /// Occurs when a right tap gesture occurs on the control.
+ ///
+ public event EventHandler? RightTapped
+ {
+ add { AddHandler(RightTappedEvent, value); }
+ remove { RemoveHandler(RightTappedEvent, value); }
+ }
+
+ ///
+ /// Occurs when a hold gesture occurs on the control.
+ ///
+ public event EventHandler? Holding
+ {
+ add { AddHandler(HoldingEvent, value); }
+ remove { RemoveHandler(HoldingEvent, value); }
+ }
+
+ ///
+ /// Occurs when a double-tap gesture occurs on the control.
+ ///
+ public event EventHandler? DoubleTapped
+ {
+ add { AddHandler(DoubleTappedEvent, value); }
+ remove { RemoveHandler(DoubleTappedEvent, value); }
+ }
+
+ private static void OnPreviewHolding(object? sender, HoldingRoutedEventArgs e)
+ {
+ if (sender is InputElement inputElement)
+ {
+ inputElement.RaiseEvent(e);
+
+ if (!e.Handled && e.HoldingState == HoldingState.Started)
+ {
+ var contextEvent = new ContextRequestedEventArgs(e.PointerEventArgs);
+ inputElement.RaiseEvent(contextEvent);
+ e.Handled = contextEvent.Handled;
+
+ if (contextEvent.Handled)
+ {
+ inputElement._isContextMenuOnHolding = true;
+ }
+ }
+ else if (e.HoldingState == HoldingState.Canceled && inputElement._isContextMenuOnHolding)
+ {
+ inputElement.RaiseEvent(new RoutedEventArgs(InputElement.ContextCanceledEvent)
+ {
+ Source = inputElement
+ });
+
+ inputElement._isContextMenuOnHolding = false;
+ }
+ else if (e.HoldingState == HoldingState.Completed)
+ {
+ inputElement._isContextMenuOnHolding = false;
+ }
+ }
+ }
+ }
+}
diff --git a/src/Avalonia.Base/Input/InputElement.cs b/src/Avalonia.Base/Input/InputElement.cs
index f929dcbe05..98b988f8cd 100644
--- a/src/Avalonia.Base/Input/InputElement.cs
+++ b/src/Avalonia.Base/Input/InputElement.cs
@@ -16,7 +16,7 @@ namespace Avalonia.Input
/// Implements input-related functionality for a control.
///
[PseudoClasses(":disabled", ":focus", ":focus-visible", ":focus-within", ":pointerover")]
- public class InputElement : Interactive, IInputElement
+ public partial class InputElement : Interactive, IInputElement
{
///
/// Defines the property.
@@ -203,24 +203,20 @@ namespace Avalonia.Input
RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
///
- /// Defines the event.
+ /// Provides event data for the event.
///
- public static readonly RoutedEvent TappedEvent = Gestures.TappedEvent;
-
- ///
- /// Defines the event.
- ///
- public static readonly RoutedEvent RightTappedEvent = Gestures.RightTappedEvent;
-
- ///
- /// Defines the event.
- ///
- public static readonly RoutedEvent HoldingEvent = Gestures.HoldingEvent;
+ public static readonly RoutedEvent ContextRequestedEvent =
+ RoutedEvent.Register(
+ nameof(ContextRequested),
+ RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
///
- /// Defines the event.
+ /// Provides event data for the event.
///
- public static readonly RoutedEvent DoubleTappedEvent = Gestures.DoubleTappedEvent;
+ public static readonly RoutedEvent ContextCanceledEvent =
+ RoutedEvent.Register(
+ nameof(ContextCanceled),
+ RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
private bool _isEffectivelyEnabled = true;
private bool _isFocused;
@@ -257,6 +253,12 @@ namespace Avalonia.Input
DoubleTappedEvent.AddClassHandler((x, e) => x.OnDoubleTapped(e));
HoldingEvent.AddClassHandler((x, e) => x.OnHolding(e));
+ Gestures.Tapped += (s, e) => (s as InputElement)?.RaiseEvent(e);
+ Gestures.RightTapped += (s, e) => (s as InputElement)?.RaiseEvent(e);
+ Gestures.DoubleTapped += (s, e) => (s as InputElement)?.RaiseEvent(e);
+
+ Gestures.Holding += OnPreviewHolding;
+
// Gesture only handlers
PointerMovedEvent.AddClassHandler((x, e) => x.OnGesturePointerMoved(e), handledEventsToo: true);
PointerPressedEvent.AddClassHandler((x, e) => x.OnGesturePointerPressed(e), handledEventsToo: true);
@@ -419,42 +421,6 @@ namespace Avalonia.Input
remove { RemoveHandler(PointerWheelChangedEvent, value); }
}
- ///
- /// Occurs when a tap gesture occurs on the control.
- ///
- public event EventHandler? Tapped
- {
- add { AddHandler(TappedEvent, value); }
- remove { RemoveHandler(TappedEvent, value); }
- }
-
- ///
- /// Occurs when a right tap gesture occurs on the control.
- ///
- public event EventHandler? RightTapped
- {
- add { AddHandler(RightTappedEvent, value); }
- remove { RemoveHandler(RightTappedEvent, value); }
- }
-
- ///
- /// Occurs when a hold gesture occurs on the control.
- ///
- public event EventHandler? Holding
- {
- add { AddHandler(HoldingEvent, value); }
- remove { RemoveHandler(HoldingEvent, value); }
- }
-
- ///
- /// Occurs when a double-tap gesture occurs on the control.
- ///
- public event EventHandler? DoubleTapped
- {
- add { AddHandler(DoubleTappedEvent, value); }
- remove { RemoveHandler(DoubleTappedEvent, value); }
- }
-
///
/// Gets or sets a value indicating whether the control can receive focus.
///
@@ -518,6 +484,24 @@ namespace Avalonia.Input
internal set { SetAndRaise(IsPointerOverProperty, ref _isPointerOver, value); }
}
+ ///
+ /// Occurs when the user has completed a context input gesture, such as a right-click.
+ ///
+ public event EventHandler? ContextRequested
+ {
+ add => AddHandler(ContextRequestedEvent, value);
+ remove => RemoveHandler(ContextRequestedEvent, value);
+ }
+
+ ///
+ /// Occurs when the context input gesture continues into another gesture, to notify the element that the context flyout should not be opened.
+ ///
+ public event EventHandler? ContextCanceled
+ {
+ add => AddHandler(ContextCanceledEvent, value);
+ remove => RemoveHandler(ContextCanceledEvent, value);
+ }
+
///
/// Gets or sets a value that indicates whether the control is included in tab navigation.
///
diff --git a/src/Avalonia.Base/Input/MouseDevice.cs b/src/Avalonia.Base/Input/MouseDevice.cs
index d9766c1707..2d112efda1 100644
--- a/src/Avalonia.Base/Input/MouseDevice.cs
+++ b/src/Avalonia.Base/Input/MouseDevice.cs
@@ -1,13 +1,10 @@
using System;
using System.Collections.Generic;
-using Avalonia.Reactive;
+using Avalonia.Input.GestureRecognizers;
using Avalonia.Input.Raw;
using Avalonia.Interactivity;
using Avalonia.Metadata;
-using Avalonia.Platform;
-using Avalonia.Utilities;
using Avalonia.VisualTree;
-using Avalonia.Input.GestureRecognizers;
#pragma warning disable CS0618
namespace Avalonia.Input
@@ -263,7 +260,7 @@ namespace Avalonia.Input
if (source != null)
{
- var e = new PointerDeltaEventArgs(Gestures.PointerTouchPadGestureMagnifyEvent, source,
+ var e = new PointerDeltaEventArgs(InputElement.PointerTouchPadGestureMagnifyEvent, source,
_pointer, root.RootElement, p, timestamp, props, inputModifiers, delta);
source?.RaiseEvent(e);
@@ -283,7 +280,7 @@ namespace Avalonia.Input
if (source != null)
{
- var e = new PointerDeltaEventArgs(Gestures.PointerTouchPadGestureRotateEvent, source,
+ var e = new PointerDeltaEventArgs(InputElement.PointerTouchPadGestureRotateEvent, source,
_pointer, root.RootElement, p, timestamp, props, inputModifiers, delta);
source?.RaiseEvent(e);
@@ -303,7 +300,7 @@ namespace Avalonia.Input
if (source != null)
{
- var e = new PointerDeltaEventArgs(Gestures.PointerTouchPadGestureSwipeEvent, source,
+ var e = new PointerDeltaEventArgs(InputElement.PointerTouchPadGestureSwipeEvent, source,
_pointer, root.RootElement, p, timestamp, props, inputModifiers, delta);
source?.RaiseEvent(e);
diff --git a/src/Avalonia.Base/Input/PinchEventArgs.cs b/src/Avalonia.Base/Input/PinchEventArgs.cs
index be373f443a..4c037f30d7 100644
--- a/src/Avalonia.Base/Input/PinchEventArgs.cs
+++ b/src/Avalonia.Base/Input/PinchEventArgs.cs
@@ -4,13 +4,13 @@ namespace Avalonia.Input
{
public class PinchEventArgs : RoutedEventArgs
{
- public PinchEventArgs(double scale, Point scaleOrigin) : base(Gestures.PinchEvent)
+ public PinchEventArgs(double scale, Point scaleOrigin) : base(InputElement.PinchEvent)
{
Scale = scale;
ScaleOrigin = scaleOrigin;
}
- public PinchEventArgs(double scale, Point scaleOrigin, double angle, double angleDelta) : base(Gestures.PinchEvent)
+ public PinchEventArgs(double scale, Point scaleOrigin, double angle, double angleDelta) : base(InputElement.PinchEvent)
{
Scale = scale;
ScaleOrigin = scaleOrigin;
@@ -41,7 +41,7 @@ namespace Avalonia.Input
public class PinchEndedEventArgs : RoutedEventArgs
{
- public PinchEndedEventArgs() : base(Gestures.PinchEndedEvent)
+ public PinchEndedEventArgs() : base(InputElement.PinchEndedEvent)
{
}
}
diff --git a/src/Avalonia.Base/Input/PullGestureEventArgs.cs b/src/Avalonia.Base/Input/PullGestureEventArgs.cs
index 34d95c87f4..14b78f8730 100644
--- a/src/Avalonia.Base/Input/PullGestureEventArgs.cs
+++ b/src/Avalonia.Base/Input/PullGestureEventArgs.cs
@@ -1,4 +1,3 @@
-using System;
using Avalonia.Interactivity;
namespace Avalonia.Input
@@ -12,8 +11,8 @@ namespace Avalonia.Input
private static int _nextId = 1;
internal static int GetNextFreeId() => _nextId++;
-
- public PullGestureEventArgs(int id, Vector delta, PullDirection pullDirection) : base(Gestures.PullGestureEvent)
+
+ public PullGestureEventArgs(int id, Vector delta, PullDirection pullDirection) : base(InputElement.PullGestureEvent)
{
Id = id;
Delta = delta;
@@ -26,7 +25,7 @@ namespace Avalonia.Input
public int Id { get; }
public PullDirection PullDirection { get; }
- public PullGestureEndedEventArgs(int id, PullDirection pullDirection) : base(Gestures.PullGestureEndedEvent)
+ public PullGestureEndedEventArgs(int id, PullDirection pullDirection) : base(InputElement.PullGestureEndedEvent)
{
Id = id;
PullDirection = pullDirection;
diff --git a/src/Avalonia.Base/Input/ScrollGestureEventArgs.cs b/src/Avalonia.Base/Input/ScrollGestureEventArgs.cs
index ac770fd0a2..150ac17226 100644
--- a/src/Avalonia.Base/Input/ScrollGestureEventArgs.cs
+++ b/src/Avalonia.Base/Input/ScrollGestureEventArgs.cs
@@ -14,7 +14,7 @@ namespace Avalonia.Input
public static int GetNextFreeId() => _nextId++;
- public ScrollGestureEventArgs(int id, Vector delta) : base(Gestures.ScrollGestureEvent)
+ public ScrollGestureEventArgs(int id, Vector delta) : base(InputElement.ScrollGestureEvent)
{
Id = id;
Delta = delta;
@@ -25,7 +25,7 @@ namespace Avalonia.Input
{
public int Id { get; }
- public ScrollGestureEndedEventArgs(int id) : base(Gestures.ScrollGestureEndedEvent)
+ public ScrollGestureEndedEventArgs(int id) : base(InputElement.ScrollGestureEndedEvent)
{
Id = id;
}
@@ -36,7 +36,7 @@ namespace Avalonia.Input
public int Id { get; }
public Vector Inertia { get; }
- internal ScrollGestureInertiaStartingEventArgs(int id, Vector inertia) : base(Gestures.ScrollGestureInertiaStartingEvent)
+ internal ScrollGestureInertiaStartingEventArgs(int id, Vector inertia) : base(InputElement.ScrollGestureInertiaStartingEvent)
{
Id = id;
Inertia = inertia;
diff --git a/src/Avalonia.Base/Input/TappedEventArgs.cs b/src/Avalonia.Base/Input/TappedEventArgs.cs
index eaffa1d8bc..a235d495d6 100644
--- a/src/Avalonia.Base/Input/TappedEventArgs.cs
+++ b/src/Avalonia.Base/Input/TappedEventArgs.cs
@@ -1,6 +1,4 @@
-using System;
using Avalonia.Interactivity;
-using Avalonia.VisualTree;
namespace Avalonia.Input
{
@@ -17,7 +15,7 @@ namespace Avalonia.Input
public IPointer Pointer => lastPointerEventArgs.Pointer;
public KeyModifiers KeyModifiers => lastPointerEventArgs.KeyModifiers;
public ulong Timestamp => lastPointerEventArgs.Timestamp;
-
+
public Point GetPosition(Visual? relativeTo) => lastPointerEventArgs.GetPosition(relativeTo);
}
}
diff --git a/src/Avalonia.Controls/ContextMenu.cs b/src/Avalonia.Controls/ContextMenu.cs
index 7790251f81..c3d66b711f 100644
--- a/src/Avalonia.Controls/ContextMenu.cs
+++ b/src/Avalonia.Controls/ContextMenu.cs
@@ -1,17 +1,17 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
-using Avalonia.Automation.Peers;
using System.Linq;
+using Avalonia.Automation;
+using Avalonia.Automation.Peers;
using Avalonia.Controls.Diagnostics;
using Avalonia.Controls.Platform;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Primitives.PopupPositioning;
using Avalonia.Input;
using Avalonia.Interactivity;
-using Avalonia.Styling;
-using Avalonia.Automation;
using Avalonia.Reactive;
+using Avalonia.Styling;
namespace Avalonia.Controls
{
@@ -65,7 +65,7 @@ namespace Avalonia.Controls
///
/// Defines the property.
///
- public static readonly StyledProperty WindowManagerAddShadowHintProperty =
+ public static readonly StyledProperty WindowManagerAddShadowHintProperty =
Popup.WindowManagerAddShadowHintProperty.AddOwner();
///
@@ -205,6 +205,7 @@ namespace Avalonia.Controls
if (e.OldValue is ContextMenu oldMenu)
{
control.ContextRequested -= ControlContextRequested;
+ control.ContextCanceled -= ControlContextCanceled;
control.AttachedToVisualTree -= ControlOnAttachedToVisualTree;
control.DetachedFromVisualTree -= ControlDetachedFromVisualTree;
oldMenu._attachedControls?.Remove(control);
@@ -214,13 +215,14 @@ namespace Avalonia.Controls
if (e.NewValue is ContextMenu)
{
control.ContextRequested += ControlContextRequested;
+ control.ContextCanceled += ControlContextCanceled;
control.AttachedToVisualTree += ControlOnAttachedToVisualTree;
control.DetachedFromVisualTree += ControlDetachedFromVisualTree;
}
-
+
if (control.IsAttachedToVisualTree)
{
- AttachControlToContextMenu(control);
+ AttachControlToContextMenu(control);
}
}
@@ -292,9 +294,9 @@ namespace Avalonia.Controls
IPopupHost? IPopupHostProvider.PopupHost => _popup?.Host;
- event Action? IPopupHostProvider.PopupHostChanged
- {
- add => _popupHostChangedHandler += value;
+ event Action? IPopupHostProvider.PopupHostChanged
+ {
+ add => _popupHostChangedHandler += value;
remove => _popupHostChangedHandler -= value;
}
@@ -384,7 +386,7 @@ namespace Avalonia.Controls
RoutedEvent = ClosedEvent,
Source = this,
});
-
+
_popupHostChangedHandler?.Invoke(null);
}
@@ -403,6 +405,17 @@ namespace Avalonia.Controls
}
}
+ private static void ControlContextCanceled(object? sender, RoutedEventArgs e)
+ {
+ if (!e.Handled
+ && sender is Control control
+ && control.ContextMenu is ContextMenu contextMenu
+ && contextMenu.IsOpen)
+ {
+ contextMenu.Close();
+ }
+ }
+
private static void ControlContextRequested(object? sender, ContextRequestedEventArgs e)
{
if (sender is Control control
@@ -412,14 +425,14 @@ namespace Avalonia.Controls
{
var requestedByPointer = e.TryGetPosition(null, out _);
contextMenu.Open(
- control,
- e.Source as Control ?? control,
+ control,
+ e.Source as Control ?? control,
requestedByPointer ? contextMenu.Placement : PlacementMode.Bottom);
e.Handled = true;
}
}
-
-
+
+
private static void ControlOnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{
AttachControlToContextMenu(sender);
diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs
index 6a6b9f6083..8efe5d6d66 100644
--- a/src/Avalonia.Controls/Control.cs
+++ b/src/Avalonia.Controls/Control.cs
@@ -23,7 +23,6 @@ namespace Avalonia.Controls
/// The control class extends and adds the following features:
///
/// - A property to allow user-defined data to be attached to the control.
- /// - and other context menu related members.
///
public class Control : InputElement, IDataTemplateHost, IVisualBrushInitialize, ISetterValue
{
@@ -58,14 +57,6 @@ namespace Avalonia.Controls
RoutedEvent.Register(
"RequestBringIntoView",
RoutingStrategies.Bubble);
-
- ///
- /// Provides event data for the event.
- ///
- public static readonly RoutedEvent ContextRequestedEvent =
- RoutedEvent.Register(
- nameof(ContextRequested),
- RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
///
/// Defines the event.
@@ -163,15 +154,6 @@ namespace Avalonia.Controls
set => SetValue(TagProperty, value);
}
- ///
- /// Occurs when the user has completed a context input gesture, such as a right-click.
- ///
- public event EventHandler? ContextRequested
- {
- add => AddHandler(ContextRequestedEvent, value);
- remove => RemoveHandler(ContextRequestedEvent, value);
- }
-
///
/// Occurs when the control has been fully constructed in the visual tree and both
/// layout and render are complete.
@@ -389,20 +371,6 @@ namespace Avalonia.Controls
ScheduleOnLoadedCore();
}
- protected override void OnHolding(HoldingRoutedEventArgs e)
- {
- base.OnHolding(e);
-
- if (e.Source == this && !e.Handled && e.HoldingState == HoldingState.Started)
- {
- // Trigger ContentRequest when hold has started
- var contextEvent = e.PointerEventArgs is { } ev ? new ContextRequestedEventArgs(ev) : new ContextRequestedEventArgs();
- RaiseEvent(contextEvent);
-
- e.Handled = contextEvent.Handled;
- }
- }
-
///
protected sealed override void OnDetachedFromVisualTreeCore(VisualTreeAttachmentEventArgs e)
{
diff --git a/src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs b/src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs
index 11fc695d15..a28cecd149 100644
--- a/src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs
+++ b/src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs
@@ -352,13 +352,13 @@ namespace Avalonia.Controls.Primitives
{
base.OnAttachedToVisualTree(e);
_parentScroller = this.GetVisualParent() as ScrollContentPresenter;
- _parentScroller?.AddHandler(Gestures.ScrollGestureEndedEvent, OnScrollGestureEnded);
+ _parentScroller?.AddHandler(InputElement.ScrollGestureEndedEvent, OnScrollGestureEnded);
}
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnDetachedFromVisualTree(e);
- _parentScroller?.RemoveHandler(Gestures.ScrollGestureEndedEvent, OnScrollGestureEnded);
+ _parentScroller?.RemoveHandler(InputElement.ScrollGestureEndedEvent, OnScrollGestureEnded);
_parentScroller = null;
}
diff --git a/src/Avalonia.Controls/Flyouts/PopupFlyoutBase.cs b/src/Avalonia.Controls/Flyouts/PopupFlyoutBase.cs
index dd0b5810bf..19d1f52850 100644
--- a/src/Avalonia.Controls/Flyouts/PopupFlyoutBase.cs
+++ b/src/Avalonia.Controls/Flyouts/PopupFlyoutBase.cs
@@ -4,12 +4,11 @@ using System.Linq;
using Avalonia.Controls.Diagnostics;
using Avalonia.Controls.Primitives.PopupPositioning;
using Avalonia.Input;
-using Avalonia.Input.Platform;
using Avalonia.Input.Raw;
+using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Logging;
using Avalonia.Reactive;
-using Avalonia.VisualTree;
namespace Avalonia.Controls.Primitives
{
@@ -22,11 +21,11 @@ namespace Avalonia.Controls.Primitives
///
public static readonly StyledProperty HorizontalOffsetProperty =
Popup.HorizontalOffsetProperty.AddOwner();
-
+
///
public static readonly StyledProperty VerticalOffsetProperty =
Popup.VerticalOffsetProperty.AddOwner();
-
+
///
public static readonly StyledProperty PlacementAnchorProperty =
Popup.PlacementAnchorProperty.AddOwner();
@@ -50,19 +49,19 @@ namespace Avalonia.Controls.Primitives
///
public static readonly StyledProperty OverlayDismissEventPassThroughProperty =
Popup.OverlayDismissEventPassThroughProperty.AddOwner();
-
+
///
/// Defines the property
///
public static readonly StyledProperty OverlayInputPassThroughElementProperty =
Popup.OverlayInputPassThroughElementProperty.AddOwner();
-
+
///
/// Defines the property
///
public static readonly StyledProperty PlacementConstraintAdjustmentProperty =
Popup.PlacementConstraintAdjustmentProperty.AddOwner();
-
+
private readonly Lazy _popupLazy;
private Rect? _enlargedPopupRect;
private PixelRect? _enlargePopupRectScreenPixelRect;
@@ -147,7 +146,7 @@ namespace Avalonia.Controls.Primitives
get => GetValue(OverlayDismissEventPassThroughProperty);
set => SetValue(OverlayDismissEventPassThroughProperty, value);
}
-
+
///
/// Gets or sets an element that should receive pointer input events even when underneath
/// the flyout's overlay.
@@ -164,7 +163,7 @@ namespace Avalonia.Controls.Primitives
get => GetValue(PlacementConstraintAdjustmentProperty);
set => SetValue(PlacementConstraintAdjustmentProperty, value);
}
-
+
IPopupHost? IPopupHostProvider.PopupHost => Popup?.Host;
event Action? IPopupHostProvider.PopupHostChanged
@@ -172,7 +171,7 @@ namespace Avalonia.Controls.Primitives
add => _popupHostChangedHandler += value;
remove => _popupHostChangedHandler -= value;
}
-
+
public event EventHandler? Closing;
public event EventHandler? Opening;
@@ -331,7 +330,7 @@ namespace Avalonia.Controls.Primitives
if (Popup?.Host is PopupRoot root)
{
// Get the popup root bounds and convert to screen coordinates
-
+
var tmp = root.Bounds.Inflate(100);
_enlargePopupRectScreenPixelRect = new PixelRect(root.PointToScreen(tmp.TopLeft), root.PointToScreen(tmp.BottomRight));
}
@@ -344,7 +343,7 @@ namespace Avalonia.Controls.Primitives
return;
}
- if (Popup?.Host is PopupRoot && pArgs.Root.RootElement is {} eventRoot)
+ if (Popup?.Host is PopupRoot && pArgs.Root.RootElement is { } eventRoot)
{
// As long as the pointer stays within the enlargedPopupRect
// the flyout stays open. If it leaves, close it
@@ -373,7 +372,7 @@ namespace Avalonia.Controls.Primitives
{
Opening?.Invoke(this, args);
}
-
+
protected virtual void OnClosing(CancelEventArgs args)
{
Closing?.Invoke(this, args);
@@ -475,14 +474,27 @@ namespace Avalonia.Controls.Primitives
if (args.OldValue is FlyoutBase)
{
c.ContextRequested -= OnControlContextRequested;
+ c.ContextCanceled -= OnControlContextCanceled;
}
if (args.NewValue is FlyoutBase)
{
c.ContextRequested += OnControlContextRequested;
+ c.ContextCanceled += OnControlContextCanceled;
}
}
}
+ private static void OnControlContextCanceled(object? sender, RoutedEventArgs e)
+ {
+ if (!e.Handled
+ && sender is Control control
+ && control.ContextFlyout is { } flyout
+ && flyout.IsOpen)
+ {
+ flyout.Hide();
+ }
+ }
+
private static void OnControlContextRequested(object? sender, ContextRequestedEventArgs e)
{
if (!e.Handled
@@ -525,7 +537,7 @@ namespace Avalonia.Controls.Primitives
internal static void SetPresenterClasses(Control? presenter, Classes classes)
{
- if(presenter is null)
+ if (presenter is null)
{
return;
}
diff --git a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
index 6527a14d5d..89993d8e66 100644
--- a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
@@ -1,13 +1,13 @@
using System;
using System.Collections.Generic;
-using Avalonia.Reactive;
+using System.Linq;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Input.GestureRecognizers;
+using Avalonia.Layout;
+using Avalonia.Reactive;
using Avalonia.Utilities;
using Avalonia.VisualTree;
-using System.Linq;
-using Avalonia.Layout;
namespace Avalonia.Controls.Presenters
{
@@ -118,9 +118,9 @@ namespace Avalonia.Controls.Presenters
public ScrollContentPresenter()
{
AddHandler(RequestBringIntoViewEvent, BringIntoViewRequested);
- AddHandler(Gestures.ScrollGestureEvent, OnScrollGesture);
- AddHandler(Gestures.ScrollGestureEndedEvent, OnScrollGestureEnded);
- AddHandler(Gestures.ScrollGestureInertiaStartingEvent, OnScrollGestureInertiaStartingEnded);
+ AddHandler(InputElement.ScrollGestureEvent, OnScrollGesture);
+ AddHandler(InputElement.ScrollGestureEndedEvent, OnScrollGestureEnded);
+ AddHandler(InputElement.ScrollGestureInertiaStartingEvent, OnScrollGestureInertiaStartingEnded);
this.GetObservable(ChildProperty).Subscribe(UpdateScrollableSubscription);
}
diff --git a/src/Avalonia.Controls/Primitives/ItemSelectionEventTriggers.cs b/src/Avalonia.Controls/Primitives/ItemSelectionEventTriggers.cs
index 196e2b98ed..bebd8080f3 100644
--- a/src/Avalonia.Controls/Primitives/ItemSelectionEventTriggers.cs
+++ b/src/Avalonia.Controls/Primitives/ItemSelectionEventTriggers.cs
@@ -31,7 +31,7 @@ public static class ItemSelectionEventTriggers
} => false,
// Select on mouse press, unless the mouse can generate gestures
- { Pointer.Type: PointerType.Mouse } => eventArgs.RoutedEvent == (Gestures.GetIsHoldWithMouseEnabled(selectable) ?
+ { Pointer.Type: PointerType.Mouse } => eventArgs.RoutedEvent == (InputElement.GetIsHoldWithMouseEnabled(selectable) ?
InputElement.PointerReleasedEvent : (RoutedEvent)InputElement.PointerPressedEvent),
// Pen "right clicks" are used for context menus, and gestures are only processed for primary input
diff --git a/src/Avalonia.Controls/PullToRefresh/ScrollViewerIRefreshInfoProviderAdapter.cs b/src/Avalonia.Controls/PullToRefresh/ScrollViewerIRefreshInfoProviderAdapter.cs
index 7ff02711d6..48063d90f8 100644
--- a/src/Avalonia.Controls/PullToRefresh/ScrollViewerIRefreshInfoProviderAdapter.cs
+++ b/src/Avalonia.Controls/PullToRefresh/ScrollViewerIRefreshInfoProviderAdapter.cs
@@ -89,8 +89,8 @@ namespace Avalonia.Controls.PullToRefresh
if (_refreshInfoProvider != null && _interactionSource != null)
{
- _interactionSource.RemoveHandler(Gestures.PullGestureEvent, _refreshInfoProvider.InteractingStateEntered);
- _interactionSource.RemoveHandler(Gestures.PullGestureEndedEvent, _refreshInfoProvider.InteractingStateExited);
+ _interactionSource.RemoveHandler(InputElement.PullGestureEvent, _refreshInfoProvider.InteractingStateEntered);
+ _interactionSource.RemoveHandler(InputElement.PullGestureEndedEvent, _refreshInfoProvider.InteractingStateExited);
}
_refreshInfoProvider = null;
@@ -129,8 +129,8 @@ namespace Avalonia.Controls.PullToRefresh
if (_interactionSource != null)
{
_interactionSource.GestureRecognizers.Add(_pullGestureRecognizer);
- _interactionSource.AddHandler(Gestures.PullGestureEvent, _refreshInfoProvider.InteractingStateEntered);
- _interactionSource.AddHandler(Gestures.PullGestureEndedEvent, _refreshInfoProvider.InteractingStateExited);
+ _interactionSource.AddHandler(InputElement.PullGestureEvent, _refreshInfoProvider.InteractingStateEntered);
+ _interactionSource.AddHandler(InputElement.PullGestureEndedEvent, _refreshInfoProvider.InteractingStateExited);
_isVisualizerInteractionSourceAttached = true;
}
@@ -169,11 +169,11 @@ namespace Avalonia.Controls.PullToRefresh
visualizerComposition.ImplicitAnimations = animation;
}
- if(_scrollViewer != null)
+ if (_scrollViewer != null)
{
var scollContentComposition = ElementComposition.GetElementVisual(_scrollViewer);
- if(scollContentComposition != null)
+ if (scollContentComposition != null)
{
var compositor = scollContentComposition.Compositor;
@@ -217,8 +217,8 @@ namespace Avalonia.Controls.PullToRefresh
if (_pullGestureRecognizer != null && _refreshInfoProvider != null)
{
element?.GestureRecognizers.Add(_pullGestureRecognizer);
- _interactionSource?.AddHandler(Gestures.PullGestureEvent, _refreshInfoProvider.InteractingStateEntered);
- _interactionSource?.AddHandler(Gestures.PullGestureEndedEvent, _refreshInfoProvider.InteractingStateExited);
+ _interactionSource?.AddHandler(InputElement.PullGestureEvent, _refreshInfoProvider.InteractingStateEntered);
+ _interactionSource?.AddHandler(InputElement.PullGestureEndedEvent, _refreshInfoProvider.InteractingStateExited);
_isVisualizerInteractionSourceAttached = true;
}
}
diff --git a/tests/Avalonia.Base.UnitTests/Input/GesturesTests.cs b/tests/Avalonia.Base.UnitTests/Input/GesturesTests.cs
index e0a35b9ab2..d46bf5084e 100644
--- a/tests/Avalonia.Base.UnitTests/Input/GesturesTests.cs
+++ b/tests/Avalonia.Base.UnitTests/Input/GesturesTests.cs
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using Avalonia.Base.UnitTests.Utilities;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Input.GestureRecognizers;
@@ -9,7 +7,6 @@ using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Threading;
using Avalonia.UnitTests;
-using Avalonia.Utilities;
using Moq;
using Xunit;
// ReSharper disable RedundantArgumentDefaultValue
@@ -19,7 +16,7 @@ namespace Avalonia.Base.UnitTests.Input
public class GesturesTests
{
private readonly MouseTestHelper _mouse = new MouseTestHelper();
-
+
[Fact]
public void Tapped_Should_Follow_Pointer_Pressed_Released()
{
@@ -64,7 +61,7 @@ namespace Avalonia.Base.UnitTests.Input
};
var raised = false;
- root.AddHandler(Gestures.TappedEvent, (_, _) => raised = true);
+ root.AddHandler(InputElement.TappedEvent, (_, _) => raised = true);
_mouse.Click(border, MouseButton.Middle);
@@ -81,7 +78,7 @@ namespace Avalonia.Base.UnitTests.Input
};
var raised = false;
- root.AddHandler(Gestures.TappedEvent, (_, _) => raised = true);
+ root.AddHandler(InputElement.TappedEvent, (_, _) => raised = true);
_mouse.Click(border, MouseButton.Right);
@@ -114,7 +111,7 @@ namespace Avalonia.Base.UnitTests.Input
};
_mouse.Click(border, MouseButton.Left);
- root.AddHandler(Gestures.TappedEvent, (_, _) => raised = true);
+ root.AddHandler(InputElement.TappedEvent, (_, _) => raised = true);
_mouse.Click(border, MouseButton.Left);
@@ -132,7 +129,7 @@ namespace Avalonia.Base.UnitTests.Input
};
var raised = false;
- root.AddHandler(Gestures.RightTappedEvent, (_, _) => raised = true);
+ root.AddHandler(InputElement.RightTappedEvent, (_, _) => raised = true);
_mouse.Click(border, MouseButton.Right);
@@ -185,7 +182,7 @@ namespace Avalonia.Base.UnitTests.Input
};
var raised = false;
- root.AddHandler(Gestures.DoubleTappedEvent, (_, _) => raised = true);
+ root.AddHandler(InputElement.DoubleTappedEvent, (_, _) => raised = true);
_mouse.Click(border, MouseButton.Middle);
_mouse.Down(border, MouseButton.Middle, clickCount: 2);
@@ -203,7 +200,7 @@ namespace Avalonia.Base.UnitTests.Input
};
var raised = false;
- root.AddHandler(Gestures.DoubleTappedEvent, (_, _) => raised = true);
+ root.AddHandler(InputElement.DoubleTappedEvent, (_, _) => raised = true);
_mouse.Click(border, MouseButton.Right);
_mouse.Down(border, MouseButton.Right, clickCount: 2);
@@ -220,22 +217,22 @@ namespace Avalonia.Base.UnitTests.Input
iSettingsMock.Setup(x => x.GetTapSize(It.IsAny())).Returns(new Size(16, 16));
AvaloniaLocator.CurrentMutable.BindToSelf(this)
.Bind().ToConstant(iSettingsMock.Object);
-
+
using var app = UnitTestApplication.Start();
Border border = new Border();
- Gestures.SetIsHoldWithMouseEnabled(border, true);
+ InputElement.SetIsHoldWithMouseEnabled(border, true);
var root = new TestRoot
{
Child = border
};
- HoldingState holding = HoldingState.Cancelled;
+ HoldingState holding = HoldingState.Canceled;
+
+ root.AddHandler(InputElement.HoldingEvent, (_, e) => holding = e.HoldingState);
- root.AddHandler(Gestures.HoldingEvent, (_, e) => holding = e.HoldingState);
-
_mouse.Down(border);
- Assert.False(holding != HoldingState.Cancelled);
-
+ Assert.False(holding != HoldingState.Canceled);
+
// Verify timer duration, but execute it immediately.
var timer = Assert.Single(Dispatcher.SnapshotTimersForUnitTests());
Assert.Equal(iSettingsMock.Object.HoldWaitDuration, timer.Interval);
@@ -247,7 +244,80 @@ namespace Avalonia.Base.UnitTests.Input
Assert.True(holding == HoldingState.Completed);
}
-
+
+ [Fact]
+ public void Started_Hold_Gesture_Should_Raise_Context_Requested_Event()
+ {
+ using var scope = AvaloniaLocator.EnterScope();
+ var iSettingsMock = new Mock();
+ iSettingsMock.Setup(x => x.HoldWaitDuration).Returns(TimeSpan.FromMilliseconds(300));
+ iSettingsMock.Setup(x => x.GetTapSize(It.IsAny())).Returns(new Size(16, 16));
+ AvaloniaLocator.CurrentMutable.BindToSelf(this)
+ .Bind().ToConstant(iSettingsMock.Object);
+
+ using var app = UnitTestApplication.Start();
+
+ var flyout = new Flyout();
+ Border border = new Border()
+ {
+ ContextFlyout = flyout
+ };
+ InputElement.SetIsHoldWithMouseEnabled(border, true);
+ var root = new TestRoot
+ {
+ Child = border
+ };
+
+ var contextRequested = false;
+
+ flyout.Opened += (s, e) => contextRequested = true;
+
+ _mouse.Down(border);
+ var timer = Assert.Single(Dispatcher.SnapshotTimersForUnitTests());
+ timer.ForceFire();
+ _mouse.Up(border);
+
+ Assert.True(contextRequested);
+ }
+
+ [Fact]
+ public void Cancelled_Hold_Gesture_Should_Cancel_Context_Flyout()
+ {
+ using var scope = AvaloniaLocator.EnterScope();
+ var iSettingsMock = new Mock();
+ iSettingsMock.Setup(x => x.HoldWaitDuration).Returns(TimeSpan.FromMilliseconds(300));
+ iSettingsMock.Setup(x => x.GetTapSize(It.IsAny())).Returns(new Size(16, 16));
+ AvaloniaLocator.CurrentMutable.BindToSelf(this)
+ .Bind().ToConstant(iSettingsMock.Object);
+
+ using var app = UnitTestApplication.Start();
+
+ var flyout = new Flyout();
+ Border border = new Border()
+ {
+ ContextFlyout = flyout
+ };
+ InputElement.SetIsHoldWithMouseEnabled(border, true);
+ var root = new TestRoot
+ {
+ Child = border
+ };
+
+ var contextRequested = false;
+ var contextCanceled = false;
+
+ flyout.Opened += (s, e) => contextRequested = true;
+ flyout.Closed += (s, e) => contextCanceled = true;
+
+ _mouse.Down(border);
+ var timer = Assert.Single(Dispatcher.SnapshotTimersForUnitTests());
+ timer.ForceFire();
+ _mouse.Move(border, new Point(100, 100));
+
+ Assert.True(contextRequested);
+ Assert.True(contextCanceled);
+ }
+
[Fact]
public void Hold_Should_Not_Raised_When_Pointer_Released_Before_Timer()
{
@@ -256,25 +326,25 @@ namespace Avalonia.Base.UnitTests.Input
iSettingsMock.Setup(x => x.HoldWaitDuration).Returns(TimeSpan.FromMilliseconds(300));
AvaloniaLocator.CurrentMutable.BindToSelf(this)
.Bind().ToConstant(iSettingsMock.Object);
-
+
using var app = UnitTestApplication.Start();
Border border = new Border();
- Gestures.SetIsHoldWithMouseEnabled(border, true);
+ InputElement.SetIsHoldWithMouseEnabled(border, true);
var root = new TestRoot
{
Child = border
};
var raised = false;
- root.AddHandler(Gestures.HoldingEvent, (_, e) => raised = e.HoldingState == HoldingState.Started);
-
+ root.AddHandler(InputElement.HoldingEvent, (_, e) => raised = e.HoldingState == HoldingState.Started);
+
_mouse.Down(border);
Assert.False(raised);
-
+
_mouse.Up(border);
Assert.False(raised);
-
+
// Verify timer duration, but execute it immediately.
var timer = Assert.Single(Dispatcher.SnapshotTimersForUnitTests());
Assert.Equal(iSettingsMock.Object.HoldWaitDuration, timer.Interval);
@@ -282,7 +352,7 @@ namespace Avalonia.Base.UnitTests.Input
Assert.False(raised);
}
-
+
[Fact]
public void Hold_Should_Not_Raised_When_Pointer_Is_Moved_Before_Timer()
{
@@ -291,25 +361,25 @@ namespace Avalonia.Base.UnitTests.Input
iSettingsMock.Setup(x => x.HoldWaitDuration).Returns(TimeSpan.FromMilliseconds(300));
AvaloniaLocator.CurrentMutable.BindToSelf(this)
.Bind().ToConstant(iSettingsMock.Object);
-
+
using var app = UnitTestApplication.Start();
Border border = new Border();
- Gestures.SetIsHoldWithMouseEnabled(border, true);
+ InputElement.SetIsHoldWithMouseEnabled(border, true);
var root = new TestRoot
{
Child = border
};
var raised = false;
- root.AddHandler(Gestures.HoldingEvent, (_, e) => raised = e.HoldingState == HoldingState.Completed);
-
+ root.AddHandler(InputElement.HoldingEvent, (_, e) => raised = e.HoldingState == HoldingState.Completed);
+
_mouse.Down(border);
Assert.False(raised);
_mouse.Move(border, position: new Point(20, 20));
Assert.False(raised);
-
+
// Verify timer duration, but execute it immediately.
var timer = Assert.Single(Dispatcher.SnapshotTimersForUnitTests());
Assert.Equal(iSettingsMock.Object.HoldWaitDuration, timer.Interval);
@@ -326,19 +396,19 @@ namespace Avalonia.Base.UnitTests.Input
iSettingsMock.Setup(x => x.HoldWaitDuration).Returns(TimeSpan.FromMilliseconds(300));
AvaloniaLocator.CurrentMutable.BindToSelf(this)
.Bind().ToConstant(iSettingsMock.Object);
-
+
using var app = UnitTestApplication.Start();
Border border = new Border();
- Gestures.SetIsHoldWithMouseEnabled(border, true);
+ InputElement.SetIsHoldWithMouseEnabled(border, true);
var root = new TestRoot
{
Child = border
};
var cancelled = false;
- root.AddHandler(Gestures.HoldingEvent, (_, e) => cancelled = e.HoldingState == HoldingState.Cancelled);
-
+ root.AddHandler(InputElement.HoldingEvent, (_, e) => cancelled = e.HoldingState == HoldingState.Canceled);
+
_mouse.Down(border);
Assert.False(cancelled);
@@ -366,15 +436,15 @@ namespace Avalonia.Base.UnitTests.Input
using var app = UnitTestApplication.Start();
Border border = new Border();
- Gestures.SetIsHoldWithMouseEnabled(border, true);
+ InputElement.SetIsHoldWithMouseEnabled(border, true);
var root = new TestRoot()
{
Child = border
};
var cancelled = false;
- root.AddHandler(Gestures.HoldingEvent, (_, e) => cancelled = e.HoldingState == HoldingState.Cancelled);
-
+ root.AddHandler(InputElement.HoldingEvent, (_, e) => cancelled = e.HoldingState == HoldingState.Canceled);
+
_mouse.Down(border);
var timer = Assert.Single(Dispatcher.SnapshotTimersForUnitTests());
@@ -400,16 +470,16 @@ namespace Avalonia.Base.UnitTests.Input
.Bind().ToConstant(iSettingsMock.Object);
using var app = UnitTestApplication.Start();
-
+
Border border = new Border();
- Gestures.SetIsHoldWithMouseEnabled(border, true);
+ InputElement.SetIsHoldWithMouseEnabled(border, true);
var testRoot = new TestRoot
{
Child = border
};
var raised = false;
- testRoot.AddHandler(Gestures.HoldingEvent, (_, e) => raised = e.HoldingState == HoldingState.Completed);
+ testRoot.AddHandler(InputElement.HoldingEvent, (_, e) => raised = e.HoldingState == HoldingState.Completed);
var secondMouse = new MouseTestHelper();
@@ -424,7 +494,7 @@ namespace Avalonia.Base.UnitTests.Input
Assert.False(raised);
}
-
+
private static void AddHandlers(
TestRoot root,
Border border,
@@ -454,10 +524,10 @@ namespace Avalonia.Base.UnitTests.Input
border.AddHandler(InputElement.PointerPressedEvent, (_, _) => result.Add("bp"));
border.AddHandler(InputElement.PointerReleasedEvent, (_, _) => result.Add("br"));
- root.AddHandler(Gestures.TappedEvent, (_, _) => result.Add("dt"));
- root.AddHandler(Gestures.DoubleTappedEvent, (_, _) => result.Add("ddt"));
- border.AddHandler(Gestures.TappedEvent, (_, _) => result.Add("bt"));
- border.AddHandler(Gestures.DoubleTappedEvent, (_, _) => result.Add("bdt"));
+ root.AddHandler(InputElement.TappedEvent, (_, _) => result.Add("dt"));
+ root.AddHandler(InputElement.DoubleTappedEvent, (_, _) => result.Add("ddt"));
+ border.AddHandler(InputElement.TappedEvent, (_, _) => result.Add("bt"));
+ border.AddHandler(InputElement.DoubleTappedEvent, (_, _) => result.Add("bdt"));
}
[Fact]
@@ -478,7 +548,7 @@ namespace Avalonia.Base.UnitTests.Input
};
var raised = false;
- root.AddHandler(Gestures.PinchEvent, (_, _) => raised = true);
+ root.AddHandler(InputElement.PinchEvent, (_, _) => raised = true);
var firstPoint = new Point(5, 5);
var secondPoint = new Point(10, 10);
@@ -506,7 +576,7 @@ namespace Avalonia.Base.UnitTests.Input
};
var raised = false;
- root.AddHandler(Gestures.PinchEvent, (_, _) => raised = true);
+ root.AddHandler(InputElement.PinchEvent, (_, _) => raised = true);
var firstPoint = new Point(5, 5);
var secondPoint = new Point(10, 10);
@@ -537,7 +607,7 @@ namespace Avalonia.Base.UnitTests.Input
};
var raised = false;
- root.AddHandler(Gestures.PinchEvent, (_, _) => raised = true);
+ root.AddHandler(InputElement.PinchEvent, (_, _) => raised = true);
var firstPoint = new Point(5, 5);
var secondPoint = new Point(10, 10);
@@ -576,7 +646,7 @@ namespace Avalonia.Base.UnitTests.Input
};
var raised = false;
- root.AddHandler(Gestures.ScrollGestureEvent, (_, _) => raised = true);
+ root.AddHandler(InputElement.ScrollGestureEvent, (_, _) => raised = true);
var firstTouch = new TouchTestHelper();
diff --git a/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs b/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs
index 51ed2296a3..914351f245 100644
--- a/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs
@@ -83,7 +83,7 @@ namespace Avalonia.Controls.UnitTests
ContextMenu = sut
};
var contextRequestedCount = 0;
- target.AddHandler(Control.ContextRequestedEvent, (s, a) => contextRequestedCount++, Interactivity.RoutingStrategies.Tunnel);
+ target.AddHandler(InputElement.ContextRequestedEvent, (s, a) => contextRequestedCount++, Interactivity.RoutingStrategies.Tunnel);
var window = PreparedWindow(target);
window.Show();
diff --git a/tests/Avalonia.Controls.UnitTests/FlyoutTests.cs b/tests/Avalonia.Controls.UnitTests/FlyoutTests.cs
index 43a6e4b42a..4d8a90f5e7 100644
--- a/tests/Avalonia.Controls.UnitTests/FlyoutTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/FlyoutTests.cs
@@ -459,7 +459,7 @@ namespace Avalonia.Controls.UnitTests
ContextFlyout = flyout
};
var contextRequestedCount = 0;
- target.AddHandler(Control.ContextRequestedEvent, (s, a) => contextRequestedCount++, Interactivity.RoutingStrategies.Tunnel);
+ target.AddHandler(InputElement.ContextRequestedEvent, (s, a) => contextRequestedCount++, Interactivity.RoutingStrategies.Tunnel);
var window = PreparedWindow(target);
window.Show();
diff --git a/tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs b/tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs
index 9faa3fdee0..f0f9b820f7 100644
--- a/tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs
+++ b/tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs
@@ -149,7 +149,7 @@ namespace Avalonia.Controls.UnitTests
Prepare(target);
var contextRaised = false;
- target.AddHandler(Control.ContextRequestedEvent, (sender, args) =>
+ target.AddHandler(InputElement.ContextRequestedEvent, (sender, args) =>
{
contextRaised = true;
args.Handled = true;
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/EventTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/EventTests.cs
index 91e9b1a7ba..a5453d4436 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/EventTests.cs
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/EventTests.cs
@@ -26,14 +26,14 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
[Fact]
public void Attached_Event_Is_Assigned()
{
- var xaml = @"";
+ var xaml = @"";
var target = new MyButton();
AvaloniaRuntimeXamlLoader.Load(xaml, rootInstance: target);
target.RaiseEvent(new RoutedEventArgs
{
- RoutedEvent = Gestures.TappedEvent,
+ RoutedEvent = InputElement.TappedEvent,
});
Assert.True(target.WasTapped);
@@ -51,7 +51,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
Assert.NotNull(target);
- target.RaiseEvent(new TappedEventArgs(Gestures.DoubleTappedEvent, null!));
+ target.RaiseEvent(new TappedEventArgs(InputElement.DoubleTappedEvent, null!));
Assert.True(host.WasTapped);
}