From d7904b34cd7995935b4dce91bc057c5480973031 Mon Sep 17 00:00:00 2001
From: affederaffe <68356204+affederaffe@users.noreply.github.com>
Date: Thu, 29 Dec 2022 20:55:14 +0100
Subject: [PATCH] Use Tmds.DBus.Protocol
---
.gitmodules | 3 +
Avalonia.Desktop.slnf | 7 +-
Avalonia.sln | 7 +
NuGet.Config | 1 +
.../AppMenuRegistrar.DBus.cs | 176 ++++
.../Avalonia.FreeDesktop.csproj | 3 +-
src/Avalonia.FreeDesktop/DBus.DBus.cs | 643 ++++++++++++
src/Avalonia.FreeDesktop/DBusFileChooser.cs | 32 -
src/Avalonia.FreeDesktop/DBusHelper.cs | 54 +-
.../DBusIme/DBusTextInputMethodBase.cs | 58 +-
.../DBusIme/Fcitx/Fcitx.DBus.cs | 627 ++++++++++++
.../DBusIme/Fcitx/FcitxDBus.cs | 69 --
.../DBusIme/Fcitx/FcitxICWrapper.cs | 32 +-
.../DBusIme/Fcitx/FcitxX11TextInputMethod.cs | 47 +-
.../DBusIme/IBus/IBus.DBus.cs | 513 ++++++++++
.../DBusIme/IBus/IBusDBus.cs | 52 -
.../DBusIme/IBus/IBusEnums.cs | 2 +-
.../DBusIme/IBus/IBusX11TextInputMethod.cs | 44 +-
.../DBusIme/X11DBusImeHelper.cs | 25 +-
src/Avalonia.FreeDesktop/DBusMenu.DBus.cs | 463 +++++++++
src/Avalonia.FreeDesktop/DBusMenu.cs | 56 --
src/Avalonia.FreeDesktop/DBusMenuExporter.cs | 432 ++++----
src/Avalonia.FreeDesktop/DBusRequest.cs | 16 -
src/Avalonia.FreeDesktop/DBusSystemDialog.cs | 107 +-
src/Avalonia.FreeDesktop/DBusTrayIconImpl.cs | 415 ++++----
.../FreeDesktopPortalDesktop.DBus.cs | 937 ++++++++++++++++++
.../StatusNotifierWatcher.DBus.cs | 351 +++++++
src/Avalonia.X11/X11Window.cs | 6 +-
src/Linux/Tmds.DBus | 1 +
29 files changed, 4272 insertions(+), 907 deletions(-)
create mode 100644 src/Avalonia.FreeDesktop/AppMenuRegistrar.DBus.cs
create mode 100644 src/Avalonia.FreeDesktop/DBus.DBus.cs
delete mode 100644 src/Avalonia.FreeDesktop/DBusFileChooser.cs
create mode 100644 src/Avalonia.FreeDesktop/DBusIme/Fcitx/Fcitx.DBus.cs
delete mode 100644 src/Avalonia.FreeDesktop/DBusIme/Fcitx/FcitxDBus.cs
create mode 100644 src/Avalonia.FreeDesktop/DBusIme/IBus/IBus.DBus.cs
delete mode 100644 src/Avalonia.FreeDesktop/DBusIme/IBus/IBusDBus.cs
create mode 100644 src/Avalonia.FreeDesktop/DBusMenu.DBus.cs
delete mode 100644 src/Avalonia.FreeDesktop/DBusMenu.cs
delete mode 100644 src/Avalonia.FreeDesktop/DBusRequest.cs
create mode 100644 src/Avalonia.FreeDesktop/FreeDesktopPortalDesktop.DBus.cs
create mode 100644 src/Avalonia.FreeDesktop/StatusNotifierWatcher.DBus.cs
create mode 160000 src/Linux/Tmds.DBus
diff --git a/.gitmodules b/.gitmodules
index 032bc879cc..16bc977251 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -7,3 +7,6 @@
[submodule "nukebuild/il-repack"]
path = nukebuild/il-repack
url = https://github.com/Gillibald/il-repack
+[submodule "Tmds.DBus"]
+ path = src/Linux/Tmds.DBus
+ url = https://github.com/affederaffe/Tmds.DBus
diff --git a/Avalonia.Desktop.slnf b/Avalonia.Desktop.slnf
index 3fa8e969c8..72eb13d0a9 100644
--- a/Avalonia.Desktop.slnf
+++ b/Avalonia.Desktop.slnf
@@ -7,9 +7,9 @@
"samples\\ControlCatalog\\ControlCatalog.csproj",
"samples\\IntegrationTestApp\\IntegrationTestApp.csproj",
"samples\\MiniMvvm\\MiniMvvm.csproj",
+ "samples\\ReactiveUIDemo\\ReactiveUIDemo.csproj",
"samples\\SampleControls\\ControlSamples.csproj",
"samples\\Sandbox\\Sandbox.csproj",
- "samples\\ReactiveUIDemo\\ReactiveUIDemo.csproj",
"src\\Avalonia.Base\\Avalonia.Base.csproj",
"src\\Avalonia.Build.Tasks\\Avalonia.Build.Tasks.csproj",
"src\\Avalonia.Controls.ColorPicker\\Avalonia.Controls.ColorPicker.csproj",
@@ -31,15 +31,16 @@
"src\\Avalonia.Themes.Simple\\Avalonia.Themes.Simple.csproj",
"src\\Avalonia.X11\\Avalonia.X11.csproj",
"src\\Linux\\Avalonia.LinuxFramebuffer\\Avalonia.LinuxFramebuffer.csproj",
+ "src\\Linux\\Tmds.DBus\\src\\Tmds.DBus.Protocol\\Tmds.DBus.Protocol.csproj",
"src\\Markup\\Avalonia.Markup.Xaml.Loader\\Avalonia.Markup.Xaml.Loader.csproj",
"src\\Markup\\Avalonia.Markup.Xaml\\Avalonia.Markup.Xaml.csproj",
"src\\Markup\\Avalonia.Markup\\Avalonia.Markup.csproj",
"src\\Skia\\Avalonia.Skia\\Avalonia.Skia.csproj",
+ "src\\tools\\DevAnalyzers\\DevAnalyzers.csproj",
+ "src\\tools\\DevGenerators\\DevGenerators.csproj",
"src\\Windows\\Avalonia.Direct2D1\\Avalonia.Direct2D1.csproj",
"src\\Windows\\Avalonia.Win32.Interop\\Avalonia.Win32.Interop.csproj",
"src\\Windows\\Avalonia.Win32\\Avalonia.Win32.csproj",
- "src\\tools\\DevAnalyzers\\DevAnalyzers.csproj",
- "src\\tools\\DevGenerators\\DevGenerators.csproj",
"tests\\Avalonia.Base.UnitTests\\Avalonia.Base.UnitTests.csproj",
"tests\\Avalonia.Benchmarks\\Avalonia.Benchmarks.csproj",
"tests\\Avalonia.Controls.DataGrid.UnitTests\\Avalonia.Controls.DataGrid.UnitTests.csproj",
diff --git a/Avalonia.sln b/Avalonia.sln
index fc42a5d63b..e399483896 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -231,6 +231,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.Browser.Blaz
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactiveUIDemo", "samples\ReactiveUIDemo\ReactiveUIDemo.csproj", "{75C47156-C5D8-44BC-A5A7-E8657C2248D6}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tmds.DBus.Protocol", "src\Linux\Tmds.DBus\src\Tmds.DBus.Protocol\Tmds.DBus.Protocol.csproj", "{29E25263-3CC3-4D55-A042-00BA136867D4}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -542,6 +544,10 @@ Global
{75C47156-C5D8-44BC-A5A7-E8657C2248D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{75C47156-C5D8-44BC-A5A7-E8657C2248D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{75C47156-C5D8-44BC-A5A7-E8657C2248D6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {29E25263-3CC3-4D55-A042-00BA136867D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {29E25263-3CC3-4D55-A042-00BA136867D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {29E25263-3CC3-4D55-A042-00BA136867D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {29E25263-3CC3-4D55-A042-00BA136867D4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -606,6 +612,7 @@ Global
{15B93A4C-1B46-43F6-B534-7B25B6E99932} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{90B08091-9BBD-4362-B712-E9F2CC62B218} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{75C47156-C5D8-44BC-A5A7-E8657C2248D6} = {9B9E3891-2366-4253-A952-D08BCEB71098}
+ {29E25263-3CC3-4D55-A042-00BA136867D4} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}
diff --git a/NuGet.Config b/NuGet.Config
index 7d2bd8abd2..7a9dd7993c 100644
--- a/NuGet.Config
+++ b/NuGet.Config
@@ -6,5 +6,6 @@
+
diff --git a/src/Avalonia.FreeDesktop/AppMenuRegistrar.DBus.cs b/src/Avalonia.FreeDesktop/AppMenuRegistrar.DBus.cs
new file mode 100644
index 0000000000..a45d1642fc
--- /dev/null
+++ b/src/Avalonia.FreeDesktop/AppMenuRegistrar.DBus.cs
@@ -0,0 +1,176 @@
+using System;
+using System.Threading.Tasks;
+
+using Tmds.DBus.Protocol;
+
+
+namespace Avalonia.FreeDesktop
+{
+ internal class Registrar : AppMenuRegistrarObject
+ {
+ private const string Interface = "com.canonical.AppMenu.Registrar";
+
+ public Registrar(RegistrarService service, ObjectPath path) : base(service, path) { }
+
+ public Task RegisterWindowAsync(uint windowId, ObjectPath menuObjectPath)
+ {
+ return Connection.CallMethodAsync(CreateMessage());
+
+ MessageBuffer CreateMessage()
+ {
+ using var writer = Connection.GetMessageWriter();
+ writer.WriteMethodCallHeader(
+ Service.Destination,
+ Path,
+ Interface,
+ signature: "uo",
+ member: "RegisterWindow",
+ flags: MessageFlags.NoReplyExpected);
+ writer.WriteUInt32(windowId);
+ writer.WriteObjectPath(menuObjectPath);
+ return writer.CreateMessage();
+ }
+ }
+
+ public Task UnregisterWindowAsync(uint windowId)
+ {
+ return Connection.CallMethodAsync(CreateMessage());
+
+ MessageBuffer CreateMessage()
+ {
+ using var writer = Connection.GetMessageWriter();
+ writer.WriteMethodCallHeader(
+ Service.Destination,
+ Path,
+ Interface,
+ signature: "u",
+ member: "UnregisterWindow");
+ writer.WriteUInt32(windowId);
+ return writer.CreateMessage();
+ }
+ }
+
+ public Task<(string Service, ObjectPath MenuObjectPath)> GetMenuForWindowAsync(uint windowId)
+ {
+ return Connection.CallMethodAsync(CreateMessage(), (Message m, object? s) => ReadMessage_so(m, (AppMenuRegistrarObject)s!), this);
+
+ MessageBuffer CreateMessage()
+ {
+ using var writer = Connection.GetMessageWriter();
+ writer.WriteMethodCallHeader(
+ Service.Destination,
+ Path,
+ Interface,
+ signature: "u",
+ member: "GetMenuForWindow");
+ writer.WriteUInt32(windowId);
+ return writer.CreateMessage();
+ }
+ }
+ }
+
+ internal class RegistrarService
+ {
+ public RegistrarService(Connection connection, string destination)
+ => (Connection, Destination) = (connection, destination);
+
+ public Connection Connection { get; }
+ public string Destination { get; }
+ public Registrar CreateRegistrar(string path) => new Registrar(this, path);
+ }
+
+ internal class AppMenuRegistrarObject
+ {
+ protected AppMenuRegistrarObject(RegistrarService service, ObjectPath path)
+ => (Service, Path) = (service, path);
+
+ public RegistrarService Service { get; }
+ public ObjectPath Path { get; }
+ protected Connection Connection => Service.Connection;
+
+ protected MessageBuffer CreateGetPropertyMessage(string @interface, string property)
+ {
+ using var writer = Connection.GetMessageWriter();
+ writer.WriteMethodCallHeader(
+ Service.Destination,
+ Path,
+ "org.freedesktop.DBus.Properties",
+ signature: "ss",
+ member: "Get");
+ writer.WriteString(@interface);
+ writer.WriteString(property);
+ return writer.CreateMessage();
+ }
+
+ protected MessageBuffer CreateGetAllPropertiesMessage(string @interface)
+ {
+ using var writer = Connection.GetMessageWriter();
+ writer.WriteMethodCallHeader(
+ Service.Destination,
+ Path,
+ "org.freedesktop.DBus.Properties",
+ signature: "s",
+ member: "GetAll");
+ writer.WriteString(@interface);
+ return writer.CreateMessage();
+ }
+
+ protected ValueTask WatchPropertiesChangedAsync(string @interface,
+ MessageValueReader> reader, Action> handler,
+ bool emitOnCapturedContext)
+ {
+ var rule = new MatchRule
+ {
+ Type = MessageType.Signal,
+ Sender = Service.Destination,
+ Path = Path,
+ Interface = "org.freedesktop.DBus.Properties",
+ Member = "PropertiesChanged",
+ Arg0 = @interface
+ };
+ return Connection.AddMatchAsync(rule, reader,
+ (Exception? ex, PropertyChanges changes, object? rs, object? hs) =>
+ ((Action>)hs!).Invoke(ex, changes),
+ this, handler, emitOnCapturedContext);
+ }
+
+ public ValueTask WatchSignalAsync(string sender, string @interface, ObjectPath path, string signal,
+ MessageValueReader reader, Action handler, bool emitOnCapturedContext)
+ {
+ var rule = new MatchRule
+ {
+ Type = MessageType.Signal,
+ Sender = sender,
+ Path = path,
+ Member = signal,
+ Interface = @interface
+ };
+ return Connection.AddMatchAsync(rule, reader,
+ (Exception? ex, TArg arg, object? rs, object? hs) => ((Action)hs!).Invoke(ex, arg),
+ this, handler, emitOnCapturedContext);
+ }
+
+ public ValueTask WatchSignalAsync(string sender, string @interface, ObjectPath path, string signal, Action handler,
+ bool emitOnCapturedContext)
+ {
+ var rule = new MatchRule
+ {
+ Type = MessageType.Signal,
+ Sender = sender,
+ Path = path,
+ Member = signal,
+ Interface = @interface
+ };
+ return Connection.AddMatchAsync