From 8845f239b609c2b0c22e286902499beb10f70c2c Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 24 May 2023 13:54:12 +0200 Subject: [PATCH] Implement transparency level hint list on win32. Other backends have the relevant code commented-out still. --- .../Platform/SkiaPlatform/TopLevelImpl.cs | 168 ++++++------ .../Offscreen/OffscreenTopLevelImpl.cs | 2 +- .../Platform/ITopLevelImpl.cs | 2 +- src/Avalonia.Controls/TopLevel.cs | 4 +- src/Avalonia.DesignerSupport/Remote/Stubs.cs | 2 +- src/Avalonia.Native/WindowImplBase.cs | 42 +-- src/Avalonia.X11/X11Window.cs | 6 +- .../Avalonia.Browser/BrowserTopLevelImpl.cs | 12 +- .../Avalonia.Headless/HeadlessWindowImpl.cs | 2 +- .../FramebufferToplevelImpl.cs | 2 +- .../Wpf/WpfTopLevelImpl.cs | 2 +- .../Avalonia.Win32/PlatformConstants.cs | 7 +- .../Composition/WinUiCompositionShared.cs | 1 + src/Windows/Avalonia.Win32/WindowImpl.cs | 244 ++++++++---------- src/iOS/Avalonia.iOS/AvaloniaView.cs | 2 +- .../CompositorTestServices.cs | 2 +- 16 files changed, 232 insertions(+), 268 deletions(-) diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs index 609b6cd519..144e2d843a 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs @@ -299,91 +299,91 @@ namespace Avalonia.Android.Platform.SkiaPlatform public double Scaling => RenderScaling; - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { - if (TransparencyLevel != transparencyLevel) - { - bool isBelowR = Build.VERSION.SdkInt < BuildVersionCodes.R; - bool isAboveR = Build.VERSION.SdkInt > BuildVersionCodes.R; - if (_view.Context is AvaloniaMainActivity activity) - { - if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur || - transparencyLevel == WindowTransparencyLevel.Mica || - transparencyLevel == WindowTransparencyLevel.None) - { - if (!isBelowR) - { - activity.SetTranslucent(false); - } - if (isAboveR) - { - activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); - - var attr = activity.Window?.Attributes; - if (attr != null) - { - attr.BlurBehindRadius = 0; - - activity.Window.Attributes = attr; - } - } - activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White)); - - if (transparencyLevel != WindowTransparencyLevel.None) - { - return; - } - } - - if (transparencyLevel == WindowTransparencyLevel.Transparent) - { - if (!isBelowR) - { - activity.SetTranslucent(true); - } - if (isAboveR) - { - activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); - - var attr = activity.Window?.Attributes; - if (attr != null) - { - attr.BlurBehindRadius = 0; - - activity.Window.Attributes = attr; - } - } - activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); - } - - if (transparencyLevel == WindowTransparencyLevel.Blur) - { - if (isAboveR) - { - activity.SetTranslucent(true); - activity.Window?.AddFlags(WindowManagerFlags.BlurBehind); - - var attr = activity.Window?.Attributes; - if (attr != null) - { - attr.BlurBehindRadius = 120; - - activity.Window.Attributes = attr; - } - activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); - } - else - { - activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); - activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White)); - - return; - } - } - - TransparencyLevel = transparencyLevel; - } - } + ////if (TransparencyLevel != transparencyLevel) + ////{ + //// bool isBelowR = Build.VERSION.SdkInt < BuildVersionCodes.R; + //// bool isAboveR = Build.VERSION.SdkInt > BuildVersionCodes.R; + //// if (_view.Context is AvaloniaMainActivity activity) + //// { + //// if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur || + //// transparencyLevel == WindowTransparencyLevel.Mica || + //// transparencyLevel == WindowTransparencyLevel.None) + //// { + //// if (!isBelowR) + //// { + //// activity.SetTranslucent(false); + //// } + //// if (isAboveR) + //// { + //// activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); + + //// var attr = activity.Window?.Attributes; + //// if (attr != null) + //// { + //// attr.BlurBehindRadius = 0; + + //// activity.Window.Attributes = attr; + //// } + //// } + //// activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White)); + + //// if (transparencyLevel != WindowTransparencyLevel.None) + //// { + //// return; + //// } + //// } + + //// if (transparencyLevel == WindowTransparencyLevel.Transparent) + //// { + //// if (!isBelowR) + //// { + //// activity.SetTranslucent(true); + //// } + //// if (isAboveR) + //// { + //// activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); + + //// var attr = activity.Window?.Attributes; + //// if (attr != null) + //// { + //// attr.BlurBehindRadius = 0; + + //// activity.Window.Attributes = attr; + //// } + //// } + //// activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); + //// } + + //// if (transparencyLevel == WindowTransparencyLevel.Blur) + //// { + //// if (isAboveR) + //// { + //// activity.SetTranslucent(true); + //// activity.Window?.AddFlags(WindowManagerFlags.BlurBehind); + + //// var attr = activity.Window?.Attributes; + //// if (attr != null) + //// { + //// attr.BlurBehindRadius = 120; + + //// activity.Window.Attributes = attr; + //// } + //// activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent)); + //// } + //// else + //// { + //// activity.Window?.ClearFlags(WindowManagerFlags.BlurBehind); + //// activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.White)); + + //// return; + //// } + //// } + + //// TransparencyLevel = transparencyLevel; + //// } + ////} } public virtual object TryGetFeature(Type featureType) diff --git a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs index 387357dddd..28b43e8397 100644 --- a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs +++ b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs @@ -89,7 +89,7 @@ namespace Avalonia.Controls.Embedding.Offscreen public Action? LostFocus { get; set; } public abstract IMouseDevice MouseDevice { get; } - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { } + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { } public WindowTransparencyLevel TransparencyLevel { get; private set; } diff --git a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs index bb6b2304af..02b96d0628 100644 --- a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs +++ b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs @@ -117,7 +117,7 @@ namespace Avalonia.Platform /// /// Sets the hint of the TopLevel. /// - void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel); + void SetTransparencyLevelHint(IReadOnlyList transparencyLevel); /// /// Gets the current of the TopLevel. diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 189dbe5e62..ca12c302f7 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -523,8 +523,8 @@ namespace Avalonia.Controls { if (PlatformImpl != null) { - ////PlatformImpl.SetTransparencyLevelHint( - //// change.GetNewValue>() ?? Array.Empty()); + PlatformImpl.SetTransparencyLevelHint( + change.GetNewValue>() ?? Array.Empty()); } } else if (change.Property == ActualThemeVariantProperty) diff --git a/src/Avalonia.DesignerSupport/Remote/Stubs.cs b/src/Avalonia.DesignerSupport/Remote/Stubs.cs index f6f5c185e9..28d1b147fd 100644 --- a/src/Avalonia.DesignerSupport/Remote/Stubs.cs +++ b/src/Avalonia.DesignerSupport/Remote/Stubs.cs @@ -179,7 +179,7 @@ namespace Avalonia.DesignerSupport.Remote public Action GotInputWhenDisabled { get; set; } - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { } + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { } public void SetWindowManagerAddShadowHint(bool enabled) { diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index c065346377..c8198f0da2 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -485,27 +485,27 @@ namespace Avalonia.Native _native?.BeginDragAndDropOperation(effects, point, clipboard, callback, sourceHandle); } - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) - { - if (TransparencyLevel != transparencyLevel) - { - if (transparencyLevel == WindowTransparencyLevel.Blur || - transparencyLevel == WindowTransparencyLevel.AcrylicBlur || - transparencyLevel == WindowTransparencyLevel.Mica) - { - transparencyLevel = WindowTransparencyLevel.AcrylicBlur; - } - - TransparencyLevel = transparencyLevel; - - _native.SetTransparencyMode(transparencyLevel == WindowTransparencyLevel.None - ? AvnWindowTransparencyMode.Opaque - : transparencyLevel == WindowTransparencyLevel.Transparent - ? AvnWindowTransparencyMode.Transparent - : AvnWindowTransparencyMode.Blur); - - TransparencyLevelChanged?.Invoke(TransparencyLevel); - } + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) + { + ////if (TransparencyLevel != transparencyLevel) + ////{ + //// if (transparencyLevel == WindowTransparencyLevel.Blur || + //// transparencyLevel == WindowTransparencyLevel.AcrylicBlur || + //// transparencyLevel == WindowTransparencyLevel.Mica) + //// { + //// transparencyLevel = WindowTransparencyLevel.AcrylicBlur; + //// } + + //// TransparencyLevel = transparencyLevel; + + //// _native.SetTransparencyMode(transparencyLevel == WindowTransparencyLevel.None + //// ? AvnWindowTransparencyMode.Opaque + //// : transparencyLevel == WindowTransparencyLevel.Transparent + //// ? AvnWindowTransparencyMode.Transparent + //// : AvnWindowTransparencyMode.Blur); + + //// TransparencyLevelChanged?.Invoke(TransparencyLevel); + ////} } public WindowTransparencyLevel TransparencyLevel { get; private set; } = WindowTransparencyLevel.None; diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 0a535d2f57..58b59a6b56 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -1307,8 +1307,10 @@ namespace Avalonia.X11 public IPopupPositioner? PopupPositioner { get; } - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) => - _transparencyHelper?.SetTransparencyRequest(transparencyLevel); + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) + { + ////_transparencyHelper?.SetTransparencyRequest(transparencyLevel); + } public void SetWindowManagerAddShadowHint(bool enabled) { diff --git a/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs b/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs index 8456dc92d0..c243a2a28b 100644 --- a/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs +++ b/src/Browser/Avalonia.Browser/BrowserTopLevelImpl.cs @@ -223,13 +223,13 @@ namespace Avalonia.Browser return null; } - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { - if (transparencyLevel == WindowTransparencyLevel.None - || transparencyLevel == WindowTransparencyLevel.Transparent) - { - TransparencyLevel = transparencyLevel; - } + ////if (transparencyLevel == WindowTransparencyLevel.None + //// || transparencyLevel == WindowTransparencyLevel.Transparent) + ////{ + //// TransparencyLevel = transparencyLevel; + ////} } public Size ClientSize => _clientSize; diff --git a/src/Headless/Avalonia.Headless/HeadlessWindowImpl.cs b/src/Headless/Avalonia.Headless/HeadlessWindowImpl.cs index 93f92d46f8..edf8275b1a 100644 --- a/src/Headless/Avalonia.Headless/HeadlessWindowImpl.cs +++ b/src/Headless/Avalonia.Headless/HeadlessWindowImpl.cs @@ -337,7 +337,7 @@ namespace Avalonia.Headless } - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { } diff --git a/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs b/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs index ccc8cab8ae..79408cd604 100644 --- a/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs +++ b/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs @@ -75,7 +75,7 @@ using Avalonia.Rendering.Composition; public Size ScaledSize => _outputBackend.PixelSize.ToSize(RenderScaling); - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { } + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { } public WindowTransparencyLevel TransparencyLevel { get; private set; } diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs index 8025779c90..64f4352c25 100644 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs +++ b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs @@ -247,7 +247,7 @@ namespace Avalonia.Win32.Interop.Wpf public IPopupImpl CreatePopup() => null; - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { } + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { } public WindowTransparencyLevel TransparencyLevel { get; private set; } diff --git a/src/Windows/Avalonia.Win32/PlatformConstants.cs b/src/Windows/Avalonia.Win32/PlatformConstants.cs index 48dd9f45da..bed78501f3 100644 --- a/src/Windows/Avalonia.Win32/PlatformConstants.cs +++ b/src/Windows/Avalonia.Win32/PlatformConstants.cs @@ -2,12 +2,13 @@ using System; namespace Avalonia.Win32 { - public static class PlatformConstants + internal static class PlatformConstants { public const string WindowHandleType = "HWND"; public const string CursorHandleType = "HCURSOR"; - internal static readonly Version Windows8 = new Version(6, 2); - internal static readonly Version Windows7 = new Version(6, 1); + public static readonly Version Windows10 = new Version(10, 0); + public static readonly Version Windows8 = new Version(6, 2); + public static readonly Version Windows7 = new Version(6, 1); } } diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionShared.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionShared.cs index 602d0a3f8a..f17805fba3 100644 --- a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionShared.cs +++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionShared.cs @@ -12,6 +12,7 @@ internal class WinUiCompositionShared : IDisposable public ICompositionBrush? MicaBrush { get; } public object SyncRoot { get; } = new(); + public static readonly Version MinAcrylicVersion = new(10, 0, 15063); public static readonly Version MinHostBackdropVersion = new(10, 0, 22000); public WinUiCompositionShared(ICompositor compositor) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index b8eb37bb33..dc9cc7f50c 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -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 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(); + // 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(); - - 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)); } } diff --git a/src/iOS/Avalonia.iOS/AvaloniaView.cs b/src/iOS/Avalonia.iOS/AvaloniaView.cs index 6ca0cf7ace..605955e44f 100644 --- a/src/iOS/Avalonia.iOS/AvaloniaView.cs +++ b/src/iOS/Avalonia.iOS/AvaloniaView.cs @@ -139,7 +139,7 @@ namespace Avalonia.iOS return null; } - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { // No-op } diff --git a/tests/Avalonia.UnitTests/CompositorTestServices.cs b/tests/Avalonia.UnitTests/CompositorTestServices.cs index de7cbc873c..734baba54f 100644 --- a/tests/Avalonia.UnitTests/CompositorTestServices.cs +++ b/tests/Avalonia.UnitTests/CompositorTestServices.cs @@ -192,7 +192,7 @@ public class CompositorTestServices : IDisposable public IMouseDevice MouseDevice { get; } = new MouseDevice(); public IPopupImpl CreatePopup() => throw new NotImplementedException(); - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) { }