diff --git a/src/Avalonia.X11/TransparencyHelper.cs b/src/Avalonia.X11/TransparencyHelper.cs index b4f8ca5aed..01dccbf12a 100644 --- a/src/Avalonia.X11/TransparencyHelper.cs +++ b/src/Avalonia.X11/TransparencyHelper.cs @@ -1,6 +1,9 @@ using System; +using System.Collections.Generic; using Avalonia.Controls; +#nullable enable + namespace Avalonia.X11 { internal class TransparencyHelper : IDisposable, X11Globals.IGlobalsSubscriber @@ -9,10 +12,10 @@ namespace Avalonia.X11 private readonly IntPtr _window; private readonly X11Globals _globals; private WindowTransparencyLevel _currentLevel; - private WindowTransparencyLevel _requestedLevel; + private IReadOnlyList? _requestedLevels; private bool _blurAtomsAreSet; - public Action TransparencyLevelChanged { get; set; } + public Action? TransparencyLevelChanged { get; set; } public WindowTransparencyLevel CurrentLevel => _currentLevel; public TransparencyHelper(X11Info x11, IntPtr window, X11Globals globals) @@ -23,28 +26,62 @@ namespace Avalonia.X11 _globals.AddSubscriber(this); } - public void SetTransparencyRequest(WindowTransparencyLevel level) + public void SetTransparencyRequest(IReadOnlyList levels) { - _requestedLevel = level; - UpdateTransparency(); - } + WindowTransparencyLevel? newLevel = null; + _requestedLevels = levels; + + foreach (var level in levels) + { + if (!IsSupported(level)) + 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); + } - private void UpdateTransparency() - { - var newLevel = UpdateAtomsAndGetTransparency(); if (newLevel != _currentLevel) { - _currentLevel = newLevel; - TransparencyLevelChanged?.Invoke(newLevel); + _currentLevel = newLevel.Value; + TransparencyLevelChanged?.Invoke(newLevel.Value); } } - - private WindowTransparencyLevel UpdateAtomsAndGetTransparency() + + private bool IsSupported(WindowTransparencyLevel level) { - var blur = _requestedLevel == WindowTransparencyLevel.Blur || - _requestedLevel == WindowTransparencyLevel.AcrylicBlur || - _requestedLevel == WindowTransparencyLevel.Mica; + // None is suppported when composition is disabled. + if (level == WindowTransparencyLevel.None) + return !_globals.IsCompositionEnabled; + + // Transparent is suppported when composition is enabled. + if (level == WindowTransparencyLevel.Transparent) + return _globals.IsCompositionEnabled; + + // Blur is supported when composition is enabled and KWin is used. + if (level == WindowTransparencyLevel.Blur) + return _globals.IsCompositionEnabled && _globals.WmName == "KWin"; + + return false; + } + private void UpdateTransparency() + { + SetTransparencyRequest(_requestedLevels ?? Array.Empty()); + } + + private void SetBlur(bool blur) + { if (blur) { if (!_blurAtomsAreSet) @@ -63,15 +100,7 @@ namespace Avalonia.X11 _blurAtomsAreSet = false; } } - - if (!_globals.IsCompositionEnabled) - return WindowTransparencyLevel.None; - if (blur && CanBlur) - return WindowTransparencyLevel.Blur; - return WindowTransparencyLevel.Transparent; } - - private bool CanBlur => _globals.WmName == "KWin" && _globals.IsCompositionEnabled; public void Dispose() { diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 58b59a6b56..7da3d31dc2 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -196,7 +196,7 @@ namespace Avalonia.X11 _rawEventGrouper = new RawEventGrouper(DispatchInput, platform.EventGrouperDispatchQueue); _transparencyHelper = new TransparencyHelper(_x11, _handle, platform.Globals); - _transparencyHelper.SetTransparencyRequest(WindowTransparencyLevel.None); + _transparencyHelper.SetTransparencyRequest(Array.Empty()); CreateIC(); @@ -1307,9 +1307,9 @@ namespace Avalonia.X11 public IPopupPositioner? PopupPositioner { get; } - public void SetTransparencyLevelHint(IReadOnlyList transparencyLevel) + public void SetTransparencyLevelHint(IReadOnlyList transparencyLevels) { - ////_transparencyHelper?.SetTransparencyRequest(transparencyLevel); + _transparencyHelper?.SetTransparencyRequest(transparencyLevels); } public void SetWindowManagerAddShadowHint(bool enabled)