Browse Source

Bump DBus stack (#18343)

pull/18361/head
affederaffe 2 years ago
committed by GitHub
parent
commit
b66471b356
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj
  2. 2
      src/Avalonia.FreeDesktop/DBusIme/DBusTextInputMethodBase.cs
  3. 8
      src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxICWrapper.cs
  4. 8
      src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxX11TextInputMethod.cs
  5. 12
      src/Avalonia.FreeDesktop/DBusIme/IBus/IBusX11TextInputMethod.cs
  6. 63
      src/Avalonia.FreeDesktop/DBusMenuExporter.cs
  7. 8
      src/Avalonia.FreeDesktop/DBusPlatformSettings.cs
  8. 46
      src/Avalonia.FreeDesktop/DBusSystemDialog.cs
  9. 18
      src/Avalonia.FreeDesktop/DBusTrayIconImpl.cs

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

@ -13,8 +13,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Tmds.DBus.Protocol" Version="0.20.0" /> <PackageReference Include="Tmds.DBus.Protocol" Version="0.21.2" />
<PackageReference Include="Tmds.DBus.SourceGenerator" Version="0.0.19" PrivateAssets="all" /> <PackageReference Include="Tmds.DBus.SourceGenerator" Version="0.0.21" PrivateAssets="all" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

2
src/Avalonia.FreeDesktop/DBusIme/DBusTextInputMethodBase.cs

@ -60,7 +60,7 @@ namespace Avalonia.FreeDesktop.DBusIme
private async Task WatchAsync() private async Task WatchAsync()
{ {
var dbus = new OrgFreedesktopDBus(Connection, "org.freedesktop.DBus", "/org/freedesktop/DBus"); var dbus = new OrgFreedesktopDBusProxy(Connection, "org.freedesktop.DBus", "/org/freedesktop/DBus");
try try
{ {
_disposables.Add(await dbus.WatchNameOwnerChangedAsync(OnNameChange)); _disposables.Add(await dbus.WatchNameOwnerChangedAsync(OnNameChange));

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

@ -7,15 +7,15 @@ namespace Avalonia.FreeDesktop.DBusIme.Fcitx
{ {
internal class FcitxICWrapper internal class FcitxICWrapper
{ {
private readonly OrgFcitxFcitxInputContext1? _modern; private readonly OrgFcitxFcitxInputContext1Proxy? _modern;
private readonly OrgFcitxFcitxInputContext? _old; private readonly OrgFcitxFcitxInputContextProxy? _old;
public FcitxICWrapper(OrgFcitxFcitxInputContext old) public FcitxICWrapper(OrgFcitxFcitxInputContextProxy old)
{ {
_old = old; _old = old;
} }
public FcitxICWrapper(OrgFcitxFcitxInputContext1 modern) public FcitxICWrapper(OrgFcitxFcitxInputContext1Proxy modern)
{ {
_modern = modern; _modern = modern;
} }

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

@ -25,18 +25,18 @@ namespace Avalonia.FreeDesktop.DBusIme.Fcitx
{ {
if (name == "org.fcitx.Fcitx") if (name == "org.fcitx.Fcitx")
{ {
var method = new OrgFcitxFcitxInputMethod(Connection, name, "/inputmethod"); var method = new OrgFcitxFcitxInputMethodProxy(Connection, name, "/inputmethod");
var resp = await method.CreateICv3Async(GetAppName(), var resp = await method.CreateICv3Async(GetAppName(),
Process.GetCurrentProcess().Id); Process.GetCurrentProcess().Id);
var proxy = new OrgFcitxFcitxInputContext(Connection, name, $"/inputcontext_{resp.Icid}"); var proxy = new OrgFcitxFcitxInputContextProxy(Connection, name, $"/inputcontext_{resp.Icid}");
_context = new FcitxICWrapper(proxy); _context = new FcitxICWrapper(proxy);
} }
else else
{ {
var method = new OrgFcitxFcitxInputMethod1(Connection, name, "/inputmethod"); var method = new OrgFcitxFcitxInputMethod1Proxy(Connection, name, "/inputmethod");
var resp = await method.CreateInputContextAsync(new[] { ("appName", GetAppName()) }); var resp = await method.CreateInputContextAsync(new[] { ("appName", GetAppName()) });
var proxy = new OrgFcitxFcitxInputContext1(Connection, name, resp.Item1); var proxy = new OrgFcitxFcitxInputContext1Proxy(Connection, name, resp.Item1);
_context = new FcitxICWrapper(proxy); _context = new FcitxICWrapper(proxy);
} }

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

@ -13,21 +13,21 @@ namespace Avalonia.FreeDesktop.DBusIme.IBus
{ {
internal class IBusX11TextInputMethod : DBusTextInputMethodBase internal class IBusX11TextInputMethod : DBusTextInputMethodBase
{ {
private OrgFreedesktopIBusService? _service; private OrgFreedesktopIBusServiceProxy? _service;
private OrgFreedesktopIBusInputContext? _context; private OrgFreedesktopIBusInputContextProxy? _context;
private string? _preeditText; private string? _preeditText;
private int _preeditCursor; private int _preeditCursor;
private bool _preeditShown = true; private bool _preeditShown = true;
private int _insideReset = 0; private int _insideReset;
public IBusX11TextInputMethod(Connection connection) : base(connection, "org.freedesktop.portal.IBus") { } public IBusX11TextInputMethod(Connection connection) : base(connection, "org.freedesktop.portal.IBus") { }
protected override async Task<bool> Connect(string name) protected override async Task<bool> Connect(string name)
{ {
var portal = new OrgFreedesktopIBusPortal(Connection, name, "/org/freedesktop/IBus"); var portal = new OrgFreedesktopIBusPortalProxy(Connection, name, "/org/freedesktop/IBus");
var path = await portal.CreateInputContextAsync(GetAppName()); var path = await portal.CreateInputContextAsync(GetAppName());
_service = new OrgFreedesktopIBusService(Connection, name, path); _service = new OrgFreedesktopIBusServiceProxy(Connection, name, path);
_context = new OrgFreedesktopIBusInputContext(Connection, name, path); _context = new OrgFreedesktopIBusInputContextProxy(Connection, name, path);
AddDisposable(await _context.WatchCommitTextAsync(OnCommitText)); AddDisposable(await _context.WatchCommitTextAsync(OnCommitText));
AddDisposable(await _context.WatchForwardKeyEventAsync(OnForwardKey)); AddDisposable(await _context.WatchForwardKeyEventAsync(OnForwardKey));
AddDisposable(await _context.WatchUpdatePreeditTextAsync(OnUpdatePreedit)); AddDisposable(await _context.WatchUpdatePreeditTextAsync(OnUpdatePreedit));

63
src/Avalonia.FreeDesktop/DBusMenuExporter.cs

@ -24,7 +24,7 @@ namespace Avalonia.FreeDesktop
public static string GenerateDBusMenuObjPath => $"/net/avaloniaui/dbusmenu/{Guid.NewGuid():N}"; public static string GenerateDBusMenuObjPath => $"/net/avaloniaui/dbusmenu/{Guid.NewGuid():N}";
private sealed class DBusMenuExporterImpl : ComCanonicalDbusmenu, ITopLevelNativeMenuExporter, IDisposable private sealed class DBusMenuExporterImpl : ComCanonicalDbusmenuHandler, ITopLevelNativeMenuExporter, IDisposable
{ {
private readonly Dictionary<int, NativeMenuItemBase> _idsToItems = new(); private readonly Dictionary<int, NativeMenuItemBase> _idsToItems = new();
private readonly Dictionary<NativeMenuItemBase, int> _itemsToIds = new(); private readonly Dictionary<NativeMenuItemBase, int> _itemsToIds = new();
@ -32,7 +32,7 @@ namespace Avalonia.FreeDesktop
private readonly PathHandler _pathHandler; private readonly PathHandler _pathHandler;
private readonly uint _xid; private readonly uint _xid;
private readonly bool _appMenu = true; private readonly bool _appMenu = true;
private ComCanonicalAppMenuRegistrar? _registrar; private ComCanonicalAppMenuRegistrarProxy? _registrar;
private NativeMenu? _menu; private NativeMenu? _menu;
private bool _disposed; private bool _disposed;
private uint _revision = 1; private uint _revision = 1;
@ -63,7 +63,7 @@ namespace Avalonia.FreeDesktop
public override Connection Connection { get; } public override Connection Connection { get; }
protected override ValueTask<(uint Revision, (int, Dictionary<string, Variant>, Variant[]) Layout)> OnGetLayoutAsync(int parentId, int recursionDepth, string[] propertyNames) protected override ValueTask<(uint Revision, (int, Dictionary<string, VariantValue>, VariantValue[]) Layout)> OnGetLayoutAsync(Message message, int parentId, int recursionDepth, string[] propertyNames)
{ {
var menu = GetMenu(parentId); var menu = GetMenu(parentId);
var layout = GetLayout(menu.item, menu.menu, recursionDepth, propertyNames); var layout = GetLayout(menu.item, menu.menu, recursionDepth, propertyNames);
@ -73,31 +73,31 @@ namespace Avalonia.FreeDesktop
OnIsNativeMenuExportedChanged?.Invoke(this, EventArgs.Empty); OnIsNativeMenuExportedChanged?.Invoke(this, EventArgs.Empty);
} }
return new ValueTask<(uint, (int, Dictionary<string, Variant>, Variant[]))>((_revision, layout)); return new ValueTask<(uint, (int, Dictionary<string, VariantValue>, VariantValue[]))>((_revision, layout));
} }
protected override ValueTask<(int, Dictionary<string, Variant>)[]> OnGetGroupPropertiesAsync(int[] ids, string[] propertyNames) protected override ValueTask<(int, Dictionary<string, VariantValue>)[]> OnGetGroupPropertiesAsync(Message message, int[] ids, string[] propertyNames)
=> new(ids.Select(id => (id, GetProperties(GetMenu(id), propertyNames))).ToArray()); => new(ids.Select(id => (id, GetProperties(GetMenu(id), propertyNames))).ToArray());
protected override ValueTask<Variant> OnGetPropertyAsync(int id, string name) => protected override ValueTask<VariantValue> OnGetPropertyAsync(Message message, int id, string name) =>
new(GetProperty(GetMenu(id), name) ?? new Variant(0)); new(GetProperty(GetMenu(id), name) ?? VariantValue.Int32(0));
protected override ValueTask OnEventAsync(int id, string eventId, VariantValue data, uint timestamp) protected override ValueTask OnEventAsync(Message message, int id, string eventId, VariantValue data, uint timestamp)
{ {
HandleEvent(id, eventId); HandleEvent(id, eventId);
return new ValueTask(); return new ValueTask();
} }
protected override ValueTask<int[]> OnEventGroupAsync((int, string, VariantValue, uint)[] events) protected override ValueTask<int[]> OnEventGroupAsync(Message message, (int, string, VariantValue, uint)[] events)
{ {
foreach (var e in events) foreach (var e in events)
HandleEvent(e.Item1, e.Item2); HandleEvent(e.Item1, e.Item2);
return new ValueTask<int[]>([]); return new ValueTask<int[]>([]);
} }
protected override ValueTask<bool> OnAboutToShowAsync(int id) => new(false); protected override ValueTask<bool> OnAboutToShowAsync(Message message, int id) => new(false);
protected override ValueTask<(int[] UpdatesNeeded, int[] IdErrors)> OnAboutToShowGroupAsync(int[] ids) => protected override ValueTask<(int[] UpdatesNeeded, int[] IdErrors)> OnAboutToShowGroupAsync(Message message, int[] ids) =>
new(([], [])); new(([], []));
private async Task InitializeAsync() private async Task InitializeAsync()
@ -106,7 +106,7 @@ namespace Avalonia.FreeDesktop
if (!_appMenu) if (!_appMenu)
return; return;
_registrar = new ComCanonicalAppMenuRegistrar(Connection, "com.canonical.AppMenu.Registrar", "/com/canonical/AppMenu/Registrar"); _registrar = new ComCanonicalAppMenuRegistrarProxy(Connection, "com.canonical.AppMenu.Registrar", "/com/canonical/AppMenu/Registrar");
try try
{ {
if (!_disposed) if (!_disposed)
@ -211,32 +211,32 @@ namespace Avalonia.FreeDesktop
private static readonly string[] s_allProperties = ["type", "label", "enabled", "visible", "shortcut", "toggle-type", "children-display", "toggle-state", "icon-data"]; private static readonly string[] s_allProperties = ["type", "label", "enabled", "visible", "shortcut", "toggle-type", "children-display", "toggle-state", "icon-data"];
private static Variant? GetProperty((NativeMenuItemBase? item, NativeMenu? menu) i, string name) private static VariantValue? GetProperty((NativeMenuItemBase? item, NativeMenu? menu) i, string name)
{ {
var (it, menu) = i; var (it, menu) = i;
if (it is NativeMenuItemSeparator) if (it is NativeMenuItemSeparator)
{ {
if (name == "type") if (name == "type")
return new Variant("separator"); return VariantValue.String("separator");
} }
else if (it is NativeMenuItem item) else if (it is NativeMenuItem item)
{ {
if (name == "type") if (name == "type")
return null; return null;
if (name == "label") if (name == "label")
return new Variant(item.Header ?? "<null>"); return VariantValue.String(item.Header ?? "<null>");
if (name == "enabled") if (name == "enabled")
{ {
if (item.Menu is not null && item.Menu.Items.Count == 0) if (item.Menu is not null && item.Menu.Items.Count == 0)
return new Variant(false); return VariantValue.Bool(false);
if (!item.IsEnabled) if (!item.IsEnabled)
return new Variant(false); return VariantValue.Bool(false);
return null; return null;
} }
if (name == "visible") if (name == "visible")
return new Variant(item.IsVisible); return VariantValue.Bool(item.IsVisible);
if (name == "shortcut") if (name == "shortcut")
{ {
@ -244,7 +244,7 @@ namespace Avalonia.FreeDesktop
return null; return null;
if (item.Gesture.KeyModifiers == 0) if (item.Gesture.KeyModifiers == 0)
return null; return null;
var lst = new Array<string>(); var lst = new List<string>();
var mod = item.Gesture; var mod = item.Gesture;
if (mod.KeyModifiers.HasAllFlags(KeyModifiers.Control)) if (mod.KeyModifiers.HasAllFlags(KeyModifiers.Control))
lst.Add("Control"); lst.Add("Control");
@ -255,19 +255,19 @@ namespace Avalonia.FreeDesktop
if (mod.KeyModifiers.HasAllFlags(KeyModifiers.Meta)) if (mod.KeyModifiers.HasAllFlags(KeyModifiers.Meta))
lst.Add("Super"); lst.Add("Super");
lst.Add(item.Gesture.Key.ToString()); lst.Add(item.Gesture.Key.ToString());
return Variant.FromArray(new Array<Array<string>>([lst])); return VariantValue.ArrayOfVariant((VariantValue[]) [VariantValue.Array(lst)]);
} }
if (name == "toggle-type") if (name == "toggle-type")
{ {
if (item.ToggleType == NativeMenuItemToggleType.CheckBox) if (item.ToggleType == NativeMenuItemToggleType.CheckBox)
return new Variant("checkmark"); return VariantValue.String("checkmark");
if (item.ToggleType == NativeMenuItemToggleType.Radio) if (item.ToggleType == NativeMenuItemToggleType.Radio)
return new Variant("radio"); return VariantValue.String("radio");
} }
if (name == "toggle-state" && item.ToggleType != NativeMenuItemToggleType.None) if (name == "toggle-state" && item.ToggleType != NativeMenuItemToggleType.None)
return new Variant(item.IsChecked ? 1 : 0); return VariantValue.Int32(item.IsChecked ? 1 : 0);
if (name == "icon-data") if (name == "icon-data")
{ {
@ -280,7 +280,7 @@ namespace Avalonia.FreeDesktop
var icon = loader.LoadIcon(item.Icon.PlatformImpl.Item); var icon = loader.LoadIcon(item.Icon.PlatformImpl.Item);
using var ms = new MemoryStream(); using var ms = new MemoryStream();
icon.Save(ms); icon.Save(ms);
return Variant.FromArray(new Array<byte>(ms.ToArray())); return VariantValue.Array(ms.ToArray());
} }
} }
} }
@ -288,7 +288,7 @@ namespace Avalonia.FreeDesktop
if (name == "children-display") if (name == "children-display")
{ {
if (menu is not null) if (menu is not null)
return new Variant("submenu"); return VariantValue.String("submenu");
return null; return null;
} }
} }
@ -296,11 +296,11 @@ namespace Avalonia.FreeDesktop
return null; return null;
} }
private static Dictionary<string, Variant> GetProperties((NativeMenuItemBase? item, NativeMenu? menu) i, string[] names) private static Dictionary<string, VariantValue> GetProperties((NativeMenuItemBase? item, NativeMenu? menu) i, string[] names)
{ {
if (names.Length == 0) if (names.Length == 0)
names = s_allProperties; names = s_allProperties;
var properties = new Dictionary<string, Variant>(); var properties = new Dictionary<string, VariantValue>();
foreach (var n in names) foreach (var n in names)
{ {
var v = GetProperty(i, n); var v = GetProperty(i, n);
@ -311,18 +311,21 @@ namespace Avalonia.FreeDesktop
return properties; return properties;
} }
private (int, Dictionary<string, Variant>, Variant[]) GetLayout(NativeMenuItemBase? item, NativeMenu? menu, int depth, string[] propertyNames) private (int, Dictionary<string, VariantValue>, VariantValue[]) GetLayout(NativeMenuItemBase? item, NativeMenu? menu, int depth, string[] propertyNames)
{ {
var id = item is null ? 0 : GetId(item); var id = item is null ? 0 : GetId(item);
var props = GetProperties((item, menu), propertyNames); var props = GetProperties((item, menu), propertyNames);
var children = depth == 0 || menu is null ? [] : new Variant[menu.Items.Count]; var children = depth == 0 || menu is null ? [] : new VariantValue[menu.Items.Count];
if (menu is not null) if (menu is not null)
{ {
for (var c = 0; c < children.Length; c++) for (var c = 0; c < children.Length; c++)
{ {
var ch = menu.Items[c]; var ch = menu.Items[c];
var layout = GetLayout(ch, (ch as NativeMenuItem)?.Menu, depth == -1 ? -1 : depth - 1, propertyNames); var layout = GetLayout(ch, (ch as NativeMenuItem)?.Menu, depth == -1 ? -1 : depth - 1, propertyNames);
children[c] = Variant.FromStruct(Struct.Create(layout.Item1, new Dict<string, Variant>(layout.Item2), new Array<Variant>(layout.Item3))); children[c] = VariantValue.Struct(
VariantValue.Int32(layout.Item1),
new Dict<string, VariantValue>(layout.Item2),
VariantValue.ArrayOfVariant(layout.Item3));
} }
} }

8
src/Avalonia.FreeDesktop/DBusPlatformSettings.cs

@ -10,7 +10,7 @@ namespace Avalonia.FreeDesktop
{ {
internal class DBusPlatformSettings : DefaultPlatformSettings internal class DBusPlatformSettings : DefaultPlatformSettings
{ {
private readonly OrgFreedesktopPortalSettings? _settings; private readonly OrgFreedesktopPortalSettingsProxy? _settings;
private PlatformColorValues? _lastColorValues; private PlatformColorValues? _lastColorValues;
private PlatformThemeVariant? _themeVariant; private PlatformThemeVariant? _themeVariant;
@ -21,7 +21,7 @@ namespace Avalonia.FreeDesktop
if (DBusHelper.DefaultConnection is not { } conn) if (DBusHelper.DefaultConnection is not { } conn)
return; return;
_settings = new OrgFreedesktopPortalSettings(conn, "org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop"); _settings = new OrgFreedesktopPortalSettingsProxy(conn, "org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop");
_ = _settings.WatchSettingChangedAsync(SettingsChangedHandler); _ = _settings.WatchSettingChangedAsync(SettingsChangedHandler);
_ = TryGetInitialValuesAsync(); _ = TryGetInitialValuesAsync();
} }
@ -46,8 +46,8 @@ namespace Avalonia.FreeDesktop
if (version >= 2) if (version >= 2)
value = await _settings!.ReadOneAsync("org.freedesktop.appearance", "color-scheme"); value = await _settings!.ReadOneAsync("org.freedesktop.appearance", "color-scheme");
else else
// Variants-in-Variants are automatically collapsed by Tmds.DBus.Protocol, so need to do so here as normally necessary // Unpack nested Variant
value = await _settings!.ReadAsync("org.freedesktop.appearance", "color-scheme"); value = (await _settings!.ReadAsync("org.freedesktop.appearance", "color-scheme")).GetVariantValue();
return ToColorScheme(value.GetUInt32()); return ToColorScheme(value.GetUInt32());
} }
catch (DBusException) catch (DBusException)

46
src/Avalonia.FreeDesktop/DBusSystemDialog.cs

@ -21,8 +21,8 @@ namespace Avalonia.FreeDesktop
return null; return null;
using var restoreContext = AvaloniaSynchronizationContext.Ensure(DispatcherPriority.Input); using var restoreContext = AvaloniaSynchronizationContext.Ensure(DispatcherPriority.Input);
var dbusFileChooser = new OrgFreedesktopPortalFileChooser(conn, "org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop"); var dbusFileChooser = new OrgFreedesktopPortalFileChooserProxy(conn, "org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop");
uint version; uint version;
try try
{ {
@ -37,11 +37,11 @@ namespace Avalonia.FreeDesktop
} }
private readonly Connection _connection; private readonly Connection _connection;
private readonly OrgFreedesktopPortalFileChooser _fileChooser; private readonly OrgFreedesktopPortalFileChooserProxy _fileChooser;
private readonly IPlatformHandle _handle; private readonly IPlatformHandle _handle;
private readonly uint _version; private readonly uint _version;
private DBusSystemDialog(Connection connection, IPlatformHandle handle, OrgFreedesktopPortalFileChooser fileChooser, uint version) private DBusSystemDialog(Connection connection, IPlatformHandle handle, OrgFreedesktopPortalFileChooserProxy fileChooser, uint version)
{ {
_connection = connection; _connection = connection;
_fileChooser = fileChooser; _fileChooser = fileChooser;
@ -59,19 +59,19 @@ namespace Avalonia.FreeDesktop
{ {
var parentWindow = $"x11:{_handle.Handle:X}"; var parentWindow = $"x11:{_handle.Handle:X}";
ObjectPath objectPath; ObjectPath objectPath;
var chooserOptions = new Dictionary<string, Variant>(); var chooserOptions = new Dictionary<string, VariantValue>();
if (TryParseFilters(options.FileTypeFilter, out var filters)) if (TryParseFilters(options.FileTypeFilter, out var filters))
chooserOptions.Add("filters", filters); chooserOptions.Add("filters", filters);
if (options.SuggestedStartLocation?.TryGetLocalPath() is { } folderPath) if (options.SuggestedStartLocation?.TryGetLocalPath() is { } folderPath)
chooserOptions.Add("current_folder", Variant.FromArray(new Array<byte>(Encoding.UTF8.GetBytes(folderPath + "\0")))); chooserOptions.Add("current_folder", VariantValue.Array(Encoding.UTF8.GetBytes(folderPath + "\0")));
chooserOptions.Add("multiple", new Variant(options.AllowMultiple)); chooserOptions.Add("multiple", VariantValue.Bool(options.AllowMultiple));
objectPath = await _fileChooser.OpenFileAsync(parentWindow, options.Title ?? string.Empty, chooserOptions); objectPath = await _fileChooser.OpenFileAsync(parentWindow, options.Title ?? string.Empty, chooserOptions);
var request = new OrgFreedesktopPortalRequest(_connection, "org.freedesktop.portal.Desktop", objectPath); var request = new OrgFreedesktopPortalRequestProxy(_connection, "org.freedesktop.portal.Desktop", objectPath);
var tsc = new TaskCompletionSource<string[]?>(); var tsc = new TaskCompletionSource<string[]?>();
using var disposable = await request.WatchResponseAsync((e, x) => using var disposable = await request.WatchResponseAsync((e, x) =>
{ {
@ -81,7 +81,7 @@ namespace Avalonia.FreeDesktop
tsc.TrySetResult(x.Results["uris"].GetArray<string>()); tsc.TrySetResult(x.Results["uris"].GetArray<string>());
}); });
var uris = await tsc.Task ?? Array.Empty<string>(); var uris = await tsc.Task ?? [];
return uris.Select(static path => new BclStorageFile(new FileInfo(new Uri(path).LocalPath))).ToList(); return uris.Select(static path => new BclStorageFile(new FileInfo(new Uri(path).LocalPath))).ToList();
} }
@ -89,17 +89,17 @@ namespace Avalonia.FreeDesktop
{ {
var parentWindow = $"x11:{_handle.Handle:X}"; var parentWindow = $"x11:{_handle.Handle:X}";
ObjectPath objectPath; ObjectPath objectPath;
var chooserOptions = new Dictionary<string, Variant>(); var chooserOptions = new Dictionary<string, VariantValue>();
if (TryParseFilters(options.FileTypeChoices, out var filters)) if (TryParseFilters(options.FileTypeChoices, out var filters))
chooserOptions.Add("filters", filters); chooserOptions.Add("filters", filters);
if (options.SuggestedFileName is { } currentName) if (options.SuggestedFileName is { } currentName)
chooserOptions.Add("current_name", new Variant(currentName)); chooserOptions.Add("current_name", VariantValue.String(currentName));
if (options.SuggestedStartLocation?.TryGetLocalPath() is { } folderPath) if (options.SuggestedStartLocation?.TryGetLocalPath() is { } folderPath)
chooserOptions.Add("current_folder", Variant.FromArray(new Array<byte>(Encoding.UTF8.GetBytes(folderPath + "\0")))); chooserOptions.Add("current_folder", VariantValue.Array(Encoding.UTF8.GetBytes(folderPath + "\0")));
objectPath = await _fileChooser.SaveFileAsync(parentWindow, options.Title ?? string.Empty, chooserOptions); objectPath = await _fileChooser.SaveFileAsync(parentWindow, options.Title ?? string.Empty, chooserOptions);
var request = new OrgFreedesktopPortalRequest(_connection, "org.freedesktop.portal.Desktop", objectPath); var request = new OrgFreedesktopPortalRequestProxy(_connection, "org.freedesktop.portal.Desktop", objectPath);
var tsc = new TaskCompletionSource<string[]?>(); var tsc = new TaskCompletionSource<string[]?>();
FilePickerFileType? selectedType = null; FilePickerFileType? selectedType = null;
using var disposable = await request.WatchResponseAsync((e, x) => using var disposable = await request.WatchResponseAsync((e, x) =>
@ -147,22 +147,22 @@ namespace Avalonia.FreeDesktop
public override async Task<IReadOnlyList<IStorageFolder>> OpenFolderPickerAsync(FolderPickerOpenOptions options) public override async Task<IReadOnlyList<IStorageFolder>> OpenFolderPickerAsync(FolderPickerOpenOptions options)
{ {
if (_version < 3) if (_version < 3)
return Array.Empty<IStorageFolder>(); return [];
var parentWindow = $"x11:{_handle.Handle:X}"; var parentWindow = $"x11:{_handle.Handle:X}";
var chooserOptions = new Dictionary<string, Variant> var chooserOptions = new Dictionary<string, VariantValue>
{ {
{ "directory", new Variant(true) }, { "directory", VariantValue.Bool(true) },
{ "multiple", new Variant(options.AllowMultiple) } { "multiple", VariantValue.Bool(options.AllowMultiple) }
}; };
if (options.SuggestedFileName is { } currentName) if (options.SuggestedFileName is { } currentName)
chooserOptions.Add("current_name", new Variant(currentName)); chooserOptions.Add("current_name", VariantValue.String(currentName));
if (options.SuggestedStartLocation?.TryGetLocalPath() is { } folderPath) if (options.SuggestedStartLocation?.TryGetLocalPath() is { } folderPath)
chooserOptions.Add("current_folder", Variant.FromArray(new Array<byte>(Encoding.UTF8.GetBytes(folderPath + "\0")))); chooserOptions.Add("current_folder", VariantValue.Array(Encoding.UTF8.GetBytes(folderPath + "\0")));
var objectPath = await _fileChooser.OpenFileAsync(parentWindow, options.Title ?? string.Empty, chooserOptions); var objectPath = await _fileChooser.OpenFileAsync(parentWindow, options.Title ?? string.Empty, chooserOptions);
var request = new OrgFreedesktopPortalRequest(_connection, "org.freedesktop.portal.Desktop", objectPath); var request = new OrgFreedesktopPortalRequestProxy(_connection, "org.freedesktop.portal.Desktop", objectPath);
var tsc = new TaskCompletionSource<string[]?>(); var tsc = new TaskCompletionSource<string[]?>();
using var disposable = await request.WatchResponseAsync((e, x) => using var disposable = await request.WatchResponseAsync((e, x) =>
{ {
@ -180,7 +180,7 @@ namespace Avalonia.FreeDesktop
.Select(static path => new BclStorageFolder(new DirectoryInfo(path))).ToList(); .Select(static path => new BclStorageFolder(new DirectoryInfo(path))).ToList();
} }
private static bool TryParseFilters(IReadOnlyList<FilePickerFileType>? fileTypes, out Variant result) private static bool TryParseFilters(IReadOnlyList<FilePickerFileType>? fileTypes, out VariantValue result)
{ {
const uint GlobStyle = 0u; const uint GlobStyle = 0u;
const uint MimeStyle = 1u; const uint MimeStyle = 1u;
@ -207,7 +207,7 @@ namespace Avalonia.FreeDesktop
filters.Add(Struct.Create(fileType.Name, new Array<Struct<uint, string>>(extensions))); filters.Add(Struct.Create(fileType.Name, new Array<Struct<uint, string>>(extensions)));
} }
result = Variant.FromArray(filters); result = filters.AsVariantValue();
return true; return true;
} }
} }

18
src/Avalonia.FreeDesktop/DBusTrayIconImpl.cs

@ -16,12 +16,12 @@ namespace Avalonia.FreeDesktop
public static readonly (int, int, byte[]) EmptyPixmap = (1, 1, [255, 0, 0, 0]); public static readonly (int, int, byte[]) EmptyPixmap = (1, 1, [255, 0, 0, 0]);
private readonly Connection? _connection; private readonly Connection? _connection;
private readonly OrgFreedesktopDBus? _dBus; private readonly OrgFreedesktopDBusProxy? _dBus;
private IDisposable? _serviceWatchDisposable; private IDisposable? _serviceWatchDisposable;
private readonly PathHandler _pathHandler = new("/StatusNotifierItem"); private readonly PathHandler _pathHandler = new("/StatusNotifierItem");
private readonly StatusNotifierItemDbusObj? _statusNotifierItemDbusObj; private readonly StatusNotifierItemDbusObj? _statusNotifierItemDbusObj;
private OrgKdeStatusNotifierWatcher? _statusNotifierWatcher; private OrgKdeStatusNotifierWatcherProxy? _statusNotifierWatcher;
private (int, int, byte[]) _icon; private (int, int, byte[]) _icon;
private string? _sysTrayServiceName; private string? _sysTrayServiceName;
@ -50,7 +50,7 @@ namespace Avalonia.FreeDesktop
IsActive = true; IsActive = true;
_dBus = new OrgFreedesktopDBus(_connection, "org.freedesktop.DBus", "/org/freedesktop/DBus"); _dBus = new OrgFreedesktopDBusProxy(_connection, "org.freedesktop.DBus", "/org/freedesktop/DBus");
var dbusMenuPath = DBusMenuExporter.GenerateDBusMenuObjPath; var dbusMenuPath = DBusMenuExporter.GenerateDBusMenuObjPath;
MenuExporter = DBusMenuExporter.TryCreateDetachedNativeMenu(dbusMenuPath, _connection); MenuExporter = DBusMenuExporter.TryCreateDetachedNativeMenu(dbusMenuPath, _connection);
@ -86,7 +86,7 @@ namespace Avalonia.FreeDesktop
if (!_serviceConnected && newOwner is not null) if (!_serviceConnected && newOwner is not null)
{ {
_serviceConnected = true; _serviceConnected = true;
_statusNotifierWatcher = new OrgKdeStatusNotifierWatcher(_connection, "org.kde.StatusNotifierWatcher", "/StatusNotifierWatcher"); _statusNotifierWatcher = new OrgKdeStatusNotifierWatcherProxy(_connection, "org.kde.StatusNotifierWatcher", "/StatusNotifierWatcher");
DestroyTrayIcon(); DestroyTrayIcon();
@ -213,7 +213,7 @@ namespace Avalonia.FreeDesktop
/// <remarks> /// <remarks>
/// Useful guide: https://web.archive.org/web/20210818173850/https://www.notmart.org/misc/statusnotifieritem/statusnotifieritem.html /// Useful guide: https://web.archive.org/web/20210818173850/https://www.notmart.org/misc/statusnotifieritem/statusnotifieritem.html
/// </remarks> /// </remarks>
internal class StatusNotifierItemDbusObj : OrgKdeStatusNotifierItem internal class StatusNotifierItemDbusObj : OrgKdeStatusNotifierItemHandler
{ {
public StatusNotifierItemDbusObj(Connection connection, ObjectPath dbusMenuPath) public StatusNotifierItemDbusObj(Connection connection, ObjectPath dbusMenuPath)
{ {
@ -225,17 +225,17 @@ namespace Avalonia.FreeDesktop
public event Action? ActivationDelegate; public event Action? ActivationDelegate;
protected override ValueTask OnContextMenuAsync(int x, int y) => new(); protected override ValueTask OnContextMenuAsync(Message message, int x, int y) => new();
protected override ValueTask OnActivateAsync(int x, int y) protected override ValueTask OnActivateAsync(Message message, int x, int y)
{ {
ActivationDelegate?.Invoke(); ActivationDelegate?.Invoke();
return new ValueTask(); return new ValueTask();
} }
protected override ValueTask OnSecondaryActivateAsync(int x, int y) => new(); protected override ValueTask OnSecondaryActivateAsync(Message message, int x, int y) => new();
protected override ValueTask OnScrollAsync(int delta, string orientation) => new(); protected override ValueTask OnScrollAsync(Message message, int delta, string orientation) => new();
public void InvalidateAll() public void InvalidateAll()
{ {

Loading…
Cancel
Save