diff --git a/src/Gtk/Perspex.Gtk/WindowImpl.cs b/src/Gtk/Perspex.Gtk/WindowImpl.cs index 2e5da0c42f..ba9964165e 100644 --- a/src/Gtk/Perspex.Gtk/WindowImpl.cs +++ b/src/Gtk/Perspex.Gtk/WindowImpl.cs @@ -57,6 +57,16 @@ namespace Perspex.Gtk set; } + public Size MaxClientSize + { + get + { + // TODO: This should take into account things such as taskbar and window border + // thickness etc. + return new Size(Screen.Width, Screen.Height); + } + } + IPlatformHandle ITopLevelImpl.Handle => _windowHandle; public Action Activated { get; set; } diff --git a/src/Perspex.Controls/Platform/IWindowImpl.cs b/src/Perspex.Controls/Platform/IWindowImpl.cs index 934daa01a6..58ef5281b0 100644 --- a/src/Perspex.Controls/Platform/IWindowImpl.cs +++ b/src/Perspex.Controls/Platform/IWindowImpl.cs @@ -10,6 +10,11 @@ namespace Perspex.Platform /// public interface IWindowImpl : ITopLevelImpl { + /// + /// Gets the maximum size of a window on the system. + /// + Size MaxClientSize { get; } + /// /// Sets the title of the window. /// diff --git a/src/Perspex.Controls/Window.cs b/src/Perspex.Controls/Window.cs index e3934ad097..fb3fee2587 100644 --- a/src/Perspex.Controls/Window.cs +++ b/src/Perspex.Controls/Window.cs @@ -57,6 +57,8 @@ namespace Perspex.Controls private object _dialogResult; + private Size _maxPlatformClientSize; + /// /// Initializes static members of the class. /// @@ -72,6 +74,7 @@ namespace Perspex.Controls public Window() : base(Locator.Current.GetService()) { + _maxPlatformClientSize = this.PlatformImpl.MaxClientSize; } /// @@ -193,7 +196,7 @@ namespace Perspex.Controls { var sizeToContent = SizeToContent; var size = ClientSize; - var desired = base.MeasureOverride(availableSize); + var desired = base.MeasureOverride(availableSize.Constrain(_maxPlatformClientSize)); switch (sizeToContent) { diff --git a/src/Perspex.SceneGraph/Thickness.cs b/src/Perspex.SceneGraph/Thickness.cs index 9861342e2b..693dd97340 100644 --- a/src/Perspex.SceneGraph/Thickness.cs +++ b/src/Perspex.SceneGraph/Thickness.cs @@ -138,6 +138,32 @@ namespace Perspex a.Bottom + b.Bottom); } + /// + /// Adds a Thickness to a Size. + /// + /// The size. + /// The thickness. + /// The equality. + public static Size operator +(Size size, Thickness thickness) + { + return new Size( + size.Width + thickness.Left + thickness.Right, + size.Height + thickness.Top + thickness.Bottom); + } + + /// + /// Subtracts a Thickness from a Size. + /// + /// The size. + /// The thickness. + /// The equality. + public static Size operator -(Size size, Thickness thickness) + { + return new Size( + size.Width - (thickness.Left + thickness.Right), + size.Height - (thickness.Top + thickness.Bottom)); + } + /// /// Parses a string. /// diff --git a/src/Windows/Perspex.Win32/WindowImpl.cs b/src/Windows/Perspex.Win32/WindowImpl.cs index 75a03b832f..4c9847087d 100644 --- a/src/Windows/Perspex.Win32/WindowImpl.cs +++ b/src/Windows/Perspex.Win32/WindowImpl.cs @@ -53,6 +53,25 @@ namespace Perspex.Win32 public Action Resized { get; set; } + public Thickness BorderThickness + { + get + { + var style = UnmanagedMethods.GetWindowLong(_hwnd, -16); + var exStyle = UnmanagedMethods.GetWindowLong(_hwnd, -20); + var padding = new UnmanagedMethods.RECT(); + + if (UnmanagedMethods.AdjustWindowRectEx(ref padding, style, false, exStyle)) + { + return new Thickness(-padding.left, -padding.top, padding.right, padding.bottom); + } + else + { + throw new Win32Exception(); + } + } + } + public Size ClientSize { get @@ -66,21 +85,16 @@ namespace Perspex.Win32 { if (value != ClientSize) { - var style = UnmanagedMethods.GetWindowLong(_hwnd, -16); - var exStyle = UnmanagedMethods.GetWindowLong(_hwnd, -20); - var padding = new UnmanagedMethods.RECT(); - - if (UnmanagedMethods.AdjustWindowRectEx(ref padding, style, false, exStyle)) - { - UnmanagedMethods.SetWindowPos( - _hwnd, - IntPtr.Zero, - 0, - 0, - -padding.left + padding.right + (int)value.Width, - -padding.top + padding.bottom + (int)value.Height, - UnmanagedMethods.SetWindowPosFlags.SWP_RESIZE); - } + value += BorderThickness; + + UnmanagedMethods.SetWindowPos( + _hwnd, + IntPtr.Zero, + 0, + 0, + (int)value.Width, + (int)value.Height, + UnmanagedMethods.SetWindowPosFlags.SWP_RESIZE); } } } @@ -97,6 +111,17 @@ namespace Perspex.Win32 set { UnmanagedMethods.EnableWindow(_hwnd, value); } } + public Size MaxClientSize + { + get + { + return new Size( + UnmanagedMethods.GetSystemMetrics(UnmanagedMethods.SystemMetric.SM_CXMAXTRACK), + UnmanagedMethods.GetSystemMetrics(UnmanagedMethods.SystemMetric.SM_CYMAXTRACK)) + - BorderThickness; + } + } + public void Activate() { UnmanagedMethods.SetActiveWindow(_hwnd);