Browse Source

Bump DBus stack (#15568)

* Bump DBus stack
- Use new Variant system

* Fix merge issues
pull/15588/head
affederaffe 2 years ago
committed by GitHub
parent
commit
5956ae71cd
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj
  2. 4
      src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxICWrapper.cs
  3. 2
      src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxX11TextInputMethod.cs
  4. 21
      src/Avalonia.FreeDesktop/DBusIme/IBus/IBusX11TextInputMethod.cs
  5. 85
      src/Avalonia.FreeDesktop/DBusMenuExporter.cs
  6. 36
      src/Avalonia.FreeDesktop/DBusPlatformSettings.cs
  7. 109
      src/Avalonia.FreeDesktop/DBusSystemDialog.cs
  8. 27
      src/Avalonia.FreeDesktop/DBusTrayIconImpl.cs

4
src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj

@ -12,8 +12,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Tmds.DBus.Protocol" Version="0.16.0" />
<PackageReference Include="Tmds.DBus.SourceGenerator" Version="0.0.15" PrivateAssets="all" />
<PackageReference Include="Tmds.DBus.Protocol" Version="0.17.0" />
<PackageReference Include="Tmds.DBus.SourceGenerator" Version="0.0.16" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>

4
src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxICWrapper.cs

@ -45,7 +45,7 @@ namespace Avalonia.FreeDesktop.DBusIme.Fcitx
public ValueTask<IDisposable> WatchForwardKeyAsync(Action<Exception?, (uint keyval, uint state, int type)> handler) =>
_old?.WatchForwardKeyAsync(handler)
?? _modern?.WatchForwardKeyAsync((e, ev) => handler.Invoke(e, (ev.keyval, ev.state, ev.type ? 1 : 0)))
?? _modern?.WatchForwardKeyAsync((e, ev) => handler.Invoke(e, (ev.Keyval, ev.State, ev.Type ? 1 : 0)))
?? new ValueTask<IDisposable>(Disposable.Empty);
public ValueTask<IDisposable> WatchUpdateFormattedPreeditAsync(
@ -53,7 +53,7 @@ namespace Avalonia.FreeDesktop.DBusIme.Fcitx
_old?.WatchUpdateFormattedPreeditAsync(handler!)
?? _modern?.WatchUpdateFormattedPreeditAsync(handler!)
?? new ValueTask<IDisposable>(Disposable.Empty);
public Task SetCapacityAsync(uint flags) =>
_old?.SetCapacityAsync(flags) ?? _modern?.SetCapabilityAsync(flags) ?? Task.CompletedTask;
}

2
src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxX11TextInputMethod.cs

@ -29,7 +29,7 @@ namespace Avalonia.FreeDesktop.DBusIme.Fcitx
var resp = await method.CreateICv3Async(GetAppName(),
Process.GetCurrentProcess().Id);
var proxy = new OrgFcitxFcitxInputContext(Connection, name, $"/inputcontext_{resp.icid}");
var proxy = new OrgFcitxFcitxInputContext(Connection, name, $"/inputcontext_{resp.Icid}");
_context = new FcitxICWrapper(proxy);
}
else

21
src/Avalonia.FreeDesktop/DBusIme/IBus/IBusX11TextInputMethod.cs

