|
|
@@ -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));
|
|
|
}
|
|
|
}
|
|
|
|