From e50816008ec7f517a73d5c72539d1cf8f965e448 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 25 May 2023 23:17:21 +0200 Subject: [PATCH] Set default transparency level. If no matching transparency level was found, use the default on all platforms. Raise `TransparencyLevelChanged` on all platforms. --- .../Platform/SkiaPlatform/TopLevelImpl.cs | 30 +++++++++++++- src/Avalonia.Native/WindowImplBase.cs | 27 ++++++++++--- src/Avalonia.X11/TransparencyHelper.cs | 40 ++++++++++--------- src/Windows/Avalonia.Win32/WindowImpl.cs | 32 +++++++++++++-- 4 files changed, 100 insertions(+), 29 deletions(-) diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs index 086de8f033..6f9fdf3569 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs @@ -46,6 +46,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform private readonly AndroidInsetsManager _insetsManager; private readonly ClipboardImpl _clipboard; private ViewImpl _view; + private WindowTransparencyLevel _transparencyLevel; public TopLevelImpl(AvaloniaView avaloniaView, bool placeOnTop = false) { @@ -69,6 +70,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform _nativeControlHost = new AndroidNativeControlHostImpl(avaloniaView); _storageProvider = new AndroidStorageProvider((Activity)avaloniaView.Context); + _transparencyLevel = WindowTransparencyLevel.None; _systemNavigationManager = new AndroidSystemNavigationManagerImpl(avaloniaView.Context as IActivityNavigationService); } @@ -275,7 +277,18 @@ namespace Avalonia.Android.Platform.SkiaPlatform public Action LostFocus { get; set; } public Action TransparencyLevelChanged { get; set; } - public WindowTransparencyLevel TransparencyLevel { get; private set; } + public WindowTransparencyLevel TransparencyLevel + { + get => _transparencyLevel; + private set + { + if (_transparencyLevel != value) + { + _transparencyLevel = value; + TransparencyLevelChanged?.Invoke(value); + } + } + } public void SetFrameThemeVariant(PlatformThemeVariant themeVariant) { @@ -312,6 +325,11 @@ namespace Avalonia.Android.Platform.SkiaPlatform continue; } + if (level == TransparencyLevel) + { + return; + } + if (level == WindowTransparencyLevel.None) { if (OperatingSystem.IsAndroidVersionAtLeast(30)) @@ -341,8 +359,16 @@ namespace Avalonia.Android.Platform.SkiaPlatform } TransparencyLevel = level; - break; + return; } + + // If we get here, we didn't find a supported level. Use the default of None. + if (OperatingSystem.IsAndroidVersionAtLeast(30)) + { + activity.SetTranslucent(false); + } + + activity.Window?.SetBackgroundDrawable(new ColorDrawable(Color.White)); } public virtual object TryGetFeature(Type featureType) diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index 0fe0c5e7c0..dfe30004b0 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -59,12 +59,12 @@ namespace Avalonia.Native private readonly IKeyboardDevice _keyboard; private readonly ICursorFactory _cursorFactory; private Size _savedLogicalSize; - private Size _lastRenderedLogicalSize; private double _savedScaling; private GlPlatformSurface _glSurface; private NativeControlHostImpl _nativeControlHost; private IStorageProvider _storageProvider; private PlatformBehaviorInhibition _platformBehaviorInhibition; + private WindowTransparencyLevel _transparencyLevel = WindowTransparencyLevel.None; internal WindowBaseImpl(IAvaloniaNativeFactory factory, AvaloniaNativePlatformOptions opts, AvaloniaNativeGlPlatformGraphics glFeature) @@ -498,17 +498,34 @@ namespace Avalonia.Native else if (level == WindowTransparencyLevel.AcrylicBlur) mode = AvnWindowTransparencyMode.Blur; - if (mode.HasValue) + if (mode.HasValue && level != TransparencyLevel) { _native?.SetTransparencyMode(mode.Value); TransparencyLevel = level; - TransparencyLevelChanged?.Invoke(TransparencyLevel); - break; + return; } } + + // If we get here, we didn't find a supported level. Use the default of None. + if (TransparencyLevel != WindowTransparencyLevel.None) + { + _native?.SetTransparencyMode(AvnWindowTransparencyMode.Opaque); + TransparencyLevel = WindowTransparencyLevel.None; + } } - public WindowTransparencyLevel TransparencyLevel { get; private set; } = WindowTransparencyLevel.None; + public WindowTransparencyLevel TransparencyLevel + { + get => _transparencyLevel; + private set + { + if (_transparencyLevel != value) + { + _transparencyLevel = value; + TransparencyLevelChanged?.Invoke(value); + } + } + } public void SetFrameThemeVariant(PlatformThemeVariant themeVariant) { diff --git a/src/Avalonia.X11/TransparencyHelper.cs b/src/Avalonia.X11/TransparencyHelper.cs index 01dccbf12a..3cc901e332 100644 --- a/src/Avalonia.X11/TransparencyHelper.cs +++ b/src/Avalonia.X11/TransparencyHelper.cs @@ -16,7 +16,19 @@ namespace Avalonia.X11 private bool _blurAtomsAreSet; public Action? TransparencyLevelChanged { get; set; } - public WindowTransparencyLevel CurrentLevel => _currentLevel; + + public WindowTransparencyLevel CurrentLevel + { + get => _currentLevel; + set + { + if (_currentLevel != value) + { + _currentLevel = value; + TransparencyLevelChanged?.Invoke(value); + } + } + } public TransparencyHelper(X11Info x11, IntPtr window, X11Globals globals) { @@ -28,7 +40,6 @@ namespace Avalonia.X11 public void SetTransparencyRequest(IReadOnlyList levels) { - WindowTransparencyLevel? newLevel = null; _requestedLevels = levels; foreach (var level in levels) @@ -37,25 +48,16 @@ namespace Avalonia.X11 continue; SetBlur(level == WindowTransparencyLevel.Blur); - newLevel = level; - break; - } - - // If no matching transparency level was found, revert to Transparent or None depending - // on whether composition is enabled. - if (!newLevel.HasValue) - { - newLevel = _globals.IsCompositionEnabled ? - WindowTransparencyLevel.Transparent : - WindowTransparencyLevel.None; - SetBlur(false); + CurrentLevel = level; + return; } - if (newLevel != _currentLevel) - { - _currentLevel = newLevel.Value; - TransparencyLevelChanged?.Invoke(newLevel.Value); - } + // If we get here, we didn't find a supported level. Use the defualt of Transparent or + // None, depending on whether composition is enabled. + SetBlur(false); + CurrentLevel = _globals.IsCompositionEnabled ? + WindowTransparencyLevel.Transparent : + WindowTransparencyLevel.None; } private bool IsSupported(WindowTransparencyLevel level) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index dc9cc7f50c..cb989cbc50 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -99,6 +99,7 @@ namespace Avalonia.Win32 private bool _hiddenWindowIsParent; private uint _langid; private bool _ignoreWmChar; + private WindowTransparencyLevel _transparencyLevel; private const int MaxPointerHistorySize = 512; private static readonly PooledList s_intermediatePointsPooledList = new(); @@ -183,6 +184,7 @@ namespace Avalonia.Win32 _storageProvider = new Win32StorageProvider(this); _nativeControlHost = new Win32NativeControlHost(this, _isUsingComposition); + _transparencyLevel = _isUsingComposition ? WindowTransparencyLevel.Transparent : WindowTransparencyLevel.None; s_instances.Add(this); } @@ -316,7 +318,18 @@ namespace Avalonia.Win32 } } - public WindowTransparencyLevel TransparencyLevel { get; private set; } + public WindowTransparencyLevel TransparencyLevel + { + get => _transparencyLevel; + private set + { + if (_transparencyLevel != value) + { + _transparencyLevel = value; + TransparencyLevelChanged?.Invoke(value); + } + } + } protected IntPtr Hwnd => _hwnd; @@ -355,7 +368,8 @@ namespace Avalonia.Win32 { if (!IsSupported(level, windowsVersion)) continue; - + if (level == TransparencyLevel) + return; if (level == WindowTransparencyLevel.Transparent) SetTransparencyTransparent(windowsVersion); else if (level == WindowTransparencyLevel.Blur) @@ -366,7 +380,19 @@ namespace Avalonia.Win32 SetTransparencyMica(windowsVersion); TransparencyLevel = level; - break; + return; + } + + // If we get here, we didn't find a supported level. Use the defualt of Transparent or + // None, depending on whether composition is enabled. + if (_isUsingComposition) + { + SetTransparencyTransparent(windowsVersion); + TransparencyLevel = WindowTransparencyLevel.Transparent; + } + else + { + TransparencyLevel = WindowTransparencyLevel.None; } }