From f10f54682161bdcfc87ea26d823924691bf90885 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 17 Jun 2021 12:49:51 +0100 Subject: [PATCH 1/4] scale flyout transient area. --- src/Avalonia.Controls/Flyouts/FlyoutBase.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Flyouts/FlyoutBase.cs b/src/Avalonia.Controls/Flyouts/FlyoutBase.cs index 4725d17d65..ea47d15914 100644 --- a/src/Avalonia.Controls/Flyouts/FlyoutBase.cs +++ b/src/Avalonia.Controls/Flyouts/FlyoutBase.cs @@ -252,7 +252,9 @@ namespace Avalonia.Controls.Primitives if (Popup?.Host is PopupRoot root) { // Get the popup root bounds and convert to screen coordinates - var tmp = root.Bounds.Inflate(100); + var topLevel = root.Parent as TopLevel; + + var tmp = root.Bounds.Inflate(topLevel.PointToClient(new PixelPoint(100, 100)).X); var scPt = root.PointToScreen(tmp.TopLeft); enlargedPopupRect = new Rect(scPt.X, scPt.Y, tmp.Width, tmp.Height); } From b80ee8672954999a2c52212bff0deb5f458078eb Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 17 Jun 2021 12:53:06 +0100 Subject: [PATCH 2/4] no need for toplevel. --- src/Avalonia.Controls/Flyouts/FlyoutBase.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Avalonia.Controls/Flyouts/FlyoutBase.cs b/src/Avalonia.Controls/Flyouts/FlyoutBase.cs index ea47d15914..b3b5b5238e 100644 --- a/src/Avalonia.Controls/Flyouts/FlyoutBase.cs +++ b/src/Avalonia.Controls/Flyouts/FlyoutBase.cs @@ -252,9 +252,7 @@ namespace Avalonia.Controls.Primitives if (Popup?.Host is PopupRoot root) { // Get the popup root bounds and convert to screen coordinates - var topLevel = root.Parent as TopLevel; - - var tmp = root.Bounds.Inflate(topLevel.PointToClient(new PixelPoint(100, 100)).X); + var tmp = root.Bounds.Inflate(root.PointToClient(new PixelPoint(100, 100)).X); var scPt = root.PointToScreen(tmp.TopLeft); enlargedPopupRect = new Rect(scPt.X, scPt.Y, tmp.Width, tmp.Height); } From 45299c15059732404ef07a88e0d2987af0186433 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 17 Jun 2021 13:04:28 +0100 Subject: [PATCH 3/4] use renderscaling. --- src/Avalonia.Controls/Flyouts/FlyoutBase.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Flyouts/FlyoutBase.cs b/src/Avalonia.Controls/Flyouts/FlyoutBase.cs index b3b5b5238e..73f2329513 100644 --- a/src/Avalonia.Controls/Flyouts/FlyoutBase.cs +++ b/src/Avalonia.Controls/Flyouts/FlyoutBase.cs @@ -4,6 +4,7 @@ using Avalonia.Input; using Avalonia.Input.Raw; using Avalonia.Layout; using Avalonia.Logging; +using Avalonia.Rendering; #nullable enable @@ -252,7 +253,8 @@ namespace Avalonia.Controls.Primitives if (Popup?.Host is PopupRoot root) { // Get the popup root bounds and convert to screen coordinates - var tmp = root.Bounds.Inflate(root.PointToClient(new PixelPoint(100, 100)).X); + + var tmp = root.Bounds.Inflate(100 * (root as IRenderRoot).RenderScaling); var scPt = root.PointToScreen(tmp.TopLeft); enlargedPopupRect = new Rect(scPt.X, scPt.Y, tmp.Width, tmp.Height); } From b78d2a0e06808c32ef1573d7dda249fc4605f342 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 17 Jun 2021 14:44:43 +0100 Subject: [PATCH 4/4] use Pixel api types when working in screen coordinates. --- src/Avalonia.Controls/Flyouts/FlyoutBase.cs | 32 +++++++++------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/Avalonia.Controls/Flyouts/FlyoutBase.cs b/src/Avalonia.Controls/Flyouts/FlyoutBase.cs index 73f2329513..e4b68c62fd 100644 --- a/src/Avalonia.Controls/Flyouts/FlyoutBase.cs +++ b/src/Avalonia.Controls/Flyouts/FlyoutBase.cs @@ -52,8 +52,9 @@ namespace Avalonia.Controls.Primitives private bool _isOpen; private Control? _target; private FlyoutShowMode _showMode = FlyoutShowMode.Standard; - private Rect? enlargedPopupRect; - private IDisposable? transientDisposable; + private Rect? _enlargedPopupRect; + private PixelRect? _enlargePopupRectScreenPixelRect; + private IDisposable? _transientDisposable; protected Popup? Popup { get; private set; } @@ -164,8 +165,10 @@ namespace Avalonia.Controls.Primitives Popup.IsOpen = false; // Ensure this isn't active - transientDisposable?.Dispose(); - transientDisposable = null; + _transientDisposable?.Dispose(); + _transientDisposable = null; + _enlargedPopupRect = null; + _enlargePopupRectScreenPixelRect = null; OnClosed(); } @@ -231,7 +234,7 @@ namespace Avalonia.Controls.Primitives } else if (ShowMode == FlyoutShowMode.TransientWithDismissOnPointerMoveAway) { - transientDisposable = InputManager.Instance?.Process.Subscribe(HandleTransientDismiss); + _transientDisposable = InputManager.Instance?.Process.Subscribe(HandleTransientDismiss); } } @@ -247,21 +250,20 @@ namespace Avalonia.Controls.Primitives // For windowed popups, enlargedPopupRect is in screen coordinates, // for overlay popups, its in OverlayLayer coordinates - if (enlargedPopupRect == null) + if (_enlargedPopupRect == null && _enlargePopupRectScreenPixelRect == null) { // Only do this once when the Flyout opens & cache the result if (Popup?.Host is PopupRoot root) { // Get the popup root bounds and convert to screen coordinates - var tmp = root.Bounds.Inflate(100 * (root as IRenderRoot).RenderScaling); - var scPt = root.PointToScreen(tmp.TopLeft); - enlargedPopupRect = new Rect(scPt.X, scPt.Y, tmp.Width, tmp.Height); + var tmp = root.Bounds.Inflate(100); + _enlargePopupRectScreenPixelRect = new PixelRect(root.PointToScreen(tmp.TopLeft), root.PointToScreen(tmp.BottomRight)); } else if (Popup?.Host is OverlayPopupHost host) { // Overlay popups are in OverlayLayer coordinates, just use that - enlargedPopupRect = host.Bounds.Inflate(100); + _enlargedPopupRect = host.Bounds.Inflate(100); } return; @@ -275,24 +277,18 @@ namespace Avalonia.Controls.Primitives // window will not close this (as pointer events stop), which // does match UWP var pt = pArgs.Root.PointToScreen(pArgs.Position); - if (!enlargedPopupRect?.Contains(new Point(pt.X, pt.Y)) ?? false) + if (!_enlargePopupRectScreenPixelRect?.Contains(pt) ?? false) { HideCore(false); - enlargedPopupRect = null; - transientDisposable?.Dispose(); - transientDisposable = null; } } else if (Popup?.Host is OverlayPopupHost) { // Same as above here, but just different coordinate space // so we don't need to translate - if (!enlargedPopupRect?.Contains(pArgs.Position) ?? false) + if (!_enlargedPopupRect?.Contains(pArgs.Position) ?? false) { HideCore(false); - enlargedPopupRect = null; - transientDisposable?.Dispose(); - transientDisposable = null; } } }