فهرست منبع

Seperate RenderScaling from DesktopScaling.

Dan Walmsley 5 سال پیش
والد
کامیت
0148106f54
31فایلهای تغییر یافته به همراه105 افزوده شده و 104 حذف شده
  1. 1 1
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  2. 1 1
      src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs
  3. 3 3
      src/Avalonia.Controls/Platform/ITopLevelImpl.cs
  4. 5 0
      src/Avalonia.Controls/Platform/IWindowBaseImpl.cs
  5. 2 2
      src/Avalonia.Controls/Primitives/PopupPositioning/ManagedPopupPositionerPopupImplHelper.cs
  6. 2 2
      src/Avalonia.Controls/TopLevel.cs
  7. 1 1
      src/Avalonia.Controls/Window.cs
  8. 1 0
      src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs
  9. 2 1
      src/Avalonia.DesignerSupport/Remote/Stubs.cs
  10. 5 4
      src/Avalonia.Headless/HeadlessWindowImpl.cs
  11. 0 15
      src/Avalonia.Native/OsxManagedPopupPositionerPopupImplHelper.cs
  12. 1 1
      src/Avalonia.Native/PopupImpl.cs
  13. 5 3
      src/Avalonia.Native/WindowImplBase.cs
  14. 2 2
      src/Avalonia.X11/X11NativeControlHost.cs
  15. 20 18
      src/Avalonia.X11/X11Window.cs
  16. 2 2
      src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs
  17. 3 3
      src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs
  18. 1 1
      src/Windows/Avalonia.Win32/PopupImpl.cs
  19. 2 2
      src/Windows/Avalonia.Win32/Win32NativeControlHost.cs
  20. 7 7
      src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs
  21. 1 1
      src/Windows/Avalonia.Win32/WindowImpl.CustomCaptionProc.cs
  22. 16 12
      src/Windows/Avalonia.Win32/WindowImpl.cs
  23. 1 1
      src/iOS/Avalonia.iOS/TopLevelImpl.cs
  24. 1 1
      tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs
  25. 1 1
      tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs
  26. 2 2
      tests/Avalonia.Controls.UnitTests/TopLevelTests.cs
  27. 5 5
      tests/Avalonia.Controls.UnitTests/WindowBaseTests.cs
  28. 7 7
      tests/Avalonia.Controls.UnitTests/WindowTests.cs
  29. 2 2
      tests/Avalonia.Controls.UnitTests/WindowingPlatformMock.cs
  30. 1 1
      tests/Avalonia.LeakTests/ControlTests.cs
  31. 2 2
      tests/Avalonia.UnitTests/MockWindowingPlatform.cs

+ 1 - 1
src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@@ -126,7 +126,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
             _view.Visibility = ViewStates.Visible;
         }
 
-        public double Scaling => 1;
+        public double RenderScaling => 1;
 
         void Draw()
         {

+ 1 - 1
src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs

@@ -35,7 +35,7 @@ namespace Avalonia.Controls.Embedding.Offscreen
             }
         }
 
-        public double Scaling
+        public double RenderScaling
         {
             get { return _scaling; }
             set

+ 3 - 3
src/Avalonia.Controls/Platform/ITopLevelImpl.cs

@@ -23,10 +23,10 @@ namespace Avalonia.Platform
         Size ClientSize { get; }
 
         /// <summary>
-        /// Gets the scaling factor for the toplevel.
+        /// Gets the scaling factor for the toplevel. This is used for rendering.
         /// </summary>
-        double Scaling { get; }
-
+        double RenderScaling { get; }
+        
         /// <summary>
         /// The list of native platform's surfaces that can be consumed by rendering subsystems.
         /// </summary>

+ 5 - 0
src/Avalonia.Controls/Platform/IWindowBaseImpl.cs

@@ -13,6 +13,11 @@ namespace Avalonia.Platform
         /// Hides the window.
         /// </summary>
         void Hide();
+        
+        /// <summary>
+        /// Gets the scaling factor for Window positioning and sizing.
+        /// </summary>
+        double DesktopScaling { get; }
 
         /// <summary>
         /// Gets the position of the window in device pixels.

+ 2 - 2
src/Avalonia.Controls/Primitives/PopupPositioning/ManagedPopupPositionerPopupImplHelper.cs

@@ -40,9 +40,9 @@ namespace Avalonia.Controls.Primitives.PopupPositioning
 
         public void MoveAndResize(Point devicePoint, Size virtualSize)
         {
-            _moveResize(new PixelPoint((int)devicePoint.X, (int)devicePoint.Y), virtualSize, _parent.Scaling);
+            _moveResize(new PixelPoint((int)devicePoint.X, (int)devicePoint.Y), virtualSize, _parent.RenderScaling);
         }
 
-        public virtual double Scaling => _parent.Scaling;
+        public virtual double Scaling => _parent.DesktopScaling;
     }
 }

+ 2 - 2
src/Avalonia.Controls/TopLevel.cs

@@ -280,10 +280,10 @@ namespace Avalonia.Controls
         }
 
         /// <inheritdoc/>
-        double ILayoutRoot.LayoutScaling => PlatformImpl?.Scaling ?? 1;
+        double ILayoutRoot.LayoutScaling => PlatformImpl?.RenderScaling ?? 1;
 
         /// <inheritdoc/>
