A cross-platform UI framework for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

139 lines
5.2 KiB

using System;
using System.Threading.Tasks;
using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Threading;
using Tmds.DBus.Protocol;
using Avalonia.FreeDesktop.DBus;
namespace Avalonia.FreeDesktop
{
internal class DBusPlatformSettings : DefaultPlatformSettings
{
private readonly Settings? _settings;
private PlatformColorValues? _lastColorValues;
private PlatformThemeVariant? _themeVariant;
private Color? _accentColor;
public DBusPlatformSettings()
{
if (DBusHelper.DefaultConnection is not { } conn)
return;
_settings = new Settings(conn, "org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop");
_ = _settings.WatchSettingChangedAsync(SettingsChangedHandler);
_ = TryGetInitialValuesAsync();
}
public override PlatformColorValues GetColorValues() => _lastColorValues ?? base.GetColorValues();
private async Task TryGetInitialValuesAsync()
{
if (_settings is { } settings)
{
_themeVariant = await TryGetThemeVariantAsync(settings);
_accentColor = await TryGetAccentColorAsync(settings);
_lastColorValues = BuildPlatformColorValues();
if (_lastColorValues is not null)
Dispatcher.UIThread.Post(() => OnColorValuesChanged(_lastColorValues));
}
}
internal void OnRequestDefaultThemeVariant()
{
_ = TryGetInitialValuesAsync();
}
private static async Task<PlatformThemeVariant?> TryGetThemeVariantAsync(Settings settings)
{
try
{
var version = await settings.GetVersionAsync();
VariantValue value;
if (version >= 2)
value = await settings.ReadOneAsync("org.freedesktop.appearance", "color-scheme");
else
// Unpack nested Variant
value = (await settings.ReadAsync("org.freedesktop.appearance", "color-scheme")).GetVariantValue();
return ToColorScheme(value.GetUInt32());
}
catch (DBusExceptionBase)
{
return null;
}
}
private static async Task<Color?> TryGetAccentColorAsync(Settings settings)
{
try
{
var version = await settings.GetVersionAsync();
VariantValue value;
if (version >= 2)
value = await settings.ReadOneAsync("org.freedesktop.appearance", "accent-color");
else
value = await settings.ReadAsync("org.freedesktop.appearance", "accent-color");
return ToAccentColor(value);
}
catch (DBusExceptionBase)
{
return null;
}
}
private void SettingsChangedHandler((string Namespace, string Key, VariantValue Value) tuple)
{
switch (tuple)
{
case ("org.freedesktop.appearance", "color-scheme", var colorScheme):
_themeVariant = ToColorScheme(colorScheme.GetUInt32());
_lastColorValues = BuildPlatformColorValues();
OnColorValuesChanged(_lastColorValues!);
break;
case ("org.freedesktop.appearance", "accent-color", var accentColor):
_accentColor = ToAccentColor(accentColor);
_lastColorValues = BuildPlatformColorValues();
OnColorValuesChanged(_lastColorValues!);
break;
}
}
private PlatformColorValues? BuildPlatformColorValues()
{
if (_themeVariant is { } themeVariant && _accentColor is { } accentColor)
return new PlatformColorValues { ThemeVariant = themeVariant, AccentColor1 = accentColor };
if (_themeVariant is { } themeVariant1)
return new PlatformColorValues { ThemeVariant = themeVariant1 };
if (_accentColor is { } accentColor1)
return new PlatformColorValues { AccentColor1 = accentColor1 };
return null;
}
private static PlatformThemeVariant ToColorScheme(uint value)
{
/*
0: No preference
1: Prefer dark appearance
2: Prefer light appearance
*/
var isDark = value == 1;
return isDark ? PlatformThemeVariant.Dark : PlatformThemeVariant.Light;
}
private static Color? ToAccentColor(VariantValue value)
{
/*
Indicates the system's preferred accent color as a tuple of RGB values
in the sRGB color space, in the range [0,1].
Out-of-range RGB values should be treated as an unset accent color.
*/
var r = value.GetItem(0).GetDouble();
var g = value.GetItem(1).GetDouble();
var b = value.GetItem(2).GetDouble();
if (r is < 0 or > 1 || g is < 0 or > 1 || b is < 0 or > 1)
return null;
return Color.FromRgb((byte)(r * 255), (byte)(g * 255), (byte)(b * 255));
}
}
}