diff --git a/src/Avalonia.Controls/Platform/IWindowImpl.cs b/src/Avalonia.Controls/Platform/IWindowImpl.cs index d7bf93a603..999f4f4201 100644 --- a/src/Avalonia.Controls/Platform/IWindowImpl.cs +++ b/src/Avalonia.Controls/Platform/IWindowImpl.cs @@ -104,5 +104,7 @@ namespace Avalonia.Platform Action ExtendClientAreaToDecorationsChanged { get; set; } Thickness ExtendedMargins { get; } + + Thickness OffScreenMargin { get; } } } diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 85935d3d2a..54e2fbb629 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -113,7 +113,11 @@ namespace Avalonia.Controls public static readonly DirectProperty WindowDecorationMarginsProperty = AvaloniaProperty.RegisterDirect(nameof(WindowDecorationMargins), o => o.WindowDecorationMargins); - + + public static readonly DirectProperty OffScreenMarginProperty = + AvaloniaProperty.RegisterDirect(nameof(OffScreenMargin), + o => o.OffScreenMargin); + /// /// Defines the property. @@ -304,6 +308,14 @@ namespace Avalonia.Controls private set => SetAndRaise(WindowDecorationMarginsProperty, ref _windowDecorationMargins, value); } + private Thickness _offScreenMargin; + + public Thickness OffScreenMargin + { + get => _offScreenMargin; + private set => SetAndRaise(OffScreenMarginProperty, ref _offScreenMargin, value); + } + /// /// Sets the system decorations (title bar, border, etc) /// @@ -507,6 +519,8 @@ namespace Avalonia.Controls IsExtendedIntoWindowDecorations = isExtended; WindowDecorationMargins = PlatformImpl.ExtendedMargins; + + OffScreenMargin = PlatformImpl.OffScreenMargin; } /// diff --git a/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs b/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs index 06c7ac6411..da7cbf815a 100644 --- a/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs +++ b/src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs @@ -91,6 +91,8 @@ namespace Avalonia.DesignerSupport.Remote public bool IsClientAreaExtendedToDecorations { get; } + public Thickness OffScreenMargin { get; } = new Thickness(); + public void Activate() { } diff --git a/src/Avalonia.DesignerSupport/Remote/Stubs.cs b/src/Avalonia.DesignerSupport/Remote/Stubs.cs index 6f5a0e6051..6859c408dd 100644 --- a/src/Avalonia.DesignerSupport/Remote/Stubs.cs +++ b/src/Avalonia.DesignerSupport/Remote/Stubs.cs @@ -43,6 +43,8 @@ namespace Avalonia.DesignerSupport.Remote public Thickness ExtendedMargins { get; } = new Thickness(); + public Thickness OffScreenMargin { get; } = new Thickness(); + public WindowStub(IWindowImpl parent = null) { if (parent != null) diff --git a/src/Avalonia.Native/WindowImpl.cs b/src/Avalonia.Native/WindowImpl.cs index 47c8291803..cbea340246 100644 --- a/src/Avalonia.Native/WindowImpl.cs +++ b/src/Avalonia.Native/WindowImpl.cs @@ -102,6 +102,8 @@ namespace Avalonia.Native public Thickness ExtendedMargins { get; } = new Thickness(); + public Thickness OffScreenMargin { get; } = new Thickness(); + public bool IsClientAreaExtendedToDecorations { get; } public void SetExtendClientAreaToDecorationsHint(bool extendIntoClientAreaHint) diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index d64f993299..086863796c 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -315,6 +315,8 @@ namespace Avalonia.X11 public Thickness ExtendedMargins { get; } = new Thickness(); + public Thickness OffScreenMargin { get; } = new Thickness(); + public bool IsClientAreaExtendedToDecorations { get; } public Action Closed { get; set; } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index b81634dce0..0c2160de2b 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -374,6 +374,11 @@ namespace Avalonia.Win32 if (windowState != _lastWindowState) { _lastWindowState = windowState; + + UpdateExtendMargins(); + + ExtendClientAreaToDecorationsChanged?.Invoke(true); + WindowStateChanged?.Invoke(windowState); } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 7c720b5612..fd7084ea29 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -42,7 +42,8 @@ namespace Avalonia.Win32 private bool _isFullScreenActive; private bool _isClientAreaExtended; private Thickness _extendedMargins; - + private Thickness _offScreenMargin; + #if USE_MANAGED_DRAG private readonly ManagedWindowResizeDragHelper _managedDrag; #endif @@ -667,6 +668,37 @@ namespace Avalonia.Win32 TaskBarList.MarkFullscreen(_hwnd, fullscreen); } + private MARGINS UpdateExtendMargins() + { + RECT borderThickness = new RECT(); + RECT borderCaptionThickness = new RECT(); + + AdjustWindowRectEx(ref borderCaptionThickness, (uint)(GetStyle()), false, 0); + AdjustWindowRectEx(ref borderThickness, (uint)(GetStyle() & ~WindowStyles.WS_CAPTION), false, 0); + borderThickness.left *= -1; + borderThickness.top *= -1; + borderCaptionThickness.left *= -1; + borderCaptionThickness.top *= -1; + + _extendedMargins = new Thickness(1 / Scaling, borderCaptionThickness.top / Scaling, 1 / Scaling, 1 / Scaling); + + if (WindowState == WindowState.Maximized) + { + _offScreenMargin = new Thickness(borderThickness.left / Scaling, borderThickness.top / Scaling, borderThickness.right / Scaling, borderThickness.bottom / Scaling); + } + else + { + _offScreenMargin = new Thickness(); + } + + MARGINS margins = new MARGINS(); + margins.cxLeftWidth = 1; + margins.cxRightWidth = 1; + margins.cyBottomHeight = 1; + margins.cyTopHeight = borderThickness.top; + return margins; + } + private void ExtendClientArea (ExtendClientAreaChromeHints hints) { if (!_isClientAreaExtended) @@ -1010,6 +1042,8 @@ namespace Avalonia.Win32 public Thickness ExtendedMargins => _extendedMargins; + public Thickness OffScreenMargin => _offScreenMargin; + private struct SavedWindowInfo { public WindowStyles Style { get; set; }