From 6bcf36e23fc61353406ee1dcb6009fe8cba6aa65 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 18 Sep 2020 01:36:17 -0700 Subject: [PATCH] windows.ui.composition compatible with acrylic blur setting. --- .../CompositionEglGlPlatformSurface.cs | 8 +- .../Composition/CompositionHost.cs | 24 +++++- src/Windows/Avalonia.Win32/WindowImpl.cs | 84 +++++++++++-------- 3 files changed, 75 insertions(+), 41 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs index 96646b9590..38ea545957 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs @@ -6,7 +6,7 @@ using Windows.UI.Composition.Interop; namespace Avalonia.Win32 { - public class CompositionEglGlPlatformSurface : EglGlPlatformSurfaceBase + internal class CompositionEglGlPlatformSurface : EglGlPlatformSurfaceBase { private readonly EglDisplay _display; private readonly EglContext _context; @@ -21,9 +21,11 @@ namespace Avalonia.Win32 _info = info; } - public void AttachToCompositionTree(IntPtr hwnd) + public IBlurHost AttachToCompositionTree(IntPtr hwnd) { - _surfaceInterop = CompositionHost.Instance.InitialiseWindowCompositionTree(hwnd, out _surface); + _surfaceInterop = CompositionHost.Instance.InitialiseWindowCompositionTree(hwnd, out _surface, out var blurHost); + + return blurHost; } public override IGlPlatformSurfaceRenderTarget CreateGlRenderTarget() diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index 958959bc93..dfcf6e1d7f 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -7,6 +7,26 @@ using WinRT; namespace Avalonia.Win32 { + internal interface IBlurHost + { + void SetBlur(bool enabled); + } + + internal class CompositionBlurHost : IBlurHost + { + Windows.UI.Composition.Visual _blurVisual; + + public CompositionBlurHost(Windows.UI.Composition.Visual blurVisual) + { + _blurVisual = blurVisual; + } + + public void SetBlur(bool enabled) + { + _blurVisual.IsVisible = enabled; + } + } + class CompositionHost { internal enum DISPATCHERQUEUE_THREAD_APARTMENTTYPE @@ -61,7 +81,7 @@ namespace Avalonia.Win32 _graphicsDevice = interop.CreateGraphicsDevice(display.GetDirect3DDevice()); } - public ICompositionDrawingSurfaceInterop InitialiseWindowCompositionTree(IntPtr hwnd, out Windows.UI.Composition.Visual surfaceVisual) + public ICompositionDrawingSurfaceInterop InitialiseWindowCompositionTree(IntPtr hwnd, out Windows.UI.Composition.Visual surfaceVisual, out IBlurHost blurHost) { var target = CreateDesktopWindowTarget(hwnd); @@ -84,6 +104,8 @@ namespace Avalonia.Win32 var blur = CreateBlur(); + blurHost = new CompositionBlurHost(blur); + container.Children.InsertAtTop(blur); var visuals = target.Root.As().Children; diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index a2bd7f57b9..46c18dea68 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -47,6 +47,7 @@ namespace Avalonia.Win32 private Thickness _offScreenMargin; private double _extendTitleBarHint = -1; private bool _isUsingComposition; + private IBlurHost _blurHost; #if USE_MANAGED_DRAG private readonly ManagedWindowResizeDragHelper _managedDrag; @@ -114,7 +115,7 @@ namespace Avalonia.Win32 if (_isUsingComposition) { var cgl = new CompositionEglGlPlatformSurface(Win32GlManager.EglFeature.DeferredContext, this); - cgl.AttachToCompositionTree(_hwnd); + _blurHost = cgl.AttachToCompositionTree(_hwnd); _gl = cgl; @@ -341,54 +342,63 @@ namespace Avalonia.Win32 private WindowTransparencyLevel Win10EnableBlur(WindowTransparencyLevel transparencyLevel) { - bool canUseAcrylic = Win32Platform.WindowsVersion.Major > 10 || Win32Platform.WindowsVersion.Build >= 19628; - - var accent = new AccentPolicy(); - var accentStructSize = Marshal.SizeOf(accent); - - if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur && !canUseAcrylic) + if (_isUsingComposition) { - transparencyLevel = WindowTransparencyLevel.Blur; - } + _blurHost?.SetBlur(transparencyLevel >= WindowTransparencyLevel.Blur); - switch (transparencyLevel) + return transparencyLevel; + } + else { - default: - case WindowTransparencyLevel.None: - accent.AccentState = AccentState.ACCENT_DISABLED; - break; + bool canUseAcrylic = Win32Platform.WindowsVersion.Major > 10 || Win32Platform.WindowsVersion.Build >= 19628; - case WindowTransparencyLevel.Transparent: - accent.AccentState = AccentState.ACCENT_ENABLE_TRANSPARENTGRADIENT; - break; + var accent = new AccentPolicy(); + var accentStructSize = Marshal.SizeOf(accent); - case WindowTransparencyLevel.Blur: - accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND; - break; + if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur && !canUseAcrylic) + { + transparencyLevel = WindowTransparencyLevel.Blur; + } - case WindowTransparencyLevel.AcrylicBlur: - case (WindowTransparencyLevel.AcrylicBlur + 1): // hack-force acrylic. - accent.AccentState = AccentState.ACCENT_ENABLE_ACRYLIC; - transparencyLevel = WindowTransparencyLevel.AcrylicBlur; - break; - } + switch (transparencyLevel) + { + default: + case WindowTransparencyLevel.None: + accent.AccentState = AccentState.ACCENT_DISABLED; + break; + + case WindowTransparencyLevel.Transparent: + accent.AccentState = AccentState.ACCENT_ENABLE_TRANSPARENTGRADIENT; + break; + + case WindowTransparencyLevel.Blur: + accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND; + break; + + case WindowTransparencyLevel.AcrylicBlur: + case (WindowTransparencyLevel.AcrylicBlur + 1): // hack-force acrylic. + accent.AccentState = AccentState.ACCENT_ENABLE_ACRYLIC; + transparencyLevel = WindowTransparencyLevel.AcrylicBlur; + break; + } - accent.AccentFlags = 2; - accent.GradientColor = 0x01000000; + accent.AccentFlags = 2; + accent.GradientColor = 0x01000000; - var accentPtr = Marshal.AllocHGlobal(accentStructSize); - Marshal.StructureToPtr(accent, accentPtr, false); + 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; + var data = new WindowCompositionAttributeData(); + data.Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY; + data.SizeOfData = accentStructSize; + data.Data = accentPtr; - SetWindowCompositionAttribute(_hwnd, ref data); + SetWindowCompositionAttribute(_hwnd, ref data); - Marshal.FreeHGlobal(accentPtr); + Marshal.FreeHGlobal(accentPtr); - return transparencyLevel; + return transparencyLevel; + } } public IEnumerable Surfaces => new object[] { Handle, _gl, _framebuffer };