-        double IRenderRoot.RenderScaling => PlatformImpl?.Scaling ?? 1;
+        double IRenderRoot.RenderScaling => PlatformImpl?.RenderScaling ?? 1;
 
         IStyleHost IStyleHost.StylingParent => _globalStyles;
 

+ 1 - 1
src/Avalonia.Controls/Window.cs

@@ -818,7 +818,7 @@ namespace Avalonia.Controls
 
         private void SetWindowStartupLocation(IWindowBaseImpl owner = null)
         {
-            var scaling = owner?.Scaling ?? PlatformImpl?.Scaling ?? 1;
+            var scaling = owner?.DesktopScaling ?? PlatformImpl?.DesktopScaling ?? 1;
 
             // TODO: We really need non-client size here.
             var rect = new PixelRect(

+ 1 - 0
src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs

@@ -36,6 +36,7 @@ namespace Avalonia.DesignerSupport.Remote
         {
         }
 
+        public double DesktopScaling => 1.0;
         public PixelPoint Position { get; set; }
         public Action<PixelPoint> PositionChanged { get; set; }
         public Action Deactivated { get; set; }

+ 2 - 1
src/Avalonia.DesignerSupport/Remote/Stubs.cs

@@ -21,7 +21,8 @@ namespace Avalonia.DesignerSupport.Remote
         public IPlatformHandle Handle { get; }
         public Size MaxAutoSizeHint { get; }
         public Size ClientSize { get; }
-        public double Scaling { get; } = 1.0;
+        public double RenderScaling { get; } = 1.0;
+        public double DesktopScaling => 1.0;
         public IEnumerable<object> Surfaces { get; }
         public Action<RawInputEventArgs> Input { get; set; }
         public Action<Rect> Paint { get; set; }

+ 5 - 4
src/Avalonia.Headless/HeadlessWindowImpl.cs

@@ -41,7 +41,8 @@ namespace Avalonia.Headless
         }
 
         public Size ClientSize { get; set; }
-        public double Scaling { get; } = 1;
+        public double RenderScaling { get; } = 1;
+        public double DesktopScaling => RenderScaling;
         public IEnumerable<object> Surfaces { get; }
         public Action<RawInputEventArgs> Input { get; set; }
         public Action<Rect> Paint { get; set; }
@@ -62,9 +63,9 @@ namespace Avalonia.Headless
 
         public IInputRoot InputRoot { get; set; }
 
-        public Point PointToClient(PixelPoint point) => point.ToPoint(Scaling);
+        public Point PointToClient(PixelPoint point) => point.ToPoint(RenderScaling);
 
-        public PixelPoint PointToScreen(Point point) => PixelPoint.FromPoint(point, Scaling);
+        public PixelPoint PointToScreen(Point point) => PixelPoint.FromPoint(point, RenderScaling);
 
         public void SetCursor(IPlatformHandle cursor)
         {
@@ -201,7 +202,7 @@ namespace Avalonia.Headless
 
         public ILockedFramebuffer Lock()
         {
-            var bmp = new WriteableBitmap(PixelSize.FromSize(ClientSize, Scaling), new Vector(96, 96) * Scaling);
+            var bmp = new WriteableBitmap(PixelSize.FromSize(ClientSize, RenderScaling), new Vector(96, 96) * RenderScaling);
             var fb = bmp.Lock();
             return new FramebufferProxy(fb, () =>
             {

+ 0 - 15
src/Avalonia.Native/OsxManagedPopupPositionerPopupImplHelper.cs

@@ -1,15 +0,0 @@
-using Avalonia.Controls.Primitives.PopupPositioning;
-using Avalonia.Platform;
-
-namespace Avalonia.Native
-{
-    class OsxManagedPopupPositionerPopupImplHelper : ManagedPopupPositionerPopupImplHelper
-    {
-        public OsxManagedPopupPositionerPopupImplHelper(IWindowBaseImpl parent, MoveResizeDelegate moveResize) : base(parent, moveResize)
-        {
-
-        }
-
-        public override double Scaling => 1;
-    }
-}

+ 1 - 1
src/Avalonia.Native/PopupImpl.cs

@@ -26,7 +26,7 @@ namespace Avalonia.Native
                 var context = _opts.UseGpu ? glFeature?.DeferredContext : null;
                 Init(factory.CreatePopup(e, context?.Context), factory.CreateScreens(), context);
             }
-            PopupPositioner = new ManagedPopupPositioner(new OsxManagedPopupPositionerPopupImplHelper(parent, MoveResize));
+            PopupPositioner = new ManagedPopupPositioner(new ManagedPopupPositionerPopupImplHelper(parent, MoveResize));
         }
 
         private void MoveResize(PixelPoint position, Size size, double scaling)

+ 5 - 3
src/Avalonia.Native/WindowImplBase.cs

@@ -81,7 +81,7 @@ namespace Avalonia.Native
                 _glSurface = new GlPlatformSurface(window, _glContext);
             Screen = new ScreenImpl(screens);
             _savedLogicalSize = ClientSize;
-            _savedScaling = Scaling;
+            _savedScaling = RenderScaling;
             _nativeControlHost = new NativeControlHostImpl(_native.CreateNativeControlHost());
 
             var monitor = Screen.AllScreens.OrderBy(x => x.PixelDensity)
@@ -369,7 +369,9 @@ namespace Avalonia.Native
             _native.SetTopMost(value);
         }
 
-        public double Scaling => _native?.GetScaling() ?? 1;
+        public double RenderScaling => _native?.GetScaling() ?? 1;
+
+        public double DesktopScaling => 1;
 
         public Action Deactivated { get; set; }
         public Action Activated { get; set; }
@@ -432,7 +434,7 @@ namespace Avalonia.Native
 
                 TransparencyLevel = transparencyLevel;
 
-                _native.SetBlurEnabled(TransparencyLevel >= WindowTransparencyLevel.Blur);
+                _native?.SetBlurEnabled(TransparencyLevel >= WindowTransparencyLevel.Blur);
                 TransparencyLevelChanged?.Invoke(TransparencyLevel);
             }
         }