@ -51,17 +51,16 @@ namespace Avalonia.FreeDesktop.DBusIme.IBus
Client.SetPreeditText(_preeditText, _preeditText == null ? null : _preeditCursor);
}
private void OnUpdatePreedit(Exception? arg1, (DBusVariantItem text, uint cursor_pos, bool visible) preeditComponents)
private void OnUpdatePreedit(Exception? arg1, (VariantValue Text, uint CursorPos, bool Visible) preeditComponents)
{
if (preeditComponents.text is { Value: DBusStructItem { Count: >= 3 } structItem } &&
structItem[2] is DBusStringItem stringItem)
if (preeditComponents.Text is { Type: VariantValueType.Struct, Count: >= 3 } structItem && structItem.GetItem(2) is { Type: VariantValueType.String} stringItem)
{
_preeditText = stringItem.Value;
_preeditText = stringItem.GetString();
_preeditCursor = _preeditText != null
? Utf16Utils.CharacterOffsetToStringOffset(_preeditText,
(int)Math.Min(preeditComponents.cursor_pos, int.MaxValue), false)
(int)Math.Min(preeditComponents.CursorPos, int.MaxValue), false)
: 0;
_preeditShown = true;
}
else
@ -102,13 +101,13 @@ namespace Avalonia.FreeDesktop.DBusIme.IBus
});
}
private void OnCommitText(Exception? e, DBusVariantItem variantItem)
private void OnCommitText(Exception? e, VariantValue variantItem)
{
if (_insideReset > 0)
if (_insideReset > 0)
{
// For some reason iBus can trigger a CommitText while being reset.
// Thankfully the signal is sent _during_ Reset call processing,
// so it arrives on-the-wire before Reset call result, so we can
// so it arrives on-the-wire before Reset call result, so we can
// check if we have any pending Reset calls and ignore the signal here
return;
}
@ -118,8 +117,8 @@ namespace Avalonia.FreeDesktop.DBusIme.IBus
return;
}
if (variantItem.Value is DBusStructItem { Count: >= 3 } structItem && structItem[2] is DBusStringItem stringItem)
FireCommit(stringItem.Value);
if (variantItem.Count >= 3 && variantItem.GetItem(2) is { Type: VariantValueType.String } stringItem)
FireCommit(stringItem.GetString());
}
protected override Task DisconnectAsync() => _service?.DestroyAsync() ?? Task.CompletedTask;

85
src/Avalonia.FreeDesktop/DBusMenuExporter.cs

