|
|
|
@ -1,4 +1,4 @@ |
|
|
|
using System; |
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.ComponentModel; |
|
|
|
using System.Diagnostics.CodeAnalysis; |
|
|
|
@ -25,6 +25,7 @@ using Avalonia.Win32.WinRT.Composition; |
|
|
|
using Avalonia.Win32.WinRT; |
|
|
|
using static Avalonia.Win32.Interop.UnmanagedMethods; |
|
|
|
using Avalonia.Input.Platform; |
|
|
|
using System.Diagnostics; |
|
|
|
|
|
|
|
namespace Avalonia.Win32 |
|
|
|
{ |
|
|
|
@ -346,82 +347,119 @@ namespace Avalonia.Win32 |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) |
|
|
|
public void SetTransparencyLevelHint(IReadOnlyList<WindowTransparencyLevel> transparencyLevels) |
|
|
|
{ |
|
|
|
TransparencyLevel = EnableBlur(transparencyLevel); |
|
|
|
} |
|
|
|
var windowsVersion = Win32Platform.WindowsVersion; |
|
|
|
|
|
|
|
private WindowTransparencyLevel EnableBlur(WindowTransparencyLevel transparencyLevel) |
|
|
|
{ |
|
|
|
if (Win32Platform.WindowsVersion.Major >= 6) |
|
|
|
{ |
|
|
|
if (DwmIsCompositionEnabled(out var compositionEnabled) != 0 || !compositionEnabled) |
|
|
|
{ |
|
|
|
return WindowTransparencyLevel.None; |
|
|
|
} |
|
|
|
else if (Win32Platform.WindowsVersion.Major >= 10) |
|
|
|
{ |
|
|
|
return Win10EnableBlur(transparencyLevel); |
|
|
|
} |
|
|
|
else if (Win32Platform.WindowsVersion.Minor >= 2) |
|
|
|
{ |
|
|
|
return Win8xEnableBlur(transparencyLevel); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
return Win7EnableBlur(transparencyLevel); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
foreach (var level in transparencyLevels) |
|
|
|
{ |
|
|
|
return WindowTransparencyLevel.None; |
|
|
|
if (!IsSupported(level, windowsVersion)) |
|
|
|
continue; |
|
|
|
|
|
|
|
if (level == WindowTransparencyLevel.Transparent) |
|
|
|
SetTransparencyTransparent(windowsVersion); |
|
|
|
else if (level == WindowTransparencyLevel.Blur) |
|
|
|
SetTransparencyBlur(windowsVersion); |
|
|
|
else if (level == WindowTransparencyLevel.AcrylicBlur) |
|
|
|
SetTransparencyAcrylicBlur(windowsVersion); |
|
|
|
else if (level == WindowTransparencyLevel.Mica) |
|
|
|
SetTransparencyMica(windowsVersion); |
|
|
|
|
|
|
|
TransparencyLevel = level; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private WindowTransparencyLevel Win7EnableBlur(WindowTransparencyLevel transparencyLevel) |
|
|
|
private bool IsSupported(WindowTransparencyLevel level, Version windowsVersion) |
|
|
|
{ |
|
|
|
if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur) |
|
|
|
{ |
|
|
|
transparencyLevel = WindowTransparencyLevel.Blur; |
|
|
|
} |
|
|
|
// Only None is suppported when composition is disabled.
|
|
|
|
if (!_isUsingComposition) |
|
|
|
return level == WindowTransparencyLevel.None; |
|
|
|
|
|
|
|
// When composition is enabled, None is not supported because the backing visual always
|
|
|
|
// has an alpha channel
|
|
|
|
if (level == WindowTransparencyLevel.None) |
|
|
|
return false; |
|
|
|
|
|
|
|
// Transparent only supported on Windows 8+.
|
|
|
|
if (level == WindowTransparencyLevel.Transparent) |
|
|
|
return windowsVersion >= PlatformConstants.Windows8; |
|
|
|
|
|
|
|
// Blur only supported on Windows 8 and lower.
|
|
|
|
if (level == WindowTransparencyLevel.Blur) |
|
|
|
return windowsVersion < PlatformConstants.Windows10; |
|
|
|
|
|
|
|
// Acrylic is supported on Windows >= 10.0.15063.
|
|
|
|
if (level == WindowTransparencyLevel.AcrylicBlur) |
|
|
|
return windowsVersion >= WinUiCompositionShared.MinAcrylicVersion; |
|
|
|
|
|
|
|
var blurInfo = new DWM_BLURBEHIND(false); |
|
|
|
// Mica is supported on Windows >= 10.0.22000.
|
|
|
|
if (level == WindowTransparencyLevel.Mica) |
|
|
|
return windowsVersion >= WinUiCompositionShared.MinHostBackdropVersion; |
|
|
|
|
|
|
|
if (transparencyLevel == WindowTransparencyLevel.Blur) |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
private void SetTransparencyTransparent(Version windowsVersion) |
|
|
|
{ |
|
|
|
// Transparent only supported with composition on Windows 8+.
|
|
|
|
if (!_isUsingComposition || windowsVersion < PlatformConstants.Windows8) |
|
|
|
return; |
|
|
|
|
|
|
|
if (windowsVersion < PlatformConstants.Windows10) |
|
|
|
{ |
|
|
|
blurInfo = new DWM_BLURBEHIND(true); |
|
|
|
// Some of the AccentState Enum's values have different meanings on Windows 8.x than on
|
|
|
|
// Windows 10, hence using ACCENT_ENABLE_BLURBEHIND to disable blurbehind ¯\_(ツ)_/¯.
|
|
|
|
// Hey, I'm just porting what was here before.
|
|
|
|
SetAccentState(AccentState.ACCENT_ENABLE_BLURBEHIND); |
|
|
|
var blurInfo = new DWM_BLURBEHIND(false); |
|
|
|
DwmEnableBlurBehindWindow(_hwnd, ref blurInfo); |
|
|
|
} |
|
|
|
|
|
|
|
SetUseHostBackdropBrush(false); |
|
|
|
_blurHost?.SetBlur(BlurEffect.None); |
|
|
|
} |
|
|
|
|
|
|
|
private void SetTransparencyBlur(Version windowsVersion) |
|
|
|
{ |
|
|
|
// Blur only supported with composition on Windows 8 and lower.
|
|
|
|
if (!_isUsingComposition || windowsVersion >= PlatformConstants.Windows10) |
|
|
|
return; |
|
|
|
|
|
|
|
// Some of the AccentState Enum's values have different meanings on Windows 8.x than on
|
|
|
|
// Windows 10.
|
|
|
|
SetAccentState(AccentState.ACCENT_DISABLED); |
|
|
|
var blurInfo = new DWM_BLURBEHIND(true); |
|
|
|
DwmEnableBlurBehindWindow(_hwnd, ref blurInfo); |
|
|
|
} |
|
|
|
|
|
|
|
if (transparencyLevel == WindowTransparencyLevel.Transparent) |
|
|
|
{ |
|
|
|
return WindowTransparencyLevel.None; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
return transparencyLevel; |
|
|
|
} |
|
|
|
private void SetTransparencyAcrylicBlur(Version windowsVersion) |
|
|
|
{ |
|
|
|
// Acrylic blur only supported with composition on Windows >= 10.0.15063.
|
|
|
|
if (!_isUsingComposition || windowsVersion < WinUiCompositionShared.MinAcrylicVersion) |
|
|
|
return; |
|
|
|
|
|
|
|
SetUseHostBackdropBrush(true); |
|
|
|
_blurHost?.SetBlur(BlurEffect.Acrylic); |
|
|
|
} |
|
|
|
|
|
|
|
private WindowTransparencyLevel Win8xEnableBlur(WindowTransparencyLevel transparencyLevel) |
|
|
|
private void SetTransparencyMica(Version windowsVersion) |
|
|
|
{ |
|
|
|
var accent = new AccentPolicy(); |
|
|
|
var accentStructSize = Marshal.SizeOf<AccentPolicy>(); |
|
|
|
// Mica only supported with composition on Windows >= 10.0.22000.
|
|
|
|
if (!_isUsingComposition || windowsVersion < WinUiCompositionShared.MinHostBackdropVersion) |
|
|
|
return; |
|
|
|
|
|
|
|
if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur) |
|
|
|
{ |
|
|
|
transparencyLevel = WindowTransparencyLevel.Blur; |
|
|
|
} |
|
|
|
SetUseHostBackdropBrush(false); |
|
|
|
_blurHost?.SetBlur(BlurEffect.Mica); |
|
|
|
} |
|
|
|
|
|
|
|
if (transparencyLevel == WindowTransparencyLevel.Transparent) |
|
|
|
{ |
|
|
|
accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
accent.AccentState = AccentState.ACCENT_DISABLED; |
|
|
|
} |
|
|
|
private void SetAccentState(AccentState state) |
|
|
|
{ |
|
|
|
var accent = new AccentPolicy(); |
|
|
|
var accentStructSize = Marshal.SizeOf(accent); |
|
|
|
|
|
|
|
//Some of the AccentState Enum's values have different meanings on Windows 8.x than on Windows 10
|
|
|
|
accent.AccentState = state; |
|
|
|
|
|
|
|
var accentPtr = Marshal.AllocHGlobal(accentStructSize); |
|
|
|
Marshal.StructureToPtr(accent, accentPtr, false); |
|
|
|
@ -432,96 +470,18 @@ namespace Avalonia.Win32 |
|
|
|
data.Data = accentPtr; |
|
|
|
|
|
|
|
SetWindowCompositionAttribute(_hwnd, ref data); |
|
|
|
|
|
|
|
Marshal.FreeHGlobal(accentPtr); |
|
|
|
|
|
|
|
if (transparencyLevel == WindowTransparencyLevel.Blur || |
|
|
|
transparencyLevel == WindowTransparencyLevel.AcrylicBlur || |
|
|
|
transparencyLevel == WindowTransparencyLevel.Mica) |
|
|
|
{ |
|
|
|
Win7EnableBlur(transparencyLevel); |
|
|
|
} |
|
|
|
|
|
|
|
return transparencyLevel; |
|
|
|
} |
|
|
|
|
|
|
|
private WindowTransparencyLevel Win10EnableBlur(WindowTransparencyLevel transparencyLevel) |
|
|
|
private void SetUseHostBackdropBrush(bool useHostBackdropBrush) |
|
|
|
{ |
|
|
|
if (_isUsingComposition) |
|
|
|
{ |
|
|
|
BlurEffect effect; |
|
|
|
|
|
|
|
if (transparencyLevel == WindowTransparencyLevel.Mica) |
|
|
|
effect = BlurEffect.Mica; |
|
|
|
else if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur) |
|
|
|
effect = BlurEffect.Acrylic; |
|
|
|
else |
|
|
|
effect = BlurEffect.None; |
|
|
|
|
|
|
|
if (Win32Platform.WindowsVersion >= WinUiCompositionShared.MinHostBackdropVersion) |
|
|
|
{ |
|
|
|
unsafe |
|
|
|
{ |
|
|
|
int pvUseBackdropBrush = effect == BlurEffect.Acrylic ? 1 : 0; |
|
|
|
DwmSetWindowAttribute(_hwnd, (int)DwmWindowAttribute.DWMWA_USE_HOSTBACKDROPBRUSH, &pvUseBackdropBrush, sizeof(int)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (Win32Platform.WindowsVersion < WinUiCompositionShared.MinHostBackdropVersion && effect == BlurEffect.Mica) |
|
|
|
{ |
|
|
|
effect = BlurEffect.Acrylic; |
|
|
|
} |
|
|
|
|
|
|
|
_blurHost?.SetBlur(effect); |
|
|
|
if (Win32Platform.WindowsVersion < WinUiCompositionShared.MinHostBackdropVersion) |
|
|
|
return; |
|
|
|
|
|
|
|
return transparencyLevel; |
|
|
|
} |
|
|
|
else |
|
|
|
unsafe |
|
|
|
{ |
|
|
|
bool canUseAcrylic = Win32Platform.WindowsVersion.Major > 10 || Win32Platform.WindowsVersion.Build >= 19628; |
|
|
|
|
|
|
|
var accent = new AccentPolicy(); |
|
|
|
var accentStructSize = Marshal.SizeOf<AccentPolicy>(); |
|
|
|
|
|
|
|
if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur && !canUseAcrylic) |
|
|
|
{ |
|
|
|
transparencyLevel = WindowTransparencyLevel.Blur; |
|
|
|
} |
|
|
|
|
|
|
|
if (transparencyLevel == WindowTransparencyLevel.Transparent) |
|
|
|
{ |
|
|
|
accent.AccentState = AccentState.ACCENT_ENABLE_TRANSPARENTGRADIENT; |
|
|
|
} |
|
|
|
else if (transparencyLevel == WindowTransparencyLevel.Blur) |
|
|
|
{ |
|
|
|
accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND; |
|
|
|
} |
|
|
|
else if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur || transparencyLevel == WindowTransparencyLevel.Mica) |
|
|
|
{ |
|
|
|
accent.AccentState = AccentState.ACCENT_ENABLE_ACRYLIC; |
|
|
|
transparencyLevel = WindowTransparencyLevel.AcrylicBlur; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
accent.AccentState = AccentState.ACCENT_DISABLED; |
|
|
|
} |
|
|
|
|
|
|
|
accent.AccentFlags = 2; |
|
|
|
accent.GradientColor = 0x01000000; |
|
|
|
|
|
|
|
var accentPtr = Marshal.AllocHGlobal(accentStructSize); |
|
|
|
Marshal.StructureToPtr(accent, accentPtr, false); |
|
|
|
|
|
|
|
var data = new WindowCompositionAttributeData(); |
|
|
|
data.Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY; |
|
|
|
data.SizeOfData = accentStructSize; |
|
|
|
data.Data = accentPtr; |
|
|
|
|
|
|
|
SetWindowCompositionAttribute(_hwnd, ref data); |
|
|
|
|
|
|
|
Marshal.FreeHGlobal(accentPtr); |
|
|
|
|
|
|
|
return transparencyLevel; |
|
|
|
var pvUseBackdropBrush = useHostBackdropBrush ? 1 : 0; |
|
|
|
DwmSetWindowAttribute(_hwnd, (int)DwmWindowAttribute.DWMWA_USE_HOSTBACKDROPBRUSH, &pvUseBackdropBrush, sizeof(int)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|