+ 2 - 2
src/Avalonia.X11/X11NativeControlHost.cs

@@ -167,7 +167,7 @@ namespace Avalonia.X11
                     XUnmapWindow(_display, _holder.Handle);
                 }
 
-                size *= _attachedTo.Window.Scaling;
+                size *= _attachedTo.Window.RenderScaling;
                 XResizeWindow(_display, _child.Handle,
                     Math.Max(1, (int)size.Width), Math.Max(1, (int)size.Height));
             }
@@ -179,7 +179,7 @@ namespace Avalonia.X11
                 CheckDisposed();
                 if (_attachedTo == null)
                     throw new InvalidOperationException("The control isn't currently attached to a toplevel");
-                bounds *= _attachedTo.Window.Scaling;
+                bounds *= _attachedTo.Window.RenderScaling;
                 
                 var pixelRect = new PixelRect((int)bounds.X, (int)bounds.Y, Math.Max(1, (int)bounds.Width),
                     Math.Max(1, (int)bounds.Height));

+ 20 - 18
src/Avalonia.X11/X11Window.cs

@@ -163,7 +163,7 @@ namespace Avalonia.X11
             var surfaces = new List<object>
             {
                 new X11FramebufferSurface(_x11.DeferredDisplay, _renderHandle, 
-                   depth, () => Scaling)
+                   depth, () => RenderScaling)
             };
             
             if (egl != null)
@@ -217,7 +217,7 @@ namespace Avalonia.X11
                 }
             }
 
-            public double Scaling => _window.Scaling;
+            public double Scaling => _window.RenderScaling;
         }
 
         void UpdateMotifHints()
@@ -284,9 +284,9 @@ namespace Avalonia.X11
             XSetWMNormalHints(_x11.Display, _handle, ref hints);
         }
 
-        public Size ClientSize => new Size(_realSize.Width / Scaling, _realSize.Height / Scaling);
+        public Size ClientSize => new Size(_realSize.Width / RenderScaling, _realSize.Height / RenderScaling);
 
-        public double Scaling
+        public double RenderScaling
         {
             get
             {
@@ -296,6 +296,8 @@ namespace Avalonia.X11
             }
             private set => _scaling = value;
         }
+        
+        public double DesktopScaling => RenderScaling;
 
         public IEnumerable<object> Surfaces { get; }
         public Action<RawInputEventArgs> Input { get; set; }
@@ -538,14 +540,14 @@ namespace Avalonia.X11
                 {
                     var monitor = _platform.X11Screens.Screens.OrderBy(x => x.PixelDensity)
                         .FirstOrDefault(m => m.Bounds.Contains(Position));
-                    newScaling = monitor?.PixelDensity ?? Scaling;
+                    newScaling = monitor?.PixelDensity ?? RenderScaling;
                 }
 