@ -60,17 +60,14 @@ namespace Avalonia.FreeDesktop
private void InitBackingProperties()
{
BackingProperties.Version = 4;
BackingProperties.Status = string.Empty;
BackingProperties.TextDirection = string.Empty;
BackingProperties.IconThemePath = Array.Empty<string>();
Version = 4;
}
protected override Connection Connection { get; }
public override string Path { get; }
protected override ValueTask<(uint revision, (int, Dictionary<string, DBusVariantItem>, DBusVariantItem[]) layout)> OnGetLayoutAsync(int parentId, int recursionDepth, string[] propertyNames)
protected override ValueTask<(uint Revision, (int, Dictionary<string, Variant>, Variant[]) Layout)> OnGetLayoutAsync(int parentId, int recursionDepth, string[] propertyNames)
{
var menu = GetMenu(parentId);
var layout = GetLayout(menu.item, menu.menu, recursionDepth, propertyNames);
@ -80,22 +77,22 @@ namespace Avalonia.FreeDesktop
OnIsNativeMenuExportedChanged?.Invoke(this, EventArgs.Empty);
}
return new ValueTask<(uint, (int, Dictionary<string, DBusVariantItem>, DBusVariantItem[]))>((_revision, layout));
return new ValueTask<(uint, (int, Dictionary<string, Variant>, Variant[]))>((_revision, layout));
}
protected override ValueTask<(int, Dictionary<string, DBusVariantItem>)[]> OnGetGroupPropertiesAsync(int[] ids, string[] propertyNames)
protected override ValueTask<(int, Dictionary<string, Variant>)[]> OnGetGroupPropertiesAsync(int[] ids, string[] propertyNames)
=> new(ids.Select(id => (id, GetProperties(GetMenu(id), propertyNames))).ToArray());
protected override ValueTask<DBusVariantItem> OnGetPropertyAsync(int id, string name) =>
new(GetProperty(GetMenu(id), name) ?? new DBusVariantItem("i", new DBusInt32Item(0)));
protected override ValueTask<Variant> OnGetPropertyAsync(int id, string name) =>
new(GetProperty(GetMenu(id), name) ?? new Variant(0));
protected override ValueTask OnEventAsync(int id, string eventId, DBusVariantItem data, uint timestamp)
protected override ValueTask OnEventAsync(int id, string eventId, VariantValue data, uint timestamp)
{
HandleEvent(id, eventId);
return new ValueTask();
}
protected override ValueTask<int[]> OnEventGroupAsync((int, string, DBusVariantItem, uint)[] events)
protected override ValueTask<int[]> OnEventGroupAsync((int, string, VariantValue, uint)[] events)
{
foreach (var e in events)
HandleEvent(e.Item1, e.Item2);
@ -104,7 +101,7 @@ namespace Avalonia.FreeDesktop
protected override ValueTask<bool> OnAboutToShowAsync(int id) => new(false);
protected override ValueTask<(int[] updatesNeeded, int[] idErrors)> OnAboutToShowGroupAsync(int[] ids) =>
protected override ValueTask<(int[] UpdatesNeeded, int[] IdErrors)> OnAboutToShowGroupAsync(int[] ids) =>
new((Array.Empty<int>(), Array.Empty<int>()));
private async Task InitializeAsync()
@ -220,35 +217,32 @@ namespace Avalonia.FreeDesktop
"type", "label", "enabled", "visible", "shortcut", "toggle-type", "children-display", "toggle-state", "icon-data"
};
private static DBusVariantItem? GetProperty((NativeMenuItemBase? item, NativeMenu? menu) i, string name)
private static Variant? GetProperty((NativeMenuItemBase? item, NativeMenu? menu) i, string name)
{
var (it, menu) = i;
if (it is NativeMenuItemSeparator)
{
if (name == "type")
return new DBusVariantItem("s", new DBusStringItem("separator"));
return new Variant("separator");
}
else if (it is NativeMenuItem item)
{
if (name == "type")
return null;
if (name == "label")
return new DBusVariantItem("s", new DBusStringItem(item.Header ?? "<null>"));
return new Variant(item.Header ?? "<null>");
if (name == "enabled")
{
if (item.Menu is not null && item.Menu.Items.Count == 0)
return new DBusVariantItem("b", new DBusBoolItem(false));
return new Variant(false);
if (!item.IsEnabled)
return new DBusVariantItem("b", new DBusBoolItem(false));
return new Variant(false);
return null;
}
if (name == "visible") {
if (!item.IsVisible)
return new DBusVariantItem("b", new DBusBoolItem(false));
return new DBusVariantItem("b", new DBusBoolItem(true));
}
if (name == "visible")
return new Variant(item.IsVisible);
if (name == "shortcut")
{
@ -256,30 +250,30 @@ namespace Avalonia.FreeDesktop
return null;
if (item.Gesture.KeyModifiers == 0)
return null;
var lst = new List<DBusItem>();
var lst = new Array<Variant>();
var mod = item.Gesture;
if (mod.KeyModifiers.HasAllFlags(KeyModifiers.Control))
lst.Add(new DBusStringItem("Control"));
lst.Add(new Variant("Control"));
if (mod.KeyModifiers.HasAllFlags(KeyModifiers.Alt))
lst.Add(new DBusStringItem("Alt"));
lst.Add(new Variant("Alt"));
if (mod.KeyModifiers.HasAllFlags(KeyModifiers.Shift))
lst.Add(new DBusStringItem("Shift"));
lst.Add(new Variant("Shift"));
if (mod.KeyModifiers.HasAllFlags(KeyModifiers.Meta))
lst.Add(new DBusStringItem("Super"));
lst.Add(new DBusStringItem(item.Gesture.Key.ToString()));
return new DBusVariantItem("aas", new DBusArrayItem(DBusType.Array, new[] { new DBusArrayItem(DBusType.String, lst) }));
lst.Add(new Variant("Super"));
lst.Add(new Variant(item.Gesture.Key.ToString()));
return Variant.FromArray(new Array<Array<Variant>>(new[] { lst }));
}
if (name == "toggle-type")
{
if (item.ToggleType == NativeMenuItemToggleType.CheckBox)
return new DBusVariantItem("s", new DBusStringItem("checkmark"));
return new Variant("checkmark");
if (item.ToggleType == NativeMenuItemToggleType.Radio)
return new DBusVariantItem("s", new DBusStringItem("radio"));
return new Variant("radio");
}
if (name == "toggle-state" && item.ToggleType != NativeMenuItemToggleType.None)
return new DBusVariantItem("i", new DBusInt32Item(item.IsChecked ? 1 : 0));
return new Variant(item.IsChecked ? 1 : 0);
if (name == "icon-data")
{
@ -292,50 +286,49 @@ namespace Avalonia.FreeDesktop
var icon = loader.LoadIcon(item.Icon.PlatformImpl.Item);
using var ms = new MemoryStream();
icon.Save(ms);
return new DBusVariantItem("ay", new DBusByteArrayItem(ms.ToArray()));
return Variant.FromArray(new Array<byte>(ms.ToArray()));
}
}
}
if (name == "children-display")
return menu is not null ? new DBusVariantItem("s", new DBusStringItem("submenu")) : null;
{
if (menu is not null)
return new Variant("submenu");
return null;
}
}
return null;
}
private static Dictionary<string, DBusVariantItem> GetProperties((NativeMenuItemBase? item, NativeMenu? menu) i, string[] names)
private static Dictionary<string, Variant> GetProperties((NativeMenuItemBase? item, NativeMenu? menu) i, string[] names)
{
if (names.Length == 0)
names = s_allProperties;
var properties = new Dictionary<string, DBusVariantItem>();
var properties = new Dictionary<string, Variant>();
foreach (var n in names)
{
var v = GetProperty(i, n);
if (v is not null)
properties.Add(n, v);
if (v.HasValue)
properties.Add(n, v.Value);
}
return properties;
}
private (int, Dictionary<string, DBusVariantItem>, DBusVariantItem[]) GetLayout(NativeMenuItemBase? item, NativeMenu? menu, int depth, string[] propertyNames)
private (int, Dictionary<string, Variant>, Variant[]) GetLayout(NativeMenuItemBase? item, NativeMenu? menu, int depth, string[] propertyNames)
{
var id = item is null ? 0 : GetId(item);
var props = GetProperties((item, menu), propertyNames);
var children = depth == 0 || menu is null ? Array.Empty<DBusVariantItem>() : new DBusVariantItem[menu.Items.Count];
var children = depth == 0 || menu is null ? Array.Empty<Variant>() : new Variant[menu.Items.Count];
if (menu is not null)
{
for (var c = 0; c < children.Length; c++)
{
var ch = menu.Items[c];
var layout = GetLayout(ch, (ch as NativeMenuItem)?.Menu, depth == -1 ? -1 : depth - 1, propertyNames);
children[c] = new DBusVariantItem("(ia{sv}av)", new DBusStructItem(new DBusItem[]
{
new DBusInt32Item(layout.Item1),
new DBusArrayItem(DBusType.DictEntry, layout.Item2.Select(static x => new DBusDictEntryItem(new DBusStringItem(x.Key), x.Value)).ToArray()),
new DBusArrayItem(DBusType.Variant, layout.Item3)
}));
children[c] = Variant.FromStruct(Struct.Create(layout.Item1, new Dict<string, Variant>(layout.Item2), new Array<Variant>(layout.Item3)));
}
}

36
src/Avalonia.FreeDesktop/DBusPlatformSettings.cs

@ -41,14 +41,12 @@ namespace Avalonia.FreeDesktop
try
{
var version = await _settings!.GetVersionPropertyAsync();
DBusVariantItem value;
VariantValue value;
if (version >= 2)
value = await _settings!.ReadOneAsync("org.freedesktop.appearance", "color-scheme");
else
value = (DBusVariantItem)(await _settings!.ReadAsync("org.freedesktop.appearance", "color-scheme")).Value;
if (value.Value is DBusUInt32Item dBusUInt32Item)
return ToColorScheme(dBusUInt32Item.Value);
return null;
value = (await _settings!.ReadAsync("org.freedesktop.appearance", "color-scheme")).GetItem(0);
return ToColorScheme(value.GetUInt32());
}
catch (DBusException)
{
@ -61,14 +59,12 @@ namespace Avalonia.FreeDesktop
try
{
var version = await _settings!.GetVersionPropertyAsync();
DBusVariantItem value;
VariantValue value;
if (version >= 2)
value = await _settings!.ReadOneAsync("org.freedesktop.appearance", "accent-color");
else
value = (DBusVariantItem)(await _settings!.ReadAsync("org.freedesktop.appearance", "accent-color")).Value;
if (value.Value is DBusStructItem dBusStructItem)
return ToAccentColor(dBusStructItem);
return null;
value = (await _settings!.ReadAsync("org.freedesktop.appearance", "accent-color")).GetItem(0);
return ToAccentColor(value);
}
catch (DBusException)
{
@ -76,20 +72,20 @@ namespace Avalonia.FreeDesktop
}
}
private void SettingsChangedHandler(Exception? exception, (string @namespace, string key, DBusVariantItem value) valueTuple)
private void SettingsChangedHandler(Exception? exception, (string Namespace, string Key, VariantValue Value) tuple)
{
if (exception is not null)
return;
switch (valueTuple)
switch (tuple)
{
case ("org.freedesktop.appearance", "color-scheme", { } colorScheme):
_themeVariant = ToColorScheme((colorScheme.Value as DBusUInt32Item)!.Value);
case ("org.freedesktop.appearance", "color-scheme", var colorScheme):
_themeVariant = ToColorScheme(colorScheme.GetUInt32());
_lastColorValues = BuildPlatformColorValues();
OnColorValuesChanged(_lastColorValues!);
break;
case ("org.freedesktop.appearance", "accent-color", { } accentColor):
_accentColor = ToAccentColor((accentColor.Value as DBusStructItem)!);
case ("org.freedesktop.appearance", "accent-color", var accentColor):
_accentColor = ToAccentColor(accentColor);
_lastColorValues = BuildPlatformColorValues();
OnColorValuesChanged(_lastColorValues!);
break;
@ -118,16 +114,16 @@ namespace Avalonia.FreeDesktop
return isDark ? PlatformThemeVariant.Dark : PlatformThemeVariant.Light;
}
private static Color? ToAccentColor(DBusStructItem value)
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[0] as DBusDoubleItem)!.Value;
var g = (value[1] as DBusDoubleItem)!.Value;
var b = (value[2] as DBusDoubleItem)!.Value;
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));

