diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs index 51399d1202..e307a80441 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs @@ -19,6 +19,7 @@ using Avalonia.Rendering; using System.Threading.Tasks; using Avalonia.Threading; using Avalonia.Interactivity; +using Avalonia.Media; namespace Avalonia.Controls.UnitTests.Primitives { @@ -1076,10 +1077,77 @@ namespace Avalonia.Controls.UnitTests.Primitives } } + [Fact] + public void GetPosition_On_Control_In_Popup_Called_From_Parent_Should_Return_Valid_Coordinates() + { + using (CreateServices()) + { + var popupContent = new Border() { Height = 100, Width = 100, Background = Brushes.Red }; + var popup = new Popup { Child = popupContent, HorizontalOffset = 40, VerticalOffset = 40, Placement = PlacementMode.AnchorAndGravity, + PlacementAnchor = PopupAnchor.TopLeft, PlacementGravity = PopupGravity.BottomRight}; + var popupParent = new Border { Child = popup }; + var root = PreparedWindow(popupParent); + + var raised = 0; + + root.LayoutManager.ExecuteInitialLayoutPass(); + popup.Open(); + root.LayoutManager.ExecuteLayoutPass(); + + var pointer = new Pointer(Pointer.GetNextFreeId(), PointerType.Mouse, true); + + var pts = popupContent.PointToScreen(new Point(10, 10)); + + Assert.Equal(new PixelPoint(50, 50), pts); + + var ev = new PointerPressedEventArgs( + popupContent, + pointer, + popupContent.VisualRoot as PopupRoot, + new Point(50 , 50), + 0, + new PointerPointProperties(RawInputModifiers.None, PointerUpdateKind.LeftButtonPressed), + KeyModifiers.None); + + Point pointRelativeToWindowContent = default; + + popupParent.AddHandler(Button.PointerPressedEvent, (s, e) => + { + ++raised; + + pointRelativeToWindowContent = e.GetPosition(popupParent); + }); + + popupContent.RaiseEvent(ev); + + Assert.Equal(1, raised); + Assert.Equal(new Point(90, 90), pointRelativeToWindowContent); + } + } + + private static PopupRoot CreateRoot(TopLevel popupParent, IPopupImpl impl = null) + { + impl ??= popupParent.PlatformImpl.CreatePopup(); + + var result = new PopupRoot(popupParent, impl) + { + Template = new FuncControlTemplate((parent, scope) => + new ContentPresenter + { + Name = "PART_ContentPresenter", + [!ContentPresenter.ContentProperty] = parent[!PopupRoot.ContentProperty], + }.RegisterInNameScope(scope)), + }; + + result.ApplyTemplate(); + + return result; + } + private IDisposable CreateServices() { return UnitTestApplication.Start(TestServices.StyledWindow.With(windowingPlatform: - new MockWindowingPlatform(null, + new MockWindowingPlatform(() => MockWindowingPlatform.CreateWindowMock().Object, x => { if(UsePopupHost) diff --git a/tests/Avalonia.UnitTests/MockWindowingPlatform.cs b/tests/Avalonia.UnitTests/MockWindowingPlatform.cs index ca71a97a6e..65612e45a0 100644 --- a/tests/Avalonia.UnitTests/MockWindowingPlatform.cs +++ b/tests/Avalonia.UnitTests/MockWindowingPlatform.cs @@ -55,6 +55,12 @@ namespace Avalonia.UnitTests windowImpl.Object.PositionChanged?.Invoke(x); }); + windowImpl.Setup(x => x.PointToScreen(It.IsAny())) + .Returns((point) => PixelPoint.FromPoint(point, 1) + position); + + windowImpl.Setup(x => x.PointToClient(It.IsAny())) + .Returns(point => (point - position).ToPoint(1)); + windowImpl.Setup(x => x.Resize(It.IsAny(), It.IsAny())) .Callback((x, y) => { @@ -83,10 +89,12 @@ namespace Avalonia.UnitTests { var popupImpl = new Mock(); var clientSize = new Size(); + var position = new PixelPoint(); var positionerHelper = new ManagedPopupPositionerPopupImplHelper(parent, (pos, size, scale) => { clientSize = size.Constrain(s_screenSize); + position = pos; popupImpl.Object.PositionChanged?.Invoke(pos); popupImpl.Object.Resized?.Invoke(clientSize, WindowResizeReason.Unspecified); }); @@ -100,6 +108,15 @@ namespace Avalonia.UnitTests popupImpl.Setup(x => x.MaxAutoSizeHint).Returns(s_screenSize); popupImpl.Setup(x => x.RenderScaling).Returns(1); popupImpl.Setup(x => x.PopupPositioner).Returns(positioner); + popupImpl.Setup(x => x.Position).Returns(()=>position); + + popupImpl.Setup(x => x.PointToScreen(It.IsAny())) + .Returns((point) => PixelPoint.FromPoint(point, 1) + position); + + popupImpl.Setup(x => x.PointToClient(It.IsAny())) + .Returns(point => (point - position).ToPoint(1)); + + popupImpl.Setup(r => r.TryGetFeature(It.IsAny())).Returns(null); popupImpl.Setup(x => x.Dispose()).Callback(() =>