-                if (Scaling != newScaling)
+                if (RenderScaling != newScaling)
                 {
                     var oldScaledSize = ClientSize;
-                    Scaling = newScaling;
-                    ScalingChanged?.Invoke(Scaling);
+                    RenderScaling = newScaling;
+                    ScalingChanged?.Invoke(RenderScaling);
                     SetMinMaxSize(_scaledMinMaxSize.minSize, _scaledMinMaxSize.maxSize);
                     if(!skipResize)
                         Resize(oldScaledSize, true);
@@ -707,9 +709,9 @@ namespace Avalonia.X11
         private void ScheduleInput(RawInputEventArgs args)
         {
             if (args is RawPointerEventArgs mouse)
-                mouse.Position = mouse.Position / Scaling;
+                mouse.Position = mouse.Position / RenderScaling;
             if (args is RawDragEvent drag)
-                drag.Location = drag.Location / Scaling;
+                drag.Location = drag.Location / RenderScaling;
             
             _lastEvent = new InputEventContainer() {Event = args};
             _inputQueue.Enqueue(_lastEvent);
@@ -816,11 +818,11 @@ namespace Avalonia.X11
 
         public void Hide() => XUnmapWindow(_x11.Display, _handle);
         
-        public Point PointToClient(PixelPoint point) => new Point((point.X - Position.X) / Scaling, (point.Y - Position.Y) / Scaling);
+        public Point PointToClient(PixelPoint point) => new Point((point.X - Position.X) / RenderScaling, (point.Y - Position.Y) / RenderScaling);
 
         public PixelPoint PointToScreen(Point point) => new PixelPoint(
-            (int)(point.X * Scaling + Position.X),
-            (int)(point.Y * Scaling + Position.Y));
+            (int)(point.X * RenderScaling + Position.X),
+            (int)(point.Y * RenderScaling + Position.Y));
         
         public void SetSystemDecorations(SystemDecorations enabled)
         {
@@ -840,7 +842,7 @@ namespace Avalonia.X11
             Resize(size, true);
         }
 
-        PixelSize ToPixelSize(Size size) => new PixelSize((int)(size.Width * Scaling), (int)(size.Height * Scaling));
+        PixelSize ToPixelSize(Size size) => new PixelSize((int)(size.Width * RenderScaling), (int)(size.Height * RenderScaling));
         
         void Resize(Size clientSize, bool force)
         {
@@ -1020,13 +1022,13 @@ namespace Avalonia.X11
         {
             _scaledMinMaxSize = (minSize, maxSize);
             var min = new PixelSize(
-                (int)(minSize.Width < 1 ? 1 : minSize.Width * Scaling),
-                (int)(minSize.Height < 1 ? 1 : minSize.Height * Scaling));
+                (int)(minSize.Width < 1 ? 1 : minSize.Width * RenderScaling),
+                (int)(minSize.Height < 1 ? 1 : minSize.Height * RenderScaling));
 
             const int maxDim = MaxWindowDimension;
             var max = new PixelSize(
-                (int)(maxSize.Width > maxDim ? maxDim : Math.Max(min.Width, maxSize.Width * Scaling)),
-                (int)(maxSize.Height > maxDim ? maxDim : Math.Max(min.Height, maxSize.Height * Scaling)));
+                (int)(maxSize.Width > maxDim ? maxDim : Math.Max(min.Width, maxSize.Width * RenderScaling)),
+                (int)(maxSize.Height > maxDim ? maxDim : Math.Max(min.Height, maxSize.Height * RenderScaling)));
             
             _minMaxSize = (min, max);
             UpdateSizeHints(null);

+ 2 - 2
src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs

@@ -65,7 +65,7 @@ namespace Avalonia.LinuxFramebuffer
         public IMouseDevice MouseDevice => new MouseDevice();
         public IPopupImpl CreatePopup() => null;
 
-        public double Scaling => _outputBackend.Scaling;
+        public double RenderScaling => _outputBackend.Scaling;
         public IEnumerable<object> Surfaces { get; }
         public Action<RawInputEventArgs> Input { get; set; }
         public Action<Rect> Paint { get; set; }
@@ -77,7 +77,7 @@ namespace Avalonia.LinuxFramebuffer
         public Action Closed { get; set; }
         public Action LostFocus { get; set; }
 
-        public Size ScaledSize => _outputBackend.PixelSize.ToSize(Scaling);
+        public Size ScaledSize => _outputBackend.PixelSize.ToSize(RenderScaling);
 
         public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { }
 

+ 3 - 3
src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs

@@ -75,7 +75,7 @@ namespace Avalonia.Win32.Interop.Wpf
         private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled)
         {
             if (msg == (int)UnmanagedMethods.WindowsMessage.WM_DPICHANGED)
-                _ttl.ScalingChanged?.Invoke(_ttl.Scaling);
+                _ttl.ScalingChanged?.Invoke(_ttl.RenderScaling);
             return IntPtr.Zero;
         }
 
@@ -84,7 +84,7 @@ namespace Avalonia.Win32.Interop.Wpf
             _currentHwndSource?.RemoveHook(_hook);
             _currentHwndSource = e.NewSource as HwndSource;
             _currentHwndSource?.AddHook(_hook);
-            _ttl.ScalingChanged?.Invoke(_ttl.Scaling);
+            _ttl.ScalingChanged?.Invoke(_ttl.RenderScaling);
         }
 
         public IRenderer CreateRenderer(IRenderRoot root)
@@ -102,7 +102,7 @@ namespace Avalonia.Win32.Interop.Wpf
         Size ITopLevelImpl.ClientSize => _finalSize;
         IMouseDevice ITopLevelImpl.MouseDevice => _mouse;
 
-        double ITopLevelImpl.Scaling => PresentationSource.FromVisual(this)?.CompositionTarget?.TransformToDevice.M11 ?? 1;
+        double ITopLevelImpl.RenderScaling => PresentationSource.FromVisual(this)?.CompositionTarget?.TransformToDevice.M11 ?? 1;
 
         IEnumerable<object> ITopLevelImpl.Surfaces => _surfaces;
 

+ 1 - 1
src/Windows/Avalonia.Win32/PopupImpl.cs

@@ -57,7 +57,7 @@ namespace Avalonia.Win32
                     {
                         var info = UnmanagedMethods.MONITORINFO.Create();
                         UnmanagedMethods.GetMonitorInfo(monitor, ref info);
-                        _maxAutoSize = info.rcWork.ToPixelRect().ToRect(Scaling).Size;
+                        _maxAutoSize = info.rcWork.ToPixelRect().ToRect(RenderScaling).Size;
                     }
                 }
 

