From 5b3d5db1d6c21338583843983f58d65a66cd99c6 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 19 May 2020 10:30:12 -0300 Subject: [PATCH 01/30] Add WindowTransparencyLevel enum. --- .../WindowTransparencyLevel.cs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/Avalonia.Controls/WindowTransparencyLevel.cs diff --git a/src/Avalonia.Controls/WindowTransparencyLevel.cs b/src/Avalonia.Controls/WindowTransparencyLevel.cs new file mode 100644 index 0000000000..f5fc0ca9dd --- /dev/null +++ b/src/Avalonia.Controls/WindowTransparencyLevel.cs @@ -0,0 +1,20 @@ +namespace Avalonia.Controls +{ + public enum WindowTransparencyLevel + { + /// + /// The window background is Black where nothing is drawn in the window. + /// + None, + + /// + /// The window background is Transparent where nothing is drawn in the window. + /// + Transparent, + + /// + /// The window background is a blur-behind where nothing is drawn in the window. + /// + Blur + } +} From cbd89289ab2b49887ef4114ef0dfa0e52db701dd Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 19 May 2020 10:45:26 -0300 Subject: [PATCH 02/30] add TransparencyLevel property to TopLevel --- .../Platform/ITopLevelImpl.cs | 6 ++++++ src/Avalonia.Controls/TopLevel.cs | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs index 98ee17ee1f..8e892ffc21 100644 --- a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs +++ b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Avalonia.Controls; using Avalonia.Input; using Avalonia.Input.Raw; using Avalonia.Rendering; @@ -106,5 +107,10 @@ namespace Avalonia.Platform IMouseDevice MouseDevice { get; } IPopupImpl CreatePopup(); + + /// + /// Gets or sets the ofthe TopLevel. + /// + WindowTransparencyLevel TransparencyLevel { get; set; } } } diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index d17f3b0423..8861c72418 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -43,6 +43,12 @@ namespace Avalonia.Controls public static readonly StyledProperty PointerOverElementProperty = AvaloniaProperty.Register(nameof(IInputRoot.PointerOverElement)); + /// + /// Represents the current . + /// + public static readonly StyledProperty TransparencyLevelProperty = + AvaloniaProperty.Register(nameof(TransparencyLevel), WindowTransparencyLevel.None); + private readonly IInputManager _inputManager; private readonly IAccessKeyHandler _accessKeyHandler; private readonly IKeyboardNavigationHandler _keyboardNavigationHandler; @@ -57,6 +63,9 @@ namespace Avalonia.Controls static TopLevel() { AffectsMeasure(ClientSizeProperty); + + TransparencyLevelProperty.Changed.AddClassHandler( + (tl, e) => { if (tl.PlatformImpl != null) tl.PlatformImpl.TransparencyLevel = (WindowTransparencyLevel)e.NewValue; }); } /// @@ -155,6 +164,15 @@ namespace Avalonia.Controls protected set { SetAndRaise(ClientSizeProperty, ref _clientSize, value); } } + /// + /// Gets or sets the . + /// + public WindowTransparencyLevel TransparencyLevel + { + get { return GetValue(TransparencyLevelProperty); } + set { SetValue(TransparencyLevelProperty, value); } + } + public ILayoutManager LayoutManager { get From a30e6d8cf68bb44ef56c9e4f088746d130e7a758 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 19 May 2020 14:19:34 -0300 Subject: [PATCH 03/30] Add framework support for TopLevel transparency level. --- .../Platform/ITopLevelImpl.cs | 2 + src/Avalonia.Controls/TopLevel.cs | 40 +++++++++++++++++++ .../EmbeddableControlRoot.xaml | 16 ++++---- .../OverlayPopupHost.xaml | 16 ++++---- src/Avalonia.Themes.Default/PopupRoot.xaml | 16 ++++---- src/Avalonia.Themes.Default/Window.xaml | 20 +++++----- 6 files changed, 80 insertions(+), 30 deletions(-) diff --git a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs index 8e892ffc21..b22962115e 100644 --- a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs +++ b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs @@ -59,6 +59,8 @@ namespace Avalonia.Platform /// Action ScalingChanged { get; set; } + Action TransparencyLevelChanged { get; set; } + /// /// Creates a new renderer for the toplevel. /// diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 8861c72418..3ac5779ed3 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -6,6 +6,7 @@ using Avalonia.Input.Raw; using Avalonia.Layout; using Avalonia.Logging; using Avalonia.LogicalTree; +using Avalonia.Media; using Avalonia.Platform; using Avalonia.Rendering; using Avalonia.Styling; @@ -14,6 +15,7 @@ using JetBrains.Annotations; namespace Avalonia.Controls { + /// /// Base class for top-level widgets. /// @@ -49,6 +51,12 @@ namespace Avalonia.Controls public static readonly StyledProperty TransparencyLevelProperty = AvaloniaProperty.Register(nameof(TransparencyLevel), WindowTransparencyLevel.None); + /// + /// Defines the property. + /// + public static readonly StyledProperty TransparencyBackgroundFallbackProperty = + AvaloniaProperty.Register(nameof(TransparencyBackgroundFallback), Brushes.White); + private readonly IInputManager _inputManager; private readonly IAccessKeyHandler _accessKeyHandler; private readonly IKeyboardNavigationHandler _keyboardNavigationHandler; @@ -56,6 +64,7 @@ namespace Avalonia.Controls private readonly IGlobalStyles _globalStyles; private Size _clientSize; private ILayoutManager _layoutManager; + private Border _transparencyFallbackBorder; /// /// Initializes static members of the class. @@ -117,6 +126,7 @@ namespace Avalonia.Controls impl.Paint = HandlePaint; impl.Resized = HandleResized; impl.ScalingChanged = HandleScalingChanged; + impl.TransparencyLevelChanged = HandleTransparencyLevelChanged; _keyboardNavigationHandler?.SetOwner(this); _accessKeyHandler?.SetOwner(this); @@ -173,6 +183,12 @@ namespace Avalonia.Controls set { SetValue(TransparencyLevelProperty, value); } } + public IBrush TransparencyBackgroundFallback + { + get => GetValue(TransparencyBackgroundFallbackProperty); + set => SetValue(TransparencyBackgroundFallbackProperty, value); + } + public ILayoutManager LayoutManager { get @@ -330,6 +346,21 @@ namespace Avalonia.Controls LayoutHelper.InvalidateSelfAndChildrenMeasure(this); } + protected virtual void HandleTransparencyLevelChanged(WindowTransparencyLevel transparencyLevel) + { + if(_transparencyFallbackBorder != null) + { + if(transparencyLevel == WindowTransparencyLevel.None) + { + _transparencyFallbackBorder.Background = TransparencyBackgroundFallback; + } + else + { + _transparencyFallbackBorder.Background = Brushes.Transparent; + } + } + } + /// protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) { @@ -339,6 +370,15 @@ namespace Avalonia.Controls $"Control '{GetType().Name}' is a top level control and cannot be added as a child."); } + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) + { + base.OnApplyTemplate(e); + + _transparencyFallbackBorder = e.NameScope.Find("PART_TransparencyFallback"); + + HandleTransparencyLevelChanged(PlatformImpl.TransparencyLevel); + } + /// /// Raises the event. /// diff --git a/src/Avalonia.Themes.Default/EmbeddableControlRoot.xaml b/src/Avalonia.Themes.Default/EmbeddableControlRoot.xaml index 1fd168c009..3acab7d7bc 100644 --- a/src/Avalonia.Themes.Default/EmbeddableControlRoot.xaml +++ b/src/Avalonia.Themes.Default/EmbeddableControlRoot.xaml @@ -3,13 +3,15 @@ - - - - + + + + + + diff --git a/src/Avalonia.Themes.Default/OverlayPopupHost.xaml b/src/Avalonia.Themes.Default/OverlayPopupHost.xaml index 56b3699c07..e57325499d 100644 --- a/src/Avalonia.Themes.Default/OverlayPopupHost.xaml +++ b/src/Avalonia.Themes.Default/OverlayPopupHost.xaml @@ -2,13 +2,15 @@ - - - + + + + + diff --git a/src/Avalonia.Themes.Default/PopupRoot.xaml b/src/Avalonia.Themes.Default/PopupRoot.xaml index cf063f5390..1a55d2f7a4 100644 --- a/src/Avalonia.Themes.Default/PopupRoot.xaml +++ b/src/Avalonia.Themes.Default/PopupRoot.xaml @@ -2,13 +2,15 @@ - - - + + + + + diff --git a/src/Avalonia.Themes.Default/Window.xaml b/src/Avalonia.Themes.Default/Window.xaml index 2a8b5d0fca..e29409e894 100644 --- a/src/Avalonia.Themes.Default/Window.xaml +++ b/src/Avalonia.Themes.Default/Window.xaml @@ -4,15 +4,17 @@ - - - - + + + + + + From fe7e8582d1639b595c65395aa1357e3e19de04e3 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 19 May 2020 14:19:57 -0300 Subject: [PATCH 04/30] add basic win32 implementation for transparency level. --- .../Interop/UnmanagedMethods.cs | 41 +++++++++++ src/Windows/Avalonia.Win32/WindowImpl.cs | 68 +++++++++++++++++++ 2 files changed, 109 insertions(+) diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index 5601ccbafe..088c4b17ac 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -1302,6 +1302,47 @@ namespace Avalonia.Win32.Interop [DllImport("dwmapi.dll")] public static extern int DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margins); + [DllImport("dwmapi.dll")] + public static extern int DwmIsCompositionEnabled(out bool enabled); + + [DllImport("user32.dll")] + internal static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttributeData data); + + [StructLayout(LayoutKind.Sequential)] + internal struct WindowCompositionAttributeData + { + public WindowCompositionAttribute Attribute; + public IntPtr Data; + public int SizeOfData; + } + + internal enum WindowCompositionAttribute + { + // ... + WCA_ACCENT_POLICY = 19 + // ... + } + + internal enum AccentState + { + ACCENT_DISABLED = 0, + ACCENT_ENABLE_GRADIENT = 1, + ACCENT_ENABLE_TRANSPARENTGRADIENT = 2, + ACCENT_ENABLE_BLURBEHIND = 3, + ACCENT_ENABLE_ACRYLIC = 4, //1703 and above + ACCENT_ENABLE_HOSTBACKDROP = 5, // RS5 1809 + ACCENT_INVALID_STATE = 6 + } + + [StructLayout(LayoutKind.Sequential)] + internal struct AccentPolicy + { + public AccentState AccentState; + public int AccentFlags; + public int GradientColor; + public int AnimationId; + } + [StructLayout(LayoutKind.Sequential)] internal struct MARGINS { diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index cc4c12ec3c..45abf9fd79 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -5,6 +5,7 @@ using System.Runtime.InteropServices; using Avalonia.Controls; using Avalonia.Input; using Avalonia.Input.Raw; +using Avalonia.Media; using Avalonia.OpenGL; using Avalonia.Platform; using Avalonia.Rendering; @@ -66,6 +67,7 @@ namespace Avalonia.Win32 private Size _minSize; private Size _maxSize; private WindowImpl _parent; + private WindowTransparencyLevel _transparencyLevel = WindowTransparencyLevel.None; public WindowImpl() { @@ -122,6 +124,8 @@ namespace Avalonia.Win32 public Action WindowStateChanged { get; set; } + public Action TransparencyLevelChanged { get; set; } + public Thickness BorderThickness { get @@ -206,6 +210,70 @@ namespace Avalonia.Win32 } } + public WindowTransparencyLevel TransparencyLevel + { + get => _transparencyLevel; + set + { + var oldValue = _transparencyLevel; + _transparencyLevel = EnableBlur(value); + + if(oldValue != _transparencyLevel) + { + TransparencyLevelChanged?.Invoke(_transparencyLevel); + } + } + } + + private WindowTransparencyLevel EnableBlur(WindowTransparencyLevel transparencyLevel) + { + if(DwmIsCompositionEnabled(out var compositionEnabled) != 0 || !compositionEnabled) + { + return WindowTransparencyLevel.None; + } + + var accent = new AccentPolicy(); + var accentStructSize = Marshal.SizeOf(accent); + + 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.Blur + 1): + accent.AccentState = AccentState.ACCENT_ENABLE_ACRYLIC; + break; + } + var bgcolor = 0x00ffffff; + + accent.GradientColor = bgcolor; + + 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); + + //todo return acheived level and check windows versions. + return transparencyLevel; + } + public IEnumerable Surfaces => new object[] { Handle, _gl, _framebuffer }; public PixelPoint Position From f9a1871d1e7f121c92a9ebedfaa7a83bcef05bc8 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 19 May 2020 14:20:17 -0300 Subject: [PATCH 05/30] add transparency demo to control catalog. --- samples/ControlCatalog/MainView.xaml | 7 ++++++- samples/ControlCatalog/MainView.xaml.cs | 7 +++++++ samples/ControlCatalog/MainWindow.xaml | 3 +-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml index 30671ef083..5d62e61d0e 100644 --- a/samples/ControlCatalog/MainView.xaml +++ b/samples/ControlCatalog/MainView.xaml @@ -2,7 +2,7 @@ xmlns:pages="clr-namespace:ControlCatalog.Pages" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="ControlCatalog.MainView" - Background="{DynamicResource ThemeBackgroundBrush}" + Background="Transparent" Foreground="{DynamicResource ThemeForegroundBrush}" FontSize="{DynamicResource FontSizeNormal}"> @@ -70,6 +70,11 @@ Light Dark + + None + Transparent + Blur + diff --git a/samples/ControlCatalog/MainView.xaml.cs b/samples/ControlCatalog/MainView.xaml.cs index 7c17b125d6..d1d54c6636 100644 --- a/samples/ControlCatalog/MainView.xaml.cs +++ b/samples/ControlCatalog/MainView.xaml.cs @@ -63,6 +63,13 @@ namespace ControlCatalog if (VisualRoot is Window window) window.SystemDecorations = (SystemDecorations)decorations.SelectedIndex; }; + + var transparencyLevels = this.Find("TransparencyLevels"); + transparencyLevels.SelectionChanged += (sender, e) => + { + if (VisualRoot is Window window) + window.TransparencyLevel = (WindowTransparencyLevel)transparencyLevels.SelectedIndex; + }; } protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) diff --git a/samples/ControlCatalog/MainWindow.xaml b/samples/ControlCatalog/MainWindow.xaml index 935db20757..a0bb956425 100644 --- a/samples/ControlCatalog/MainWindow.xaml +++ b/samples/ControlCatalog/MainWindow.xaml @@ -7,8 +7,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="clr-namespace:ControlCatalog.ViewModels" xmlns:v="clr-namespace:ControlCatalog.Views" - x:Class="ControlCatalog.MainWindow" WindowState="{Binding WindowState, Mode=TwoWay}"> - + x:Class="ControlCatalog.MainWindow" WindowState="{Binding WindowState, Mode=TwoWay}" Background="Transparent"> From 30b81f1ded2753d08c1023a5cbb7c08012794e96 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 19 May 2020 14:20:44 -0300 Subject: [PATCH 06/30] Add stubs for transparency in other toplevel impls. --- .../Embedding/Offscreen/OffscreenTopLevelImpl.cs | 6 ++++++ src/Avalonia.DesignerSupport/Remote/Stubs.cs | 4 ++++ src/Avalonia.Native/WindowImplBase.cs | 4 ++++ src/Avalonia.X11/X11Window.cs | 4 ++++ .../Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs | 6 ++++++ 5 files changed, 24 insertions(+) diff --git a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs index 29f0374301..5d7c968173 100644 --- a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs +++ b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs @@ -49,6 +49,9 @@ namespace Avalonia.Controls.Embedding.Offscreen public Action Paint { get; set; } public Action Resized { get; set; } public Action ScalingChanged { get; set; } + + public Action TransparencyLevelChanged { get; set; } + public void SetInputRoot(IInputRoot inputRoot) => InputRoot = inputRoot; public virtual Point PointToClient(PixelPoint point) => point.ToPoint(1); @@ -61,6 +64,9 @@ namespace Avalonia.Controls.Embedding.Offscreen public Action Closed { get; set; } public abstract IMouseDevice MouseDevice { get; } + + public WindowTransparencyLevel TransparencyLevel { get => WindowTransparencyLevel.None; set { } } + public IPopupImpl CreatePopup() => null; } } diff --git a/src/Avalonia.DesignerSupport/Remote/Stubs.cs b/src/Avalonia.DesignerSupport/Remote/Stubs.cs index 484cf3bc97..0b5d2cb2b9 100644 --- a/src/Avalonia.DesignerSupport/Remote/Stubs.cs +++ b/src/Avalonia.DesignerSupport/Remote/Stubs.cs @@ -37,6 +37,8 @@ namespace Avalonia.DesignerSupport.Remote public WindowState WindowState { get; set; } public Action WindowStateChanged { get; set; } + public Action TransparencyLevelChanged { get; set; } + public WindowStub(IWindowImpl parent = null) { if (parent != null) @@ -141,6 +143,8 @@ namespace Avalonia.DesignerSupport.Remote public IPopupPositioner PopupPositioner { get; } public Action GotInputWhenDisabled { get; set; } + + public WindowTransparencyLevel TransparencyLevel { get => WindowTransparencyLevel.None; set { } } } class ClipboardStub : IClipboard diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index 47127fafe0..3b616ef76b 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -369,6 +369,8 @@ namespace Avalonia.Native Action ITopLevelImpl.ScalingChanged { get; set; } + public Action TransparencyLevelChanged { get; set; } + public IScreenImpl Screen { get; private set; } // TODO @@ -389,6 +391,8 @@ namespace Avalonia.Native _native.BeginDragAndDropOperation(effects, point, clipboard, callback, sourceHandle); } + public WindowTransparencyLevel TransparencyLevel { get => WindowTransparencyLevel.None; set { } } + public IPlatformHandle Handle { get; private set; } } } diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 643b037b3f..84f0b8c877 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -300,6 +300,9 @@ namespace Avalonia.X11 public Action Activated { get; set; } public Func Closing { get; set; } public Action WindowStateChanged { get; set; } + + public Action TransparencyLevelChanged { get; set; } + public Action Closed { get; set; } public Action PositionChanged { get; set; } @@ -1083,5 +1086,6 @@ namespace Avalonia.X11 public IPopupPositioner PopupPositioner { get; } public ITopLevelNativeMenuExporter NativeMenuExporter { get; } + public WindowTransparencyLevel TransparencyLevel { get; set; } } } diff --git a/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs b/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs index 9844cdc03b..fa518bafec 100644 --- a/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs +++ b/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Avalonia.Controls; using Avalonia.Input; using Avalonia.Input.Raw; using Avalonia.LinuxFramebuffer.Input; @@ -70,6 +71,9 @@ namespace Avalonia.LinuxFramebuffer public Action Paint { get; set; } public Action Resized { get; set; } public Action ScalingChanged { get; set; } + + public Action TransparencyLevelChanged { get; set; } + public Action Closed { get; set; } public event Action LostFocus { @@ -78,5 +82,7 @@ namespace Avalonia.LinuxFramebuffer } public Size ScaledSize => _outputBackend.PixelSize.ToSize(Scaling); + + public WindowTransparencyLevel TransparencyLevel { get => WindowTransparencyLevel.None; set { } } } } From 0c3f2aa856d30ba04a99a0e14f802c81678a1583 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 19 May 2020 15:18:48 -0300 Subject: [PATCH 07/30] implement transparency api on osx. --- native/Avalonia.Native/inc/avalonia-native.h | 1 + native/Avalonia.Native/src/OSX/window.h | 3 ++ native/Avalonia.Native/src/OSX/window.mm | 29 ++++++++++++++++++++ src/Avalonia.Native/WindowImplBase.cs | 17 +++++++++++- 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/native/Avalonia.Native/inc/avalonia-native.h b/native/Avalonia.Native/inc/avalonia-native.h index 7782165263..b86c679397 100644 --- a/native/Avalonia.Native/inc/avalonia-native.h +++ b/native/Avalonia.Native/inc/avalonia-native.h @@ -258,6 +258,7 @@ AVNCOM(IAvnWindowBase, 02) : IUnknown virtual HRESULT ObtainNSViewHandleRetained(void** retOut) = 0; virtual HRESULT BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point, IAvnClipboard* clipboard, IAvnDndResultCallback* cb, void* sourceHandle) = 0; + virtual HRESULT SetBlurEnabled (bool enable) = 0; }; AVNCOM(IAvnPopup, 03) : virtual IAvnWindowBase diff --git a/native/Avalonia.Native/src/OSX/window.h b/native/Avalonia.Native/src/OSX/window.h index ca60914526..bdf3007a28 100644 --- a/native/Avalonia.Native/src/OSX/window.h +++ b/native/Avalonia.Native/src/OSX/window.h @@ -3,6 +3,9 @@ class WindowBaseImpl; +@interface AutoFitContentVisualEffectView : NSVisualEffectView +@end + @interface AvnView : NSView -(AvnView* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent; -(NSEvent* _Nonnull) lastMouseDownEvent; diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm index fed2176580..abfae3cf1e 100644 --- a/native/Avalonia.Native/src/OSX/window.mm +++ b/native/Avalonia.Native/src/OSX/window.mm @@ -20,6 +20,7 @@ public: View = NULL; Window = NULL; } + NSVisualEffectView* VisualEffect; AvnView* View; AvnWindow* Window; ComPtr BaseEvents; @@ -47,6 +48,12 @@ public: [Window setStyleMask:NSWindowStyleMaskBorderless]; [Window setBackingType:NSBackingStoreBuffered]; + + VisualEffect = [AutoFitContentVisualEffectView new]; + [VisualEffect setBlendingMode:NSVisualEffectBlendingModeBehindWindow]; + [VisualEffect setMaterial:NSVisualEffectMaterialLight]; + [VisualEffect setAutoresizesSubviews:true]; + [Window setContentView: View]; } @@ -383,6 +390,18 @@ public: return *ppv == nil ? E_FAIL : S_OK; } + virtual HRESULT SetBlurEnabled (bool enable) override + { + [Window setContentView: enable ? VisualEffect : View]; + + if(enable) + { + [VisualEffect addSubview:View]; + } + + return S_OK; + } + virtual HRESULT BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point, IAvnClipboard* clipboard, IAvnDndResultCallback* cb, void* sourceHandle) override @@ -911,6 +930,16 @@ protected: NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEventTrackingRunLoopMode, NSModalPanelRunLoopMode, NSRunLoopCommonModes, NSConnectionReplyMode, nil]; +@implementation AutoFitContentVisualEffectView +-(void)setFrameSize:(NSSize)newSize +{ + [super setFrameSize:newSize]; + if([[self subviews] count] == 0) + return; + [[self subviews][0] setFrameSize: newSize]; +} +@end + @implementation AvnView { ComPtr _parent; diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index 3b616ef76b..2442c2cba4 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -391,7 +391,22 @@ namespace Avalonia.Native _native.BeginDragAndDropOperation(effects, point, clipboard, callback, sourceHandle); } - public WindowTransparencyLevel TransparencyLevel { get => WindowTransparencyLevel.None; set { } } + private WindowTransparencyLevel _transparencyLevel; + + public WindowTransparencyLevel TransparencyLevel + { + get => _transparencyLevel; + set + { + if(_transparencyLevel != value) + { + _transparencyLevel = value; + + _native.SetBlurEnabled(_transparencyLevel >= WindowTransparencyLevel.Blur); + TransparencyLevelChanged?.Invoke(_transparencyLevel); + } + } + } public IPlatformHandle Handle { get; private set; } } From a37b2daf2cf48a7c377ae57b98e213c0def335bd Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 20 May 2020 09:34:58 -0300 Subject: [PATCH 08/30] set hidden flag --- src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs | 8 ++++++++ src/Windows/Avalonia.Win32/WindowImpl.cs | 7 +++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index 088c4b17ac..92a06279bb 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -1334,6 +1334,14 @@ namespace Avalonia.Win32.Interop ACCENT_INVALID_STATE = 6 } + internal enum AccentFlags + { + DrawLeftBorder = 0x20, + DrawTopBorder = 0x40, + DrawRightBorder = 0x80, + DrawBottomBorder = 0x100, + } + [StructLayout(LayoutKind.Sequential)] internal struct AccentPolicy { diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 45abf9fd79..ae9c2c9030 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -247,14 +247,17 @@ namespace Avalonia.Win32 break; case WindowTransparencyLevel.Blur: - accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND; + accent.AccentState = AccentState.ACCENT_ENABLE_ACRYLIC; break; case (WindowTransparencyLevel.Blur + 1): accent.AccentState = AccentState.ACCENT_ENABLE_ACRYLIC; break; } - var bgcolor = 0x00ffffff; + + var version = Environment.OSVersion; + accent.AccentFlags = 2;// (int)(AccentFlags.DrawBottomBorder | AccentFlags.DrawLeftBorder | AccentFlags.DrawRightBorder | AccentFlags.DrawTopBorder); + var bgcolor = 0x00FFFFFF; accent.GradientColor = bgcolor; From 8d899096bb5b91c8852448f495674241f4bb691a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 20 May 2020 10:14:46 -0300 Subject: [PATCH 09/30] implement appropriate blur level depending on windows 10 version. --- .../Interop/UnmanagedMethods.cs | 29 ++++++++++++++++ src/Windows/Avalonia.Win32/WindowImpl.cs | 34 ++++++++++++------- 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index 92a06279bb..b06708ebd2 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -1305,6 +1305,35 @@ namespace Avalonia.Win32.Interop [DllImport("dwmapi.dll")] public static extern int DwmIsCompositionEnabled(out bool enabled); + [StructLayout(LayoutKind.Sequential)] + internal struct RTL_OSVERSIONINFOEX + { + internal uint dwOSVersionInfoSize; + internal uint dwMajorVersion; + internal uint dwMinorVersion; + internal uint dwBuildNumber; + internal uint dwPlatformId; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + internal string szCSDVersion; + } + + [DllImport("ntdll")] + private static extern int RtlGetVersion(out RTL_OSVERSIONINFOEX lpVersionInformation); + + internal static Version RtlGetVersion() + { + RTL_OSVERSIONINFOEX v = new RTL_OSVERSIONINFOEX(); + v.dwOSVersionInfoSize = (uint)Marshal.SizeOf(v); + if (RtlGetVersion(out v) == 0) + { + return new Version((int)v.dwMajorVersion, (int)v.dwMinorVersion, (int)v.dwBuildNumber, (int)v.dwPlatformId); + } + else + { + throw new Exception("RtlGetVersion failed!"); + } + } + [DllImport("user32.dll")] internal static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttributeData data); diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index ae9c2c9030..dd9a350b85 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -210,15 +210,15 @@ namespace Avalonia.Win32 } } - public WindowTransparencyLevel TransparencyLevel + public WindowTransparencyLevel TransparencyLevel { get => _transparencyLevel; - set + set { var oldValue = _transparencyLevel; _transparencyLevel = EnableBlur(value); - if(oldValue != _transparencyLevel) + if (oldValue != _transparencyLevel) { TransparencyLevelChanged?.Invoke(_transparencyLevel); } @@ -227,7 +227,21 @@ namespace Avalonia.Win32 private WindowTransparencyLevel EnableBlur(WindowTransparencyLevel transparencyLevel) { - if(DwmIsCompositionEnabled(out var compositionEnabled) != 0 || !compositionEnabled) + var version = RtlGetVersion(); + bool canUseTransparency = false; + bool canUseAcrylic = false; + + if (version.Major >= 10) + { + canUseTransparency = true; + + if (version.Build >= 19628) + { + canUseAcrylic = true; + } + } + + if (!canUseTransparency || DwmIsCompositionEnabled(out var compositionEnabled) != 0 || !compositionEnabled) { return WindowTransparencyLevel.None; } @@ -247,19 +261,16 @@ namespace Avalonia.Win32 break; case WindowTransparencyLevel.Blur: - accent.AccentState = AccentState.ACCENT_ENABLE_ACRYLIC; + accent.AccentState = canUseAcrylic ? AccentState.ACCENT_ENABLE_ACRYLIC : AccentState.ACCENT_ENABLE_BLURBEHIND; break; - case (WindowTransparencyLevel.Blur + 1): + case (WindowTransparencyLevel.Blur + 1): // hack force acrylic on windows 10. accent.AccentState = AccentState.ACCENT_ENABLE_ACRYLIC; break; } - var version = Environment.OSVersion; - accent.AccentFlags = 2;// (int)(AccentFlags.DrawBottomBorder | AccentFlags.DrawLeftBorder | AccentFlags.DrawRightBorder | AccentFlags.DrawTopBorder); - var bgcolor = 0x00FFFFFF; - - accent.GradientColor = bgcolor; + accent.AccentFlags = 2; + accent.GradientColor = 0x00FFFFFF; var accentPtr = Marshal.AllocHGlobal(accentStructSize); Marshal.StructureToPtr(accent, accentPtr, false); @@ -273,7 +284,6 @@ namespace Avalonia.Win32 Marshal.FreeHGlobal(accentPtr); - //todo return acheived level and check windows versions. return transparencyLevel; } From 9e9565f40f5222b477cdc4607c5f3ec2eab1f430 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 20 May 2020 10:39:00 -0300 Subject: [PATCH 10/30] fix border only margin. --- src/Windows/Avalonia.Win32/WindowImpl.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index dd9a350b85..2cf87c1556 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -861,9 +861,14 @@ namespace Avalonia.Win32 if (!_isFullScreenActive) { + var margin = newProperties.Decorations == SystemDecorations.BorderOnly ? 1 : 0; + var margins = new MARGINS { - cyBottomHeight = newProperties.Decorations == SystemDecorations.BorderOnly ? 1 : 0 + cyBottomHeight = margin, + cxRightWidth = margin, + cxLeftWidth = margin, + cyTopHeight = margin }; DwmExtendFrameIntoClientArea(_hwnd, ref margins); From 58c518c573d73722075f1151ad15ee1b8ce18756 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 20 May 2020 11:12:38 -0300 Subject: [PATCH 11/30] Add Hint / Actual properties for Transparency. --- samples/ControlCatalog/MainView.xaml.cs | 2 +- src/Avalonia.Controls/TopLevel.cs | 44 ++++++++++++++++++++----- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/samples/ControlCatalog/MainView.xaml.cs b/samples/ControlCatalog/MainView.xaml.cs index d1d54c6636..8c4818fb07 100644 --- a/samples/ControlCatalog/MainView.xaml.cs +++ b/samples/ControlCatalog/MainView.xaml.cs @@ -68,7 +68,7 @@ namespace ControlCatalog transparencyLevels.SelectionChanged += (sender, e) => { if (VisualRoot is Window window) - window.TransparencyLevel = (WindowTransparencyLevel)transparencyLevels.SelectedIndex; + window.TransparencyLevelHint = (WindowTransparencyLevel)transparencyLevels.SelectedIndex; }; } diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 3ac5779ed3..55212eb3dc 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -46,13 +46,21 @@ namespace Avalonia.Controls AvaloniaProperty.Register(nameof(IInputRoot.PointerOverElement)); /// - /// Represents the current . + /// Defines the property. /// - public static readonly StyledProperty TransparencyLevelProperty = - AvaloniaProperty.Register(nameof(TransparencyLevel), WindowTransparencyLevel.None); + public static readonly StyledProperty TransparencyLevelHintProperty = + AvaloniaProperty.Register(nameof(TransparencyLevelHint), WindowTransparencyLevel.None); /// - /// Defines the property. + /// Defines the property. + /// + public static readonly DirectProperty ActualTransparencyLevelProperty = + AvaloniaProperty.RegisterDirect(nameof(ActualTransparencyLevel), + o => o.ActualTransparencyLevel, + unsetValue: WindowTransparencyLevel.None); + + /// + /// Defines the property. /// public static readonly StyledProperty TransparencyBackgroundFallbackProperty = AvaloniaProperty.Register(nameof(TransparencyBackgroundFallback), Brushes.White); @@ -63,6 +71,7 @@ namespace Avalonia.Controls private readonly IPlatformRenderInterface _renderInterface; private readonly IGlobalStyles _globalStyles; private Size _clientSize; + private WindowTransparencyLevel _actualTransparencyLevel; private ILayoutManager _layoutManager; private Border _transparencyFallbackBorder; @@ -73,7 +82,7 @@ namespace Avalonia.Controls { AffectsMeasure(ClientSizeProperty); - TransparencyLevelProperty.Changed.AddClassHandler( + TransparencyLevelHintProperty.Changed.AddClassHandler( (tl, e) => { if (tl.PlatformImpl != null) tl.PlatformImpl.TransparencyLevel = (WindowTransparencyLevel)e.NewValue; }); } @@ -103,6 +112,8 @@ namespace Avalonia.Controls PlatformImpl = impl; + _actualTransparencyLevel = WindowTransparencyLevel.None; + dependencyResolver = dependencyResolver ?? AvaloniaLocator.Current; var styler = TryGetService(dependencyResolver); @@ -175,14 +186,27 @@ namespace Avalonia.Controls } /// - /// Gets or sets the . + /// Gets or sets the that the TopLevel should use when possible. /// - public WindowTransparencyLevel TransparencyLevel + public WindowTransparencyLevel TransparencyLevelHint { - get { return GetValue(TransparencyLevelProperty); } - set { SetValue(TransparencyLevelProperty, value); } + get { return GetValue(TransparencyLevelHintProperty); } + set { SetValue(TransparencyLevelHintProperty, value); } } + /// + /// Gets the acheived that the platform was able to provide. + /// + public WindowTransparencyLevel ActualTransparencyLevel + { + get => _actualTransparencyLevel; + private set => SetAndRaise(ActualTransparencyLevelProperty, ref _actualTransparencyLevel, value); + } + + /// + /// Gets or sets the that transparency will blend with when transparency is not supported. + /// By default this is a solid white brush. + /// public IBrush TransparencyBackgroundFallback { get => GetValue(TransparencyBackgroundFallbackProperty); @@ -359,6 +383,8 @@ namespace Avalonia.Controls _transparencyFallbackBorder.Background = Brushes.Transparent; } } + + ActualTransparencyLevel = transparencyLevel; } /// From 4011cb3f4944a31c23b15913ce3630e77a0464a9 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 20 May 2020 11:27:23 -0300 Subject: [PATCH 12/30] Use Hint/Actual naming --- .../Embedding/Offscreen/OffscreenTopLevelImpl.cs | 2 +- src/Avalonia.Controls/Platform/ITopLevelImpl.cs | 7 +++++-- src/Avalonia.Controls/TopLevel.cs | 4 ++-- src/Avalonia.DesignerSupport/Remote/Stubs.cs | 2 +- src/Avalonia.Native/WindowImplBase.cs | 2 +- src/Avalonia.X11/X11Window.cs | 2 +- .../Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs | 2 +- src/Windows/Avalonia.Win32/WindowImpl.cs | 2 +- 8 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs index 5d7c968173..625acb17c3 100644 --- a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs +++ b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs @@ -65,7 +65,7 @@ namespace Avalonia.Controls.Embedding.Offscreen public Action Closed { get; set; } public abstract IMouseDevice MouseDevice { get; } - public WindowTransparencyLevel TransparencyLevel { get => WindowTransparencyLevel.None; set { } } + public WindowTransparencyLevel TransparencyLevelHint { get => WindowTransparencyLevel.None; set { } } public IPopupImpl CreatePopup() => null; } diff --git a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs index b22962115e..4bcfaf91d6 100644 --- a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs +++ b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs @@ -59,6 +59,9 @@ namespace Avalonia.Platform /// Action ScalingChanged { get; set; } + /// + /// Gets or sets a method called when the toplevel's TransparencyLevel changes. + /// Action TransparencyLevelChanged { get; set; } /// @@ -111,8 +114,8 @@ namespace Avalonia.Platform IPopupImpl CreatePopup(); /// - /// Gets or sets the ofthe TopLevel. + /// Gets or sets the of the TopLevel. /// - WindowTransparencyLevel TransparencyLevel { get; set; } + WindowTransparencyLevel TransparencyLevelHint { get; set; } } } diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 55212eb3dc..1bf33acf42 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -83,7 +83,7 @@ namespace Avalonia.Controls AffectsMeasure(ClientSizeProperty); TransparencyLevelHintProperty.Changed.AddClassHandler( - (tl, e) => { if (tl.PlatformImpl != null) tl.PlatformImpl.TransparencyLevel = (WindowTransparencyLevel)e.NewValue; }); + (tl, e) => { if (tl.PlatformImpl != null) tl.PlatformImpl.TransparencyLevelHint = (WindowTransparencyLevel)e.NewValue; }); } /// @@ -402,7 +402,7 @@ namespace Avalonia.Controls _transparencyFallbackBorder = e.NameScope.Find("PART_TransparencyFallback"); - HandleTransparencyLevelChanged(PlatformImpl.TransparencyLevel); + HandleTransparencyLevelChanged(PlatformImpl.TransparencyLevelHint); } /// diff --git a/src/Avalonia.DesignerSupport/Remote/Stubs.cs b/src/Avalonia.DesignerSupport/Remote/Stubs.cs index 0b5d2cb2b9..95284f18fe 100644 --- a/src/Avalonia.DesignerSupport/Remote/Stubs.cs +++ b/src/Avalonia.DesignerSupport/Remote/Stubs.cs @@ -144,7 +144,7 @@ namespace Avalonia.DesignerSupport.Remote public Action GotInputWhenDisabled { get; set; } - public WindowTransparencyLevel TransparencyLevel { get => WindowTransparencyLevel.None; set { } } + public WindowTransparencyLevel TransparencyLevelHint { get => WindowTransparencyLevel.None; set { } } } class ClipboardStub : IClipboard diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index 2442c2cba4..5852675fb6 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -393,7 +393,7 @@ namespace Avalonia.Native private WindowTransparencyLevel _transparencyLevel; - public WindowTransparencyLevel TransparencyLevel + public WindowTransparencyLevel TransparencyLevelHint { get => _transparencyLevel; set diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 84f0b8c877..6006135a2b 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -1086,6 +1086,6 @@ namespace Avalonia.X11 public IPopupPositioner PopupPositioner { get; } public ITopLevelNativeMenuExporter NativeMenuExporter { get; } - public WindowTransparencyLevel TransparencyLevel { get; set; } + public WindowTransparencyLevel TransparencyLevelHint { get; set; } } } diff --git a/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs b/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs index fa518bafec..3f50e1e4eb 100644 --- a/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs +++ b/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs @@ -83,6 +83,6 @@ namespace Avalonia.LinuxFramebuffer public Size ScaledSize => _outputBackend.PixelSize.ToSize(Scaling); - public WindowTransparencyLevel TransparencyLevel { get => WindowTransparencyLevel.None; set { } } + public WindowTransparencyLevel TransparencyLevelHint { get => WindowTransparencyLevel.None; set { } } } } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 2cf87c1556..005df2b99b 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -210,7 +210,7 @@ namespace Avalonia.Win32 } } - public WindowTransparencyLevel TransparencyLevel + public WindowTransparencyLevel TransparencyLevelHint { get => _transparencyLevel; set From 21e3642a2ca2ca4cd5c35b484eefdc3a4e36fd5e Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 20 May 2020 11:42:33 -0300 Subject: [PATCH 13/30] encapsulate and cache os version. --- src/Windows/Avalonia.Win32/Win32Platform.cs | 5 +++++ src/Windows/Avalonia.Win32/WindowImpl.cs | 5 ++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs index c01bc8e16d..e25c5e4733 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -58,6 +58,11 @@ namespace Avalonia.Win32 CreateMessageWindow(); } + /// + /// Gets the actual WindowsVersion. Same as the info returned from RtlGetVersion. + /// + public static Version WindowsVersion { get; } = RtlGetVersion(); + public static bool UseDeferredRendering => Options.UseDeferredRendering; internal static bool UseOverlayPopups => Options.OverlayPopups; public static Win32PlatformOptions Options { get; private set; } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 005df2b99b..105823d206 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -227,15 +227,14 @@ namespace Avalonia.Win32 private WindowTransparencyLevel EnableBlur(WindowTransparencyLevel transparencyLevel) { - var version = RtlGetVersion(); bool canUseTransparency = false; bool canUseAcrylic = false; - if (version.Major >= 10) + if (Win32Platform.WindowsVersion.Major >= 10) { canUseTransparency = true; - if (version.Build >= 19628) + if (Win32Platform.WindowsVersion.Build >= 19628) { canUseAcrylic = true; } From 20916d49db969af5f1d7650e52721c45b906efe2 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 20 May 2020 15:39:02 -0300 Subject: [PATCH 14/30] fix transparency fallback border. --- src/Avalonia.Themes.Default/EmbeddableControlRoot.xaml | 5 +++-- src/Avalonia.Themes.Default/OverlayPopupHost.xaml | 5 +++-- src/Avalonia.Themes.Default/PopupRoot.xaml | 5 +++-- src/Avalonia.Themes.Default/Window.xaml | 5 +++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/Avalonia.Themes.Default/EmbeddableControlRoot.xaml b/src/Avalonia.Themes.Default/EmbeddableControlRoot.xaml index 3acab7d7bc..9ffe51fae8 100644 --- a/src/Avalonia.Themes.Default/EmbeddableControlRoot.xaml +++ b/src/Avalonia.Themes.Default/EmbeddableControlRoot.xaml @@ -3,7 +3,8 @@ - + + - + diff --git a/src/Avalonia.Themes.Default/OverlayPopupHost.xaml b/src/Avalonia.Themes.Default/OverlayPopupHost.xaml index e57325499d..36dbc1b761 100644 --- a/src/Avalonia.Themes.Default/OverlayPopupHost.xaml +++ b/src/Avalonia.Themes.Default/OverlayPopupHost.xaml @@ -2,7 +2,8 @@ - + + - + diff --git a/src/Avalonia.Themes.Default/PopupRoot.xaml b/src/Avalonia.Themes.Default/PopupRoot.xaml index 1a55d2f7a4..9af4f5a910 100644 --- a/src/Avalonia.Themes.Default/PopupRoot.xaml +++ b/src/Avalonia.Themes.Default/PopupRoot.xaml @@ -2,7 +2,8 @@ - + + - + diff --git a/src/Avalonia.Themes.Default/Window.xaml b/src/Avalonia.Themes.Default/Window.xaml index e29409e894..0e7ec42856 100644 --- a/src/Avalonia.Themes.Default/Window.xaml +++ b/src/Avalonia.Themes.Default/Window.xaml @@ -4,7 +4,8 @@ - + + - + From f88f94cce35d8a1aea2aba1c376ba0af58cd5767 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 20 May 2020 17:11:15 -0300 Subject: [PATCH 15/30] fix win 10 version number check --- src/Windows/Avalonia.Win32/WindowImpl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 105823d206..6a78c150e0 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -234,7 +234,7 @@ namespace Avalonia.Win32 { canUseTransparency = true; - if (Win32Platform.WindowsVersion.Build >= 19628) + if (Win32Platform.WindowsVersion.Major > 10 || Win32Platform.WindowsVersion.Build >= 19628) { canUseAcrylic = true; } From b818ca05d4193648b20c3c4f7e6af9ffa639cbf0 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 20 May 2020 18:23:37 -0300 Subject: [PATCH 16/30] always draw the border. --- src/Windows/Avalonia.Win32/WindowImpl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 6a78c150e0..5eb92a4023 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -268,7 +268,7 @@ namespace Avalonia.Win32 break; } - accent.AccentFlags = 2; + accent.AccentFlags = 2 | (int)(AccentFlags.DrawLeftBorder | AccentFlags.DrawBottomBorder | AccentFlags.DrawRightBorder | AccentFlags.DrawTopBorder); accent.GradientColor = 0x00FFFFFF; var accentPtr = Marshal.AllocHGlobal(accentStructSize); From d1049fd79fcc9ffe64853bbd181c557d38c67f9a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 20 May 2020 18:37:33 -0300 Subject: [PATCH 17/30] dont use property for setting transparency level hint. --- .../Offscreen/OffscreenTopLevelImpl.cs | 4 +++- .../Platform/ITopLevelImpl.cs | 9 ++++++-- src/Avalonia.Controls/TopLevel.cs | 4 ++-- src/Avalonia.DesignerSupport/Remote/Stubs.cs | 4 +++- src/Avalonia.Native/WindowImplBase.cs | 20 +++++++--------- src/Avalonia.X11/X11Window.cs | 5 +++- .../FramebufferToplevelImpl.cs | 4 +++- src/Windows/Avalonia.Win32/WindowImpl.cs | 23 ++++++++----------- 8 files changed, 40 insertions(+), 33 deletions(-) diff --git a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs index 625acb17c3..09f9ed7c1b 100644 --- a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs +++ b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevelImpl.cs @@ -65,7 +65,9 @@ namespace Avalonia.Controls.Embedding.Offscreen public Action Closed { get; set; } public abstract IMouseDevice MouseDevice { get; } - public WindowTransparencyLevel TransparencyLevelHint { get => WindowTransparencyLevel.None; set { } } + public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { } + + public WindowTransparencyLevel TransparencyLevel { get; private set; } public IPopupImpl CreatePopup() => null; } diff --git a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs index 4bcfaf91d6..c7875f6413 100644 --- a/src/Avalonia.Controls/Platform/ITopLevelImpl.cs +++ b/src/Avalonia.Controls/Platform/ITopLevelImpl.cs @@ -114,8 +114,13 @@ namespace Avalonia.Platform IPopupImpl CreatePopup(); /// - /// Gets or sets the of the TopLevel. + /// Sets the hint of the TopLevel. /// - WindowTransparencyLevel TransparencyLevelHint { get; set; } + void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel); + + /// + /// Gets the current of the TopLevel. + /// + WindowTransparencyLevel TransparencyLevel { get; } } } diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 6c09420f35..b61623a759 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -83,7 +83,7 @@ namespace Avalonia.Controls AffectsMeasure(ClientSizeProperty); TransparencyLevelHintProperty.Changed.AddClassHandler( - (tl, e) => { if (tl.PlatformImpl != null) tl.PlatformImpl.TransparencyLevelHint = (WindowTransparencyLevel)e.NewValue; }); + (tl, e) => { if (tl.PlatformImpl != null) tl.PlatformImpl.SetTransparencyLevelHint((WindowTransparencyLevel)e.NewValue); }); } /// @@ -402,7 +402,7 @@ namespace Avalonia.Controls _transparencyFallbackBorder = e.NameScope.Find("PART_TransparencyFallback"); - HandleTransparencyLevelChanged(PlatformImpl.TransparencyLevelHint); + HandleTransparencyLevelChanged(PlatformImpl.TransparencyLevel); } /// diff --git a/src/Avalonia.DesignerSupport/Remote/Stubs.cs b/src/Avalonia.DesignerSupport/Remote/Stubs.cs index 95284f18fe..a9665b1519 100644 --- a/src/Avalonia.DesignerSupport/Remote/Stubs.cs +++ b/src/Avalonia.DesignerSupport/Remote/Stubs.cs @@ -144,7 +144,9 @@ namespace Avalonia.DesignerSupport.Remote public Action GotInputWhenDisabled { get; set; } - public WindowTransparencyLevel TransparencyLevelHint { get => WindowTransparencyLevel.None; set { } } + public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { } + + public WindowTransparencyLevel TransparencyLevel { get; private set; } } class ClipboardStub : IClipboard diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index 5852675fb6..5072d98256 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -391,23 +391,19 @@ namespace Avalonia.Native _native.BeginDragAndDropOperation(effects, point, clipboard, callback, sourceHandle); } - private WindowTransparencyLevel _transparencyLevel; - - public WindowTransparencyLevel TransparencyLevelHint + public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { - get => _transparencyLevel; - set + if (TransparencyLevel != transparencyLevel) { - if(_transparencyLevel != value) - { - _transparencyLevel = value; + TransparencyLevel = transparencyLevel; - _native.SetBlurEnabled(_transparencyLevel >= WindowTransparencyLevel.Blur); - TransparencyLevelChanged?.Invoke(_transparencyLevel); - } - } + _native.SetBlurEnabled(TransparencyLevel >= WindowTransparencyLevel.Blur); + TransparencyLevelChanged?.Invoke(TransparencyLevel); + } } + public WindowTransparencyLevel TransparencyLevel { get; private set; } + public IPlatformHandle Handle { get; private set; } } } diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 6006135a2b..bce82b2954 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -1086,6 +1086,9 @@ namespace Avalonia.X11 public IPopupPositioner PopupPositioner { get; } public ITopLevelNativeMenuExporter NativeMenuExporter { get; } - public WindowTransparencyLevel TransparencyLevelHint { get; set; } + + public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { } + + public WindowTransparencyLevel TransparencyLevel { get; private set; } } } diff --git a/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs b/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs index 3f50e1e4eb..d4a29e39c6 100644 --- a/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs +++ b/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs @@ -83,6 +83,8 @@ namespace Avalonia.LinuxFramebuffer public Size ScaledSize => _outputBackend.PixelSize.ToSize(Scaling); - public WindowTransparencyLevel TransparencyLevelHint { get => WindowTransparencyLevel.None; set { } } + public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { } + + public WindowTransparencyLevel TransparencyLevel { get; private set; } } } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 5eb92a4023..e9c14274cd 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -66,8 +66,7 @@ namespace Avalonia.Win32 private OleDropTarget _dropTarget; private Size _minSize; private Size _maxSize; - private WindowImpl _parent; - private WindowTransparencyLevel _transparencyLevel = WindowTransparencyLevel.None; + private WindowImpl _parent; public WindowImpl() { @@ -210,18 +209,16 @@ namespace Avalonia.Win32 } } - public WindowTransparencyLevel TransparencyLevelHint + public WindowTransparencyLevel TransparencyLevel { get; private set; } + + public void SetTransparencyLevelHint (WindowTransparencyLevel transparencyLevel) { - get => _transparencyLevel; - set - { - var oldValue = _transparencyLevel; - _transparencyLevel = EnableBlur(value); + var level = EnableBlur(transparencyLevel); - if (oldValue != _transparencyLevel) - { - TransparencyLevelChanged?.Invoke(_transparencyLevel); - } + if (TransparencyLevel != level) + { + TransparencyLevel = level; + TransparencyLevelChanged?.Invoke(TransparencyLevel); } } @@ -281,7 +278,7 @@ namespace Avalonia.Win32 SetWindowCompositionAttribute(_hwnd, ref data); - Marshal.FreeHGlobal(accentPtr); + Marshal.FreeHGlobal(accentPtr); return transparencyLevel; } From 1a5c8fcf3f9f92067f07385da71f2df742276fde Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Thu, 21 May 2020 01:12:19 +0300 Subject: [PATCH 18/30] X11 transparency reporting and blur support --- src/Avalonia.X11/TransparencyHelper.cs | 83 +++++++++++ src/Avalonia.X11/X11Atoms.cs | 2 + src/Avalonia.X11/X11Globals.cs | 183 +++++++++++++++++++++++++ src/Avalonia.X11/X11Platform.cs | 2 + src/Avalonia.X11/X11Window.cs | 15 +- 5 files changed, 282 insertions(+), 3 deletions(-) create mode 100644 src/Avalonia.X11/TransparencyHelper.cs create mode 100644 src/Avalonia.X11/X11Globals.cs diff --git a/src/Avalonia.X11/TransparencyHelper.cs b/src/Avalonia.X11/TransparencyHelper.cs new file mode 100644 index 0000000000..6d62d21ec6 --- /dev/null +++ b/src/Avalonia.X11/TransparencyHelper.cs @@ -0,0 +1,83 @@ +using System; +using Avalonia.Controls; + +namespace Avalonia.X11 +{ + class TransparencyHelper : IDisposable, X11Globals.IGlobalsSubscriber + { + private readonly X11Info _x11; + private readonly IntPtr _window; + private readonly X11Globals _globals; + private WindowTransparencyLevel _currentLevel; + private WindowTransparencyLevel _requestedLevel; + private bool _isCompositing; + private bool _blurAtomsAreSet; + + public Action TransparencyLevelChanged { get; set; } + public WindowTransparencyLevel CurrentLevel => _currentLevel; + + public TransparencyHelper(X11Info x11, IntPtr window, X11Globals globals) + { + _x11 = x11; + _window = window; + _globals = globals; + _globals.AddSubscriber(this); + } + + public void SetTransparencyRequest(WindowTransparencyLevel level) + { + _requestedLevel = level; + UpdateTransparency(); + } + + private void UpdateTransparency() + { + var newLevel = UpdateAtomsAndGetTransparency(); + if (newLevel != _currentLevel) + { + _currentLevel = newLevel; + TransparencyLevelChanged?.Invoke(newLevel); + } + } + + private WindowTransparencyLevel UpdateAtomsAndGetTransparency() + { + if (_requestedLevel >= WindowTransparencyLevel.Blur) + { + if (!_blurAtomsAreSet) + { + IntPtr value = IntPtr.Zero; + XLib.XChangeProperty(_x11.Display, _window, _x11.Atoms._KDE_NET_WM_BLUR_BEHIND_REGION, + _x11.Atoms.XA_CARDINAL, 32, PropertyMode.Replace, ref value, 1); + _blurAtomsAreSet = true; + } + } + else + { + if (_blurAtomsAreSet) + { + XLib.XDeleteProperty(_x11.Display, _window, _x11.Atoms._KDE_NET_WM_BLUR_BEHIND_REGION); + _blurAtomsAreSet = false; + } + } + + if (!_globals.IsCompositionEnabled) + return WindowTransparencyLevel.None; + if (_requestedLevel >= WindowTransparencyLevel.Blur && CanBlur) + return WindowTransparencyLevel.Blur; + return WindowTransparencyLevel.Transparent; + } + + + private bool CanBlur => _globals.WmName == "KWin" && _globals.IsCompositionEnabled; + + public void Dispose() + { + _globals.RemoveSubscriber(this); + } + + void X11Globals.IGlobalsSubscriber.WmChanged(string wmName) => UpdateTransparency(); + + void X11Globals.IGlobalsSubscriber.CompositionChanged(bool compositing) => UpdateTransparency(); + } +} diff --git a/src/Avalonia.X11/X11Atoms.cs b/src/Avalonia.X11/X11Atoms.cs index 523b65c115..dd16fae386 100644 --- a/src/Avalonia.X11/X11Atoms.cs +++ b/src/Avalonia.X11/X11Atoms.cs @@ -185,6 +185,8 @@ namespace Avalonia.X11 public readonly IntPtr UTF8_STRING; public readonly IntPtr UTF16_STRING; public readonly IntPtr ATOM_PAIR; + public readonly IntPtr MANAGER; + public readonly IntPtr _KDE_NET_WM_BLUR_BEHIND_REGION; public X11Atoms(IntPtr display) diff --git a/src/Avalonia.X11/X11Globals.cs b/src/Avalonia.X11/X11Globals.cs new file mode 100644 index 0000000000..54032831f6 --- /dev/null +++ b/src/Avalonia.X11/X11Globals.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using static Avalonia.X11.XLib; +namespace Avalonia.X11 +{ + unsafe class X11Globals + { + private readonly AvaloniaX11Platform _plat; + private readonly int _screenNumber; + private readonly X11Info _x11; + private readonly IntPtr _rootWindow; + private readonly IntPtr _compositingAtom; + private readonly List _subscribers = new List(); + + private string _wmName; + private IntPtr _compositionAtomOwner; + private bool _isCompositionEnabled; + + public X11Globals(AvaloniaX11Platform plat) + { + _plat = plat; + _x11 = plat.Info; + _screenNumber = XDefaultScreen(_x11.Display); + _rootWindow = XRootWindow(_x11.Display, _screenNumber); + plat.Windows[_rootWindow] = OnRootWindowEvent; + XSelectInput(_x11.Display, _rootWindow, + new IntPtr((int)(EventMask.StructureNotifyMask | EventMask.PropertyChangeMask))); + _compositingAtom = XInternAtom(_x11.Display, "_NET_WM_CM_S" + _screenNumber, false); + UpdateWmName(); + UpdateCompositingAtomOwner(); + } + + public string WmName + { + get => _wmName; + private set + { + if (_wmName != value) + { + _wmName = value; + // The collection might change during enumeration + foreach (var s in _subscribers.ToList()) + s.WmChanged(value); + } + } + } + + private IntPtr CompositionAtomOwner + { + get => _compositionAtomOwner; + set + { + if (_compositionAtomOwner != value) + { + _compositionAtomOwner = value; + IsCompositionEnabled = _compositionAtomOwner != IntPtr.Zero; + } + } + } + + public bool IsCompositionEnabled + { + get => _isCompositionEnabled; + set + { + if (_isCompositionEnabled != value) + { + _isCompositionEnabled = value; + // The collection might change during enumeration + foreach (var s in _subscribers.ToList()) + s.CompositionChanged(value); + } + } + } + + + IntPtr GetSupportingWmCheck(IntPtr window) + { + XGetWindowProperty(_x11.Display, _rootWindow, _x11.Atoms._NET_SUPPORTING_WM_CHECK, + IntPtr.Zero, new IntPtr(IntPtr.Size), false, + _x11.Atoms.XA_WINDOW, out IntPtr actualType, out int actualFormat, out IntPtr nitems, + out IntPtr bytesAfter, out IntPtr prop); + if (nitems.ToInt32() != 1) + return IntPtr.Zero; + try + { + if (actualType != _x11.Atoms.XA_WINDOW) + return IntPtr.Zero; + return *(IntPtr*)prop.ToPointer(); + } + finally + { + XFree(prop); + } + } + + void UpdateCompositingAtomOwner() + { + // This procedure is described in https://tronche.com/gui/x/icccm/sec-2.html#s-2.8 + + // Check the server-side selection owner + var newOwner = XGetSelectionOwner(_x11.Display, _compositingAtom); + while (CompositionAtomOwner != newOwner) + { + // We have a new owner, unsubscribe from the previous one first + if (CompositionAtomOwner != IntPtr.Zero) + { + _plat.Windows.Remove(CompositionAtomOwner); + XSelectInput(_x11.Display, CompositionAtomOwner, IntPtr.Zero); + } + + // Set it as the current owner and select input + CompositionAtomOwner = newOwner; + if (CompositionAtomOwner != IntPtr.Zero) + { + _plat.Windows[newOwner] = HandleCompositionAtomOwnerEvents; + XSelectInput(_x11.Display, CompositionAtomOwner, new IntPtr((int)(EventMask.StructureNotifyMask))); + } + + // Check for the new owner again and repeat the procedure if it was changed between XGetSelectionOwner and XSelectInput call + newOwner = XGetSelectionOwner(_x11.Display, _compositingAtom); + } + } + + private void HandleCompositionAtomOwnerEvents(XEvent ev) + { + if(ev.type == XEventName.DestroyNotify) + UpdateCompositingAtomOwner(); + } + + void UpdateWmName() => WmName = GetWmName(); + + string GetWmName() + { + var wm = GetSupportingWmCheck(_rootWindow); + if (wm == IntPtr.Zero || wm != GetSupportingWmCheck(wm)) + return null; + XGetWindowProperty(_x11.Display, wm, _x11.Atoms._NET_WM_NAME, + IntPtr.Zero, new IntPtr(0x7fffffff), + false, _x11.Atoms.UTF8_STRING, out var actualType, out var actualFormat, + out var nitems, out _, out var prop); + if (nitems == IntPtr.Zero) + return null; + try + { + if (actualFormat != 8) + return null; + return Marshal.PtrToStringAnsi(prop, nitems.ToInt32()); + } + finally + { + XFree(prop); + } + } + + private void OnRootWindowEvent(XEvent ev) + { + if (ev.type == XEventName.PropertyNotify) + { + if(ev.PropertyEvent.atom == _x11.Atoms._NET_SUPPORTING_WM_CHECK) + UpdateWmName(); + } + + if (ev.type == XEventName.ClientMessage) + { + if(ev.ClientMessageEvent.message_type == _x11.Atoms.MANAGER + && ev.ClientMessageEvent.ptr2 == _compositingAtom) + UpdateCompositingAtomOwner(); + } + } + + public interface IGlobalsSubscriber + { + void WmChanged(string wmName); + void CompositionChanged(bool compositing); + } + + public void AddSubscriber(IGlobalsSubscriber subscriber) => _subscribers.Add(subscriber); + public void RemoveSubscriber(IGlobalsSubscriber subscriber) => _subscribers.Remove(subscriber); + } +} diff --git a/src/Avalonia.X11/X11Platform.cs b/src/Avalonia.X11/X11Platform.cs index a1bfa682f5..c2b3926ffd 100644 --- a/src/Avalonia.X11/X11Platform.cs +++ b/src/Avalonia.X11/X11Platform.cs @@ -26,6 +26,7 @@ namespace Avalonia.X11 public IX11Screens X11Screens { get; private set; } public IScreenImpl Screens { get; private set; } public X11PlatformOptions Options { get; private set; } + public X11Globals Globals { get; private set; } public void Initialize(X11PlatformOptions options) { Options = options; @@ -36,6 +37,7 @@ namespace Avalonia.X11 throw new Exception("XOpenDisplay failed"); XError.Init(); Info = new X11Info(Display, DeferredDisplay); + Globals = new X11Globals(this); //TODO: log if (options.UseDBusMenu) DBusHelper.TryInitialize(); diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index bce82b2954..4899f0efc0 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -43,6 +43,7 @@ namespace Avalonia.X11 private bool _wasMappedAtLeastOnce = false; private double? _scalingOverride; private bool _disabled; + private TransparencyHelper _transparencyHelper; public object SyncRoot { get; } = new object(); @@ -176,6 +177,9 @@ namespace Avalonia.X11 UpdateSizeHints(null); _xic = XCreateIC(_x11.Xim, XNames.XNInputStyle, XIMProperties.XIMPreeditNothing | XIMProperties.XIMStatusNothing, XNames.XNClientWindow, _handle, IntPtr.Zero); + _transparencyHelper = new TransparencyHelper(_x11, _handle, platform.Globals); + _transparencyHelper.SetTransparencyRequest(WindowTransparencyLevel.None); + XFlush(_x11.Display); if(_popup) PopupPositioner = new ManagedPopupPositioner(new ManagedPopupPositionerPopupImplHelper(popupParent, MoveResize)); @@ -301,7 +305,11 @@ namespace Avalonia.X11 public Func Closing { get; set; } public Action WindowStateChanged { get; set; } - public Action TransparencyLevelChanged { get; set; } + public Action TransparencyLevelChanged + { + get => _transparencyHelper.TransparencyLevelChanged; + set => _transparencyHelper.TransparencyLevelChanged = value; + } public Action Closed { get; set; } public Action PositionChanged { get; set; } @@ -1087,8 +1095,9 @@ namespace Avalonia.X11 public IPopupPositioner PopupPositioner { get; } public ITopLevelNativeMenuExporter NativeMenuExporter { get; } - public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { } + public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) => + _transparencyHelper.SetTransparencyRequest(transparencyLevel); - public WindowTransparencyLevel TransparencyLevel { get; private set; } + public WindowTransparencyLevel TransparencyLevel => _transparencyHelper.CurrentLevel; } } From 2354db63063f03942a8de9604f534be6fbe3e87c Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 20 May 2020 19:18:01 -0300 Subject: [PATCH 19/30] take into account the requested transparency hint when setting the fallback. --- src/Avalonia.Controls/TopLevel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index b61623a759..b7ff30680c 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -374,7 +374,7 @@ namespace Avalonia.Controls { if(_transparencyFallbackBorder != null) { - if(transparencyLevel == WindowTransparencyLevel.None) + if(transparencyLevel == WindowTransparencyLevel.None || TransparencyLevelHint == WindowTransparencyLevel.None) { _transparencyFallbackBorder.Background = TransparencyBackgroundFallback; } From aff7815d98682629b3f67a181ee3a8af687bc15c Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 20 May 2020 19:27:07 -0300 Subject: [PATCH 20/30] HandleTransparencyChanged when Hint changes. --- src/Avalonia.Controls/TopLevel.cs | 9 ++++++++- src/Windows/Avalonia.Win32/WindowImpl.cs | 8 +------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index b7ff30680c..53b9d081d4 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -83,7 +83,14 @@ namespace Avalonia.Controls AffectsMeasure(ClientSizeProperty); TransparencyLevelHintProperty.Changed.AddClassHandler( - (tl, e) => { if (tl.PlatformImpl != null) tl.PlatformImpl.SetTransparencyLevelHint((WindowTransparencyLevel)e.NewValue); }); + (tl, e) => + { + if (tl.PlatformImpl != null) + { + tl.PlatformImpl.SetTransparencyLevelHint((WindowTransparencyLevel)e.NewValue); + tl.HandleTransparencyLevelChanged(tl.PlatformImpl.TransparencyLevel); + } + }); } /// diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index e9c14274cd..193f60a7cf 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -213,13 +213,7 @@ namespace Avalonia.Win32 public void SetTransparencyLevelHint (WindowTransparencyLevel transparencyLevel) { - var level = EnableBlur(transparencyLevel); - - if (TransparencyLevel != level) - { - TransparencyLevel = level; - TransparencyLevelChanged?.Invoke(TransparencyLevel); - } + TransparencyLevel = EnableBlur(transparencyLevel); } private WindowTransparencyLevel EnableBlur(WindowTransparencyLevel transparencyLevel) From df43cd75698fa9a2d97b3a0ccac6821c4e0ff78d Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 20 May 2020 21:30:29 -0300 Subject: [PATCH 21/30] fix wpf integration. --- src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs index 2887468046..b30831667b 100644 --- a/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs +++ b/src/Windows/Avalonia.Win32.Interop/Wpf/WpfTopLevelImpl.cs @@ -5,6 +5,7 @@ using System.Windows; using System.Windows.Input; using System.Windows.Interop; using System.Windows.Media; +using Avalonia.Controls; using Avalonia.Controls.Embedding; using Avalonia.Input; using Avalonia.Input.Raw; @@ -236,6 +237,9 @@ namespace Avalonia.Win32.Interop.Wpf Action ITopLevelImpl.Paint { get; set; } Action ITopLevelImpl.Resized { get; set; } Action ITopLevelImpl.ScalingChanged { get; set; } + + Action ITopLevelImpl.TransparencyLevelChanged { get; set; } + Action ITopLevelImpl.Closed { get; set; } public new event Action LostFocus; @@ -248,5 +252,9 @@ namespace Avalonia.Win32.Interop.Wpf } public IPopupImpl CreatePopup() => null; + + public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { } + + public WindowTransparencyLevel TransparencyLevel { get; private set; } } } From 4bc1801c2af491dcd9ff6c903c37b4c11421c7b0 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 21 May 2020 19:55:28 -0300 Subject: [PATCH 22/30] fix popup tests. --- .../Primitives/PopupRootTests.cs | 9 +++++++-- .../Avalonia.Controls.UnitTests/Primitives/PopupTests.cs | 4 ++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs index ddf109f80e..08b9c75dbc 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs @@ -77,8 +77,13 @@ namespace Avalonia.Controls.UnitTests.Primitives var templatedChild = ((Visual)target.Host).GetVisualChildren().Single(); - Assert.IsType(templatedChild); - var contentPresenter = templatedChild.VisualChildren.Single(); + Assert.IsType(templatedChild); + + var visualLayerManager = templatedChild.GetVisualChildren().Skip(1).Single(); + + Assert.IsType(visualLayerManager); + + var contentPresenter = visualLayerManager.VisualChildren.Single(); Assert.IsType(contentPresenter); diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs index 0b9c94f850..fd06ba295b 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs @@ -275,6 +275,8 @@ namespace Avalonia.Controls.UnitTests.Primitives Assert.Equal( new[] { + "Panel", + "Border", "VisualLayerManager", "ContentPresenter", "ContentPresenter", @@ -289,6 +291,8 @@ namespace Avalonia.Controls.UnitTests.Primitives Assert.Equal( new object[] { + popupRoot, + popupRoot, popupRoot, popupRoot, target, From cfbd6991f6f7223c973df79b957c0f8100fa48e0 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 22 May 2020 08:39:25 -0300 Subject: [PATCH 23/30] always give fallback if you dont get the setting asked for. --- src/Avalonia.Controls/TopLevel.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 53b9d081d4..be2efc23e7 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -381,7 +381,9 @@ namespace Avalonia.Controls { if(_transparencyFallbackBorder != null) { - if(transparencyLevel == WindowTransparencyLevel.None || TransparencyLevelHint == WindowTransparencyLevel.None) + if(transparencyLevel == WindowTransparencyLevel.None || + TransparencyLevelHint == WindowTransparencyLevel.None || + transparencyLevel != TransparencyLevelHint) { _transparencyFallbackBorder.Background = TransparencyBackgroundFallback; } From 2db3eee7b924c9bb0a3f2710781f973330c181b0 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 22 May 2020 08:49:39 -0300 Subject: [PATCH 24/30] add blurbehind api for someone to use for win7 support in future. --- .../Interop/UnmanagedMethods.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index b06708ebd2..da52c3116e 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -1305,6 +1305,34 @@ namespace Avalonia.Win32.Interop [DllImport("dwmapi.dll")] public static extern int DwmIsCompositionEnabled(out bool enabled); + [DllImport("dwmapi.dll")] + public static extern void DwmEnableBlurBehindWindow(IntPtr hwnd, ref DWM_BLURBEHIND blurBehind); + + [Flags] + public enum DWM_BB + { + Enable = 1, + BlurRegion = 2, + TransitionMaximized = 4 + } + + [StructLayout(LayoutKind.Sequential)] + public struct DWM_BLURBEHIND + { + public DWM_BB dwFlags; + public bool fEnable; + public IntPtr hRgnBlur; + public bool fTransitionOnMaximized; + + public DWM_BLURBEHIND(bool enabled) + { + fEnable = enabled ? true : false; + hRgnBlur = IntPtr.Zero; + fTransitionOnMaximized = false; + dwFlags = DWM_BB.Enable; + } + } + [StructLayout(LayoutKind.Sequential)] internal struct RTL_OSVERSIONINFOEX { From 3dbe59062a58070a7ba62535cf62030edcbc5285 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 22 May 2020 08:53:34 -0300 Subject: [PATCH 25/30] fix win32 generating borders in blur / transparent mode. --- src/Windows/Avalonia.Win32/WindowImpl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 193f60a7cf..b2b173ce64 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -259,7 +259,7 @@ namespace Avalonia.Win32 break; } - accent.AccentFlags = 2 | (int)(AccentFlags.DrawLeftBorder | AccentFlags.DrawBottomBorder | AccentFlags.DrawRightBorder | AccentFlags.DrawTopBorder); + accent.AccentFlags = 2; accent.GradientColor = 0x00FFFFFF; var accentPtr = Marshal.AllocHGlobal(accentStructSize); From 3e7b8933b2a0e0a4fdc1b0d1da022136e3a47c7e Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 22 May 2020 08:59:06 -0300 Subject: [PATCH 26/30] whitespace fixes. --- src/Avalonia.Controls/TopLevel.cs | 1 - src/Avalonia.X11/TransparencyHelper.cs | 1 - src/Avalonia.X11/X11Globals.cs | 1 - src/Windows/Avalonia.Win32/WindowImpl.cs | 2 +- 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index be2efc23e7..fa5f16f891 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -15,7 +15,6 @@ using JetBrains.Annotations; namespace Avalonia.Controls { - /// /// Base class for top-level widgets. /// diff --git a/src/Avalonia.X11/TransparencyHelper.cs b/src/Avalonia.X11/TransparencyHelper.cs index 6d62d21ec6..0578680136 100644 --- a/src/Avalonia.X11/TransparencyHelper.cs +++ b/src/Avalonia.X11/TransparencyHelper.cs @@ -68,7 +68,6 @@ namespace Avalonia.X11 return WindowTransparencyLevel.Transparent; } - private bool CanBlur => _globals.WmName == "KWin" && _globals.IsCompositionEnabled; public void Dispose() diff --git a/src/Avalonia.X11/X11Globals.cs b/src/Avalonia.X11/X11Globals.cs index 54032831f6..afde15b808 100644 --- a/src/Avalonia.X11/X11Globals.cs +++ b/src/Avalonia.X11/X11Globals.cs @@ -75,7 +75,6 @@ namespace Avalonia.X11 } } - IntPtr GetSupportingWmCheck(IntPtr window) { XGetWindowProperty(_x11.Display, _rootWindow, _x11.Atoms._NET_SUPPORTING_WM_CHECK, diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index b2b173ce64..b7ec6e0d5a 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -66,7 +66,7 @@ namespace Avalonia.Win32 private OleDropTarget _dropTarget; private Size _minSize; private Size _maxSize; - private WindowImpl _parent; + private WindowImpl _parent; public WindowImpl() { From 730862b753d6eafc2e053cbd2db2840c77d9b0ba Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 22 May 2020 09:35:30 -0300 Subject: [PATCH 27/30] Add acrylic blur level with fallbacks to blur reported. --- src/Avalonia.Controls/TopLevel.cs | 16 +++++++++++++++- src/Avalonia.Controls/WindowTransparencyLevel.cs | 7 ++++++- src/Avalonia.Native/WindowImplBase.cs | 5 +++++ src/Windows/Avalonia.Win32/WindowImpl.cs | 11 +++++++++-- 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index fa5f16f891..bd41eb5f28 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -376,13 +376,27 @@ namespace Avalonia.Controls LayoutHelper.InvalidateSelfAndChildrenMeasure(this); } + private bool TransparencyLevelsMatch (WindowTransparencyLevel requested, WindowTransparencyLevel received) + { + if(requested == received) + { + return true; + } + else if(requested >= WindowTransparencyLevel.Blur && received >= WindowTransparencyLevel.Blur) + { + return true; + } + + return false; + } + protected virtual void HandleTransparencyLevelChanged(WindowTransparencyLevel transparencyLevel) { if(_transparencyFallbackBorder != null) { if(transparencyLevel == WindowTransparencyLevel.None || TransparencyLevelHint == WindowTransparencyLevel.None || - transparencyLevel != TransparencyLevelHint) + !TransparencyLevelsMatch(TransparencyLevelHint, transparencyLevel)) { _transparencyFallbackBorder.Background = TransparencyBackgroundFallback; } diff --git a/src/Avalonia.Controls/WindowTransparencyLevel.cs b/src/Avalonia.Controls/WindowTransparencyLevel.cs index f5fc0ca9dd..ce7c03efbb 100644 --- a/src/Avalonia.Controls/WindowTransparencyLevel.cs +++ b/src/Avalonia.Controls/WindowTransparencyLevel.cs @@ -15,6 +15,11 @@ /// /// The window background is a blur-behind where nothing is drawn in the window. /// - Blur + Blur, + + /// + /// The window background is a blur-behind with a high blur radius. This level may fallback to Blur. + /// + AcrylicBlur } } diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index 5072d98256..77200b0a95 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -395,6 +395,11 @@ namespace Avalonia.Native { if (TransparencyLevel != transparencyLevel) { + if (transparencyLevel >= WindowTransparencyLevel.Blur) + { + transparencyLevel = WindowTransparencyLevel.AcrylicBlur; + } + TransparencyLevel = transparencyLevel; _native.SetBlurEnabled(TransparencyLevel >= WindowTransparencyLevel.Blur); diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index b7ec6e0d5a..0cf5a73b9f 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -239,6 +239,11 @@ namespace Avalonia.Win32 var accent = new AccentPolicy(); var accentStructSize = Marshal.SizeOf(accent); + if(transparencyLevel == WindowTransparencyLevel.AcrylicBlur && !canUseAcrylic) + { + transparencyLevel = WindowTransparencyLevel.Blur; + } + switch (transparencyLevel) { default: @@ -251,11 +256,13 @@ namespace Avalonia.Win32 break; case WindowTransparencyLevel.Blur: - accent.AccentState = canUseAcrylic ? AccentState.ACCENT_ENABLE_ACRYLIC : AccentState.ACCENT_ENABLE_BLURBEHIND; + accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND; break; - case (WindowTransparencyLevel.Blur + 1): // hack force acrylic on windows 10. + case WindowTransparencyLevel.AcrylicBlur: + case (WindowTransparencyLevel.AcrylicBlur + 1): // hack-force acrylic. accent.AccentState = AccentState.ACCENT_ENABLE_ACRYLIC; + transparencyLevel = WindowTransparencyLevel.AcrylicBlur; break; } From c0a04699feeb2fc271b491ec0c595288675f65a5 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 22 May 2020 09:51:34 -0300 Subject: [PATCH 28/30] add acrylic blur option. --- samples/ControlCatalog/MainView.xaml | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml index 5d62e61d0e..add5dbde84 100644 --- a/samples/ControlCatalog/MainView.xaml +++ b/samples/ControlCatalog/MainView.xaml @@ -74,6 +74,7 @@ None Transparent Blur + AcrylicBlur From 76316e4a4473979b36f00fe23dcd2d8a3d5ac0e4 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 22 May 2020 10:09:08 -0300 Subject: [PATCH 29/30] osx reports transparent as its minimum transparency level. --- src/Avalonia.Native/WindowImplBase.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index 77200b0a95..a7ca528b2b 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -400,6 +400,11 @@ namespace Avalonia.Native transparencyLevel = WindowTransparencyLevel.AcrylicBlur; } + if(transparencyLevel == WindowTransparencyLevel.None) + { + transparencyLevel = WindowTransparencyLevel.Transparent; + } + TransparencyLevel = transparencyLevel; _native.SetBlurEnabled(TransparencyLevel >= WindowTransparencyLevel.Blur); @@ -407,7 +412,7 @@ namespace Avalonia.Native } } - public WindowTransparencyLevel TransparencyLevel { get; private set; } + public WindowTransparencyLevel TransparencyLevel { get; private set; } = WindowTransparencyLevel.Transparent; public IPlatformHandle Handle { get; private set; } } From ea2fc5459022657a8bb5138dafaf09361ce2abae Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 22 May 2020 10:10:24 -0300 Subject: [PATCH 30/30] initialise render target transparency in toplevel. --- src/Avalonia.Controls/TopLevel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index bd41eb5f28..8335e03487 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -118,7 +118,7 @@ namespace Avalonia.Controls PlatformImpl = impl; - _actualTransparencyLevel = WindowTransparencyLevel.None; + _actualTransparencyLevel = PlatformImpl.TransparencyLevel; dependencyResolver = dependencyResolver ?? AvaloniaLocator.Current; var styler = TryGetService(dependencyResolver);