diff --git a/src/Gtk/Perspex.Gtk/WindowImpl.cs b/src/Gtk/Perspex.Gtk/WindowImpl.cs index c9ed1bdfcd..057379899d 100644 --- a/src/Gtk/Perspex.Gtk/WindowImpl.cs +++ b/src/Gtk/Perspex.Gtk/WindowImpl.cs @@ -129,6 +129,8 @@ namespace Perspex.Gtk public Action Resized { get; set; } + public Action ScalingChanged { get; set; } + public IPopupImpl CreatePopup() { return new PopupImpl(); diff --git a/src/Perspex.Controls/Platform/ITopLevelImpl.cs b/src/Perspex.Controls/Platform/ITopLevelImpl.cs index 2bfb1f4a9a..57ffb3ef9d 100644 --- a/src/Perspex.Controls/Platform/ITopLevelImpl.cs +++ b/src/Perspex.Controls/Platform/ITopLevelImpl.cs @@ -62,6 +62,11 @@ namespace Perspex.Platform /// Action Resized { get; set; } + /// + /// Gets or sets a method called when the window's scaling changes. + /// + Action ScalingChanged { get; set; } + /// /// Activates the window. /// diff --git a/src/Perspex.Controls/Platform/PlatformManager.cs b/src/Perspex.Controls/Platform/PlatformManager.cs index 400c77d559..55dc4cce48 100644 --- a/src/Perspex.Controls/Platform/PlatformManager.cs +++ b/src/Perspex.Controls/Platform/PlatformManager.cs @@ -131,8 +131,6 @@ namespace Perspex.Controls.Platform public Action Paint { get; set; } public Action Resized { get; set; } - - public Action Activated { get { return _tl.Activated; } @@ -151,6 +149,12 @@ namespace Perspex.Controls.Platform set { _tl.Deactivated = value; } } + public Action ScalingChanged + { + get { return _tl.ScalingChanged; } + set { _tl.ScalingChanged = value; } + } + public void Dispose() => _tl.Dispose(); public IPlatformHandle Handle => _tl.Handle; diff --git a/src/Perspex.Controls/TopLevel.cs b/src/Perspex.Controls/TopLevel.cs index 92cc25f51a..3f02f73bc3 100644 --- a/src/Perspex.Controls/TopLevel.cs +++ b/src/Perspex.Controls/TopLevel.cs @@ -12,6 +12,7 @@ using Perspex.Layout; using Perspex.Platform; using Perspex.Rendering; using Perspex.Styling; +using Perspex.VisualTree; namespace Perspex.Controls { @@ -99,6 +100,7 @@ namespace Perspex.Controls PlatformImpl.Closed = HandleClosed; PlatformImpl.Input = HandleInput; PlatformImpl.Resized = HandleResized; + PlatformImpl.ScalingChanged = HandleScalingChanged; _keyboardNavigationHandler?.SetOwner(this); _accessKeyHandler?.SetOwner(this); @@ -280,6 +282,19 @@ namespace Perspex.Controls PlatformImpl.Invalidate(new Rect(clientSize)); } + /// + /// Handles a window scaling change notification from + /// . + /// + /// The window scaling. + protected virtual void HandleScalingChanged(double scaling) + { + foreach (ILayoutable control in this.GetSelfAndVisualDescendents()) + { + control.InvalidateMeasure(); + } + } + /// protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) { diff --git a/src/Windows/Perspex.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Perspex.Win32/Interop/UnmanagedMethods.cs index e75174012f..5e50f35feb 100644 --- a/src/Windows/Perspex.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Perspex.Win32/Interop/UnmanagedMethods.cs @@ -489,6 +489,7 @@ namespace Perspex.Win32.Interop WM_WTSSESSION_CHANGE = 0x02B1, WM_TABLET_FIRST = 0x02c0, WM_TABLET_LAST = 0x02df, + WM_DPICHANGED = 0x02E0, WM_CUT = 0x0300, WM_COPY = 0x0301, WM_PASTE = 0x0302, diff --git a/src/Windows/Perspex.Win32/WindowImpl.cs b/src/Windows/Perspex.Win32/WindowImpl.cs index e16c5991f8..d0b7dd1158 100644 --- a/src/Windows/Perspex.Win32/WindowImpl.cs +++ b/src/Windows/Perspex.Win32/WindowImpl.cs @@ -52,6 +52,8 @@ namespace Perspex.Win32 public Action Resized { get; set; } + public Action ScalingChanged { get; set; } + public Thickness BorderThickness { get @@ -359,6 +361,12 @@ namespace Perspex.Win32 return IntPtr.Zero; + case UnmanagedMethods.WindowsMessage.WM_DPICHANGED: + var dpi = (int)wParam & 0xffff; + _scaling = dpi / 96.0; + ScalingChanged?.Invoke(_scaling); + break; + case UnmanagedMethods.WindowsMessage.WM_KEYDOWN: case UnmanagedMethods.WindowsMessage.WM_SYSKEYDOWN: e = new RawKeyEventArgs(