+ 2 - 2
src/Windows/Avalonia.Win32/Win32NativeControlHost.cs

@@ -176,7 +176,7 @@ namespace Avalonia.Win32
                     UnmanagedMethods.SetWindowPosFlags.SWP_NOACTIVATE);
                 if (_attachedTo == null || _child == null)
                     return;
-                size *= _attachedTo.Window.Scaling;
+                size *= _attachedTo.Window.RenderScaling;
                 UnmanagedMethods.MoveWindow(_child.Handle, 0, 0,
                     Math.Max(1, (int)size.Width), Math.Max(1, (int)size.Height), false);
             }
@@ -186,7 +186,7 @@ namespace Avalonia.Win32
                 CheckDisposed();
                 if (_attachedTo == null)
                     throw new InvalidOperationException("The control isn't currently attached to a toplevel");
-                bounds *= _attachedTo.Window.Scaling;
+                bounds *= _attachedTo.Window.RenderScaling;
                 var pixelRect = new PixelRect((int)bounds.X, (int)bounds.Y, Math.Max(1, (int)bounds.Width),
                     Math.Max(1, (int)bounds.Height));
                 

+ 7 - 7
src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs

@@ -343,7 +343,7 @@ namespace Avalonia.Win32
                         {
                             if (BeginPaint(_hwnd, out PAINTSTRUCT ps) != IntPtr.Zero)
                             {
-                                var f = Scaling;
+                                var f = RenderScaling;
                                 var r = ps.rcPaint;
                                 Paint?.Invoke(new Rect(r.left / f, r.top / f, (r.right - r.left) / f,
                                     (r.bottom - r.top) / f));
@@ -368,7 +368,7 @@ namespace Avalonia.Win32
                              size == SizeCommand.Maximized))
                         {
                             var clientSize = new Size(ToInt32(lParam) & 0xffff, ToInt32(lParam) >> 16);
-                            Resized(clientSize / Scaling);
+                            Resized(clientSize / RenderScaling);
                         }
 
                         var windowState = size == SizeCommand.Maximized ?
@@ -406,25 +406,25 @@ namespace Avalonia.Win32
                         if (_minSize.Width > 0)
                         {
                             mmi.ptMinTrackSize.X =
-                                (int)((_minSize.Width * Scaling) + BorderThickness.Left + BorderThickness.Right);
+                                (int)((_minSize.Width * RenderScaling) + BorderThickness.Left + BorderThickness.Right);
                         }
 
                         if (_minSize.Height > 0)
                         {
                             mmi.ptMinTrackSize.Y =
-                                (int)((_minSize.Height * Scaling) + BorderThickness.Top + BorderThickness.Bottom);
+                                (int)((_minSize.Height * RenderScaling) + BorderThickness.Top + BorderThickness.Bottom);
                         }
 
                         if (!double.IsInfinity(_maxSize.Width) && _maxSize.Width > 0)
                         {
                             mmi.ptMaxTrackSize.X =
-                                (int)((_maxSize.Width * Scaling) + BorderThickness.Left + BorderThickness.Right);
+                                (int)((_maxSize.Width * RenderScaling) + BorderThickness.Left + BorderThickness.Right);
                         }
 
                         if (!double.IsInfinity(_maxSize.Height) && _maxSize.Height > 0)
                         {
                             mmi.ptMaxTrackSize.Y =
-                                (int)((_maxSize.Height * Scaling) + BorderThickness.Top + BorderThickness.Bottom);
+                                (int)((_maxSize.Height * RenderScaling) + BorderThickness.Top + BorderThickness.Bottom);
                         }
 
                         Marshal.StructureToPtr(mmi, lParam, true);
@@ -480,7 +480,7 @@ namespace Avalonia.Win32
 
         private Point DipFromLParam(IntPtr lParam)
         {
-            return new Point((short)(ToInt32(lParam) & 0xffff), (short)(ToInt32(lParam) >> 16)) / Scaling;
+            return new Point((short)(ToInt32(lParam) & 0xffff), (short)(ToInt32(lParam) >> 16)) / RenderScaling;
         }
 
         private PixelPoint PointFromLParam(IntPtr lParam)

+ 1 - 1
src/Windows/Avalonia.Win32/WindowImpl.CustomCaptionProc.cs

@@ -37,7 +37,7 @@ namespace Avalonia.Win32
 
             if (_extendTitleBarHint >= 0)
             {
-                border_thickness.top = (int)(_extendedMargins.Top * Scaling);
+                border_thickness.top = (int)(_extendedMargins.Top * RenderScaling);
             }
 
             // Determine if the hit test is for resizing. Default middle (1,1).

+ 16 - 12
src/Windows/Avalonia.Win32/WindowImpl.cs

@@ -164,7 +164,9 @@ namespace Avalonia.Win32
             }
         }
 
-        public double Scaling => _scaling;
+        public double RenderScaling => _scaling;
+
+        public double DesktopScaling => RenderScaling;
 
         public Size ClientSize
         {
@@ -172,7 +174,7 @@ namespace Avalonia.Win32
             {
                 GetClientRect(_hwnd, out var rect);
 
-                return new Size(rect.right, rect.bottom) / Scaling;
+                return new Size(rect.right, rect.bottom) / RenderScaling;
             }
         }
 
