Browse Source

Raise pointer enter/leave events in correct order.

Previously, enter events were raised before leave events.
pull/1811/head
Steven Kirk 8 years ago
parent
commit
895a24fb9e
  1. 20
      src/Avalonia.Input/MouseDevice.cs
  2. 67
      tests/Avalonia.Input.UnitTests/MouseDeviceTests.cs

20
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;
}
}
}

67
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<IRenderer>();
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<PointerEventArgs> 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(

Loading…
Cancel
Save