diff --git a/src/Avalonia.Controls/Primitives/Popup.cs b/src/Avalonia.Controls/Primitives/Popup.cs index c24d1cef2d..81d01ff74f 100644 --- a/src/Avalonia.Controls/Primitives/Popup.cs +++ b/src/Avalonia.Controls/Primitives/Popup.cs @@ -10,6 +10,7 @@ using Avalonia.LogicalTree; using Avalonia.Metadata; using Avalonia.Rendering; using Avalonia.VisualTree; +using Avalonia.Layout; namespace Avalonia.Controls.Primitives { @@ -39,6 +40,18 @@ namespace Avalonia.Controls.Primitives public static readonly StyledProperty PlacementModeProperty = AvaloniaProperty.Register(nameof(PlacementMode), defaultValue: PlacementMode.Bottom); + /// + /// Defines the property. + /// + public static readonly StyledProperty HorizontalOffsetProperty = + AvaloniaProperty.Register(nameof(HorizontalOffset)); + + /// + /// Defines the property. + /// + public static readonly StyledProperty VerticalOffsetProperty = + AvaloniaProperty.Register(nameof(VerticalOffset)); + /// /// Defines the property. /// @@ -122,6 +135,24 @@ namespace Avalonia.Controls.Primitives set { SetValue(PlacementModeProperty, value); } } + /// + /// Gets or sets the Horizontal offset of the popup in relation to the + /// + public double HorizontalOffset + { + get { return GetValue(HorizontalOffsetProperty); } + set { SetValue(HorizontalOffsetProperty, value); } + } + + /// + /// Gets or sets the Vertical offset of the popup in relation to the + /// + public double VerticalOffset + { + get { return GetValue(VerticalOffsetProperty); } + set { SetValue(VerticalOffsetProperty, value); } + } + /// /// Gets or sets the control that is used to determine the popup's position. /// @@ -287,18 +318,26 @@ namespace Avalonia.Controls.Primitives if (target?.GetVisualRoot() == null) { mode = PlacementMode.Pointer; - } + } switch (mode) { case PlacementMode.Pointer: - return MouseDevice.Instance?.Position ?? default(Point); + if (MouseDevice.Instance != null) + { + // Scales the Horizontal and Vertical offset to screen co-ordinates. + var screenOffset = new Point(HorizontalOffset * (PopupRoot as ILayoutRoot).LayoutScaling, VerticalOffset * (PopupRoot as ILayoutRoot).LayoutScaling); + return MouseDevice.Instance.Position + screenOffset; + } + + return default(Point); case PlacementMode.Bottom: - return target?.PointToScreen(new Point(0, target.Bounds.Height)) ?? zero; + + return target?.PointToScreen(new Point(0 + HorizontalOffset, target.Bounds.Height + VerticalOffset)) ?? zero; case PlacementMode.Right: - return target?.PointToScreen(new Point(target.Bounds.Width, 0)) ?? zero; + return target?.PointToScreen(new Point(target.Bounds.Width + HorizontalOffset, 0 + VerticalOffset)) ?? zero; default: throw new InvalidOperationException("Invalid value for Popup.PlacementMode");