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/samples/ControlCatalog/Pages/ScreenPage.cs b/samples/ControlCatalog/Pages/ScreenPage.cs index 823f59e030..ff62b834c4 100644 --- a/samples/ControlCatalog/Pages/ScreenPage.cs +++ b/samples/ControlCatalog/Pages/ScreenPage.cs @@ -62,10 +62,10 @@ 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.Scaling * 100}%"); context.DrawText(formattedText, boundsRect.Position.WithY(boundsRect.Size.Height + 40)); - formattedText = CreateFormattedText($"Primary: {screen.Primary}"); + 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 976faed3fd..4898c5f912 100644 --- a/src/Avalonia.Controls/Platform/Screen.cs +++ b/src/Avalonia.Controls/Platform/Screen.cs @@ -1,21 +1,64 @@ -namespace Avalonia.Platform +using System; + +namespace Avalonia.Platform { + /// + /// Represents a single display screen. + /// public class Screen { - public double PixelDensity { get; } + /// + /// Gets the scaling factor applied to the screen by the operating system. + /// + /// + /// Multiply this value by 100 to get a percentage. + /// Both X and Y scaling factors are assumed uniform. + /// + public double Scaling { get; } + + /// + [Obsolete("Use the Scaling property instead.")] + public double PixelDensity => Scaling; + /// + /// 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 area may be smaller than to account for notches and + /// other block-out areas such as taskbars etc. + /// public PixelRect WorkingArea { get; } - public bool Primary { get; } - - public Screen(double pixelDensity, PixelRect bounds, PixelRect workingArea, bool primary) + /// + /// Gets a value indicating whether the screen is the primary one. + /// + public bool IsPrimary { get; } + + /// + [Obsolete("Use the IsPrimary property instead.")] + public bool Primary => 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.PixelDensity = pixelDensity; + this.Scaling = scaling; this.Bounds = bounds; this.WorkingArea = workingArea; - this.Primary = primary; + this.IsPrimary = isPrimary; } } } diff --git a/src/Avalonia.Controls/Screens.cs b/src/Avalonia.Controls/Screens.cs index a554f82f61..dde6b71e6e 100644 --- a/src/Avalonia.Controls/Screens.cs +++ b/src/Avalonia.Controls/Screens.cs @@ -8,14 +8,31 @@ 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 the device. + /// public int ScreenCount => _iScreenImpl?.ScreenCount ?? 0; + + /// + /// Gets the list of all screens available on the device. + /// public IReadOnlyList All => _iScreenImpl?.AllScreens ?? Array.Empty(); - public Screen? Primary => All.FirstOrDefault(x => x.Primary); + /// + /// 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; @@ -25,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 34de439c94..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.PixelDensity) + 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 bcaafb6a53..ba6029b350 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.Scaling, s.Bounds, s.WorkingArea, s.IsPrimary)).ToArray(); } interface IX11Screens @@ -281,30 +281,34 @@ 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; } - 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) { - Primary = 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 f24c33cafa..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.PixelDensity) + 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 346d6e5adb..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.PixelDensity, 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.PixelDensity, size.Height * _hiddenWindow.Screens.Primary.PixelDensity); + 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.PixelDensity); + _moveResize(new PixelPoint((int)devicePoint.X, (int)devicePoint.Y), virtualSize, _hiddenWindow.Screens.Primary.Scaling); } - public double Scaling => _hiddenWindow.Screens.Primary.PixelDensity; + public double Scaling => _hiddenWindow.Screens.Primary.Scaling; } } 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; } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 0f243fcf9f..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.Primary)?.PixelDensity ?? 1; + private double PrimaryScreenRenderScaling => Screen.AllScreens.FirstOrDefault(screen => screen.IsPrimary)?.Scaling ?? 1; public double RenderScaling => _scaling;