109
src/Avalonia.FreeDesktop/DBusSystemDialog.cs

@ -56,14 +56,15 @@ namespace Avalonia.FreeDesktop
{
var parentWindow = $"x11:{_handle.Handle:X}";
ObjectPath objectPath;
var chooserOptions = new Dictionary<string, DBusVariantItem>();
var filters = ParseFilters(options.FileTypeFilter);
if (filters is not null)
var chooserOptions = new Dictionary<string, Variant>();
if (TryParseFilters(options.FileTypeFilter, out var filters))
chooserOptions.Add("filters", filters);
if (options.SuggestedStartLocation?.TryGetLocalPath() is { } folderPath)
chooserOptions.Add("current_folder", new DBusVariantItem("ay", new DBusByteArrayItem(Encoding.UTF8.GetBytes(folderPath + "\0"))));
chooserOptions.Add("multiple", new DBusVariantItem("b", new DBusBoolItem(options.AllowMultiple)));
chooserOptions.Add("current_folder", Variant.FromArray(new Array<byte>(Encoding.UTF8.GetBytes(folderPath + "\0"))));
chooserOptions.Add("multiple", new Variant(options.AllowMultiple));
objectPath = await _fileChooser.OpenFileAsync(parentWindow, options.Title ?? string.Empty, chooserOptions);
@ -74,7 +75,7 @@ namespace Avalonia.FreeDesktop
if (e is not null)
tsc.TrySetException(e);
else
tsc.TrySetResult((x.results["uris"].Value as DBusArrayItem)?.Select(static y => (y as DBusStringItem)!.Value).ToArray());
tsc.TrySetResult(x.Results["uris"].GetArray<string>());
});
var uris = await tsc.Task ?? Array.Empty<string>();
@ -85,15 +86,14 @@ namespace Avalonia.FreeDesktop
{
var parentWindow = $"x11:{_handle.Handle:X}";
ObjectPath objectPath;
var chooserOptions = new Dictionary<string, DBusVariantItem>();
var filters = ParseFilters(options.FileTypeChoices);
if (filters is not null)
var chooserOptions = new Dictionary<string, Variant>();
if (TryParseFilters(options.FileTypeChoices, out var filters))
chooserOptions.Add("filters", filters);
if (options.SuggestedFileName is { } currentName)
chooserOptions.Add("current_name", new DBusVariantItem("s", new DBusStringItem(currentName)));
chooserOptions.Add("current_name", new Variant(currentName));
if (options.SuggestedStartLocation?.TryGetLocalPath() is { } folderPath)
chooserOptions.Add("current_folder", new DBusVariantItem("ay", new DBusByteArrayItem(Encoding.UTF8.GetBytes(folderPath + "\0"))));
chooserOptions.Add("current_folder", Variant.FromArray(new Array<byte>(Encoding.UTF8.GetBytes(folderPath + "\0"))));
objectPath = await _fileChooser.SaveFileAsync(parentWindow, options.Title ?? string.Empty, chooserOptions);
var request = new OrgFreedesktopPortalRequest(_connection, "org.freedesktop.portal.Desktop", objectPath);
@ -102,41 +102,31 @@ namespace Avalonia.FreeDesktop
using var disposable = await request.WatchResponseAsync((e, x) =>
{
if (e is not null)
{
tsc.TrySetException(e);
}
else
{
if(x.results.TryGetValue("current_filter", out var value))
if (x.Results.TryGetValue("current_filter", out var currentFilter))
{
var currentFilter = value.Value as DBusStructItem;
if(currentFilter != null)
var name = currentFilter.GetItem(0).GetString();
selectedType = new FilePickerFileType(name);
var patterns = new List<string>();
var mimeTypes = new List<string>();
var types = currentFilter.GetItem(1).GetArray<VariantValue>();
foreach(var t in types)
{
var name = (currentFilter[0] as DBusStringItem)?.Value.ToString() ?? "";
selectedType = new FilePickerFileType(name);
if(currentFilter[1] is DBusArrayItem types)
{
List<string> filters = new List<string>();
List<string> mimeTypes = new List<string>();
foreach(var t in types)
{
if(t is DBusStructItem filter)
{
if((filter[0] as DBusUInt32Item)?.Value == 1)
{
mimeTypes.Add((filter[1] as DBusStringItem)?.Value.ToString() ?? "");
}
else
{
filters.Add((filter[1] as DBusStringItem)?.Value.ToString() ?? "");
}
}
}
selectedType.Patterns = filters;
selectedType.MimeTypes = mimeTypes;
}
if (t.GetItem(0).GetUInt32() == 1)
mimeTypes.Add(t.GetItem(1).GetString());
else
patterns.Add(t.GetItem(1).GetString());
}
selectedType.Patterns = patterns;
selectedType.MimeTypes = mimeTypes;
}
tsc.TrySetResult((x.results["uris"].Value as DBusArrayItem)?.Select(static y => (y as DBusStringItem)!.Value).ToArray());
tsc.TrySetResult(x.Results["uris"].GetArray<string>());
}
});
@ -157,16 +147,16 @@ namespace Avalonia.FreeDesktop
return Array.Empty<IStorageFolder>();
var parentWindow = $"x11:{_handle.Handle:X}";
var chooserOptions = new Dictionary<string, DBusVariantItem>
var chooserOptions = new Dictionary<string, Variant>
{
{ "directory", new DBusVariantItem("b", new DBusBoolItem(true)) },
{ "multiple", new DBusVariantItem("b", new DBusBoolItem(options.AllowMultiple)) }
{ "directory", new Variant(true) },
{ "multiple", new Variant(options.AllowMultiple) }
};
if (options.SuggestedFileName is { } currentName)
chooserOptions.Add("current_name", new DBusVariantItem("s", new DBusStringItem(currentName)));
chooserOptions.Add("current_name", new Variant(currentName));
if (options.SuggestedStartLocation?.TryGetLocalPath() is { } folderPath)
chooserOptions.Add("current_folder", new DBusVariantItem("ay", new DBusByteArrayItem(Encoding.UTF8.GetBytes(folderPath + "\0"))));
chooserOptions.Add("current_folder", Variant.FromArray(new Array<byte>(Encoding.UTF8.GetBytes(folderPath + "\0"))));
var objectPath = await _fileChooser.OpenFileAsync(parentWindow, options.Title ?? string.Empty, chooserOptions);
var request = new OrgFreedesktopPortalRequest(_connection, "org.freedesktop.portal.Desktop", objectPath);
@ -176,7 +166,7 @@ namespace Avalonia.FreeDesktop
if (e is not null)
tsc.TrySetException(e);
else
tsc.TrySetResult((x.results["uris"].Value as DBusArrayItem)?.Select(static y => (y as DBusStringItem)!.Value).ToArray());
tsc.TrySetResult(x.Results["uris"].GetArray<string>());
});
var uris = await tsc.Task ?? Array.Empty<string>();
@ -187,40 +177,35 @@ namespace Avalonia.FreeDesktop
.Select(static path => new BclStorageFolder(new DirectoryInfo(path))).ToList();
}
private static DBusVariantItem? ParseFilters(IReadOnlyList<FilePickerFileType>? fileTypes)
private static bool TryParseFilters(IReadOnlyList<FilePickerFileType>? fileTypes, out Variant result)
{
const uint GlobStyle = 0u;
const uint MimeStyle = 1u;
// Example: [('Images', [(0, '*.ico'), (1, 'image/png')]), ('Text', [(0, '*.txt')])]
if (fileTypes is null)
return null;
{
result = default;
return false;
}
var filters = new List<DBusItem>();
var filters = new Array<Struct<string, Array<Struct<uint, string>>>>();
foreach (var fileType in fileTypes)
{
var extensions = new List<DBusItem>();
var extensions = new List<Struct<uint, string>>();
if (fileType.Patterns?.Count > 0)
extensions.AddRange(
fileType.Patterns.Select(static pattern =>
new DBusStructItem(new DBusItem[] { new DBusUInt32Item(GlobStyle), new DBusStringItem(pattern) })));
extensions.AddRange(fileType.Patterns.Select(static pattern => Struct.Create(GlobStyle, pattern)));
else if (fileType.MimeTypes?.Count > 0)
extensions.AddRange(
fileType.MimeTypes.Select(static mimeType =>
new DBusStructItem(new DBusItem[] { new DBusUInt32Item(MimeStyle), new DBusStringItem(mimeType) })));
extensions.AddRange(fileType.MimeTypes.Select(static mimeType => Struct.Create(MimeStyle, mimeType)));
else
continue;
filters.Add(new DBusStructItem(
new DBusItem[]
{
new DBusStringItem(fileType.Name),
new DBusArrayItem(DBusType.Struct, extensions)
}));
filters.Add(Struct.Create(fileType.Name, new Array<Struct<uint, string>>(extensions)));
}
return filters.Count > 0 ? new DBusVariantItem("a(sa(us))", new DBusArrayItem(DBusType.Struct, filters)) : null;
result = Variant.FromArray(filters);
return true;
}
}
}

