Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for Mica Light & Dark based on Win11 #12196

Merged
merged 4 commits into from
Jul 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/Windows/Avalonia.Win32/WinRT/Composition/D2DEffects.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ class D2DEffects
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);

Expand Down
104 changes: 104 additions & 0 deletions src/Windows/Avalonia.Win32/WinRT/Composition/WinUIEffectBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,110 @@ public override void OnUnreferencedFromNative()
_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
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -25,7 +26,8 @@ public void Dispose()
{
_compositionRoundedRectangleGeometry?.Dispose();
_blur.Dispose();
_mica?.Dispose();
_micaLight?.Dispose();
_micaDark?.Dispose();
_visual.Dispose();
_surfaceBrush.Dispose();
_target.Dispose();
Expand All @@ -50,14 +52,20 @@ public WinUiCompositedWindow(EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInf
_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();
Expand All @@ -68,9 +76,6 @@ public WinUiCompositedWindow(EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInf
using var compositionBrush = _surfaceBrush.QueryInterface<ICompositionBrush>();
spriteVisual.SetBrush(compositionBrush);
_target.SetRoot(containerVisual);



}

public void SetSurface(ICompositionSurface surface) => _surfaceBrush.SetSurface(surface);
Expand All @@ -79,12 +84,13 @@ public void SetBlur(BlurEffect blurEffect)
{
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);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ internal class WinUiCompositionShared : IDisposable
public ICompositor5 Compositor5 { get; }
public ICompositorDesktopInterop DesktopInterop { get; }
public ICompositionBrush BlurBrush { get; }
public ICompositionBrush? MicaBrush { get; }
public ICompositionBrush? MicaBrushLight { get; }
public ICompositionBrush? MicaBrushDark { get; }
public object SyncRoot { get; } = new();

public static readonly Version MinWinCompositionVersion = new(10, 0, 17134);
Expand All @@ -21,14 +22,16 @@ public WinUiCompositionShared(ICompositor compositor)
Compositor = compositor.CloneReference();
Compositor5 = compositor.QueryInterface<ICompositor5>();
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<ICompositorDesktopInterop>();
}

public void Dispose()
{
BlurBrush.Dispose();
MicaBrush?.Dispose();
MicaBrushLight?.Dispose();
MicaBrushDark?.Dispose();
DesktopInterop.Dispose();
Compositor.Dispose();
Compositor5.Dispose();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,77 @@
using System;
using System.Numerics;
using MicroCom.Runtime;

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<ICompositionEffectSourceParameterFactory>(
"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<ICompositionBrush>();

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<ICompositionBrush>();

using var compositorWithBlurredWallpaperBackdropBrush =
compositor.QueryInterface<ICompositorWithBlurredWallpaperBackdropBrush>();
using var blurredWallpaperBackdropBrush =
compositorWithBlurredWallpaperBackdropBrush?.TryCreateBlurredWallpaperBackdropBrush();
return blurredWallpaperBackdropBrush?.QueryInterface<ICompositionBrush>();
using var micaBackdropBrush = blurredWallpaperBackdropBrush?.QueryInterface<ICompositionBrush>();


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<ICompositionBrush>();
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<ICompositionBrush>();
return micaBackdropBrush1.CloneReference();
}

public static ICompositionBrush CreateAcrylicBlurBackdropBrush(ICompositor compositor)
Expand Down Expand Up @@ -97,4 +154,15 @@ public static ICompositionBrush CreateBackdropBrush(ICompositor compositor)
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<IGraphicsEffectSource>();
handle = backdropString.Handle;
return backDropParameterAsSource;
}
}
3 changes: 2 additions & 1 deletion src/Windows/Avalonia.Win32/WinRT/IBlurHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ internal enum BlurEffect
{
None,
Acrylic,
Mica
MicaLight,
MicaDark
}

internal interface IBlurHost
Expand Down
23 changes: 21 additions & 2 deletions src/Windows/Avalonia.Win32/WinRT/WinRTPropertyValue.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace Avalonia.Win32.WinRT
Expand All @@ -16,7 +17,15 @@ public WinRTPropertyValue(uint u)
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; }
Expand Down Expand Up @@ -62,7 +71,17 @@ public WinRTPropertyValue(uint u)

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<float>());
Marshal.Copy(_singleArray, 0, allocCoTaskMem, _singleArray.Length);
float* s = (float*)allocCoTaskMem;

return s;
}

public unsafe double* GetDoubleArray(uint* __valueSize) => throw NotImplemented;

Expand Down
Loading