From 30fd91121e638e0a835a305993793b4e709db51c Mon Sep 17 00:00:00 2001 From: robloo Date: Sat, 8 Oct 2022 14:43:02 -0400 Subject: [PATCH 01/16] Comment and update the Screen class --- samples/ControlCatalog/Pages/ScreenPage.cs | 2 +- src/Avalonia.Controls/Platform/Screen.cs | 25 ++++++++++++++++++++-- src/Avalonia.Controls/Screens.cs | 16 +++++++++++++- src/Avalonia.X11/X11Screens.cs | 8 +++---- src/Windows/Avalonia.Win32/WindowImpl.cs | 2 +- 5 files changed, 44 insertions(+), 9 deletions(-) diff --git a/samples/ControlCatalog/Pages/ScreenPage.cs b/samples/ControlCatalog/Pages/ScreenPage.cs index 823f59e030..6a4ed5a890 100644 --- a/samples/ControlCatalog/Pages/ScreenPage.cs +++ b/samples/ControlCatalog/Pages/ScreenPage.cs @@ -65,7 +65,7 @@ namespace ControlCatalog.Pages formattedText = CreateFormattedText($"Scaling: {screen.PixelDensity * 100}%"); context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 40)); - formattedText = CreateFormattedText($"Primary: {screen.Primary}"); + formattedText = CreateFormattedText($"Primary: {screen.IsPrimary}"); context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 60)); formattedText = diff --git a/src/Avalonia.Controls/Platform/Screen.cs b/src/Avalonia.Controls/Platform/Screen.cs index 976faed3fd..0f287fd5da 100644 --- a/src/Avalonia.Controls/Platform/Screen.cs +++ b/src/Avalonia.Controls/Platform/Screen.cs @@ -1,21 +1,42 @@ namespace Avalonia.Platform { + /// + /// Represents a single display screen. + /// public class Screen { + /// + /// Gets the pixel density of the screen. + /// This is a scaling factor so multiply by 100 to get a percentage. + /// + /// + /// Both X and Y density are assumed uniform. + /// public double PixelDensity { get; } + /// + /// Gets the overall pixel-size of the screen. + /// This generally is the raw pixel counts in both the X and Y direction. + /// public PixelRect Bounds { get; } + /// + /// Gets the actual working-area pixel-size of the screen. + /// This may be smaller to account for notches and other block-out areas. + /// public PixelRect WorkingArea { get; } - public bool Primary { get; } + /// + /// Gets a value indicating whether the screen is the primary one. + /// + public bool IsPrimary { get; } public Screen(double pixelDensity, PixelRect bounds, PixelRect workingArea, bool primary) { this.PixelDensity = pixelDensity; this.Bounds = bounds; this.WorkingArea = workingArea; - this.Primary = primary; + this.IsPrimary = primary; } } } diff --git a/src/Avalonia.Controls/Screens.cs b/src/Avalonia.Controls/Screens.cs index a554f82f61..da37959402 100644 --- a/src/Avalonia.Controls/Screens.cs +++ b/src/Avalonia.Controls/Screens.cs @@ -8,13 +8,27 @@ using Avalonia.VisualTree; namespace Avalonia.Controls { + /// + /// Represents all screens available on a device. + /// public class Screens { private readonly IScreenImpl _iScreenImpl; + /// + /// Gets the total number of screens available on this device. + /// public int ScreenCount => _iScreenImpl?.ScreenCount ?? 0; + + /// + /// Gets the list of all screens available on this device. + /// public IReadOnlyList All => _iScreenImpl?.AllScreens ?? Array.Empty(); - public Screen? Primary => All.FirstOrDefault(x => x.Primary); + + /// + /// Gets the primary screen on this device. + /// + public Screen? Primary => All.FirstOrDefault(x => x.IsPrimary); public Screens(IScreenImpl iScreenImpl) { diff --git a/src/Avalonia.X11/X11Screens.cs b/src/Avalonia.X11/X11Screens.cs index bcaafb6a53..a65f09ee63 100644 --- a/src/Avalonia.X11/X11Screens.cs +++ b/src/Avalonia.X11/X11Screens.cs @@ -9,7 +9,7 @@ using JetBrains.Annotations; namespace Avalonia.X11 { - class X11Screens : IScreenImpl + class X11Screens : IScreenImpl { private IX11Screens _impl; @@ -218,7 +218,7 @@ namespace Avalonia.X11 public int ScreenCount => _impl.Screens.Length; public IReadOnlyList AllScreens => - _impl.Screens.Select(s => new Screen(s.PixelDensity, s.Bounds, s.WorkingArea, s.Primary)).ToArray(); + _impl.Screens.Select(s => new Screen(s.PixelDensity, s.Bounds, s.WorkingArea, s.IsPrimary)).ToArray(); } interface IX11Screens @@ -281,7 +281,7 @@ namespace Avalonia.X11 { private const int FullHDWidth = 1920; private const int FullHDHeight = 1080; - public bool Primary { get; } + public bool IsPrimary { get; } public string Name { get; set; } public PixelRect Bounds { get; set; } public Size? PhysicalSize { get; set; } @@ -291,7 +291,7 @@ namespace Avalonia.X11 public X11Screen(PixelRect bounds, bool primary, string name, Size? physicalSize, double? pixelDensity) { - Primary = primary; + IsPrimary = primary; Name = name; Bounds = bounds; if (physicalSize == null && pixelDensity == null) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 0f243fcf9f..9741f3f804 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -224,7 +224,7 @@ namespace Avalonia.Win32 } } - private double PrimaryScreenRenderScaling => Screen.AllScreens.FirstOrDefault(screen => screen.Primary)?.PixelDensity ?? 1; + private double PrimaryScreenRenderScaling => Screen.AllScreens.FirstOrDefault(screen => screen.IsPrimary)?.PixelDensity ?? 1; public double RenderScaling => _scaling; From 31a15075ed6947e6f7998279d6daf59438304728 Mon Sep 17 00:00:00 2001 From: robloo Date: Sat, 8 Oct 2022 14:47:26 -0400 Subject: [PATCH 02/16] Rename missed parameter --- src/Avalonia.Controls/Platform/Screen.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/Platform/Screen.cs b/src/Avalonia.Controls/Platform/Screen.cs index 0f287fd5da..cdab81705f 100644 --- a/src/Avalonia.Controls/Platform/Screen.cs +++ b/src/Avalonia.Controls/Platform/Screen.cs @@ -31,12 +31,12 @@ /// public bool IsPrimary { get; } - public Screen(double pixelDensity, PixelRect bounds, PixelRect workingArea, bool primary) + public Screen(double pixelDensity, PixelRect bounds, PixelRect workingArea, bool isPrimary) { this.PixelDensity = pixelDensity; this.Bounds = bounds; this.WorkingArea = workingArea; - this.IsPrimary = primary; + this.IsPrimary = isPrimary; } } } From cc915f888cca167e32157f66a81654c8959e1374 Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Sun, 16 Oct 2022 16:31:00 +0200 Subject: [PATCH 03/16] fix: Under Windows - Arithmetic operation resulted in an overflow. --- src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index 9d1920498b..f28f4fd740 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -1877,7 +1877,7 @@ namespace Avalonia.Win32.Interop public static uint LGID(IntPtr HKL) { - return (uint)(HKL.ToInt32() & 0xffff); + return (uint)(HKL.ToInt64() & 0xffff); } public const int SORT_DEFAULT = 0; From 6bc689a662cd9f8154fed77fd6aa13e494cbb3ad Mon Sep 17 00:00:00 2001 From: robloo Date: Tue, 18 Oct 2022 21:10:59 -0400 Subject: [PATCH 04/16] Updates from code review --- samples/ControlCatalog/Pages/ScreenPage.cs | 2 +- src/Avalonia.Controls/Platform/Screen.cs | 35 +++++++++++++++------- src/Avalonia.Native/WindowImplBase.cs | 2 +- src/Avalonia.X11/X11Window.cs | 2 +- src/Windows/Avalonia.Win32/TrayIconImpl.cs | 8 ++--- src/Windows/Avalonia.Win32/WindowImpl.cs | 2 +- 6 files changed, 33 insertions(+), 18 deletions(-) diff --git a/samples/ControlCatalog/Pages/ScreenPage.cs b/samples/ControlCatalog/Pages/ScreenPage.cs index 6a4ed5a890..119bc09888 100644 --- a/samples/ControlCatalog/Pages/ScreenPage.cs +++ b/samples/ControlCatalog/Pages/ScreenPage.cs @@ -62,7 +62,7 @@ namespace ControlCatalog.Pages CreateFormattedText($"WorkArea: {screen.WorkingArea.Width}:{screen.WorkingArea.Height}"); context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 20)); - formattedText = CreateFormattedText($"Scaling: {screen.PixelDensity * 100}%"); + formattedText = CreateFormattedText($"Scaling: {screen.Scale * 100}%"); context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 40)); formattedText = CreateFormattedText($"Primary: {screen.IsPrimary}"); diff --git a/src/Avalonia.Controls/Platform/Screen.cs b/src/Avalonia.Controls/Platform/Screen.cs index cdab81705f..e5b8ca5555 100644 --- a/src/Avalonia.Controls/Platform/Screen.cs +++ b/src/Avalonia.Controls/Platform/Screen.cs @@ -1,4 +1,6 @@ -namespace Avalonia.Platform +using System; + +namespace Avalonia.Platform { /// /// Represents a single display screen. @@ -6,34 +8,47 @@ public class Screen { /// - /// Gets the pixel density of the screen. - /// This is a scaling factor so multiply by 100 to get a percentage. + /// Gets the scaling factor applied to the screen by the operating system. /// /// - /// Both X and Y density are assumed uniform. + /// Multiply this value by 100 to get a percentage. + /// Both X and Y scaling factors are assumed uniform. /// - public double PixelDensity { get; } + public double Scale { get; } + + /// + [Obsolete("Use the Scale property instead.")] + public double PixelDensity => Scale; /// /// Gets the overall pixel-size of the screen. - /// This generally is the raw pixel counts in both the X and Y direction. /// + /// + /// This generally is the raw pixel counts in both the X and Y direction. + /// public PixelRect Bounds { get; } /// /// Gets the actual working-area pixel-size of the screen. - /// This may be smaller to account for notches and other block-out areas. /// + /// + /// This area may be smaller than to account for notches and + /// other block-out areas such as taskbars etc. + /// public PixelRect WorkingArea { get; } /// /// Gets a value indicating whether the screen is the primary one. /// public bool IsPrimary { get; } - - public Screen(double pixelDensity, PixelRect bounds, PixelRect workingArea, bool isPrimary) + + /// + [Obsolete("Use the IsPrimary property instead.")] + public bool Primary => IsPrimary; + + public Screen(double scale, PixelRect bounds, PixelRect workingArea, bool isPrimary) { - this.PixelDensity = pixelDensity; + this.Scale = scale; this.Bounds = bounds; this.WorkingArea = workingArea; this.IsPrimary = isPrimary; diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index 34de439c94..8bb2b0a713 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -92,7 +92,7 @@ namespace Avalonia.Native _savedScaling = RenderScaling; _nativeControlHost = new NativeControlHostImpl(_native.CreateNativeControlHost()); - var monitor = Screen.AllScreens.OrderBy(x => x.PixelDensity) + var monitor = Screen.AllScreens.OrderBy(x => x.Scale) .FirstOrDefault(m => m.Bounds.Contains(Position)); Resize(new Size(monitor.WorkingArea.Width * 0.75d, monitor.WorkingArea.Height * 0.7d), PlatformResizeReason.Layout); diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index f24c33cafa..75b741ac77 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -120,7 +120,7 @@ namespace Avalonia.X11 if (!_popup && Screen != null) { - var monitor = Screen.AllScreens.OrderBy(x => x.PixelDensity) + var monitor = Screen.AllScreens.OrderBy(x => x.Scale) .FirstOrDefault(m => m.Bounds.Contains(Position)); if (monitor != null) diff --git a/src/Windows/Avalonia.Win32/TrayIconImpl.cs b/src/Windows/Avalonia.Win32/TrayIconImpl.cs index 346d6e5adb..93bdfda652 100644 --- a/src/Windows/Avalonia.Win32/TrayIconImpl.cs +++ b/src/Windows/Avalonia.Win32/TrayIconImpl.cs @@ -216,7 +216,7 @@ namespace Avalonia.Win32 { Anchor = PopupAnchor.TopLeft, Gravity = PopupGravity.BottomRight, - AnchorRectangle = new Rect(Position.ToPoint(1) / Screens.Primary.PixelDensity, new Size(1, 1)), + AnchorRectangle = new Rect(Position.ToPoint(1) / Screens.Primary.Scale, new Size(1, 1)), Size = finalRect.Size, ConstraintAdjustment = PopupPositionerConstraintAdjustment.FlipX | PopupPositionerConstraintAdjustment.FlipY, }); @@ -244,16 +244,16 @@ namespace Avalonia.Win32 { var point = _hiddenWindow.Screens.Primary.Bounds.TopLeft; var size = _hiddenWindow.Screens.Primary.Bounds.Size; - return new Rect(point.X, point.Y, size.Width * _hiddenWindow.Screens.Primary.PixelDensity, size.Height * _hiddenWindow.Screens.Primary.PixelDensity); + return new Rect(point.X, point.Y, size.Width * _hiddenWindow.Screens.Primary.Scale, size.Height * _hiddenWindow.Screens.Primary.Scale); } } public void MoveAndResize(Point devicePoint, Size virtualSize) { - _moveResize(new PixelPoint((int)devicePoint.X, (int)devicePoint.Y), virtualSize, _hiddenWindow.Screens.Primary.PixelDensity); + _moveResize(new PixelPoint((int)devicePoint.X, (int)devicePoint.Y), virtualSize, _hiddenWindow.Screens.Primary.Scale); } - public double Scaling => _hiddenWindow.Screens.Primary.PixelDensity; + public double Scaling => _hiddenWindow.Screens.Primary.Scale; } } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 9741f3f804..cd8515eaa6 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -224,7 +224,7 @@ namespace Avalonia.Win32 } } - private double PrimaryScreenRenderScaling => Screen.AllScreens.FirstOrDefault(screen => screen.IsPrimary)?.PixelDensity ?? 1; + private double PrimaryScreenRenderScaling => Screen.AllScreens.FirstOrDefault(screen => screen.IsPrimary)?.Scale ?? 1; public double RenderScaling => _scaling; From f271654d64885ffae707bf00e7b787a1ec39c62a Mon Sep 17 00:00:00 2001 From: Giuseppe Lippolis Date: Wed, 19 Oct 2022 09:49:06 +0200 Subject: [PATCH 05/16] fix: CS8350 --- src/Avalonia.Base/Media/PathMarkupParser.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Base/Media/PathMarkupParser.cs b/src/Avalonia.Base/Media/PathMarkupParser.cs index 30c5206125..cf12bf5126 100644 --- a/src/Avalonia.Base/Media/PathMarkupParser.cs +++ b/src/Avalonia.Base/Media/PathMarkupParser.cs @@ -188,7 +188,7 @@ namespace Avalonia.Media _isOpen = true; } - private void SetFillRule(ref ReadOnlySpan span) + private void SetFillRule(scoped ref ReadOnlySpan span) { ThrowIfDisposed(); @@ -452,7 +452,7 @@ namespace Avalonia.Media return !span.IsEmpty && (span[0] == ',' || span[0] == '-' || span[0] == '.' || char.IsDigit(span[0])); } - private static bool ReadArgument(ref ReadOnlySpan remaining, out ReadOnlySpan argument) + private static bool ReadArgument(scoped ref ReadOnlySpan remaining, out ReadOnlySpan argument) { remaining = SkipWhitespace(remaining); if (remaining.IsEmpty) From 10b584d95c7dd903f18f706e1f64cdcaffbd18a2 Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Wed, 19 Oct 2022 22:14:48 +0200 Subject: [PATCH 06/16] After the fix still causing issues, I figured the value must be >0xffff_ffff so not fitting. I changed to logic to handle that case too. --- src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index f28f4fd740..3bcc395abe 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -1877,7 +1877,10 @@ namespace Avalonia.Win32.Interop public static uint LGID(IntPtr HKL) { - return (uint)(HKL.ToInt64() & 0xffff); + unchecked + { + return (uint)((ulong)HKL & 0xffff); + } } public const int SORT_DEFAULT = 0; From d816726ef000545ea547bd1e24ea58be56bdb7c9 Mon Sep 17 00:00:00 2001 From: robloo Date: Wed, 19 Oct 2022 21:19:13 -0400 Subject: [PATCH 07/16] Rename Scale to Scaling and update more comments --- samples/ControlCatalog/Pages/ScreenPage.cs | 2 +- src/Avalonia.Controls/Platform/IScreenImpl.cs | 6 +++++ src/Avalonia.Controls/Platform/Screen.cs | 19 ++++++++++----- src/Avalonia.Controls/Screens.cs | 13 ++++++---- src/Avalonia.Native/ScreenImpl.cs | 4 ++-- src/Avalonia.Native/WindowImplBase.cs | 2 +- src/Avalonia.Native/avn.idl | 4 ++-- src/Avalonia.X11/X11Screens.cs | 24 +++++++++++-------- src/Avalonia.X11/X11Window.cs | 8 +++---- src/Windows/Avalonia.Win32/TrayIconImpl.cs | 8 +++---- src/Windows/Avalonia.Win32/WindowImpl.cs | 2 +- 11 files changed, 56 insertions(+), 36 deletions(-) diff --git a/samples/ControlCatalog/Pages/ScreenPage.cs b/samples/ControlCatalog/Pages/ScreenPage.cs index 119bc09888..ab75e4a4e2 100644 --- a/samples/ControlCatalog/Pages/ScreenPage.cs +++ b/samples/ControlCatalog/Pages/ScreenPage.cs @@ -65,7 +65,7 @@ namespace ControlCatalog.Pages formattedText = CreateFormattedText($"Scaling: {screen.Scale * 100}%"); context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 40)); - formattedText = CreateFormattedText($"Primary: {screen.IsPrimary}"); + formattedText = CreateFormattedText($"IsPrimary: {screen.IsPrimary}"); context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 60)); formattedText = diff --git a/src/Avalonia.Controls/Platform/IScreenImpl.cs b/src/Avalonia.Controls/Platform/IScreenImpl.cs index fcae3b6493..e2a0b3e3f3 100644 --- a/src/Avalonia.Controls/Platform/IScreenImpl.cs +++ b/src/Avalonia.Controls/Platform/IScreenImpl.cs @@ -6,8 +6,14 @@ namespace Avalonia.Platform [Unstable] public interface IScreenImpl { + /// + /// Gets the total number of screens available on the device. + /// int ScreenCount { get; } + /// + /// Gets the list of all screens available on the device. + /// IReadOnlyList AllScreens { get; } Screen? ScreenFromWindow(IWindowBaseImpl window); diff --git a/src/Avalonia.Controls/Platform/Screen.cs b/src/Avalonia.Controls/Platform/Screen.cs index e5b8ca5555..4898c5f912 100644 --- a/src/Avalonia.Controls/Platform/Screen.cs +++ b/src/Avalonia.Controls/Platform/Screen.cs @@ -14,11 +14,11 @@ namespace Avalonia.Platform /// Multiply this value by 100 to get a percentage. /// Both X and Y scaling factors are assumed uniform. /// - public double Scale { get; } + public double Scaling { get; } - /// - [Obsolete("Use the Scale property instead.")] - public double PixelDensity => Scale; + /// + [Obsolete("Use the Scaling property instead.")] + public double PixelDensity => Scaling; /// /// Gets the overall pixel-size of the screen. @@ -46,9 +46,16 @@ namespace Avalonia.Platform [Obsolete("Use the IsPrimary property instead.")] public bool Primary => IsPrimary; - public Screen(double scale, PixelRect bounds, PixelRect workingArea, bool isPrimary) + /// + /// Initializes a new instance of the class. + /// + /// The scaling factor applied to the screen by the operating system. + /// The overall pixel-size of the screen. + /// The actual working-area pixel-size of the screen. + /// Whether the screen is the primary one. + public Screen(double scaling, PixelRect bounds, PixelRect workingArea, bool isPrimary) { - this.Scale = scale; + this.Scaling = scaling; this.Bounds = bounds; this.WorkingArea = workingArea; this.IsPrimary = isPrimary; diff --git a/src/Avalonia.Controls/Screens.cs b/src/Avalonia.Controls/Screens.cs index da37959402..dde6b71e6e 100644 --- a/src/Avalonia.Controls/Screens.cs +++ b/src/Avalonia.Controls/Screens.cs @@ -16,20 +16,23 @@ namespace Avalonia.Controls private readonly IScreenImpl _iScreenImpl; /// - /// Gets the total number of screens available on this device. + /// Gets the total number of screens available on the device. /// public int ScreenCount => _iScreenImpl?.ScreenCount ?? 0; /// - /// Gets the list of all screens available on this device. + /// Gets the list of all screens available on the device. /// public IReadOnlyList All => _iScreenImpl?.AllScreens ?? Array.Empty(); /// - /// Gets the primary screen on this device. + /// Gets the primary screen on the device. /// public Screen? Primary => All.FirstOrDefault(x => x.IsPrimary); + /// + /// Initializes a new instance of the class. + /// public Screens(IScreenImpl iScreenImpl) { _iScreenImpl = iScreenImpl; @@ -39,14 +42,14 @@ namespace Avalonia.Controls { return _iScreenImpl.ScreenFromRect(bounds); } - + public Screen? ScreenFromWindow(IWindowBaseImpl window) { return _iScreenImpl.ScreenFromWindow(window); } public Screen? ScreenFromPoint(PixelPoint point) - { + { return _iScreenImpl.ScreenFromPoint(point); } diff --git a/src/Avalonia.Native/ScreenImpl.cs b/src/Avalonia.Native/ScreenImpl.cs index 83db2e8a28..53bd12cde1 100644 --- a/src/Avalonia.Native/ScreenImpl.cs +++ b/src/Avalonia.Native/ScreenImpl.cs @@ -30,10 +30,10 @@ namespace Avalonia.Native var screen = _native.GetScreen(i); result[i] = new Screen( - screen.PixelDensity, + screen.Scaling, screen.Bounds.ToAvaloniaPixelRect(), screen.WorkingArea.ToAvaloniaPixelRect(), - screen.Primary.FromComBool()); + screen.IsPrimary.FromComBool()); } return result; diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index 8bb2b0a713..381741cea9 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -92,7 +92,7 @@ namespace Avalonia.Native _savedScaling = RenderScaling; _nativeControlHost = new NativeControlHostImpl(_native.CreateNativeControlHost()); - var monitor = Screen.AllScreens.OrderBy(x => x.Scale) + var monitor = Screen.AllScreens.OrderBy(x => x.Scaling) .FirstOrDefault(m => m.Bounds.Contains(Position)); Resize(new Size(monitor.WorkingArea.Width * 0.75d, monitor.WorkingArea.Height * 0.7d), PlatformResizeReason.Layout); diff --git a/src/Avalonia.Native/avn.idl b/src/Avalonia.Native/avn.idl index a98d213887..b0bff07146 100644 --- a/src/Avalonia.Native/avn.idl +++ b/src/Avalonia.Native/avn.idl @@ -256,8 +256,8 @@ struct AvnScreen { AvnRect Bounds; AvnRect WorkingArea; - float PixelDensity; - bool Primary; + float Scaling; + bool IsPrimary; } enum AvnPixelFormat diff --git a/src/Avalonia.X11/X11Screens.cs b/src/Avalonia.X11/X11Screens.cs index a65f09ee63..ba6029b350 100644 --- a/src/Avalonia.X11/X11Screens.cs +++ b/src/Avalonia.X11/X11Screens.cs @@ -218,7 +218,7 @@ namespace Avalonia.X11 public int ScreenCount => _impl.Screens.Length; public IReadOnlyList AllScreens => - _impl.Screens.Select(s => new Screen(s.PixelDensity, s.Bounds, s.WorkingArea, s.IsPrimary)).ToArray(); + _impl.Screens.Select(s => new Screen(s.Scaling, s.Bounds, s.WorkingArea, s.IsPrimary)).ToArray(); } interface IX11Screens @@ -285,26 +285,30 @@ namespace Avalonia.X11 public string Name { get; set; } public PixelRect Bounds { get; set; } public Size? PhysicalSize { get; set; } - public double PixelDensity { get; set; } + public double Scaling { get; set; } public PixelRect WorkingArea { get; set; } - public X11Screen(PixelRect bounds, bool primary, - string name, Size? physicalSize, double? pixelDensity) + public X11Screen( + PixelRect bounds, + bool isPrimary, + string name, + Size? physicalSize, + double? scaling) { - IsPrimary = primary; + IsPrimary = isPrimary; Name = name; Bounds = bounds; - if (physicalSize == null && pixelDensity == null) + if (physicalSize == null && scaling == null) { - PixelDensity = 1; + Scaling = 1; } - else if (pixelDensity == null) + else if (scaling == null) { - PixelDensity = GuessPixelDensity(bounds, physicalSize.Value); + Scaling = GuessPixelDensity(bounds, physicalSize.Value); } else { - PixelDensity = pixelDensity.Value; + Scaling = scaling.Value; PhysicalSize = physicalSize; } } diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 75b741ac77..690ac0ebce 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -120,7 +120,7 @@ namespace Avalonia.X11 if (!_popup && Screen != null) { - var monitor = Screen.AllScreens.OrderBy(x => x.Scale) + var monitor = Screen.AllScreens.OrderBy(x => x.Scaling) .FirstOrDefault(m => m.Bounds.Contains(Position)); if (monitor != null) @@ -570,9 +570,9 @@ namespace Avalonia.X11 newScaling = _scalingOverride.Value; else { - var monitor = _platform.X11Screens.Screens.OrderBy(x => x.PixelDensity) + var monitor = _platform.X11Screens.Screens.OrderBy(x => x.Scaling) .FirstOrDefault(m => m.Bounds.Contains(Position)); - newScaling = monitor?.PixelDensity ?? RenderScaling; + newScaling = monitor?.Scaling ?? RenderScaling; } if (RenderScaling != newScaling) @@ -994,7 +994,7 @@ namespace Avalonia.X11 public IScreenImpl Screen => _platform.Screens; - public Size MaxAutoSizeHint => _platform.X11Screens.Screens.Select(s => s.Bounds.Size.ToSize(s.PixelDensity)) + public Size MaxAutoSizeHint => _platform.X11Screens.Screens.Select(s => s.Bounds.Size.ToSize(s.Scaling)) .OrderByDescending(x => x.Width + x.Height).FirstOrDefault(); diff --git a/src/Windows/Avalonia.Win32/TrayIconImpl.cs b/src/Windows/Avalonia.Win32/TrayIconImpl.cs index 93bdfda652..8d565d7fef 100644 --- a/src/Windows/Avalonia.Win32/TrayIconImpl.cs +++ b/src/Windows/Avalonia.Win32/TrayIconImpl.cs @@ -216,7 +216,7 @@ namespace Avalonia.Win32 { Anchor = PopupAnchor.TopLeft, Gravity = PopupGravity.BottomRight, - AnchorRectangle = new Rect(Position.ToPoint(1) / Screens.Primary.Scale, new Size(1, 1)), + AnchorRectangle = new Rect(Position.ToPoint(1) / Screens.Primary.Scaling, new Size(1, 1)), Size = finalRect.Size, ConstraintAdjustment = PopupPositionerConstraintAdjustment.FlipX | PopupPositionerConstraintAdjustment.FlipY, }); @@ -244,16 +244,16 @@ namespace Avalonia.Win32 { var point = _hiddenWindow.Screens.Primary.Bounds.TopLeft; var size = _hiddenWindow.Screens.Primary.Bounds.Size; - return new Rect(point.X, point.Y, size.Width * _hiddenWindow.Screens.Primary.Scale, size.Height * _hiddenWindow.Screens.Primary.Scale); + return new Rect(point.X, point.Y, size.Width * _hiddenWindow.Screens.Primary.Scaling, size.Height * _hiddenWindow.Screens.Primary.Scaling); } } public void MoveAndResize(Point devicePoint, Size virtualSize) { - _moveResize(new PixelPoint((int)devicePoint.X, (int)devicePoint.Y), virtualSize, _hiddenWindow.Screens.Primary.Scale); + _moveResize(new PixelPoint((int)devicePoint.X, (int)devicePoint.Y), virtualSize, _hiddenWindow.Screens.Primary.Scaling); } - public double Scaling => _hiddenWindow.Screens.Primary.Scale; + public double Scaling => _hiddenWindow.Screens.Primary.Scaling; } } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index cd8515eaa6..5374614379 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -224,7 +224,7 @@ namespace Avalonia.Win32 } } - private double PrimaryScreenRenderScaling => Screen.AllScreens.FirstOrDefault(screen => screen.IsPrimary)?.Scale ?? 1; + private double PrimaryScreenRenderScaling => Screen.AllScreens.FirstOrDefault(screen => screen.IsPrimary)?.Scaling ?? 1; public double RenderScaling => _scaling; From 91d25f7416981eebebe769757d944627b2f7ab8c Mon Sep 17 00:00:00 2001 From: robloo Date: Thu, 20 Oct 2022 20:12:40 -0400 Subject: [PATCH 08/16] Fix missed property rename --- samples/ControlCatalog/Pages/ScreenPage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/ControlCatalog/Pages/ScreenPage.cs b/samples/ControlCatalog/Pages/ScreenPage.cs index ab75e4a4e2..ff62b834c4 100644 --- a/samples/ControlCatalog/Pages/ScreenPage.cs +++ b/samples/ControlCatalog/Pages/ScreenPage.cs @@ -62,7 +62,7 @@ namespace ControlCatalog.Pages CreateFormattedText($"WorkArea: {screen.WorkingArea.Width}:{screen.WorkingArea.Height}"); context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 20)); - formattedText = CreateFormattedText($"Scaling: {screen.Scale * 100}%"); + formattedText = CreateFormattedText($"Scaling: {screen.Scaling * 100}%"); context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 40)); formattedText = CreateFormattedText($"IsPrimary: {screen.IsPrimary}"); From 1d19c37a37aa106c14002cbb88af701625f6fb34 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 22 Oct 2022 09:43:51 +0100 Subject: [PATCH 09/16] wasm prevent touch flashing android. --- src/Web/Avalonia.Web/AvaloniaView.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Web/Avalonia.Web/AvaloniaView.cs b/src/Web/Avalonia.Web/AvaloniaView.cs index 296e411fa8..098b06a0a2 100644 --- a/src/Web/Avalonia.Web/AvaloniaView.cs +++ b/src/Web/Avalonia.Web/AvaloniaView.cs @@ -77,8 +77,7 @@ namespace Avalonia.Web _topLevelImpl.SetCssCursor = (cursor) => { - InputHelper.SetCursor(_containerElement, cursor); // macOS - InputHelper.SetCursor(_canvas, cursor); // windows + InputHelper.SetCursor(_containerElement, cursor); }; _topLevel.Prepare(); From eb1c1971f1d92eb68d319cf4b3c032800f2d6600 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 22 Oct 2022 10:28:51 +0100 Subject: [PATCH 10/16] remove cursor style when we want normal cursor. --- src/Web/Avalonia.Web/webapp/modules/avalonia/input.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Web/Avalonia.Web/webapp/modules/avalonia/input.ts b/src/Web/Avalonia.Web/webapp/modules/avalonia/input.ts index 768414ccab..8198e09738 100644 --- a/src/Web/Avalonia.Web/webapp/modules/avalonia/input.ts +++ b/src/Web/Avalonia.Web/webapp/modules/avalonia/input.ts @@ -159,7 +159,12 @@ export class InputHelper { } public static setCursor(inputElement: HTMLInputElement, kind: string) { - inputElement.style.cursor = kind; + if(kind == "pointer"){ + inputElement.style.removeProperty("cursor"); + } + else { + inputElement.style.cursor = kind; + } } public static setBounds(inputElement: HTMLInputElement, x: number, y: number, caretWidth: number, caretHeight: number, caret: number) { From 116146e847ad8b3506de58ff6469a17b1ae729b9 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 22 Oct 2022 12:23:57 +0100 Subject: [PATCH 11/16] smooth resizing wasm. --- .../ControlCatalog.Web/ControlCatalog.Web.csproj | 5 ++--- samples/ControlCatalog.Web/Roots.xml | 1 + .../webapp/modules/avalonia/canvas.ts | 16 ++++++++-------- .../webapp/modules/avalonia/input.ts | 5 ++--- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/samples/ControlCatalog.Web/ControlCatalog.Web.csproj b/samples/ControlCatalog.Web/ControlCatalog.Web.csproj index 0ddec3444b..06a5466619 100644 --- a/samples/ControlCatalog.Web/ControlCatalog.Web.csproj +++ b/samples/ControlCatalog.Web/ControlCatalog.Web.csproj @@ -16,9 +16,8 @@ full true true - true - -O3 - -O3 + -O2 + -O2 diff --git a/samples/ControlCatalog.Web/Roots.xml b/samples/ControlCatalog.Web/Roots.xml index 3c13098159..b07fd86fa2 100644 --- a/samples/ControlCatalog.Web/Roots.xml +++ b/samples/ControlCatalog.Web/Roots.xml @@ -3,4 +3,5 @@ + diff --git a/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts b/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts index 9ae9b3d2a8..8f3539b4f8 100644 --- a/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts +++ b/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts @@ -210,23 +210,23 @@ interface SizeWatcherInstance { export class SizeWatcher { static observer: ResizeObserver; static elements: Map; + private static lastMove: number; public static observe(element: HTMLElement, elementId: string | undefined, callback: (width: number, height: number) => void): void { if (!element || !callback) { return; } - SizeWatcher.init(); + callback(element.clientWidth, element.clientHeight); - const watcherElement = element as SizeWatcherElement; - watcherElement.SizeWatcher = { - callback + const handleResize = (args: UIEvent) => { + if (Date.now() - this.lastMove > 33) { + callback(element.clientWidth, element.clientHeight); + SizeWatcher.lastMove = Date.now(); + } }; - SizeWatcher.elements.set(elementId ?? element.id, element); - SizeWatcher.observer.observe(element); - - SizeWatcher.invoke(element); + window.addEventListener("resize", handleResize); } public static unobserve(elementId: string): void { diff --git a/src/Web/Avalonia.Web/webapp/modules/avalonia/input.ts b/src/Web/Avalonia.Web/webapp/modules/avalonia/input.ts index 8198e09738..ddc1f54ae7 100644 --- a/src/Web/Avalonia.Web/webapp/modules/avalonia/input.ts +++ b/src/Web/Avalonia.Web/webapp/modules/avalonia/input.ts @@ -159,10 +159,9 @@ export class InputHelper { } public static setCursor(inputElement: HTMLInputElement, kind: string) { - if(kind == "pointer"){ + if (kind === "pointer") { inputElement.style.removeProperty("cursor"); - } - else { + } else { inputElement.style.cursor = kind; } } From 38717dafbbccc958089d532794819cb2517b019c Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 22 Oct 2022 12:52:02 +0100 Subject: [PATCH 12/16] smooth resizing attempt 2. --- src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts b/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts index 8f3539b4f8..010c9cfacc 100644 --- a/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts +++ b/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts @@ -217,10 +217,12 @@ export class SizeWatcher { return; } + SizeWatcher.lastMove = Date.now(); + callback(element.clientWidth, element.clientHeight); const handleResize = (args: UIEvent) => { - if (Date.now() - this.lastMove > 33) { + if (Date.now() - SizeWatcher.lastMove > 40) { callback(element.clientWidth, element.clientHeight); SizeWatcher.lastMove = Date.now(); } From f5d3f9b2d332a5a68b316779493085ec4b064f80 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 22 Oct 2022 13:40:40 +0100 Subject: [PATCH 13/16] we dont handle gl makecurrent. --- .../webapp/modules/avalonia/canvas.ts | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts b/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts index 010c9cfacc..62f62fe46f 100644 --- a/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts +++ b/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts @@ -106,12 +106,6 @@ export class Canvas { // add the draw to the next frame this.renderLoopRequest = window.requestAnimationFrame(() => { - if (this.glInfo) { - const GL = (globalThis as any).AvaloniaGL; - // make current - GL.makeContextCurrent(this.glInfo.context); - } - if (this.htmlCanvas.width !== this.newWidth) { this.htmlCanvas.width = this.newWidth ?? 0; } @@ -131,6 +125,11 @@ export class Canvas { } public setCanvasSize(width: number, height: number): void { + if (this.renderLoopRequest !== 0) { + window.cancelAnimationFrame(this.renderLoopRequest); + this.renderLoopRequest = 0; + } + this.newWidth = width; this.newHeight = height; @@ -142,11 +141,7 @@ export class Canvas { this.htmlCanvas.height = this.newHeight; } - if (this.glInfo) { - const GL = (globalThis as any).AvaloniaGL; - // make current - GL.makeContextCurrent(this.glInfo.context); - } + this.requestAnimationFrame(); } public static setCanvasSize(element: HTMLCanvasElement, width: number, height: number): void { From cd8358303e2d9cf4edde7ca9999ad82a4c72d474 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 22 Oct 2022 14:26:03 +0100 Subject: [PATCH 14/16] 30fps resize. --- src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts b/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts index 62f62fe46f..47c501cbb7 100644 --- a/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts +++ b/src/Web/Avalonia.Web/webapp/modules/avalonia/canvas.ts @@ -217,7 +217,7 @@ export class SizeWatcher { callback(element.clientWidth, element.clientHeight); const handleResize = (args: UIEvent) => { - if (Date.now() - SizeWatcher.lastMove > 40) { + if (Date.now() - SizeWatcher.lastMove > 33) { callback(element.clientWidth, element.clientHeight); SizeWatcher.lastMove = Date.now(); } From 6f5bae821b47e4671da4456ad3acbed7b15bd6a2 Mon Sep 17 00:00:00 2001 From: robloo Date: Sat, 22 Oct 2022 11:38:48 -0400 Subject: [PATCH 15/16] Fix usage of updated Screen properties This fixes the macOS build --- native/Avalonia.Native/src/OSX/Screens.mm | 4 ++-- src/Windows/Avalonia.Win32/WinScreen.cs | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/Screens.mm b/native/Avalonia.Native/src/OSX/Screens.mm index b9c75ed742..83ab1bfd01 100644 --- a/native/Avalonia.Native/src/OSX/Screens.mm +++ b/native/Avalonia.Native/src/OSX/Screens.mm @@ -41,9 +41,9 @@ public: ret->WorkingArea.X = [screen visibleFrame].origin.x; ret->WorkingArea.Y = ConvertPointY(ToAvnPoint([screen visibleFrame].origin)).Y - ret->WorkingArea.Height; - ret->PixelDensity = [screen backingScaleFactor]; + ret->Scaling = [screen backingScaleFactor]; - ret->Primary = index == 0; + ret->IsPrimary = index == 0; return S_OK; } diff --git a/src/Windows/Avalonia.Win32/WinScreen.cs b/src/Windows/Avalonia.Win32/WinScreen.cs index f103cc3b66..1038f41a17 100644 --- a/src/Windows/Avalonia.Win32/WinScreen.cs +++ b/src/Windows/Avalonia.Win32/WinScreen.cs @@ -7,7 +7,8 @@ namespace Avalonia.Win32 { private readonly IntPtr _hMonitor; - public WinScreen(double pixelDensity, PixelRect bounds, PixelRect workingArea, bool primary, IntPtr hMonitor) : base(pixelDensity, bounds, workingArea, primary) + public WinScreen(double scaling, PixelRect bounds, PixelRect workingArea, bool isPrimary, IntPtr hMonitor) + : base(scaling, bounds, workingArea, isPrimary) { _hMonitor = hMonitor; } From ab02289d9377cfaa38c72bcfae9cf31ce1f6478b Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sun, 23 Oct 2022 18:22:03 +0100 Subject: [PATCH 16/16] fix distortion on mobile chrome browser. --- src/Web/Avalonia.Web/webapp/modules/avalonia/dom.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Web/Avalonia.Web/webapp/modules/avalonia/dom.ts b/src/Web/Avalonia.Web/webapp/modules/avalonia/dom.ts index 668212964c..385cdd4c41 100644 --- a/src/Web/Avalonia.Web/webapp/modules/avalonia/dom.ts +++ b/src/Web/Avalonia.Web/webapp/modules/avalonia/dom.ts @@ -19,7 +19,6 @@ export class AvaloniaDOM { canvas.classList.add("avalonia-canvas"); canvas.style.backgroundColor = "#ccc"; canvas.style.width = "100%"; - canvas.style.height = "100%"; canvas.style.position = "absolute"; // Native controls host