@@ -180,7 +182,7 @@ namespace Avalonia.Win32
 
         public IPlatformHandle Handle { get; private set; }
 
-        public virtual Size MaxAutoSizeHint => new Size(_maxTrackSize.X / Scaling, _maxTrackSize.Y / Scaling);
+        public virtual Size MaxAutoSizeHint => new Size(_maxTrackSize.X / RenderScaling, _maxTrackSize.Y / RenderScaling);
 
         public IMouseDevice MouseDevice => _mouseDevice;
 
@@ -342,8 +344,8 @@ namespace Avalonia.Win32
 
         public void Resize(Size value)
         {
-            int requestedClientWidth = (int)(value.Width * Scaling);
-            int requestedClientHeight = (int)(value.Height * Scaling);
+            int requestedClientWidth = (int)(value.Width * RenderScaling);
+            int requestedClientHeight = (int)(value.Height * RenderScaling);
 
             GetClientRect(_hwnd, out var clientRect);
 
@@ -395,7 +397,7 @@ namespace Avalonia.Win32
 
         public void Invalidate(Rect rect)
         {
-            var scaling = Scaling;
+            var scaling = RenderScaling;
             var r = new RECT
             {
                 left = (int)Math.Floor(rect.X * scaling),
@@ -411,12 +413,12 @@ namespace Avalonia.Win32
         {
             var p = new POINT { X = point.X, Y = point.Y };
             UnmanagedMethods.ScreenToClient(_hwnd, ref p);
-            return new Point(p.X, p.Y) / Scaling;
+            return new Point(p.X, p.Y) / RenderScaling;
         }
 
         public PixelPoint PointToScreen(Point point)
         {
-            point *= Scaling;
+            point *= RenderScaling;
             var p = new POINT { X = (int)point.X, Y = (int)point.Y };
             ClientToScreen(_hwnd, ref p);
             return new PixelPoint(p.X, p.Y);
@@ -710,19 +712,19 @@ namespace Avalonia.Win32
 
             if (_extendTitleBarHint != -1)
             {
-                borderCaptionThickness.top = (int)(_extendTitleBarHint * Scaling);                
+                borderCaptionThickness.top = (int)(_extendTitleBarHint * RenderScaling);                
             }
 
             margins.cyTopHeight = _extendChromeHints.HasFlag(ExtendClientAreaChromeHints.SystemChrome) && !_extendChromeHints.HasFlag(ExtendClientAreaChromeHints.PreferSystemChrome) ? borderCaptionThickness.top : 1;
 
             if (WindowState == WindowState.Maximized)
             {
-                _extendedMargins = new Thickness(0, (borderCaptionThickness.top - borderThickness.top) / Scaling, 0, 0);
-                _offScreenMargin = new Thickness(borderThickness.left / Scaling, borderThickness.top / Scaling, borderThickness.right / Scaling, borderThickness.bottom / Scaling);
+                _extendedMargins = new Thickness(0, (borderCaptionThickness.top - borderThickness.top) / RenderScaling, 0, 0);
+                _offScreenMargin = new Thickness(borderThickness.left / RenderScaling, borderThickness.top / RenderScaling, borderThickness.right / RenderScaling, borderThickness.bottom / RenderScaling);
             }
             else
             {
-                _extendedMargins = new Thickness(0, (borderCaptionThickness.top) / Scaling, 0, 0);
+                _extendedMargins = new Thickness(0, (borderCaptionThickness.top) / RenderScaling, 0, 0);
                 _offScreenMargin = new Thickness();
             }
 
@@ -1034,6 +1036,8 @@ namespace Avalonia.Win32
             }
         }
 
+        double EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo.Scaling => RenderScaling;
+
         IntPtr EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo.Handle => Handle.Handle;
 
         public void SetExtendClientAreaToDecorationsHint(bool hint)

+ 1 - 1
src/iOS/Avalonia.iOS/TopLevelImpl.cs

@@ -48,7 +48,7 @@ namespace Avalonia.iOS
 
         public new IPlatformHandle Handle => null;
 
-        public double Scaling => UIScreen.MainScreen.Scale;
+        public double RenderScaling => UIScreen.MainScreen.Scale;
 
        
         public override void LayoutSubviews() => Resized?.Invoke(ClientSize);

+ 1 - 1
tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs

@@ -296,7 +296,7 @@ namespace Avalonia.Controls.UnitTests
 
             var windowImpl = MockWindowingPlatform.CreateWindowMock();
             popupImpl = MockWindowingPlatform.CreatePopupMock(windowImpl.Object);
-            popupImpl.SetupGet(x => x.Scaling).Returns(1);
+            popupImpl.SetupGet(x => x.RenderScaling).Returns(1);
             windowImpl.Setup(x => x.CreatePopup()).Returns(popupImpl.Object);
 
             windowImpl.Setup(x => x.Screen).Returns(screenImpl.Object);

+ 1 - 1
tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs

@@ -191,7 +191,7 @@ namespace Avalonia.Controls.UnitTests
         {
             var windowImpl = new Mock<IWindowImpl>();
             windowImpl.SetupProperty(x => x.Closed);
-            windowImpl.Setup(x => x.Scaling).Returns(1);
+            windowImpl.Setup(x => x.RenderScaling).Returns(1);
 
             var services = TestServices.StyledWindow.With(
                 windowingPlatform: new MockWindowingPlatform(() => windowImpl.Object));

+ 2 - 2
tests/Avalonia.Controls.UnitTests/TopLevelTests.cs

@@ -93,7 +93,7 @@ namespace Avalonia.Controls.UnitTests
             {
                 var impl = new Mock<ITopLevelImpl>();
                 impl.SetupProperty(x => x.Resized);
-                impl.SetupGet(x => x.Scaling).Returns(1);
+                impl.SetupGet(x => x.RenderScaling).Returns(1);
 
                 var target = new TestTopLevel(impl.Object)
                 {
@@ -290,7 +290,7 @@ namespace Avalonia.Controls.UnitTests
             using (UnitTestApplication.Start(TestServices.StyledWindow))
             {
                 var impl = new Mock<ITopLevelImpl>();
-                impl.SetupGet(x => x.Scaling).Returns(1);
+                impl.SetupGet(x => x.RenderScaling).Returns(1);
 
                 var child = new Border { Classes = { "foo" } };
                 var target = new TestTopLevel(impl.Object)

+ 5 - 5
tests/Avalonia.Controls.UnitTests/WindowBaseTests.cs

@@ -110,7 +110,7 @@ namespace Avalonia.Controls.UnitTests
         public void IsVisible_Should_Be_False_Atfer_Impl_Signals_Close()
         {
             var windowImpl = new Mock<IPopupImpl>();
-            windowImpl.Setup(x => x.Scaling).Returns(1);
+            windowImpl.Setup(x => x.RenderScaling).Returns(1);
             windowImpl.SetupProperty(x => x.Closed);
 
             using (UnitTestApplication.Start(TestServices.StyledWindow))
@@ -128,7 +128,7 @@ namespace Avalonia.Controls.UnitTests
         public void Setting_IsVisible_True_Shows_Window()
         {
             var windowImpl = new Mock<IPopupImpl>();
-            windowImpl.Setup(x => x.Scaling).Returns(1);
+            windowImpl.Setup(x => x.RenderScaling).Returns(1);
 
             using (UnitTestApplication.Start(TestServices.StyledWindow))
             {
@@ -143,7 +143,7 @@ namespace Avalonia.Controls.UnitTests
         public void Setting_IsVisible_False_Hides_Window()
         {
             var windowImpl = new Mock<IPopupImpl>();
-            windowImpl.Setup(x => x.Scaling).Returns(1);
+            windowImpl.Setup(x => x.RenderScaling).Returns(1);
 
             using (UnitTestApplication.Start(TestServices.StyledWindow))
             {
@@ -208,7 +208,7 @@ namespace Avalonia.Controls.UnitTests
             {
                 var renderer = new Mock<IRenderer>();
                 var windowImpl = new Mock<IPopupImpl>();
-                windowImpl.Setup(x => x.Scaling).Returns(1);
+                windowImpl.Setup(x => x.RenderScaling).Returns(1);
                 windowImpl.SetupProperty(x => x.Closed);
                 windowImpl.Setup(x => x.CreateRenderer(It.IsAny<IRenderRoot>())).Returns(renderer.Object);
 
@@ -237,7 +237,7 @@ namespace Avalonia.Controls.UnitTests
 
             public TestWindowBase(IRenderer renderer = null)
                 : base(Mock.Of<IWindowBaseImpl>(x => 
-                    x.Scaling == 1 &&
+                    x.RenderScaling == 1 &&
                     x.CreateRenderer(It.IsAny<IRenderRoot>()) == renderer))
             {
             }

+ 7 - 7
tests/Avalonia.Controls.UnitTests/WindowTests.cs

@@ -100,7 +100,7 @@ namespace Avalonia.Controls.UnitTests
         {
             var windowImpl = new Mock<IWindowImpl>();
             windowImpl.SetupProperty(x => x.Closed);
-            windowImpl.Setup(x => x.Scaling).Returns(1);
+            windowImpl.Setup(x => x.RenderScaling).Returns(1);
 
             var services = TestServices.StyledWindow.With(
                 windowingPlatform: new MockWindowingPlatform(() => windowImpl.Object));
@@ -206,7 +206,7 @@ namespace Avalonia.Controls.UnitTests
                 var parent = new Mock<Window>();
                 var windowImpl = new Mock<IWindowImpl>();
                 windowImpl.SetupProperty(x => x.Closed);
-                windowImpl.Setup(x => x.Scaling).Returns(1);
+                windowImpl.Setup(x => x.RenderScaling).Returns(1);
 
                 var target = new Window(windowImpl.Object);
                 var task = target.ShowDialog<bool>(parent.Object);
@@ -245,7 +245,7 @@ namespace Avalonia.Controls.UnitTests
                 var parent = new Mock<Window>();
                 var windowImpl = new Mock<IWindowImpl>();
                 windowImpl.SetupProperty(x => x.Closed);
-                windowImpl.Setup(x => x.Scaling).Returns(1);
+                windowImpl.Setup(x => x.RenderScaling).Returns(1);
 
                 var target = new Window(windowImpl.Object);
                 var task = target.ShowDialog<bool>(parent.Object);
@@ -273,7 +273,7 @@ namespace Avalonia.Controls.UnitTests
 
             var windowImpl = MockWindowingPlatform.CreateWindowMock();
             windowImpl.Setup(x => x.ClientSize).Returns(new Size(800, 480));
-            windowImpl.Setup(x => x.Scaling).Returns(1);
+            windowImpl.Setup(x => x.RenderScaling).Returns(1);
             windowImpl.Setup(x => x.Screen).Returns(screens.Object);
 
             using (UnitTestApplication.Start(TestServices.StyledWindow))
@@ -298,12 +298,12 @@ namespace Avalonia.Controls.UnitTests
             var parentWindowImpl = MockWindowingPlatform.CreateWindowMock();
             parentWindowImpl.Setup(x => x.ClientSize).Returns(new Size(800, 480));
             parentWindowImpl.Setup(x => x.MaxAutoSizeHint).Returns(new Size(1920, 1080));
-            parentWindowImpl.Setup(x => x.Scaling).Returns(1);
+            parentWindowImpl.Setup(x => x.RenderScaling).Returns(1);
 
             var windowImpl = MockWindowingPlatform.CreateWindowMock();
             windowImpl.Setup(x => x.ClientSize).Returns(new Size(320, 200));
             windowImpl.Setup(x => x.MaxAutoSizeHint).Returns(new Size(1920, 1080));
-            windowImpl.Setup(x => x.Scaling).Returns(1);
+            windowImpl.Setup(x => x.RenderScaling).Returns(1);
 
             var parentWindowServices = TestServices.StyledWindow.With(
                 windowingPlatform: new MockWindowingPlatform(() => parentWindowImpl.Object));
@@ -565,7 +565,7 @@ namespace Avalonia.Controls.UnitTests
         private IWindowImpl CreateImpl(Mock<IRenderer> renderer)
         {
             return Mock.Of<IWindowImpl>(x =>
-                x.Scaling == 1 &&
+                x.RenderScaling == 1 &&
                 x.CreateRenderer(It.IsAny<IRenderRoot>()) == renderer.Object);
         }
 

+ 2 - 2
tests/Avalonia.Controls.UnitTests/WindowingPlatformMock.cs

@@ -17,7 +17,7 @@ namespace Avalonia.Controls.UnitTests
 
         public IWindowImpl CreateWindow()
         {
-            return _windowImpl?.Invoke() ?? Mock.Of<IWindowImpl>(x => x.Scaling == 1);
+            return _windowImpl?.Invoke() ?? Mock.Of<IWindowImpl>(x => x.RenderScaling == 1);
         }
 
         public IWindowImpl CreateEmbeddableWindow()
@@ -25,6 +25,6 @@ namespace Avalonia.Controls.UnitTests
             throw new NotImplementedException();
         }
 
-        public IPopupImpl CreatePopup() => _popupImpl?.Invoke() ?? Mock.Of<IPopupImpl>(x => x.Scaling == 1);
+        public IPopupImpl CreatePopup() => _popupImpl?.Invoke() ?? Mock.Of<IPopupImpl>(x => x.RenderScaling == 1);
     }
 }

+ 1 - 1
tests/Avalonia.LeakTests/ControlTests.cs

@@ -355,7 +355,7 @@ namespace Avalonia.LeakTests
                 var renderer = new Mock<IRenderer>();
                 renderer.Setup(x => x.Dispose());
                 var impl = new Mock<IWindowImpl>();
-                impl.SetupGet(x => x.Scaling).Returns(1);
+                impl.SetupGet(x => x.RenderScaling).Returns(1);
                 impl.SetupProperty(x => x.Closed);
                 impl.Setup(x => x.CreateRenderer(It.IsAny<IRenderRoot>())).Returns(renderer.Object);
                 impl.Setup(x => x.Dispose()).Callback(() => impl.Object.Closed());

+ 2 - 2
tests/Avalonia.UnitTests/MockWindowingPlatform.cs

@@ -29,7 +29,7 @@ namespace Avalonia.UnitTests
             windowImpl.SetupAllProperties();
             windowImpl.Setup(x => x.ClientSize).Returns(() => clientSize);
             windowImpl.Setup(x => x.MaxAutoSizeHint).Returns(s_screenSize);
-            windowImpl.Setup(x => x.Scaling).Returns(1);
+            windowImpl.Setup(x => x.RenderScaling).Returns(1);
             windowImpl.Setup(x => x.Screen).Returns(CreateScreenMock().Object);
             windowImpl.Setup(x => x.Position).Returns(() => position);
             SetupToplevel(windowImpl);
@@ -81,7 +81,7 @@ namespace Avalonia.UnitTests
             popupImpl.SetupAllProperties();
             popupImpl.Setup(x => x.ClientSize).Returns(() => clientSize);
             popupImpl.Setup(x => x.MaxAutoSizeHint).Returns(s_screenSize);
-            popupImpl.Setup(x => x.Scaling).Returns(1);
+            popupImpl.Setup(x => x.RenderScaling).Returns(1);
             popupImpl.Setup(x => x.PopupPositioner).Returns(positioner);
             
             SetupToplevel(popupImpl);