From f89a0b2ac9323b38cd9c376f8bf2ed30814a1bd5 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 14 Jul 2023 10:57:45 +0200 Subject: [PATCH 1/8] Added failing test for #11220. --- .../SelectingItemsControlTests_SelectedValue.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_SelectedValue.cs b/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_SelectedValue.cs index e9b8895174..9ea12c62fb 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_SelectedValue.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_SelectedValue.cs @@ -268,6 +268,22 @@ namespace Avalonia.Controls.UnitTests.Primitives Assert.True(called); } + [Fact] + public void Handles_Null_SelectedItem_When_SelectedValueBinding_Assigned() + { + // Issue #11220 + var items = new object[] { null }; + var sic = new SelectingItemsControl + { + ItemsSource = items, + SelectedIndex = 0, + SelectedValueBinding = new Binding("Name"), + Template = Template() + }; + + Assert.Null(sic.SelectedValue); + } + private static FuncControlTemplate Template() { return new FuncControlTemplate((control, scope) => From c7da9c4bb86cc3583e796a45106ebb9fb8e6ad0d Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 14 Jul 2023 11:01:38 +0200 Subject: [PATCH 2/8] Allow null item in BindingHelper.Evaluate. Fixes #11220. --- src/Avalonia.Controls/Primitives/SelectingItemsControl.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs index e22d03273a..66ed1a27e2 100644 --- a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs +++ b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs @@ -1395,10 +1395,8 @@ namespace Avalonia.Controls.Primitives public object Evaluate(object? dataContext) { - dataContext = dataContext ?? throw new ArgumentNullException(nameof(dataContext)); - // Only update the DataContext if necessary - if (!dataContext.Equals(DataContext)) + if (!Equals(dataContext, DataContext)) DataContext = dataContext; return GetValue(ValueProperty); From 43e1d99bdd70315aa069f867928a053b0b22eb23 Mon Sep 17 00:00:00 2001 From: Lighto Date: Fri, 14 Jul 2023 15:44:14 +0300 Subject: [PATCH 3/8] Added support for Mica Light & Dark based on Win11 --- samples/ControlCatalog/MainView.xaml | 3 +- .../WindowTransparencyLevel.cs | 9 +- .../WinRT/Composition/D2DEffects.cs | 3 + .../WinRT/Composition/WinUIEffectBase.cs | 104 ++++++++++++++++++ .../Composition/WinUiCompositedWindow.cs | 27 +++-- .../Composition/WinUiCompositionShared.cs | 8 +- .../Composition/WinUiCompositionUtils.cs | 75 ++++++++++++- src/Windows/Avalonia.Win32/WinRT/IBlurHost.cs | 3 +- .../WinRT/WinRTPropertyValue.cs | 23 +++- src/Windows/Avalonia.Win32/WindowImpl.cs | 22 +++- 10 files changed, 253 insertions(+), 24 deletions(-) diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml index 7ed2d67379..0a1621d02a 100644 --- a/samples/ControlCatalog/MainView.xaml +++ b/samples/ControlCatalog/MainView.xaml @@ -226,7 +226,8 @@ Transparent Blur AcrylicBlur - Mica + MicaLight + MicaDark - /// The window background is based on desktop wallpaper tint with a blur. This will only work on Windows 11 + /// The window background is based on desktop wallpaper tint with a light blur. This will only work on Windows 11 /// - public static WindowTransparencyLevel Mica { get; } = new(nameof(Mica)); + public static WindowTransparencyLevel MicaLight { get; } = new(nameof(MicaLight)); + + /// + /// The window background is based on desktop wallpaper tint with a dark blur. This will only work on Windows 11 + /// + public static WindowTransparencyLevel MicaDark { get; } = new(nameof(MicaDark)); public override string ToString() { diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/D2DEffects.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/D2DEffects.cs index bef5a55b06..98e1077885 100644 --- a/src/Windows/Avalonia.Win32/WinRT/Composition/D2DEffects.cs +++ b/src/Windows/Avalonia.Win32/WinRT/Composition/D2DEffects.cs @@ -28,6 +28,9 @@ namespace Avalonia.Win32.WinRT.Composition public static readonly Guid CLSID_D2D1Border = new Guid(0x2A2D49C0, 0x4ACF, 0x43C7, 0x8C, 0x6A, 0x7C, 0x4A, 0x27, 0x87, 0x4D, 0x27); + public static readonly Guid CLSID_D2D1Opacity = + new Guid("811d79a4-de28-4454-8094-c64685f8bd4c"); + public static readonly Guid CLSID_D2D1Brightness = new Guid(0x8CEA8D1E, 0x77B0, 0x4986, 0xB3, 0xB9, 0x2F, 0x0C, 0x0E, 0xAE, 0x78, 0x87); diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUIEffectBase.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUIEffectBase.cs index 1a922b4acd..10dbcfcc6b 100644 --- a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUIEffectBase.cs +++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUIEffectBase.cs @@ -52,6 +52,110 @@ namespace Avalonia.Win32.WinRT.Composition _sources = null; } } + + class BorderEffect : WinUIEffectBase + { + private readonly int _x; + private readonly int _y; + public override Guid EffectId => D2DEffects.CLSID_D2D1Border; + public override uint PropertyCount => 2; + + public BorderEffect(int x, int y, params IGraphicsEffectSource[] _sources):base(_sources) + { + _x = x; + _y = y; + } + + public override IPropertyValue? GetProperty(uint index) + { + if (index == 0) + return new WinRTPropertyValue((uint)_x); + if (index == 1) + return new WinRTPropertyValue((uint)_y); + return null; + } + } + + class BlendEffect : WinUIEffectBase + { + private readonly int _mode; + + public BlendEffect(int mode, params IGraphicsEffectSource[] _sources) : base(_sources) + { + _mode = mode; + } + + public override Guid EffectId => D2DEffects.CLSID_D2D1Blend; + public override uint PropertyCount => 1; + + public override IPropertyValue? GetProperty(uint index) + { + if (index == 0) + return new WinRTPropertyValue((uint)_mode); + return null; + } + } + + class CompositeStepEffect : WinUIEffectBase + { + private readonly float _mode; + + public CompositeStepEffect(int mode, params IGraphicsEffectSource[] _sources) : base(_sources) + { + _mode = mode; + } + + public override Guid EffectId => D2DEffects.CLSID_D2D1Composite; + public override uint PropertyCount => 1; + + public override IPropertyValue? GetProperty(uint index) + { + if (index == 0) + return new WinRTPropertyValue((uint)_mode); + return null; + } + } + + class OpacityEffect : WinUIEffectBase + { + private readonly float _opacity; + + public OpacityEffect(float opacity, params IGraphicsEffectSource[] _sources) : base(_sources) + { + _opacity = opacity; + } + + public override Guid EffectId => D2DEffects.CLSID_D2D1Opacity; + public override uint PropertyCount => 1; + + public override IPropertyValue? GetProperty(uint index) + { + if (index == 0) + return new WinRTPropertyValue(_opacity); + return null; + } + } + + class ColorSourceEffect : WinUIEffectBase + { + private readonly float[] _color; + + public ColorSourceEffect(float[] color) + { + _color = color; + } + + public override Guid EffectId => D2DEffects.CLSID_D2D1Flood; + public override uint PropertyCount => 1; + + public override IPropertyValue? GetProperty(uint index) + { + if (index == 0) + return new WinRTPropertyValue(_color); + return null; + } + } + internal class WinUIGaussianBlurEffect : WinUIEffectBase { diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindow.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindow.cs index 2f22ba99f9..d87c8d1361 100644 --- a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindow.cs +++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindow.cs @@ -12,7 +12,8 @@ internal class WinUiCompositedWindow : IDisposable public EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo WindowInfo { get; } private readonly WinUiCompositionShared _shared; private readonly ICompositionRoundedRectangleGeometry? _compositionRoundedRectangleGeometry; - private readonly IVisual? _mica; + private readonly IVisual? _micaLight; + private readonly IVisual? _micaDark; private readonly IVisual _blur; private readonly IVisual _visual; private PixelSize _size; @@ -25,7 +26,8 @@ internal class WinUiCompositedWindow : IDisposable { _compositionRoundedRectangleGeometry?.Dispose(); _blur.Dispose(); - _mica?.Dispose(); + _micaLight?.Dispose(); + _micaDark?.Dispose(); _visual.Dispose(); _surfaceBrush.Dispose(); _target.Dispose(); @@ -50,14 +52,20 @@ internal class WinUiCompositedWindow : IDisposable _target.SetRoot(containerVisual); _blur = WinUiCompositionUtils.CreateBlurVisual(shared.Compositor, shared.BlurBrush); - if (shared.MicaBrush != null) + if (shared.MicaBrushLight != null) { - _mica = WinUiCompositionUtils.CreateBlurVisual(shared.Compositor, shared.MicaBrush); - containerChildren.InsertAtTop(_mica); + _micaLight = WinUiCompositionUtils.CreateBlurVisual(shared.Compositor, shared.MicaBrushLight); + containerChildren.InsertAtTop(_micaLight); + } + + if (shared.MicaBrushDark != null) + { + _micaDark = WinUiCompositionUtils.CreateBlurVisual(shared.Compositor, shared.MicaBrushDark); + containerChildren.InsertAtTop(_micaDark); } _compositionRoundedRectangleGeometry = - WinUiCompositionUtils.ClipVisual(shared.Compositor, backdropCornerRadius, _blur, _mica); + WinUiCompositionUtils.ClipVisual(shared.Compositor, backdropCornerRadius, _blur, _micaLight, _micaDark); containerChildren.InsertAtTop(_blur); using var spriteVisual = shared.Compositor.CreateSpriteVisual(); @@ -79,12 +87,13 @@ internal class WinUiCompositedWindow : IDisposable { lock (_shared.SyncRoot) { - _blur.SetIsVisible(blurEffect == BlurEffect.Acrylic - || blurEffect == BlurEffect.Mica && _mica == null ? + || (blurEffect == BlurEffect.MicaLight && _micaLight == null) || + (blurEffect == BlurEffect.MicaDark && _micaDark == null) ? 1 : 0); - _mica?.SetIsVisible(blurEffect == BlurEffect.Mica ? 1 : 0); + _micaLight?.SetIsVisible(blurEffect == BlurEffect.MicaLight ? 1 : 0); + _micaDark?.SetIsVisible(blurEffect == BlurEffect.MicaDark ? 1 : 0); } } diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionShared.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionShared.cs index b3a328d097..5c7f490710 100644 --- a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionShared.cs +++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionShared.cs @@ -9,6 +9,8 @@ internal class WinUiCompositionShared : IDisposable public ICompositor5 Compositor5 { get; } public ICompositorDesktopInterop DesktopInterop { get; } public ICompositionBrush BlurBrush { get; } + public ICompositionBrush? MicaBrushLight { get; } + public ICompositionBrush? MicaBrushDark { get; } public ICompositionBrush? MicaBrush { get; } public object SyncRoot { get; } = new(); @@ -21,14 +23,16 @@ internal class WinUiCompositionShared : IDisposable Compositor = compositor.CloneReference(); Compositor5 = compositor.QueryInterface(); BlurBrush = WinUiCompositionUtils.CreateAcrylicBlurBackdropBrush(compositor); - MicaBrush = WinUiCompositionUtils.CreateMicaBackdropBrush(compositor); + MicaBrushLight = WinUiCompositionUtils.CreateMicaBackdropBrush(compositor, 242, 0.6f); + MicaBrushDark = WinUiCompositionUtils.CreateMicaBackdropBrush(compositor, 32, 0.8f); DesktopInterop = compositor.QueryInterface(); } public void Dispose() { BlurBrush.Dispose(); - MicaBrush?.Dispose(); + MicaBrushLight?.Dispose(); + MicaBrushDark?.Dispose(); DesktopInterop.Dispose(); Compositor.Dispose(); Compositor5.Dispose(); diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionUtils.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionUtils.cs index 7b970868df..1a130698ee 100644 --- a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionUtils.cs +++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionUtils.cs @@ -1,3 +1,4 @@ +using System; using System.Numerics; using MicroCom.Runtime; @@ -5,16 +6,75 @@ namespace Avalonia.Win32.WinRT.Composition; internal static class WinUiCompositionUtils { - public static ICompositionBrush? CreateMicaBackdropBrush(ICompositor compositor) + public static ICompositionBrush? CreateMicaBackdropBrush(ICompositor compositor, float color, float opacity) { if (Win32Platform.WindowsVersion.Build < 22000) return null; + using var backDropParameterFactory = + NativeWinRTMethods.CreateActivationFactory( + "Windows.UI.Composition.CompositionEffectSourceParameter"); + + + var tint = new[] { color / 255f, color / 255f, color / 255f, 255f / 255f }; + + using var tintColorEffect = new ColorSourceEffect(tint); + + + using var tintOpacityEffect = new OpacityEffect(1.0f, tintColorEffect); + using var tintOpacityEffectFactory = compositor.CreateEffectFactory(tintOpacityEffect); + using var tintOpacityEffectBrushEffect = tintOpacityEffectFactory.CreateBrush(); + using var tintOpacityEffectBrush = tintOpacityEffectBrushEffect.QueryInterface(); + + using var luminosityColorEffect = new ColorSourceEffect(tint); + + using var luminosityOpacityEffect = new OpacityEffect(opacity, luminosityColorEffect); + using var luminosityOpacityEffectFactory = compositor.CreateEffectFactory(luminosityOpacityEffect); + using var luminosityOpacityEffectBrushEffect = luminosityOpacityEffectFactory.CreateBrush(); + using var luminosityOpacityEffectBrush = + luminosityOpacityEffectBrushEffect.QueryInterface(); + + + // using var backDropParameterAsSource = GetParameterSource("BlurredWallpaperBackdrop", backDropParameterFactory, out var backdropHandle); + // using var backdropCompositionBrsuh = backDropParameterAsSource.QueryInterface(); using var compositorWithBlurredWallpaperBackdropBrush = compositor.QueryInterface(); using var blurredWallpaperBackdropBrush = compositorWithBlurredWallpaperBackdropBrush?.TryCreateBlurredWallpaperBackdropBrush(); - return blurredWallpaperBackdropBrush?.QueryInterface(); + using var micaBackdropBrush = blurredWallpaperBackdropBrush?.QueryInterface(); + + + using var backgroundParameterAsSource = + GetParameterSource("Background", backDropParameterFactory, out var backgroundHandle); + using var foregroundParameterAsSource = + GetParameterSource("Foreground", backDropParameterFactory, out var foregroundHandle); + + using var luminosityBlendEffect = + new BlendEffect(23, backgroundParameterAsSource, foregroundParameterAsSource); + using var luminosityBlendEffectFactory = compositor.CreateEffectFactory(luminosityBlendEffect); + using var luminosityBlendEffectBrush = luminosityBlendEffectFactory.CreateBrush(); + using var luminosityBlendEffectBrush1 = luminosityBlendEffectBrush.QueryInterface(); + luminosityBlendEffectBrush.SetSourceParameter(backgroundHandle, micaBackdropBrush); + luminosityBlendEffectBrush.SetSourceParameter(foregroundHandle, luminosityOpacityEffectBrush); + + + using var backgroundParameterAsSource1 = + GetParameterSource("Background", backDropParameterFactory, out var backgroundHandle1); + using var foregroundParameterAsSource1 = + GetParameterSource("Foreground", backDropParameterFactory, out var foregroundHandle1); + + using var colorBlendEffect = + new BlendEffect(22, backgroundParameterAsSource1, foregroundParameterAsSource1); + using var colorBlendEffectFactory = compositor.CreateEffectFactory(colorBlendEffect); + using var colorBlendEffectBrush = colorBlendEffectFactory.CreateBrush(); + colorBlendEffectBrush.SetSourceParameter(backgroundHandle1, luminosityBlendEffectBrush1); + colorBlendEffectBrush.SetSourceParameter(foregroundHandle1, tintOpacityEffectBrush); + + + // colorBlendEffectBrush.SetSourceParameter(backgroundHandle, micaBackdropBrush); + + using var micaBackdropBrush1 = colorBlendEffectBrush.QueryInterface(); + return micaBackdropBrush1.CloneReference(); } public static ICompositionBrush CreateAcrylicBlurBackdropBrush(ICompositor compositor) @@ -97,4 +157,15 @@ internal static class WinUiCompositionUtils brush?.Dispose(); } } + + private static IGraphicsEffectSource GetParameterSource(string name, + ICompositionEffectSourceParameterFactory backDropParameterFactory, out IntPtr handle) + { + var backdropString = new HStringInterop(name); + var backDropParameter = + backDropParameterFactory.Create(backdropString.Handle); + var backDropParameterAsSource = backDropParameter.QueryInterface(); + handle = backdropString.Handle; + return backDropParameterAsSource; + } } diff --git a/src/Windows/Avalonia.Win32/WinRT/IBlurHost.cs b/src/Windows/Avalonia.Win32/WinRT/IBlurHost.cs index a3918d9ae6..5f2e752af8 100644 --- a/src/Windows/Avalonia.Win32/WinRT/IBlurHost.cs +++ b/src/Windows/Avalonia.Win32/WinRT/IBlurHost.cs @@ -4,7 +4,8 @@ { None, Acrylic, - Mica + MicaLight, + MicaDark } internal interface IBlurHost diff --git a/src/Windows/Avalonia.Win32/WinRT/WinRTPropertyValue.cs b/src/Windows/Avalonia.Win32/WinRT/WinRTPropertyValue.cs index 684e7ff7b5..8874902d4e 100644 --- a/src/Windows/Avalonia.Win32/WinRT/WinRTPropertyValue.cs +++ b/src/Windows/Avalonia.Win32/WinRT/WinRTPropertyValue.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace Avalonia.Win32.WinRT @@ -16,7 +17,15 @@ namespace Avalonia.Win32.WinRT UInt32 = u; Type = PropertyType.UInt32; } - + + public WinRTPropertyValue(float[] uiColor) + { + Type = PropertyType.SingleArray; + _singleArray = uiColor; + } + + private readonly float[]? _singleArray; + public PropertyType Type { get; } public int IsNumericScalar { get; } public byte UInt8 { get; } @@ -62,7 +71,17 @@ namespace Avalonia.Win32.WinRT public unsafe ulong* GetUInt64Array(uint* __valueSize) => throw NotImplemented; - public unsafe float* GetSingleArray(uint* __valueSize) => throw NotImplemented; + public unsafe float* GetSingleArray(uint* __valueSize) + { + if (_singleArray == null) + throw NotImplemented; + *__valueSize = (uint)_singleArray.Length; + var allocCoTaskMem = Marshal.AllocCoTaskMem(_singleArray.Length * Unsafe.SizeOf()); + Marshal.Copy(_singleArray, 0, allocCoTaskMem, _singleArray.Length); + float* s = (float*)allocCoTaskMem; + + return s; + } public unsafe double* GetDoubleArray(uint* __valueSize) => throw NotImplemented; diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 057cdb2db0..2b16bbe275 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -374,8 +374,10 @@ namespace Avalonia.Win32 SetTransparencyBlur(windowsVersion); else if (level == WindowTransparencyLevel.AcrylicBlur) SetTransparencyAcrylicBlur(windowsVersion); - else if (level == WindowTransparencyLevel.Mica) - SetTransparencyMica(windowsVersion); + else if (level == WindowTransparencyLevel.MicaLight) + SetTransparencyMicaLight(windowsVersion); + else if (level == WindowTransparencyLevel.MicaDark) + SetTransparencyMicaDark(windowsVersion); TransparencyLevel = level; return; @@ -418,7 +420,7 @@ namespace Avalonia.Win32 return windowsVersion >= WinUiCompositionShared.MinAcrylicVersion; // Mica is supported on Windows >= 10.0.22000. - if (level == WindowTransparencyLevel.Mica) + if (level == WindowTransparencyLevel.MicaLight || level == WindowTransparencyLevel.MicaDark) return windowsVersion >= WinUiCompositionShared.MinHostBackdropVersion; return false; @@ -467,14 +469,24 @@ namespace Avalonia.Win32 _blurHost?.SetBlur(BlurEffect.Acrylic); } - private void SetTransparencyMica(Version windowsVersion) + private void SetTransparencyMicaLight(Version windowsVersion) { // Mica only supported with composition on Windows >= 10.0.22000. if (!_isUsingComposition || windowsVersion < WinUiCompositionShared.MinHostBackdropVersion) return; SetUseHostBackdropBrush(false); - _blurHost?.SetBlur(BlurEffect.Mica); + _blurHost?.SetBlur(BlurEffect.MicaLight); + } + + private void SetTransparencyMicaDark(Version windowsVersion) + { + // Mica only supported with composition on Windows >= 10.0.22000. + if (!_isUsingComposition || windowsVersion < WinUiCompositionShared.MinHostBackdropVersion) + return; + + SetUseHostBackdropBrush(false); + _blurHost?.SetBlur(BlurEffect.MicaDark); } private void SetAccentState(AccentState state) From 432dafac91dc4cb61ffd338f7d8afcf5d4ab6540 Mon Sep 17 00:00:00 2001 From: Lighto Date: Fri, 14 Jul 2023 18:38:35 +0300 Subject: [PATCH 4/8] Removed unused old property --- .../Avalonia.Win32/WinRT/Composition/WinUiCompositionShared.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionShared.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionShared.cs index 5c7f490710..7a775afb3a 100644 --- a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionShared.cs +++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionShared.cs @@ -11,7 +11,6 @@ internal class WinUiCompositionShared : IDisposable public ICompositionBrush BlurBrush { get; } public ICompositionBrush? MicaBrushLight { get; } public ICompositionBrush? MicaBrushDark { get; } - public ICompositionBrush? MicaBrush { get; } public object SyncRoot { get; } = new(); public static readonly Version MinWinCompositionVersion = new(10, 0, 17134); From c126db5b554349893e45e43a0cf289a601dedc20 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sat, 15 Jul 2023 18:29:40 +0600 Subject: [PATCH 5/8] Added AvaloniaFilePreview target --- packages/Avalonia/AvaloniaBuildTasks.targets | 26 ++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/packages/Avalonia/AvaloniaBuildTasks.targets b/packages/Avalonia/AvaloniaBuildTasks.targets index 33f22f4d02..6af35ff0d2 100644 --- a/packages/Avalonia/AvaloniaBuildTasks.targets +++ b/packages/Avalonia/AvaloniaBuildTasks.targets @@ -144,4 +144,30 @@ + + + Build + + + + + http://127.0.0.1:6001 + $(OutputPath)/$(AssemblyName).dll + MainWindow.axaml + $(APreviewExecutable) + $([System.IO.Path]::ChangeExtension('$(APreviewExecutable)', '.deps.json')) + $([System.IO.Path]::ChangeExtension('$(APreviewExecutable)', '.runtimeconfig.json')) + $([System.IO.Path]::GetFullPath('$(APreviewFile)')) + + + + + + + + + + + + From 55c03069b1e9cf681cde74a476038118296c340f Mon Sep 17 00:00:00 2001 From: Lighto Date: Sat, 15 Jul 2023 22:18:59 +0300 Subject: [PATCH 6/8] Changed Mica dark/light based on theme --- samples/ControlCatalog/MainView.xaml | 3 +- .../WindowTransparencyLevel.cs | 9 ++--- .../Composition/WinUiCompositedWindow.cs | 3 -- src/Windows/Avalonia.Win32/WindowImpl.cs | 33 +++++++++---------- 4 files changed, 19 insertions(+), 29 deletions(-) diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml index 0a1621d02a..7ed2d67379 100644 --- a/samples/ControlCatalog/MainView.xaml +++ b/samples/ControlCatalog/MainView.xaml @@ -226,8 +226,7 @@ Transparent Blur AcrylicBlur - MicaLight - MicaDark + Mica - /// The window background is based on desktop wallpaper tint with a light blur. This will only work on Windows 11 + /// The window background is based on desktop wallpaper tint with a blur. This will only work on Windows 11 /// - public static WindowTransparencyLevel MicaLight { get; } = new(nameof(MicaLight)); + public static WindowTransparencyLevel Mica { get; } = new(nameof(Mica)); - /// - /// The window background is based on desktop wallpaper tint with a dark blur. This will only work on Windows 11 - /// - public static WindowTransparencyLevel MicaDark { get; } = new(nameof(MicaDark)); - public override string ToString() { return _value; diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindow.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindow.cs index d87c8d1361..d720e525d3 100644 --- a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindow.cs +++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindow.cs @@ -76,9 +76,6 @@ internal class WinUiCompositedWindow : IDisposable using var compositionBrush = _surfaceBrush.QueryInterface(); spriteVisual.SetBrush(compositionBrush); _target.SetRoot(containerVisual); - - - } public void SetSurface(ICompositionSurface surface) => _surfaceBrush.SetSurface(surface); diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 2b16bbe275..044c2cad67 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -106,6 +106,7 @@ namespace Avalonia.Win32 private static POINTER_PEN_INFO[]? s_historyPenInfos; private static POINTER_INFO[]? s_historyInfos; private static MOUSEMOVEPOINT[]? s_mouseHistoryInfos; + private PlatformThemeVariant _currentThemeVariant; public WindowImpl() { @@ -374,10 +375,8 @@ namespace Avalonia.Win32 SetTransparencyBlur(windowsVersion); else if (level == WindowTransparencyLevel.AcrylicBlur) SetTransparencyAcrylicBlur(windowsVersion); - else if (level == WindowTransparencyLevel.MicaLight) - SetTransparencyMicaLight(windowsVersion); - else if (level == WindowTransparencyLevel.MicaDark) - SetTransparencyMicaDark(windowsVersion); + else if (level == WindowTransparencyLevel.Mica) + SetTransparencyMica(windowsVersion); TransparencyLevel = level; return; @@ -420,7 +419,7 @@ namespace Avalonia.Win32 return windowsVersion >= WinUiCompositionShared.MinAcrylicVersion; // Mica is supported on Windows >= 10.0.22000. - if (level == WindowTransparencyLevel.MicaLight || level == WindowTransparencyLevel.MicaDark) + if (level == WindowTransparencyLevel.Mica) return windowsVersion >= WinUiCompositionShared.MinHostBackdropVersion; return false; @@ -469,24 +468,19 @@ namespace Avalonia.Win32 _blurHost?.SetBlur(BlurEffect.Acrylic); } - private void SetTransparencyMicaLight(Version windowsVersion) + private void SetTransparencyMica(Version windowsVersion) { // Mica only supported with composition on Windows >= 10.0.22000. if (!_isUsingComposition || windowsVersion < WinUiCompositionShared.MinHostBackdropVersion) return; SetUseHostBackdropBrush(false); - _blurHost?.SetBlur(BlurEffect.MicaLight); - } - - private void SetTransparencyMicaDark(Version windowsVersion) - { - // Mica only supported with composition on Windows >= 10.0.22000. - if (!_isUsingComposition || windowsVersion < WinUiCompositionShared.MinHostBackdropVersion) - return; - - SetUseHostBackdropBrush(false); - _blurHost?.SetBlur(BlurEffect.MicaDark); + _blurHost?.SetBlur(_currentThemeVariant switch + { + PlatformThemeVariant.Light => BlurEffect.MicaLight, + PlatformThemeVariant.Dark => BlurEffect.MicaDark, + _ => throw new ArgumentOutOfRangeException() + }); } private void SetAccentState(AccentState state) @@ -790,6 +784,7 @@ namespace Avalonia.Win32 public unsafe void SetFrameThemeVariant(PlatformThemeVariant themeVariant) { + _currentThemeVariant = themeVariant; if (Win32Platform.WindowsVersion.Build >= 22000) { var pvUseBackdropBrush = themeVariant == PlatformThemeVariant.Dark ? 1 : 0; @@ -798,6 +793,10 @@ namespace Avalonia.Win32 (int)DwmWindowAttribute.DWMWA_USE_IMMERSIVE_DARK_MODE, &pvUseBackdropBrush, sizeof(int)); + if (TransparencyLevel == WindowTransparencyLevel.Mica) + { + SetTransparencyMica(Win32Platform.WindowsVersion); + } } } From 7a0e0c41a40baf60cce214ee6756f95ca75fd7a8 Mon Sep 17 00:00:00 2001 From: Lighto Date: Sat, 15 Jul 2023 22:20:50 +0300 Subject: [PATCH 7/8] Removed unnecessary spaces --- src/Avalonia.Controls/WindowTransparencyLevel.cs | 2 +- .../WinRT/Composition/WinUiCompositionUtils.cs | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Avalonia.Controls/WindowTransparencyLevel.cs b/src/Avalonia.Controls/WindowTransparencyLevel.cs index 9604a7ef5c..bce6e21e68 100644 --- a/src/Avalonia.Controls/WindowTransparencyLevel.cs +++ b/src/Avalonia.Controls/WindowTransparencyLevel.cs @@ -36,7 +36,7 @@ public readonly record struct WindowTransparencyLevel /// The window background is based on desktop wallpaper tint with a blur. This will only work on Windows 11 /// public static WindowTransparencyLevel Mica { get; } = new(nameof(Mica)); - + public override string ToString() { return _value; diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionUtils.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionUtils.cs index 1a130698ee..29c1e1fe27 100644 --- a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionUtils.cs +++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositionUtils.cs @@ -33,10 +33,7 @@ internal static class WinUiCompositionUtils using var luminosityOpacityEffectBrushEffect = luminosityOpacityEffectFactory.CreateBrush(); using var luminosityOpacityEffectBrush = luminosityOpacityEffectBrushEffect.QueryInterface(); - - - // using var backDropParameterAsSource = GetParameterSource("BlurredWallpaperBackdrop", backDropParameterFactory, out var backdropHandle); - // using var backdropCompositionBrsuh = backDropParameterAsSource.QueryInterface(); + using var compositorWithBlurredWallpaperBackdropBrush = compositor.QueryInterface(); using var blurredWallpaperBackdropBrush = From 746a027bd80e2f1b8f837abad11a851c17125077 Mon Sep 17 00:00:00 2001 From: Sorien Date: Sat, 15 Jul 2023 22:19:12 +0200 Subject: [PATCH 8/8] Fix typo --- src/Avalonia.Native/NativePlatformSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Native/NativePlatformSettings.cs b/src/Avalonia.Native/NativePlatformSettings.cs index 53d3da0378..42d05d831c 100644 --- a/src/Avalonia.Native/NativePlatformSettings.cs +++ b/src/Avalonia.Native/NativePlatformSettings.cs @@ -23,7 +23,7 @@ internal class NativePlatformSettings : DefaultPlatformSettings AvnPlatformThemeVariant.Dark => (PlatformThemeVariant.Dark, ColorContrastPreference.NoPreference), AvnPlatformThemeVariant.Light => (PlatformThemeVariant.Light, ColorContrastPreference.NoPreference), AvnPlatformThemeVariant.HighContrastDark => (PlatformThemeVariant.Dark, ColorContrastPreference.High), - AvnPlatformThemeVariant.HighContrastLight => (PlatformThemeVariant.Dark, ColorContrastPreference.High), + AvnPlatformThemeVariant.HighContrastLight => (PlatformThemeVariant.Light, ColorContrastPreference.High), _ => throw new ArgumentOutOfRangeException() }; var color = _platformSettings.AccentColor;