Skip to content

Commit

Permalink
feat: Add Win32Properties.WindowCornerHintProperty attached property
Browse files Browse the repository at this point in the history
  • Loading branch information
BAndysc committed Oct 28, 2024
1 parent 0944e04 commit a996eda
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 12 deletions.
5 changes: 5 additions & 0 deletions src/Avalonia.Controls/Platform/IWin32OptionsTopLevelImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,10 @@ public interface IWin32OptionsTopLevelImpl : ITopLevelImpl
/// Gets or sets a custom callback for the window's WndProc
/// </summary>
public CustomWndProcHookCallback? WndProcHookCallback { get; set; }

/// <summary>
/// Sets hints that configure the shape of window corners.
/// </summary>
void SetWindowCornerHints(Win32WindowCornerHints hints);
}
}
30 changes: 30 additions & 0 deletions src/Avalonia.Controls/Platform/Win32CornerHints.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;

namespace Avalonia.Platform;

/// <summary>
/// Specifies hints for window corner appearance.
/// </summary>
[Flags]
public enum Win32WindowCornerHints
{
/// <summary>
/// Default Avalonia behavior.
/// </summary>
NoHint,

/// <summary>
/// The platform's default corner style.
/// </summary>
PlatformDefault,

/// <summary>
/// Rounded corners for the window.
/// </summary>
Rounded,

/// <summary>
/// Prevents corners from being rounded.
/// </summary>
DoNotRound
}
17 changes: 17 additions & 0 deletions src/Avalonia.Controls/Platform/Win32Properties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ namespace Avalonia.Controls
/// </summary>
public static class Win32Properties
{
public static readonly AttachedProperty<Win32WindowCornerHints> WindowCornerHintProperty =
AvaloniaProperty.RegisterAttached<Win32Properties, Window, Win32WindowCornerHints>("WindowCornerHint");

public static void SetWindowCornerHint(Window obj, Win32WindowCornerHints value) => obj.SetValue(WindowCornerHintProperty, value);
public static Win32WindowCornerHints GetWindowCornerHint(Window obj) => obj.GetValue(WindowCornerHintProperty);

public delegate (uint style, uint exStyle) CustomWindowStylesCallback(uint style, uint exStyle);
public delegate IntPtr CustomWndProcHookCallback(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam, ref bool handled);

Expand Down Expand Up @@ -70,5 +76,16 @@ public static void RemoveWndProcHookCallback(TopLevel topLevel, CustomWndProcHoo
toplevelImpl.WndProcHookCallback -= callback;
}
}

static Win32Properties()
{
WindowCornerHintProperty.Changed.AddClassHandler<Window>((window, e) =>
{
if (window.PlatformImpl is IWin32OptionsTopLevelImpl toplevelImpl)
{
toplevelImpl.SetWindowCornerHints(e.GetNewValue<Win32WindowCornerHints>());
}
});
}
}
}
47 changes: 35 additions & 12 deletions src/Windows/Avalonia.Win32/WindowImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ internal partial class WindowImpl : IWindowImpl, EglGlPlatformSurface.IEglWindow
private POINT _maxTrackSize;
private WindowImpl? _parent;
private ExtendClientAreaChromeHints _extendChromeHints = ExtendClientAreaChromeHints.Default;
private Win32WindowCornerHints _cornerHints;
private bool _isCloseRequested;
private bool _shown;
private bool _hiddenWindowIsParent;
Expand Down Expand Up @@ -1133,6 +1134,30 @@ private MARGINS UpdateExtendMargins()
return margins;
}

private static DwmWindowCornerPreference HintsToCornerPreference(Win32WindowCornerHints cornerHints, DwmWindowCornerPreference noHintDefault)
{
return cornerHints switch
{
Win32WindowCornerHints.NoHint => noHintDefault,
Win32WindowCornerHints.PlatformDefault => DwmWindowCornerPreference.DWMWCP_DEFAULT,
Win32WindowCornerHints.Rounded => DwmWindowCornerPreference.DWMWCP_ROUND,
Win32WindowCornerHints.DoNotRound => DwmWindowCornerPreference.DWMWCP_DONOTROUND,
_ => throw new ArgumentOutOfRangeException(nameof(cornerHints), cornerHints, null)
};
}

private void UpdateWindowCornerPreference()
{
int cornerPreference = (int)HintsToCornerPreference(_cornerHints,
_isClientAreaExtended && WindowState != WindowState.FullScreen ?
DwmWindowCornerPreference.DWMWCP_ROUND :
DwmWindowCornerPreference.DWMWCP_DEFAULT);
unsafe
{
DwmSetWindowAttribute(_hwnd, (int)DwmWindowAttribute.DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPreference, sizeof(int));
}
}

private void ExtendClientArea()
{
if (!_shown)
Expand All @@ -1151,12 +1176,6 @@ private void ExtendClientArea()
{
var margins = UpdateExtendMargins();
DwmExtendFrameIntoClientArea(_hwnd, ref margins);

unsafe
{
int cornerPreference = (int)DwmWindowCornerPreference.DWMWCP_ROUND;
DwmSetWindowAttribute(_hwnd, (int)DwmWindowAttribute.DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPreference, sizeof(int));
}
}
else
{
Expand All @@ -1165,14 +1184,10 @@ private void ExtendClientArea()

_offScreenMargin = new Thickness();
_extendedMargins = new Thickness();

unsafe
{
int cornerPreference = (int)DwmWindowCornerPreference.DWMWCP_DEFAULT;
DwmSetWindowAttribute(_hwnd, (int)DwmWindowAttribute.DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPreference, sizeof(int));
}
}

UpdateWindowCornerPreference();

if (!_isClientAreaExtended || (_extendChromeHints.HasAllFlags(ExtendClientAreaChromeHints.SystemChrome) &&
!_extendChromeHints.HasAllFlags(ExtendClientAreaChromeHints.PreferSystemChrome)))
{
Expand Down Expand Up @@ -1592,6 +1607,14 @@ public void SetExtendClientAreaTitleBarHeightHint(double titleBarHeight)
ExtendClientArea();
}

/// <inheritdoc/>
public void SetWindowCornerHints(Win32WindowCornerHints hints)
{
_cornerHints = hints;

UpdateWindowCornerPreference();
}

/// <inheritdoc/>
public void GetWindowsZOrder(Span<Window> windows, Span<long> zOrder)
{
Expand Down

0 comments on commit a996eda

Please sign in to comment.