From 895a24fb9e55b613cb738816b11f6f2e71205d45 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 13 Aug 2018 09:27:54 +0200 Subject: [PATCH] Raise pointer enter/leave events in correct order. Previously, enter events were raised before leave events. --- src/Avalonia.Input/MouseDevice.cs | 20 +++--- .../MouseDeviceTests.cs | 67 +++++++++++++++++++ 2 files changed, 77 insertions(+), 10 deletions(-) diff --git a/src/Avalonia.Input/MouseDevice.cs b/src/Avalonia.Input/MouseDevice.cs index af1953fa9e..7689f55d80 100644 --- a/src/Avalonia.Input/MouseDevice.cs +++ b/src/Avalonia.Input/MouseDevice.cs @@ -346,12 +346,7 @@ namespace Avalonia.Input IInputElement branch = null; - var e = new PointerEventArgs - { - RoutedEvent = InputElement.PointerEnterEvent, - Device = device, - }; - + var e = new PointerEventArgs { Device = device, }; var el = element; while (el != null) @@ -361,15 +356,22 @@ namespace Avalonia.Input branch = el; break; } + el = (IInputElement)el.VisualParent; + } + el = root.PointerOverElement; + e.RoutedEvent = InputElement.PointerLeaveEvent; + + while (el != null && el != branch) + { e.Source = el; e.Handled = false; el.RaiseEvent(e); el = (IInputElement)el.VisualParent; } - el = root.PointerOverElement; - e.RoutedEvent = InputElement.PointerLeaveEvent; + el = root.PointerOverElement = element; + e.RoutedEvent = InputElement.PointerEnterEvent; while (el != null && el != branch) { @@ -378,8 +380,6 @@ namespace Avalonia.Input el.RaiseEvent(e); el = (IInputElement)el.VisualParent; } - - root.PointerOverElement = element; } } } diff --git a/tests/Avalonia.Input.UnitTests/MouseDeviceTests.cs b/tests/Avalonia.Input.UnitTests/MouseDeviceTests.cs index a732742b0b..5853d1e82b 100644 --- a/tests/Avalonia.Input.UnitTests/MouseDeviceTests.cs +++ b/tests/Avalonia.Input.UnitTests/MouseDeviceTests.cs @@ -1,10 +1,12 @@ using Avalonia.Controls; using Avalonia.Input.Raw; +using Avalonia.Interactivity; using Avalonia.Rendering; using Avalonia.UnitTests; using Avalonia.VisualTree; using Moq; using System; +using System.Collections.Generic; using Xunit; namespace Avalonia.Input.UnitTests @@ -128,6 +130,71 @@ namespace Avalonia.Input.UnitTests } } + [Fact] + public void PointerEnter_Leave_Should_Be_Raised_In_Correct_Order() + { + var renderer = new Mock(); + var result = new List<(object, string)>(); + + void HandleEvent(object sender, PointerEventArgs e) + { + result.Add((sender, e.RoutedEvent.Name)); + } + + using (TestApplication(renderer.Object)) + { + var inputManager = InputManager.Instance; + + Canvas canvas; + Border border; + Decorator decorator; + + var root = new TestRoot + { + MouseDevice = new MouseDevice(), + Renderer = renderer.Object, + Child = new Panel + { + Children = + { + (canvas = new Canvas()), + (border = new Border + { + Child = decorator = new Decorator(), + }) + } + } + }; + + SetHit(renderer, canvas); + SendMouseMove(inputManager, root); + + AddEnterLeaveHandlers(HandleEvent, root, canvas, border, decorator); + SetHit(renderer, decorator); + SendMouseMove(inputManager, root); + + Assert.Equal( + new[] + { + ((object)canvas, "PointerLeave"), + ((object)decorator, "PointerEnter"), + ((object)border, "PointerEnter"), + }, + result); + } + } + + private void AddEnterLeaveHandlers( + EventHandler handler, + params IControl[] controls) + { + foreach (var c in controls) + { + c.PointerEnter += handler; + c.PointerLeave += handler; + } + } + private void SendMouseMove(IInputManager inputManager, TestRoot root) { inputManager.ProcessInput(new RawMouseEventArgs(