Browse Source

Set default transparency level.

If no matching transparency level was found, use the default on all platforms.

Raise `TransparencyLevelChanged` on all platforms.
Steven Kirk 2 years ago
parent
commit
e50816008e

+ 28 - 2
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<WindowTransparencyLevel> 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)

+ 22 - 5
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)
         {

+ 21 - 19
src/Avalonia.X11/TransparencyHelper.cs

@@ -16,7 +16,19 @@ namespace Avalonia.X11
         private bool _blurAtomsAreSet;
         
         public Action<WindowTransparencyLevel>? 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<WindowTransparencyLevel> 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)

+ 29 - 3
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<RawPointerPoint> 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;
             }
         }