瀏覽代碼

Revert "Reapply (#15568) + Updates (#16129)" (#16175)

This reverts commit 9c955d3b3d0c49b162747bada0a103f67cc1705b.
Nikita Tsukanov 1 年之前
父節點
當前提交
1639aabd3c

+ 0 - 10
api/Avalonia.FreeDesktop.nupkg.xml

@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids -->
-<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
-  <Suppression>
-    <DiagnosticId>CP0001</DiagnosticId>
-    <Target>T:Tmds.DBus.SourceGenerator.PropertyChanges`1</Target>
-    <Left>baseline/netstandard2.0/Avalonia.FreeDesktop.dll</Left>
-    <Right>target/netstandard2.0/Avalonia.FreeDesktop.dll</Right>
-  </Suppression>
-</Suppressions>

+ 2 - 2
src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj

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

+ 2 - 2
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;
     }

+ 1 - 1
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

+ 11 - 10
src/Avalonia.FreeDesktop/DBusIme/IBus/IBusX11TextInputMethod.cs

@@ -51,16 +51,17 @@ namespace Avalonia.FreeDesktop.DBusIme.IBus
                 Client.SetPreeditText(_preeditText, _preeditText == null ? null : _preeditCursor);
         }
 
-        private void OnUpdatePreedit(Exception? arg1, (VariantValue Text, uint CursorPos, bool Visible) preeditComponents)
+        private void OnUpdatePreedit(Exception? arg1, (DBusVariantItem text, uint cursor_pos, bool visible) preeditComponents)
         {
-            if (preeditComponents.Text is { Type: VariantValueType.Struct, Count: >= 3 } structItem && structItem.GetItem(2) is { Type: VariantValueType.String} stringItem)
+            if (preeditComponents.text is { Value: DBusStructItem { Count: >= 3 } structItem } &&
+                structItem[2] is DBusStringItem stringItem)
             {
-                _preeditText = stringItem.GetString();
+                _preeditText = stringItem.Value;
                 _preeditCursor = _preeditText != null
                     ? Utf16Utils.CharacterOffsetToStringOffset(_preeditText,
-                        (int)Math.Min(preeditComponents.CursorPos, int.MaxValue), false)
+                        (int)Math.Min(preeditComponents.cursor_pos, int.MaxValue), false)
                     : 0;
-
+                
                 _preeditShown = true;
             }
             else
@@ -101,13 +102,13 @@ namespace Avalonia.FreeDesktop.DBusIme.IBus
             });
         }
 
-        private void OnCommitText(Exception? e, VariantValue variantItem)
+        private void OnCommitText(Exception? e, DBusVariantItem 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;
             }
@@ -117,8 +118,8 @@ namespace Avalonia.FreeDesktop.DBusIme.IBus
                 return;
             }
 
-            if (variantItem.Count >= 3 && variantItem.GetItem(2) is { Type: VariantValueType.String } stringItem)
-                FireCommit(stringItem.GetString());
+            if (variantItem.Value is DBusStructItem { Count: >= 3 } structItem && structItem[2] is DBusStringItem stringItem)
+                FireCommit(stringItem.Value);
         }
 
         protected override Task DisconnectAsync() => _service?.DestroyAsync() ?? Task.CompletedTask;

+ 53 - 50
src/Avalonia.FreeDesktop/DBusMenuExporter.cs

@@ -43,10 +43,7 @@ namespace Avalonia.FreeDesktop
                 InitBackingProperties();
                 Connection = connection;
                 _xid = (uint)xid.ToInt32();
-                
-                PathHandler = new PathHandler(GenerateDBusMenuObjPath);
-                PathHandler.Add(this);
-                
+                Path = GenerateDBusMenuObjPath;
                 SetNativeMenu(new NativeMenu());
                 _ = InitializeAsync();
             }
@@ -56,22 +53,24 @@ namespace Avalonia.FreeDesktop
                 InitBackingProperties();
                 Connection = connection;
                 _appMenu = false;
-                
-                PathHandler = new PathHandler(path);
-                PathHandler.Add(this);
-                
+                Path = path;
                 SetNativeMenu(new NativeMenu());
                 _ = InitializeAsync();
             }
 
             private void InitBackingProperties()
             {
-                Version = 4;
+                BackingProperties.Version = 4;
+                BackingProperties.Status = string.Empty;
+                BackingProperties.TextDirection = string.Empty;
+                BackingProperties.IconThemePath = Array.Empty<string>();
             }
 
-            public override Connection Connection { get; }
+            protected override Connection Connection { get; }
 
-            protected override ValueTask<(uint Revision, (int, Dictionary<string, Variant>, Variant[]) Layout)> OnGetLayoutAsync(int parentId, int recursionDepth, string[] propertyNames)
+            public override string Path { get; }
+
+            protected override ValueTask<(uint revision, (int, Dictionary<string, DBusVariantItem>, DBusVariantItem[]) layout)> OnGetLayoutAsync(int parentId, int recursionDepth, string[] propertyNames)
             {
                 var menu = GetMenu(parentId);
                 var layout = GetLayout(menu.item, menu.menu, recursionDepth, propertyNames);
@@ -81,22 +80,22 @@ namespace Avalonia.FreeDesktop
                     OnIsNativeMenuExportedChanged?.Invoke(this, EventArgs.Empty);
                 }
 
-                return new ValueTask<(uint, (int, Dictionary<string, Variant>, Variant[]))>((_revision, layout));
+                return new ValueTask<(uint, (int, Dictionary<string, DBusVariantItem>, DBusVariantItem[]))>((_revision, layout));
             }
 
-            protected override ValueTask<(int, Dictionary<string, Variant>)[]> OnGetGroupPropertiesAsync(int[] ids, string[] propertyNames)
+            protected override ValueTask<(int, Dictionary<string, DBusVariantItem>)[]> OnGetGroupPropertiesAsync(int[] ids, string[] propertyNames)
                 => new(ids.Select(id => (id, GetProperties(GetMenu(id), propertyNames))).ToArray());
 
-            protected override ValueTask<Variant> OnGetPropertyAsync(int id, string name) =>
-                new(GetProperty(GetMenu(id), name) ?? new Variant(0));
+            protected override ValueTask<DBusVariantItem> OnGetPropertyAsync(int id, string name) =>
+                new(GetProperty(GetMenu(id), name) ?? new DBusVariantItem("i", new DBusInt32Item(0)));
 
-            protected override ValueTask OnEventAsync(int id, string eventId, VariantValue data, uint timestamp)
+            protected override ValueTask OnEventAsync(int id, string eventId, DBusVariantItem data, uint timestamp)
             {
                 HandleEvent(id, eventId);
                 return new ValueTask();
             }
 
-            protected override ValueTask<int[]> OnEventGroupAsync((int, string, VariantValue, uint)[] events)
+            protected override ValueTask<int[]> OnEventGroupAsync((int, string, DBusVariantItem, uint)[] events)
             {
                 foreach (var e in events)
                     HandleEvent(e.Item1, e.Item2);
@@ -105,12 +104,12 @@ 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()
             {
-                Connection.AddMethodHandler(this.PathHandler!);
+                Connection.AddMethodHandler(this);
                 if (!_appMenu)
                     return;
 
@@ -118,7 +117,7 @@ namespace Avalonia.FreeDesktop
                 try
                 {
                     if (!_disposed)
-                        await _registrar.RegisterWindowAsync(_xid, this.PathHandler!.Path);
+                        await _registrar.RegisterWindowAsync(_xid, Path);
                 }
                 catch
                 {
@@ -221,32 +220,35 @@ namespace Avalonia.FreeDesktop
                 "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 DBusVariantItem? GetProperty((NativeMenuItemBase? item, NativeMenu? menu) i, string name)
             {
                 var (it, menu) = i;
 
                 if (it is NativeMenuItemSeparator)
                 {
                     if (name == "type")
-                        return new Variant("separator");
+                        return new DBusVariantItem("s", new DBusStringItem("separator"));
                 }
                 else if (it is NativeMenuItem item)
                 {
                     if (name == "type")
                         return null;
                     if (name == "label")
-                        return new Variant(item.Header ?? "<null>");
+                        return new DBusVariantItem("s", new DBusStringItem(item.Header ?? "<null>"));
                     if (name == "enabled")
                     {
                         if (item.Menu is not null && item.Menu.Items.Count == 0)
-                            return new Variant(false);
+                            return new DBusVariantItem("b", new DBusBoolItem(false));
                         if (!item.IsEnabled)
-                            return new Variant(false);
+                            return new DBusVariantItem("b", new DBusBoolItem(false));
                         return null;
                     }
 
-                    if (name == "visible")
-                        return new Variant(item.IsVisible);
+                    if (name == "visible") {
+                        if (!item.IsVisible)
+                            return new DBusVariantItem("b", new DBusBoolItem(false));
+                        return new DBusVariantItem("b", new DBusBoolItem(true));
+                    }
 
                     if (name == "shortcut")
                     {
@@ -254,30 +256,30 @@ namespace Avalonia.FreeDesktop
                             return null;
                         if (item.Gesture.KeyModifiers == 0)
                             return null;
-                        var lst = new Array<Variant>();
+                        var lst = new List<DBusItem>();
                         var mod = item.Gesture;
                         if (mod.KeyModifiers.HasAllFlags(KeyModifiers.Control))
-                            lst.Add(new Variant("Control"));
+                            lst.Add(new DBusStringItem("Control"));
                         if (mod.KeyModifiers.HasAllFlags(KeyModifiers.Alt))
-                            lst.Add(new Variant("Alt"));
+                            lst.Add(new DBusStringItem("Alt"));
                         if (mod.KeyModifiers.HasAllFlags(KeyModifiers.Shift))
-                            lst.Add(new Variant("Shift"));
+                            lst.Add(new DBusStringItem("Shift"));
                         if (mod.KeyModifiers.HasAllFlags(KeyModifiers.Meta))
-                            lst.Add(new Variant("Super"));
-                        lst.Add(new Variant(item.Gesture.Key.ToString()));
-                        return Variant.FromArray(new Array<Array<Variant>>(new[] { lst }));
+                            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) }));
                     }
 
                     if (name == "toggle-type")
                     {
                         if (item.ToggleType == NativeMenuItemToggleType.CheckBox)
-                            return new Variant("checkmark");
+                            return new DBusVariantItem("s", new DBusStringItem("checkmark"));
                         if (item.ToggleType == NativeMenuItemToggleType.Radio)
-                            return new Variant("radio");
+                            return new DBusVariantItem("s", new DBusStringItem("radio"));
                     }
 
                     if (name == "toggle-state" && item.ToggleType != NativeMenuItemToggleType.None)
-                        return new Variant(item.IsChecked ? 1 : 0);
+                        return new DBusVariantItem("i", new DBusInt32Item(item.IsChecked ? 1 : 0));
 
                     if (name == "icon-data")
                     {
@@ -290,49 +292,50 @@ namespace Avalonia.FreeDesktop
                                 var icon = loader.LoadIcon(item.Icon.PlatformImpl.Item);
                                 using var ms = new MemoryStream();
                                 icon.Save(ms);
-                                return Variant.FromArray(new Array<byte>(ms.ToArray()));
+                                return new DBusVariantItem("ay", new DBusByteArrayItem(ms.ToArray()));
                             }
                         }
                     }
 
                     if (name == "children-display")
-                    {
-                        if (menu is not null)
-                            return new Variant("submenu");
-                        return null;
-                    }
+                        return menu is not null ? new DBusVariantItem("s", new DBusStringItem("submenu")) : null;
                 }
 
                 return null;
             }
 
-            private static Dictionary<string, Variant> GetProperties((NativeMenuItemBase? item, NativeMenu? menu) i, string[] names)
+            private static Dictionary<string, DBusVariantItem> GetProperties((NativeMenuItemBase? item, NativeMenu? menu) i, string[] names)
             {
                 if (names.Length == 0)
                     names = s_allProperties;
-                var properties = new Dictionary<string, Variant>();
+                var properties = new Dictionary<string, DBusVariantItem>();
                 foreach (var n in names)
                 {
                     var v = GetProperty(i, n);
-                    if (v.HasValue)
-                        properties.Add(n, v.Value);
+                    if (v is not null)
+                        properties.Add(n, v);
                 }
 
                 return properties;
             }
 
-            private (int, Dictionary<string, Variant>, Variant[]) GetLayout(NativeMenuItemBase? item, NativeMenu? menu, int depth, string[] propertyNames)
+            private (int, Dictionary<string, DBusVariantItem>, DBusVariantItem[]) 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<Variant>() : new Variant[menu.Items.Count];
+                var children = depth == 0 || menu is null ? Array.Empty<DBusVariantItem>() : new DBusVariantItem[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] = Variant.FromStruct(Struct.Create(layout.Item1, new Dict<string, Variant>(layout.Item2), new Array<Variant>(layout.Item3)));
+                        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)
+                        }));
                     }
                 }
 

+ 20 - 16
src/Avalonia.FreeDesktop/DBusPlatformSettings.cs

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

+ 62 - 47
src/Avalonia.FreeDesktop/DBusSystemDialog.cs

@@ -59,15 +59,14 @@ namespace Avalonia.FreeDesktop
         {
             var parentWindow = $"x11:{_handle.Handle:X}";
             ObjectPath objectPath;
-            var chooserOptions = new Dictionary<string, Variant>();
-
-            if (TryParseFilters(options.FileTypeFilter, out var filters))
+            var chooserOptions = new Dictionary<string, DBusVariantItem>();
+            var filters = ParseFilters(options.FileTypeFilter);
+            if (filters is not null)
                 chooserOptions.Add("filters", filters);
 
             if (options.SuggestedStartLocation?.TryGetLocalPath()  is { } folderPath)
-                chooserOptions.Add("current_folder", Variant.FromArray(new Array<byte>(Encoding.UTF8.GetBytes(folderPath + "\0"))));
-
-            chooserOptions.Add("multiple", new Variant(options.AllowMultiple));
+                chooserOptions.Add("current_folder", new DBusVariantItem("ay", new DBusByteArrayItem(Encoding.UTF8.GetBytes(folderPath + "\0"))));
+            chooserOptions.Add("multiple", new DBusVariantItem("b", new DBusBoolItem(options.AllowMultiple)));
 
             objectPath = await _fileChooser.OpenFileAsync(parentWindow, options.Title ?? string.Empty, chooserOptions);
 
@@ -78,7 +77,7 @@ namespace Avalonia.FreeDesktop
                 if (e is not null)
                     tsc.TrySetException(e);
                 else
-                    tsc.TrySetResult(x.Results["uris"].GetArray<string>());
+                    tsc.TrySetResult((x.results["uris"].Value as DBusArrayItem)?.Select(static y => (y as DBusStringItem)!.Value).ToArray());
             });
 
             var uris = await tsc.Task ?? Array.Empty<string>();
@@ -89,14 +88,15 @@ namespace Avalonia.FreeDesktop
         {
             var parentWindow = $"x11:{_handle.Handle:X}";
             ObjectPath objectPath;
-            var chooserOptions = new Dictionary<string, Variant>();
-            if (TryParseFilters(options.FileTypeChoices, out var filters))
+            var chooserOptions = new Dictionary<string, DBusVariantItem>();
+            var filters = ParseFilters(options.FileTypeChoices);
+            if (filters is not null)
                 chooserOptions.Add("filters", filters);
 
             if (options.SuggestedFileName is { } currentName)
-                chooserOptions.Add("current_name", new Variant(currentName));
+                chooserOptions.Add("current_name", new DBusVariantItem("s", new DBusStringItem(currentName)));
             if (options.SuggestedStartLocation?.TryGetLocalPath()  is { } folderPath)
-                chooserOptions.Add("current_folder", Variant.FromArray(new Array<byte>(Encoding.UTF8.GetBytes(folderPath + "\0"))));
+                chooserOptions.Add("current_folder", new DBusVariantItem("ay", new DBusByteArrayItem(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);
@@ -105,31 +105,41 @@ 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 currentFilter))
+                    if(x.results.TryGetValue("current_filter", out var value))
                     {
-                        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 currentFilter = value.Value as DBusStructItem;
+                        if(currentFilter != null)
                         {
-                            if (t.GetItem(0).GetUInt32() == 1)
-                                mimeTypes.Add(t.GetItem(1).GetString());
-                            else
-                                patterns.Add(t.GetItem(1).GetString());
+                            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;
+                            }
                         }
-
-                        selectedType.Patterns = patterns;
-                        selectedType.MimeTypes = mimeTypes;
                     }
-
-                    tsc.TrySetResult(x.Results["uris"].GetArray<string>());
+                    tsc.TrySetResult((x.results["uris"].Value as DBusArrayItem)?.Select(static y => (y as DBusStringItem)!.Value).ToArray());
                 }
             });
 
@@ -150,16 +160,16 @@ namespace Avalonia.FreeDesktop
                 return Array.Empty<IStorageFolder>();
 
             var parentWindow = $"x11:{_handle.Handle:X}";
-            var chooserOptions = new Dictionary<string, Variant>
+            var chooserOptions = new Dictionary<string, DBusVariantItem>
             {
-                { "directory", new Variant(true) },
-                { "multiple", new Variant(options.AllowMultiple) }
+                { "directory", new DBusVariantItem("b", new DBusBoolItem(true)) },
+                { "multiple", new DBusVariantItem("b", new DBusBoolItem(options.AllowMultiple)) }
             };
 
             if (options.SuggestedFileName is { } currentName)
-                chooserOptions.Add("current_name", new Variant(currentName));
+                chooserOptions.Add("current_name", new DBusVariantItem("s", new DBusStringItem(currentName)));
             if (options.SuggestedStartLocation?.TryGetLocalPath()  is { } folderPath)
-                chooserOptions.Add("current_folder", Variant.FromArray(new Array<byte>(Encoding.UTF8.GetBytes(folderPath + "\0"))));
+                chooserOptions.Add("current_folder", new DBusVariantItem("ay", new DBusByteArrayItem(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);
@@ -169,7 +179,7 @@ namespace Avalonia.FreeDesktop
                 if (e is not null)
                     tsc.TrySetException(e);
                 else
-                    tsc.TrySetResult(x.Results["uris"].GetArray<string>());
+                    tsc.TrySetResult((x.results["uris"].Value as DBusArrayItem)?.Select(static y => (y as DBusStringItem)!.Value).ToArray());
             });
 
             var uris = await tsc.Task ?? Array.Empty<string>();
@@ -180,35 +190,40 @@ namespace Avalonia.FreeDesktop
                 .Select(static path => new BclStorageFolder(new DirectoryInfo(path))).ToList();
         }
 
-        private static bool TryParseFilters(IReadOnlyList<FilePickerFileType>? fileTypes, out Variant result)
+        private static DBusVariantItem? ParseFilters(IReadOnlyList<FilePickerFileType>? fileTypes)
         {
             const uint GlobStyle = 0u;
             const uint MimeStyle = 1u;
 
             // Example: [('Images', [(0, '*.ico'), (1, 'image/png')]), ('Text', [(0, '*.txt')])]
             if (fileTypes is null)
-            {
-                result = default;
-                return false;
-            }
+                return null;
 
-            var filters = new Array<Struct<string, Array<Struct<uint, string>>>>();
+            var filters = new List<DBusItem>();
 
             foreach (var fileType in fileTypes)
             {
-                var extensions = new List<Struct<uint, string>>();
+                var extensions = new List<DBusItem>();
                 if (fileType.Patterns?.Count > 0)
-                    extensions.AddRange(fileType.Patterns.Select(static pattern => Struct.Create(GlobStyle, pattern)));
+                    extensions.AddRange(
+                        fileType.Patterns.Select(static pattern =>
+                            new DBusStructItem(new DBusItem[] { new DBusUInt32Item(GlobStyle), new DBusStringItem(pattern) })));
                 else if (fileType.MimeTypes?.Count > 0)
-                    extensions.AddRange(fileType.MimeTypes.Select(static mimeType => Struct.Create(MimeStyle, mimeType)));
+                    extensions.AddRange(
+                        fileType.MimeTypes.Select(static mimeType =>
+                            new DBusStructItem(new DBusItem[] { new DBusUInt32Item(MimeStyle), new DBusStringItem(mimeType) })));
                 else
                     continue;
 
-                filters.Add(Struct.Create(fileType.Name, new Array<Struct<uint, string>>(extensions)));
+                filters.Add(new DBusStructItem(
+                    new DBusItem[]
+                    {
+                        new DBusStringItem(fileType.Name),
+                        new DBusArrayItem(DBusType.Struct, extensions)
+                    }));
             }
 
-            result = Variant.FromArray(filters);
-            return true;
+            return filters.Count > 0 ? new DBusVariantItem("a(sa(us))", new DBusArrayItem(DBusType.Struct, filters)) : null;
         }
     }
 }

+ 24 - 12
src/Avalonia.FreeDesktop/DBusTrayIconImpl.cs

@@ -58,7 +58,7 @@ namespace Avalonia.FreeDesktop
             MenuExporter = DBusMenuExporter.TryCreateDetachedNativeMenu(_dbusMenuPath, _connection);
            
             _statusNotifierItemDbusObj = new StatusNotifierItemDbusObj(_connection, _dbusMenuPath);
-            _connection.AddMethodHandler(_statusNotifierItemDbusObj.PathHandler!);
+            _connection.AddMethodHandler(_statusNotifierItemDbusObj);
             
             WatchAsync();
         }
@@ -84,7 +84,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");
@@ -216,15 +216,27 @@ namespace Avalonia.FreeDesktop
         public StatusNotifierItemDbusObj(Connection connection, ObjectPath dbusMenuPath)
         {
             Connection = connection;
-            Menu = dbusMenuPath;
-            PathHandler = new PathHandler("/StatusNotifierItem");
-            PathHandler.Add(this);
+            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);
             InvalidateAll();
         }
 
+        protected override Connection Connection { get; }
+
+        public override string Path => "/StatusNotifierItem";
+
         public event Action? ActivationDelegate;
 
-        public override Connection Connection { get; }
         protected override ValueTask OnContextMenuAsync(int x, int y) => new();
 
         protected override ValueTask OnActivateAsync(int x, int y)
@@ -244,12 +256,12 @@ namespace Avalonia.FreeDesktop
             EmitNewAttentionIcon();
             EmitNewOverlayIcon();
             EmitNewToolTip();
-            EmitNewStatus(Status);
+            EmitNewStatus(BackingProperties.Status);
         }
 
         public void SetIcon((int, int, byte[]) dbusPixmap)
         {
-            IconPixmap = new[] { dbusPixmap };
+            BackingProperties.IconPixmap = new[] { dbusPixmap };
             InvalidateAll();
         }
 
@@ -258,10 +270,10 @@ namespace Avalonia.FreeDesktop
             if (text is null)
                 return;
 
-            Id = text;
-            Category = "ApplicationStatus";
-            Status = text;
-            Title = text;
+            BackingProperties.Id = text;
+            BackingProperties.Category = "ApplicationStatus";
+            BackingProperties.Status = text;
+            BackingProperties.Title = text;
             InvalidateAll();
         }
     }