From 49ee55fca4a0ae93862cf67f296454579739fd0a Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 9 Jun 2022 17:04:36 +0200 Subject: [PATCH 1/2] Make GridSplitter scaling aware. When comparing sizes in `GridSplitter.MoveSplitter`, account for `UseLayoutRounding` and DPI scaling by using an epsilon that is the size of a device pixel. --- src/Avalonia.Controls/GridSplitter.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/GridSplitter.cs b/src/Avalonia.Controls/GridSplitter.cs index 216e43e1f0..00ab856c31 100644 --- a/src/Avalonia.Controls/GridSplitter.cs +++ b/src/Avalonia.Controls/GridSplitter.cs @@ -60,6 +60,7 @@ namespace Avalonia.Controls private static readonly Cursor s_rowSplitterCursor = new Cursor(StandardCursorType.SizeNorthSouth); private ResizeData? _resizeData; + private double _scaling = 1; /// /// Indicates whether the Splitter resizes the Columns, Rows, or Both. @@ -348,6 +349,12 @@ namespace Avalonia.Controls } } + protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) + { + base.OnAttachedToVisualTree(e); + _scaling = e.Root.RenderScaling; + } + protected override void OnPointerEnter(PointerEventArgs e) { base.OnPointerEnter(e); @@ -630,13 +637,17 @@ namespace Avalonia.Controls { double actualLength1 = GetActualLength(definition1); double actualLength2 = GetActualLength(definition2); + double pixelLength = 1 / _scaling; + double epsilon = pixelLength + LayoutHelper.LayoutEpsilon; // When splitting, Check to see if the total pixels spanned by the definitions - // is the same as before starting resize. If not cancel the drag. + // is the same as before starting resize. If not cancel the drag. We need to account for + // layout rounding here, so ignore differences of less than a device pixel to avoid problems + // that WPF has, such as https://stackoverflow.com/questions/28464843. if (_resizeData.SplitBehavior == SplitBehavior.Split && !MathUtilities.AreClose( actualLength1 + actualLength2, - _resizeData.OriginalDefinition1ActualLength + _resizeData.OriginalDefinition2ActualLength, LayoutHelper.LayoutEpsilon)) + _resizeData.OriginalDefinition1ActualLength + _resizeData.OriginalDefinition2ActualLength, epsilon)) { CancelResize(); From 553c4bc114470d81b6ac91584f1787e56f2c7c53 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 9 Jun 2022 18:45:37 +0200 Subject: [PATCH 2/2] Read scaling when starting a drag operation. Previous implementation didn't update the scaling when moving between monitors. --- src/Avalonia.Controls/GridSplitter.cs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Avalonia.Controls/GridSplitter.cs b/src/Avalonia.Controls/GridSplitter.cs index 00ab856c31..784d33ed58 100644 --- a/src/Avalonia.Controls/GridSplitter.cs +++ b/src/Avalonia.Controls/GridSplitter.cs @@ -60,7 +60,6 @@ namespace Avalonia.Controls private static readonly Cursor s_rowSplitterCursor = new Cursor(StandardCursorType.SizeNorthSouth); private ResizeData? _resizeData; - private double _scaling = 1; /// /// Indicates whether the Splitter resizes the Columns, Rows, or Both. @@ -222,7 +221,8 @@ namespace Avalonia.Controls ShowsPreview = showsPreview, ResizeDirection = resizeDirection, SplitterLength = Math.Min(Bounds.Width, Bounds.Height), - ResizeBehavior = GetEffectiveResizeBehavior(resizeDirection) + ResizeBehavior = GetEffectiveResizeBehavior(resizeDirection), + Scaling = (VisualRoot as ILayoutRoot)?.LayoutScaling ?? 1, }; // Store the rows and columns to resize on drag events. @@ -349,12 +349,6 @@ namespace Avalonia.Controls } } - protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) - { - base.OnAttachedToVisualTree(e); - _scaling = e.Root.RenderScaling; - } - protected override void OnPointerEnter(PointerEventArgs e) { base.OnPointerEnter(e); @@ -637,7 +631,7 @@ namespace Avalonia.Controls { double actualLength1 = GetActualLength(definition1); double actualLength2 = GetActualLength(definition2); - double pixelLength = 1 / _scaling; + double pixelLength = 1 / _resizeData.Scaling; double epsilon = pixelLength + LayoutHelper.LayoutEpsilon; // When splitting, Check to see if the total pixels spanned by the definitions @@ -809,6 +803,9 @@ namespace Avalonia.Controls // The minimum of Width/Height of Splitter. Used to ensure splitter // isn't hidden by resizing a row/column smaller than the splitter. public double SplitterLength; + + // The current layout scaling factor. + public double Scaling; } }