27
src/Avalonia.FreeDesktop/DBusTrayIconImpl.cs

@ -77,7 +77,7 @@ namespace Avalonia.FreeDesktop
if (_isDisposed || _connection is null || name != "org.kde.StatusNotifierWatcher")
return;
if (!_serviceConnected & newOwner is not null)
if (!_serviceConnected && newOwner is not null)
{
_serviceConnected = true;
_statusNotifierWatcher = new OrgKdeStatusNotifierWatcher(_connection, "org.kde.StatusNotifierWatcher", "/StatusNotifierWatcher");
@ -212,18 +212,7 @@ namespace Avalonia.FreeDesktop
public StatusNotifierItemDbusObj(Connection connection, ObjectPath dbusMenuPath)
{
Connection = connection;
BackingProperties.Menu = dbusMenuPath;
BackingProperties.Category = string.Empty;
BackingProperties.Status = string.Empty;
BackingProperties.Id = string.Empty;
BackingProperties.Title = string.Empty;
BackingProperties.IconPixmap = Array.Empty<(int, int, byte[])>();
BackingProperties.AttentionIconName = string.Empty;
BackingProperties.AttentionIconPixmap = Array.Empty<(int, int, byte[])>();
BackingProperties.AttentionMovieName = string.Empty;
BackingProperties.OverlayIconName = string.Empty;
BackingProperties.OverlayIconPixmap = Array.Empty<(int, int, byte[])>();
BackingProperties.ToolTip = (string.Empty, Array.Empty<(int, int, byte[])>(), string.Empty, string.Empty);
Menu = dbusMenuPath;
InvalidateAll();
}
@ -252,12 +241,12 @@ namespace Avalonia.FreeDesktop
EmitNewAttentionIcon();
EmitNewOverlayIcon();
EmitNewToolTip();
EmitNewStatus(BackingProperties.Status);
EmitNewStatus(Status);
}
public void SetIcon((int, int, byte[]) dbusPixmap)
{
BackingProperties.IconPixmap = new[] { dbusPixmap };
IconPixmap = new[] { dbusPixmap };
InvalidateAll();
}
@ -266,10 +255,10 @@ namespace Avalonia.FreeDesktop
if (text is null)
return;
BackingProperties.Id = text;
BackingProperties.Category = "ApplicationStatus";
BackingProperties.Status = text;
BackingProperties.Title = text;
Id = text;
Category = "ApplicationStatus";
Status = text;
Title = text;
InvalidateAll();
}
}

Loading…
Cancel
Save