diff --git a/src/Avalonia.FreeDesktop/DBusPlatformSettings.cs b/src/Avalonia.FreeDesktop/DBusPlatformSettings.cs new file mode 100644 index 0000000000..82b4a72e74 --- /dev/null +++ b/src/Avalonia.FreeDesktop/DBusPlatformSettings.cs @@ -0,0 +1,74 @@ +using System; +using System.Threading.Tasks; +using Avalonia.Logging; +using Avalonia.Platform; + +namespace Avalonia.FreeDesktop; + +internal class DBusPlatformSettings : DefaultPlatformSettings +{ + private readonly IDBusSettings? _settings; + private PlatformColorValues? _lastColorValues; + + public DBusPlatformSettings() + { + _settings = DBusHelper.TryInitialize()? + .CreateProxy("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop"); + + if (_settings is not null) + { + _ = _settings.WatchSettingChangedAsync(SettingsChangedHandler); + + _ = TryGetInitialValue(); + } + } + + public override PlatformColorValues GetColorValues() + { + return _lastColorValues ?? base.GetColorValues(); + } + + private async Task TryGetInitialValue() + { + var colorSchemeTask = _settings!.ReadAsync("org.freedesktop.appearance", "color-scheme"); + if (colorSchemeTask.Status == TaskStatus.RanToCompletion) + { + _lastColorValues = GetColorValuesFromSetting(colorSchemeTask.Result); + } + else + { + try + { + var value = await colorSchemeTask; + _lastColorValues = GetColorValuesFromSetting(value); + OnColorValuesChanged(_lastColorValues.Value); + } + catch (Exception ex) + { + _lastColorValues = base.GetColorValues(); + Logger.TryGet(LogEventLevel.Error, LogArea.FreeDesktopPlatform)?.Log(this, "Unable to get setting value", ex); + } + } + } + + private void SettingsChangedHandler((string @namespace, string key, object value) tuple) + { + if (tuple.@namespace == "org.freedesktop.appearance" + && tuple.key == "color-scheme") + { + /* + 0: No preference + 1: Prefer dark appearance + 2: Prefer light appearance + */ + _lastColorValues = GetColorValuesFromSetting(tuple.value); + OnColorValuesChanged(_lastColorValues.Value); + } + } + + private static PlatformColorValues GetColorValuesFromSetting(object value) + { + var isDark = value?.ToString() == "1"; + return new PlatformColorValues(isDark ? PlatformThemeVariant.Dark : PlatformThemeVariant.Light); + } +} diff --git a/src/Avalonia.FreeDesktop/DBusSettings.cs b/src/Avalonia.FreeDesktop/DBusSettings.cs new file mode 100644 index 0000000000..05911981c7 --- /dev/null +++ b/src/Avalonia.FreeDesktop/DBusSettings.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Tmds.DBus; + +namespace Avalonia.FreeDesktop; + +[DBusInterface("org.freedesktop.portal.Settings")] +internal interface IDBusSettings : IDBusObject +{ + Task<(string @namespace, IDictionary)> ReadAllAsync(string[] namespaces); + + Task ReadAsync(string @namespace, string key); + + Task WatchSettingChangedAsync(Action<(string @namespace, string key, object value)> handler, Action? onError = null); +} diff --git a/src/Avalonia.X11/X11Platform.cs b/src/Avalonia.X11/X11Platform.cs index 9692e0a384..7820f8a3c2 100644 --- a/src/Avalonia.X11/X11Platform.cs +++ b/src/Avalonia.X11/X11Platform.cs @@ -80,7 +80,7 @@ namespace Avalonia.X11 .Bind().ToFunc(() => KeyboardDevice) .Bind().ToConstant(new X11CursorFactory(Display)) .Bind().ToConstant(new X11Clipboard(this)) - .Bind().ToSingleton() + .Bind().ToSingleton() .Bind().ToConstant(new X11IconLoader()) .Bind().ToConstant(new LinuxMountedVolumeInfoProvider()) .Bind().ToConstant(new X11PlatformLifetimeEvents(this)); diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 810a806c8a..4b0e8473cc 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -1225,6 +1225,8 @@ namespace Avalonia.X11 public WindowTransparencyLevel TransparencyLevel => _transparencyHelper?.CurrentLevel ?? WindowTransparencyLevel.None; + public void SetFrameThemeVariant(PlatformThemeVariant themeVariant) { } + public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; } = new AcrylicPlatformCompensationLevels(1, 0.8, 0.8); public bool NeedsManagedDecorations => false; diff --git a/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs b/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs index ac54365f51..1c2fad56a6 100644 --- a/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs +++ b/src/Linux/Avalonia.LinuxFramebuffer/FramebufferToplevelImpl.cs @@ -83,6 +83,8 @@ namespace Avalonia.LinuxFramebuffer public WindowTransparencyLevel TransparencyLevel { get; private set; } + public void SetFrameThemeVariant(PlatformThemeVariant themeVariant) { } + public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; } = new AcrylicPlatformCompensationLevels(1, 1, 1); } }