diff --git a/src/Avalonia.Base/Input/Gestures.cs b/src/Avalonia.Base/Input/Gestures.cs index 11ef425b8e..496052ad35 100644 --- a/src/Avalonia.Base/Input/Gestures.cs +++ b/src/Avalonia.Base/Input/Gestures.cs @@ -43,7 +43,7 @@ namespace Avalonia.Input RoutedEvent.Register( "PointerSwipeGesture", RoutingStrategies.Bubble, typeof(Gestures)); - private static readonly WeakReference s_lastPress = new WeakReference(null); + private static readonly WeakReference s_lastPress = new WeakReference(null); private static Point s_lastPressPoint; static Gestures() @@ -52,32 +52,32 @@ namespace Avalonia.Input InputElement.PointerReleasedEvent.RouteFinished.Subscribe(PointerReleased); } - public static void AddTappedHandler(IInteractive element, EventHandler handler) + public static void AddTappedHandler(Interactive element, EventHandler handler) { element.AddHandler(TappedEvent, handler); } - public static void AddDoubleTappedHandler(IInteractive element, EventHandler handler) + public static void AddDoubleTappedHandler(Interactive element, EventHandler handler) { element.AddHandler(DoubleTappedEvent, handler); } - public static void AddRightTappedHandler(IInteractive element, EventHandler handler) + public static void AddRightTappedHandler(Interactive element, EventHandler handler) { element.AddHandler(RightTappedEvent, handler); } - public static void RemoveTappedHandler(IInteractive element, EventHandler handler) + public static void RemoveTappedHandler(Interactive element, EventHandler handler) { element.RemoveHandler(TappedEvent, handler); } - public static void RemoveDoubleTappedHandler(IInteractive element, EventHandler handler) + public static void RemoveDoubleTappedHandler(Interactive element, EventHandler handler) { element.RemoveHandler(DoubleTappedEvent, handler); } - public static void RemoveRightTappedHandler(IInteractive element, EventHandler handler) + public static void RemoveRightTappedHandler(Interactive element, EventHandler handler) { element.RemoveHandler(RightTappedEvent, handler); } @@ -102,10 +102,12 @@ namespace Avalonia.Input } else if (e.ClickCount % 2 == 0 && e.GetCurrentPoint(visual).Properties.IsLeftButtonPressed) { - if (s_lastPress.TryGetTarget(out var target) && target == e.Source) + if (s_lastPress.TryGetTarget(out var target) && + target == e.Source && + e.Source is Interactive i) { s_isDoubleTapped = true; - e.Source.RaiseEvent(new TappedEventArgs(DoubleTappedEvent, e)); + i.RaiseEvent(new TappedEventArgs(DoubleTappedEvent, e)); } } } @@ -119,7 +121,8 @@ namespace Avalonia.Input if (s_lastPress.TryGetTarget(out var target) && target == e.Source && - e.InitialPressMouseButton is MouseButton.Left or MouseButton.Right) + e.InitialPressMouseButton is MouseButton.Left or MouseButton.Right && + e.Source is Interactive i) { var point = e.GetCurrentPoint((Visual)target); var settings = AvaloniaLocator.Current.GetService(); @@ -131,13 +134,13 @@ namespace Avalonia.Input { if (e.InitialPressMouseButton == MouseButton.Right) { - e.Source.RaiseEvent(new TappedEventArgs(RightTappedEvent, e)); + i.RaiseEvent(new TappedEventArgs(RightTappedEvent, e)); } //s_isDoubleTapped needed here to prevent invoking Tapped event when DoubleTapped is called. //This behaviour matches UWP behaviour. else if (s_isDoubleTapped == false) { - e.Source.RaiseEvent(new TappedEventArgs(TappedEvent, e)); + i.RaiseEvent(new TappedEventArgs(TappedEvent, e)); } } } diff --git a/src/Avalonia.Base/Input/IInputElement.cs b/src/Avalonia.Base/Input/IInputElement.cs index 58493bb3ba..6c20d20b4d 100644 --- a/src/Avalonia.Base/Input/IInputElement.cs +++ b/src/Avalonia.Base/Input/IInputElement.cs @@ -2,9 +2,6 @@ using System; using System.Collections.Generic; using Avalonia.Interactivity; using Avalonia.Metadata; -using Avalonia.VisualTree; - -#nullable enable namespace Avalonia.Input { @@ -12,7 +9,7 @@ namespace Avalonia.Input /// Defines input-related functionality for a control. /// [NotClientImplementable] - public interface IInputElement : IInteractive + public interface IInputElement { /// /// Occurs when the control receives focus. @@ -128,5 +125,32 @@ namespace Avalonia.Input /// Gets the key bindings for the element. /// List KeyBindings { get; } + + /// + /// Adds a handler for the specified routed event. + /// + /// The routed event. + /// The handler. + /// The routing strategies to listen to. + /// Whether handled events should also be listened for. + /// A disposable that terminates the event subscription. + void AddHandler( + RoutedEvent routedEvent, + Delegate handler, + RoutingStrategies routes = RoutingStrategies.Direct | RoutingStrategies.Bubble, + bool handledEventsToo = false); + + /// + /// Removes a handler for the specified routed event. + /// + /// The routed event. + /// The handler. + void RemoveHandler(RoutedEvent routedEvent, Delegate handler); + + /// + /// Raises a routed event. + /// + /// The event args. + void RaiseEvent(RoutedEventArgs e); } } diff --git a/src/Avalonia.Base/Input/KeyboardDevice.cs b/src/Avalonia.Base/Input/KeyboardDevice.cs index 73d3ac08dd..9d23cc49d9 100644 --- a/src/Avalonia.Base/Input/KeyboardDevice.cs +++ b/src/Avalonia.Base/Input/KeyboardDevice.cs @@ -133,7 +133,7 @@ namespace Avalonia.Input { if (element != FocusedElement) { - var interactive = FocusedElement as IInteractive; + var interactive = FocusedElement as Interactive; if (FocusedElement != null && (!((Visual)FocusedElement).IsAttachedToVisualTree || @@ -152,7 +152,7 @@ namespace Avalonia.Input RoutedEvent = InputElement.LostFocusEvent, }); - interactive = element as IInteractive; + interactive = element as Interactive; interactive?.RaiseEvent(new GotFocusEventArgs { diff --git a/src/Avalonia.Base/Input/PointerDeltaEventArgs.cs b/src/Avalonia.Base/Input/PointerDeltaEventArgs.cs index 6ba5ce06e6..af0fa83382 100644 --- a/src/Avalonia.Base/Input/PointerDeltaEventArgs.cs +++ b/src/Avalonia.Base/Input/PointerDeltaEventArgs.cs @@ -7,7 +7,7 @@ namespace Avalonia.Input { public Vector Delta { get; set; } - internal PointerDeltaEventArgs(RoutedEvent routedEvent, IInteractive? source, + internal PointerDeltaEventArgs(RoutedEvent routedEvent, object? source, IPointer pointer, Visual rootVisual, Point rootVisualPosition, ulong timestamp, PointerPointProperties properties, KeyModifiers modifiers, Vector delta) : base(routedEvent, source, pointer, rootVisual, rootVisualPosition, diff --git a/src/Avalonia.Base/Input/PointerEventArgs.cs b/src/Avalonia.Base/Input/PointerEventArgs.cs index b9da7fcd2c..d736253728 100644 --- a/src/Avalonia.Base/Input/PointerEventArgs.cs +++ b/src/Avalonia.Base/Input/PointerEventArgs.cs @@ -14,7 +14,7 @@ namespace Avalonia.Input private readonly Lazy?>? _previousPoints; internal PointerEventArgs(RoutedEvent routedEvent, - IInteractive? source, + object? source, IPointer pointer, Visual? rootVisual, Point rootVisualPosition, ulong timestamp, @@ -30,9 +30,9 @@ namespace Avalonia.Input Timestamp = timestamp; KeyModifiers = modifiers; } - + internal PointerEventArgs(RoutedEvent routedEvent, - IInteractive? source, + object? source, IPointer pointer, Visual? rootVisual, Point rootVisualPosition, ulong timestamp, @@ -125,7 +125,7 @@ namespace Avalonia.Input public class PointerPressedEventArgs : PointerEventArgs { internal PointerPressedEventArgs( - IInteractive source, + object source, IPointer pointer, Visual rootVisual, Point rootVisualPosition, ulong timestamp, @@ -144,7 +144,7 @@ namespace Avalonia.Input public class PointerReleasedEventArgs : PointerEventArgs { internal PointerReleasedEventArgs( - IInteractive source, IPointer pointer, + object source, IPointer pointer, Visual rootVisual, Point rootVisualPosition, ulong timestamp, PointerPointProperties properties, KeyModifiers modifiers, MouseButton initialPressMouseButton) @@ -164,7 +164,7 @@ namespace Avalonia.Input { public IPointer Pointer { get; } - internal PointerCaptureLostEventArgs(IInteractive source, IPointer pointer) : base(InputElement.PointerCaptureLostEvent) + internal PointerCaptureLostEventArgs(object source, IPointer pointer) : base(InputElement.PointerCaptureLostEvent) { Pointer = pointer; Source = source; diff --git a/src/Avalonia.Base/Input/PointerWheelEventArgs.cs b/src/Avalonia.Base/Input/PointerWheelEventArgs.cs index 151ca41d46..a3de0eaaea 100644 --- a/src/Avalonia.Base/Input/PointerWheelEventArgs.cs +++ b/src/Avalonia.Base/Input/PointerWheelEventArgs.cs @@ -7,7 +7,7 @@ namespace Avalonia.Input { public Vector Delta { get; set; } - internal PointerWheelEventArgs(IInteractive source, IPointer pointer, Visual rootVisual, + internal PointerWheelEventArgs(object source, IPointer pointer, Visual rootVisual, Point rootVisualPosition, ulong timestamp, PointerPointProperties properties, KeyModifiers modifiers, Vector delta) : base(InputElement.PointerWheelChangedEvent, source, pointer, rootVisual, rootVisualPosition, diff --git a/src/Avalonia.Base/Interactivity/EventRoute.cs b/src/Avalonia.Base/Interactivity/EventRoute.cs index 8f826835da..3491465a68 100644 --- a/src/Avalonia.Base/Interactivity/EventRoute.cs +++ b/src/Avalonia.Base/Interactivity/EventRoute.cs @@ -43,7 +43,7 @@ namespace Avalonia.Interactivity /// `DynamicInvoke` on the handler. /// public void Add( - IInteractive target, + Interactive target, Delegate handler, RoutingStrategies routes, bool handledEventsToo = false, @@ -60,7 +60,7 @@ namespace Avalonia.Interactivity /// Adds a class handler to the route. /// /// The target on which the event should be raised. - public void AddClassHandler(IInteractive target) + public void AddClassHandler(Interactive target) { target = target ?? throw new ArgumentNullException(nameof(target)); @@ -73,7 +73,7 @@ namespace Avalonia.Interactivity /// /// The event source. /// The event args. - public void RaiseEvent(IInteractive source, RoutedEventArgs e) + public void RaiseEvent(Interactive source, RoutedEventArgs e) { source = source ?? throw new ArgumentNullException(nameof(source)); e = e ?? throw new ArgumentNullException(nameof(e)); @@ -125,7 +125,7 @@ namespace Avalonia.Interactivity throw new ArgumentException("Event source may not be null", nameof(e)); } - IInteractive? lastTarget = null; + Interactive? lastTarget = null; var start = 0; var end = _route.Count; var step = 1; @@ -177,7 +177,7 @@ namespace Avalonia.Interactivity private readonly struct RouteItem { public RouteItem( - IInteractive target, + Interactive target, Delegate? handler, Action? adapter, RoutingStrategies routes, @@ -190,7 +190,7 @@ namespace Avalonia.Interactivity HandledEventsToo = handledEventsToo; } - public IInteractive Target { get; } + public Interactive Target { get; } public Delegate? Handler { get; } public Action? Adapter { get; } public RoutingStrategies Routes { get; } diff --git a/src/Avalonia.Base/Interactivity/IInteractive.cs b/src/Avalonia.Base/Interactivity/IInteractive.cs deleted file mode 100644 index 980bf54f1f..0000000000 --- a/src/Avalonia.Base/Interactivity/IInteractive.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using Avalonia.Metadata; - -#nullable enable - -namespace Avalonia.Interactivity -{ - /// - /// Interface for objects that raise routed events. - /// - [NotClientImplementable] - public interface IInteractive - { - /// - /// Gets the interactive parent of the object for bubbling and tunneling events. - /// - IInteractive? InteractiveParent { get; } - - /// - /// Adds a handler for the specified routed event. - /// - /// The routed event. - /// The handler. - /// The routing strategies to listen to. - /// Whether handled events should also be listened for. - /// A disposable that terminates the event subscription. - void AddHandler( - RoutedEvent routedEvent, - Delegate handler, - RoutingStrategies routes = RoutingStrategies.Direct | RoutingStrategies.Bubble, - bool handledEventsToo = false); - - /// - /// Removes a handler for the specified routed event. - /// - /// The routed event. - /// The handler. - void RemoveHandler(RoutedEvent routedEvent, Delegate handler); - - /// - /// Adds the object's handlers for a routed event to an event route. - /// - /// The event. - /// The event route. - void AddToEventRoute(RoutedEvent routedEvent, EventRoute route); - - /// - /// Raises a routed event. - /// - /// The event args. - void RaiseEvent(RoutedEventArgs e); - } -} diff --git a/src/Avalonia.Base/Interactivity/Interactive.cs b/src/Avalonia.Base/Interactivity/Interactive.cs index 916bf2c944..821e00d784 100644 --- a/src/Avalonia.Base/Interactivity/Interactive.cs +++ b/src/Avalonia.Base/Interactivity/Interactive.cs @@ -10,14 +10,14 @@ namespace Avalonia.Interactivity /// /// Base class for objects that raise routed events. /// - public class Interactive : Layoutable, IInteractive + public class Interactive : Layoutable { private Dictionary>? _eventHandlers; /// /// Gets the interactive parent of the object for bubbling and tunneling events. /// - IInteractive? IInteractive.InteractiveParent => this.VisualParent as IInteractive; + protected internal virtual Interactive? InteractiveParent => VisualParent as Interactive; /// /// Adds a handler for the specified routed event. @@ -125,21 +125,6 @@ namespace Avalonia.Interactivity route.RaiseEvent(this, e); } - void IInteractive.AddToEventRoute(RoutedEvent routedEvent, EventRoute route) - { - routedEvent = routedEvent ?? throw new ArgumentNullException(nameof(routedEvent)); - route = route ?? throw new ArgumentNullException(nameof(route)); - - if (_eventHandlers != null && - _eventHandlers.TryGetValue(routedEvent, out var subscriptions)) - { - foreach (var sub in subscriptions) - { - route.Add(this, sub.Handler, sub.Routes, sub.HandledEventsToo, sub.InvokeAdapter); - } - } - } - /// /// Builds an event route for a routed event. /// @@ -151,7 +136,7 @@ namespace Avalonia.Interactivity /// and should be avoided if there are no handlers for an event. In these cases you can call /// this method to build the event route and check the /// property to see if there are any handlers registered on the route. If there are, call - /// to raise the event. + /// to raise the event. /// protected EventRoute BuildEventRoute(RoutedEvent e) { @@ -163,7 +148,7 @@ namespace Avalonia.Interactivity if (e.RoutingStrategies.HasAllFlags(RoutingStrategies.Bubble) || e.RoutingStrategies.HasAllFlags(RoutingStrategies.Tunnel)) { - IInteractive? element = this; + Interactive? element = this; while (element != null) { @@ -183,7 +168,7 @@ namespace Avalonia.Interactivity result.AddClassHandler(this); } - ((IInteractive)this).AddToEventRoute(e, result); + AddToEventRoute(e, result); } return result; @@ -202,6 +187,21 @@ namespace Avalonia.Interactivity subscriptions.Add(subscription); } + private void AddToEventRoute(RoutedEvent routedEvent, EventRoute route) + { + routedEvent = routedEvent ?? throw new ArgumentNullException(nameof(routedEvent)); + route = route ?? throw new ArgumentNullException(nameof(route)); + + if (_eventHandlers != null && + _eventHandlers.TryGetValue(routedEvent, out var subscriptions)) + { + foreach (var sub in subscriptions) + { + route.Add(this, sub.Handler, sub.Routes, sub.HandledEventsToo, sub.InvokeAdapter); + } + } + } + private readonly struct EventSubscription { public EventSubscription( diff --git a/src/Avalonia.Base/Interactivity/InteractiveExtensions.cs b/src/Avalonia.Base/Interactivity/InteractiveExtensions.cs index ee6b623b5f..b12cf64fdf 100644 --- a/src/Avalonia.Base/Interactivity/InteractiveExtensions.cs +++ b/src/Avalonia.Base/Interactivity/InteractiveExtensions.cs @@ -5,7 +5,7 @@ using System.Reactive.Linq; namespace Avalonia.Interactivity { /// - /// Provides extension methods for the interface. + /// Provides extension methods for the interface. /// public static class InteractiveExtensions { @@ -19,7 +19,7 @@ namespace Avalonia.Interactivity /// The routing strategies to listen to. /// Whether handled events should also be listened for. /// A disposable that terminates the event subscription. - public static IDisposable AddDisposableHandler(this IInteractive o, RoutedEvent routedEvent, + public static IDisposable AddDisposableHandler(this Interactive o, RoutedEvent routedEvent, EventHandler handler, RoutingStrategies routes = RoutingStrategies.Direct | RoutingStrategies.Bubble, bool handledEventsToo = false) where TEventArgs : RoutedEventArgs @@ -31,6 +31,8 @@ namespace Avalonia.Interactivity state => state.instance.RemoveHandler(state.routedEvent, state.handler)); } + public static Interactive? GetInteractiveParent(this Interactive o) => o.InteractiveParent; + /// /// Gets an observable for a . /// @@ -42,7 +44,7 @@ namespace Avalonia.Interactivity /// An observable which fires each time the event is raised. /// public static IObservable GetObservable( - this IInteractive o, + this Interactive o, RoutedEvent routedEvent, RoutingStrategies routes = RoutingStrategies.Direct | RoutingStrategies.Bubble, bool handledEventsToo = false) diff --git a/src/Avalonia.Base/Interactivity/RoutedEvent.cs b/src/Avalonia.Base/Interactivity/RoutedEvent.cs index 37edb24cc1..7046871538 100644 --- a/src/Avalonia.Base/Interactivity/RoutedEvent.cs +++ b/src/Avalonia.Base/Interactivity/RoutedEvent.cs @@ -116,7 +116,7 @@ namespace Avalonia.Interactivity public IDisposable AddClassHandler( Action handler, RoutingStrategies routes = RoutingStrategies.Direct | RoutingStrategies.Bubble, - bool handledEventsToo = false) where TTarget : class, IInteractive + bool handledEventsToo = false) where TTarget : Interactive { void Adapter(object? sender, RoutedEventArgs e) { diff --git a/src/Avalonia.Base/Interactivity/RoutedEventArgs.cs b/src/Avalonia.Base/Interactivity/RoutedEventArgs.cs index 2b660e7080..17164bd333 100644 --- a/src/Avalonia.Base/Interactivity/RoutedEventArgs.cs +++ b/src/Avalonia.Base/Interactivity/RoutedEventArgs.cs @@ -28,7 +28,7 @@ namespace Avalonia.Interactivity /// /// The routed event associated with these event args. /// The source object that raised the routed event. - public RoutedEventArgs(RoutedEvent? routedEvent, IInteractive? source) + public RoutedEventArgs(RoutedEvent? routedEvent, object? source) { RoutedEvent = routedEvent; Source = source; @@ -55,6 +55,6 @@ namespace Avalonia.Interactivity /// /// Gets or sets the source object that raised the routed event. /// - public IInteractive? Source { get; set; } + public object? Source { get; set; } } } diff --git a/src/Avalonia.Controls/Primitives/OverlayPopupHost.cs b/src/Avalonia.Controls/Primitives/OverlayPopupHost.cs index 1f90e5babb..cd26ea4f6e 100644 --- a/src/Avalonia.Controls/Primitives/OverlayPopupHost.cs +++ b/src/Avalonia.Controls/Primitives/OverlayPopupHost.cs @@ -9,7 +9,7 @@ using Avalonia.VisualTree; namespace Avalonia.Controls.Primitives { - public class OverlayPopupHost : ContentControl, IPopupHost, IInteractive, IManagedPopupPositionerPopup + public class OverlayPopupHost : ContentControl, IPopupHost, IManagedPopupPositionerPopup { /// /// Defines the property. @@ -42,15 +42,14 @@ namespace Avalonia.Controls.Primitives set => SetValue(TransformProperty, value); } - /// - IInteractive? IInteractive.InteractiveParent => Parent; - bool IPopupHost.Topmost { get => false; set { /* Not currently supported in overlay popups */ } } + protected internal override Interactive? InteractiveParent => Parent; + public void Dispose() => Hide(); diff --git a/src/Avalonia.Controls/Primitives/PopupRoot.cs b/src/Avalonia.Controls/Primitives/PopupRoot.cs index 008ec89ec3..57ec864cad 100644 --- a/src/Avalonia.Controls/Primitives/PopupRoot.cs +++ b/src/Avalonia.Controls/Primitives/PopupRoot.cs @@ -12,7 +12,7 @@ namespace Avalonia.Controls.Primitives /// /// The root window of a . /// - public sealed class PopupRoot : WindowBase, IInteractive, IHostedVisualTreeRoot, IDisposable, IStyleHost, IPopupHost + public sealed class PopupRoot : WindowBase, IHostedVisualTreeRoot, IDisposable, IStyleHost, IPopupHost { /// /// Defines the property. @@ -72,7 +72,7 @@ namespace Avalonia.Controls.Primitives /// /// Popup events are passed to their parent window. This facilitates this. /// - IInteractive? IInteractive.InteractiveParent => Parent; + protected internal override Interactive? InteractiveParent => Parent; /// /// Gets the control that is hosting the popup root. diff --git a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs index 899981b2ec..f8951b3fa3 100644 --- a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs +++ b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs @@ -386,7 +386,7 @@ namespace Avalonia.Controls.Primitives /// /// The control that raised the event. /// The container or null if the event did not originate in a container. - protected Control? GetContainerFromEventSource(IInteractive? eventSource) + protected Control? GetContainerFromEventSource(object? eventSource) { for (var current = eventSource as Visual; current != null; current = current.VisualParent) { @@ -780,7 +780,7 @@ namespace Avalonia.Controls.Primitives /// false. /// protected bool UpdateSelectionFromEventSource( - IInteractive? eventSource, + object? eventSource, bool select = true, bool rangeModifier = false, bool toggleModifier = false, diff --git a/src/Avalonia.Controls/SizeChangedEventArgs.cs b/src/Avalonia.Controls/SizeChangedEventArgs.cs index 2dc642b163..85ea3b8472 100644 --- a/src/Avalonia.Controls/SizeChangedEventArgs.cs +++ b/src/Avalonia.Controls/SizeChangedEventArgs.cs @@ -23,7 +23,7 @@ namespace Avalonia.Controls /// /// The routed event associated with these event args. /// The source object that raised the routed event. - public SizeChangedEventArgs(RoutedEvent? routedEvent, IInteractive? source) + public SizeChangedEventArgs(RoutedEvent? routedEvent, object? source) : base(routedEvent, source) { } @@ -37,7 +37,7 @@ namespace Avalonia.Controls /// The new size (or bounds) of the object. public SizeChangedEventArgs( RoutedEvent? routedEvent, - IInteractive? source, + object? source, Size previousSize, Size newSize) : base(routedEvent, source) diff --git a/src/Avalonia.Controls/TextChangedEventArgs.cs b/src/Avalonia.Controls/TextChangedEventArgs.cs index 77c609f19b..1418154256 100644 --- a/src/Avalonia.Controls/TextChangedEventArgs.cs +++ b/src/Avalonia.Controls/TextChangedEventArgs.cs @@ -12,7 +12,7 @@ namespace Avalonia.Controls { } - public TextChangedEventArgs(RoutedEvent? routedEvent, IInteractive? source) + public TextChangedEventArgs(RoutedEvent? routedEvent, Interactive? source) : base(routedEvent, source) { } diff --git a/src/Avalonia.Controls/TextChangingEventArgs.cs b/src/Avalonia.Controls/TextChangingEventArgs.cs index 4dedbc927b..09e7d5b258 100644 --- a/src/Avalonia.Controls/TextChangingEventArgs.cs +++ b/src/Avalonia.Controls/TextChangingEventArgs.cs @@ -12,7 +12,7 @@ namespace Avalonia.Controls { } - public TextChangingEventArgs(RoutedEvent? routedEvent, IInteractive? source) + public TextChangingEventArgs(RoutedEvent? routedEvent, Interactive? source) : base(routedEvent, source) { } diff --git a/src/Avalonia.Controls/TreeView.cs b/src/Avalonia.Controls/TreeView.cs index 0c7729e436..2fa4a02fa2 100644 --- a/src/Avalonia.Controls/TreeView.cs +++ b/src/Avalonia.Controls/TreeView.cs @@ -752,7 +752,7 @@ namespace Avalonia.Controls /// false. /// protected bool UpdateSelectionFromEventSource( - IInteractive eventSource, + object eventSource, bool select = true, bool rangeModifier = false, bool toggleModifier = false, @@ -774,7 +774,7 @@ namespace Avalonia.Controls /// /// The control that raised the event. /// The container or null if the event did not originate in a container. - protected TreeViewItem? GetContainerFromEventSource(IInteractive eventSource) + protected TreeViewItem? GetContainerFromEventSource(object eventSource) { var item = ((Visual)eventSource).GetSelfAndVisualAncestors() .OfType() diff --git a/src/Avalonia.Native/AvaloniaNativeDragSource.cs b/src/Avalonia.Native/AvaloniaNativeDragSource.cs index 7ac00b3ebb..bec45c2d71 100644 --- a/src/Avalonia.Native/AvaloniaNativeDragSource.cs +++ b/src/Avalonia.Native/AvaloniaNativeDragSource.cs @@ -6,7 +6,6 @@ using Avalonia.Input; using Avalonia.Input.Platform; using Avalonia.Interactivity; using Avalonia.Native.Interop; -using Avalonia.Platform; using Avalonia.VisualTree; namespace Avalonia.Native @@ -19,14 +18,14 @@ namespace Avalonia.Native { _factory = factory; } - - TopLevel FindRoot(IInteractive interactive) + + private static TopLevel FindRoot(object? element) { - while (interactive != null && !(interactive is Visual)) - interactive = interactive.InteractiveParent; - if (interactive == null) + while (element is Interactive interactive && element is not Visual) + element = interactive.GetInteractiveParent(); + if (element == null) return null; - var visual = (Visual)interactive; + var visual = (Visual)element; return visual.GetVisualRoot() as TopLevel; } diff --git a/tests/Avalonia.Base.UnitTests/Interactivity/InteractiveTests.cs b/tests/Avalonia.Base.UnitTests/Interactivity/InteractiveTests.cs index a8b9a31aeb..3f80599b28 100644 --- a/tests/Avalonia.Base.UnitTests/Interactivity/InteractiveTests.cs +++ b/tests/Avalonia.Base.UnitTests/Interactivity/InteractiveTests.cs @@ -363,7 +363,7 @@ namespace Avalonia.Base.UnitTests.Interactivity var invoked = new List(); EventHandler handler = (s, e) => invoked.Add(((TestInteractive)s).Name); var parent = CreateTree(ev, handler, RoutingStrategies.Bubble | RoutingStrategies.Tunnel); - var target = (IInteractive)parent.GetVisualChildren().Single(); + var target = (Interactive)parent.GetVisualChildren().Single(); EventHandler removeHandler = (s, e) => { diff --git a/tests/Avalonia.Controls.UnitTests/ButtonTests.cs b/tests/Avalonia.Controls.UnitTests/ButtonTests.cs index 74fb389021..8bd51ec500 100644 --- a/tests/Avalonia.Controls.UnitTests/ButtonTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ButtonTests.cs @@ -379,7 +379,7 @@ namespace Avalonia.Controls.UnitTests } } - private KeyEventArgs CreateKeyDownEvent(Key key, IInteractive source = null) + private KeyEventArgs CreateKeyDownEvent(Key key, Interactive source = null) { return new KeyEventArgs { RoutedEvent = InputElement.KeyDownEvent, Key = key, Source = source }; } diff --git a/tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs b/tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs index d5b867cd6c..15ff6e68e3 100644 --- a/tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs @@ -11,15 +11,15 @@ namespace Avalonia.Controls.UnitTests.Platform { public class DefaultMenuInteractionHandlerTests { - static PointerEventArgs CreateArgs(RoutedEvent ev, IInteractive source) + static PointerEventArgs CreateArgs(RoutedEvent ev, object source) => new PointerEventArgs(ev, source, new FakePointer(), (Visual)source, default, 0, PointerPointProperties.None, default); - static PointerPressedEventArgs CreatePressed(IInteractive source) => new PointerPressedEventArgs(source, - new FakePointer(), (Visual)source, default, 0, new PointerPointProperties(RawInputModifiers.None, PointerUpdateKind.LeftButtonPressed), + static PointerPressedEventArgs CreatePressed(object source) => new PointerPressedEventArgs(source, + new FakePointer(), (Visual)source, default,0, new PointerPointProperties (RawInputModifiers.None, PointerUpdateKind.LeftButtonPressed), default); - - static PointerReleasedEventArgs CreateReleased(IInteractive source) => new PointerReleasedEventArgs(source, - new FakePointer(), (Visual)source, default, 0, + + static PointerReleasedEventArgs CreateReleased(object source) => new PointerReleasedEventArgs(source, + new FakePointer(), (Visual)source, default,0, new PointerPointProperties(RawInputModifiers.None, PointerUpdateKind.LeftButtonReleased), default, MouseButton.Left); diff --git a/tests/Avalonia.UnitTests/MouseTestHelper.cs b/tests/Avalonia.UnitTests/MouseTestHelper.cs index d1b83f3456..c9e4274d15 100644 --- a/tests/Avalonia.UnitTests/MouseTestHelper.cs +++ b/tests/Avalonia.UnitTests/MouseTestHelper.cs @@ -38,13 +38,13 @@ namespace Avalonia.UnitTests private MouseButton _pressedButton; - public void Down(IInteractive target, MouseButton mouseButton = MouseButton.Left, Point position = default, + public void Down(Interactive target, MouseButton mouseButton = MouseButton.Left, Point position = default, KeyModifiers modifiers = default, int clickCount = 1) { Down(target, target, mouseButton, position, modifiers, clickCount); } - public void Down(IInteractive target, IInteractive source, MouseButton mouseButton = MouseButton.Left, + public void Down(Interactive target, Interactive source, MouseButton mouseButton = MouseButton.Left, Point position = default, KeyModifiers modifiers = default, int clickCount = 1) { _pressedButtons |= Convert(mouseButton); @@ -64,18 +64,18 @@ namespace Avalonia.UnitTests } } - public void Move(IInteractive target, in Point position, KeyModifiers modifiers = default) => Move(target, target, position, modifiers); - public void Move(IInteractive target, IInteractive source, in Point position, KeyModifiers modifiers = default) + public void Move(Interactive target, in Point position, KeyModifiers modifiers = default) => Move(target, target, position, modifiers); + 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(), new PointerPointProperties((RawInputModifiers)_pressedButtons, PointerUpdateKind.Other), modifiers)); } - public void Up(IInteractive target, MouseButton mouseButton = MouseButton.Left, Point position = default, + public void Up(Interactive target, MouseButton mouseButton = MouseButton.Left, Point position = default, KeyModifiers modifiers = default) => Up(target, target, mouseButton, position, modifiers); - public void Up(IInteractive target, IInteractive source, MouseButton mouseButton = MouseButton.Left, + public void Up(Interactive target, Interactive source, MouseButton mouseButton = MouseButton.Left, Point position = default, KeyModifiers modifiers = default) { var conv = Convert(mouseButton); @@ -95,23 +95,23 @@ namespace Avalonia.UnitTests Move(target, source, position); } - public void Click(IInteractive target, MouseButton button = MouseButton.Left, Point position = default, + public void Click(Interactive target, MouseButton button = MouseButton.Left, Point position = default, KeyModifiers modifiers = default) => Click(target, target, button, position, modifiers); - public void Click(IInteractive target, IInteractive source, MouseButton button = MouseButton.Left, + public void Click(Interactive target, Interactive source, MouseButton button = MouseButton.Left, Point position = default, KeyModifiers modifiers = default) { Down(target, source, button, position, modifiers); Up(target, source, button, position, modifiers); } - public void Enter(IInteractive target) + public void Enter(Interactive target) { target.RaiseEvent(new PointerEventArgs(InputElement.PointerEnteredEvent, target, _pointer, (Visual)target, default, Timestamp(), new PointerPointProperties((RawInputModifiers)_pressedButtons, PointerUpdateKind.Other), KeyModifiers.None)); } - public void Leave(IInteractive target) + public void Leave(Interactive target) { target.RaiseEvent(new PointerEventArgs(InputElement.PointerExitedEvent, target, _pointer, (Visual)target, default, Timestamp(), new PointerPointProperties((RawInputModifiers)_pressedButtons, PointerUpdateKind.Other), KeyModifiers.None));