From 1de1639a76b994230f699d9ac59e8b4eea7760fb Mon Sep 17 00:00:00 2001
From: Jumar Macato <16554748+jmacato@users.noreply.github.com>
Date: Sat, 8 Jun 2024 16:20:10 +0800
Subject: [PATCH] fail
---
Avalonia.sln.DotSettings | 43 ---
.../Automation/AtspiMainContext.cs | 260 ++++++++++--------
.../Automation/MethodHandlerMultiplexer.cs | 75 +++++
.../org.a11y.atspi.accessible.root.xml | 181 ++++++------
.../Tmds.DBus.Protocol/DBusConnection.cs | 32 ++-
.../Tmds.DBus.Protocol/PathNodeDictionary.cs | 20 +-
.../Properties/launchSettings.json | 8 +
7 files changed, 334 insertions(+), 285 deletions(-)
delete mode 100644 Avalonia.sln.DotSettings
create mode 100644 src/Avalonia.FreeDesktop/Automation/MethodHandlerMultiplexer.cs
create mode 100644 src/Linux/Tmds.DBus.SourceGenerator/Properties/launchSettings.json
diff --git a/Avalonia.sln.DotSettings b/Avalonia.sln.DotSettings
deleted file mode 100644
index cc58566622..0000000000
--- a/Avalonia.sln.DotSettings
+++ /dev/null
@@ -1,43 +0,0 @@
-
- ExplicitlyExcluded
- ExplicitlyExcluded
- ExplicitlyExcluded
- DO_NOT_SHOW
- HINT
- <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
- <Policy Inspect="True" Prefix="set_" Suffix="" Style="aa_bb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
- <Policy Inspect="True" Prefix="" Suffix="_" Style="aa_bb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
- <Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="False" Prefix="I" Suffix="" Style="AaBb" />
- <Policy Inspect="False" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="False" Prefix="" Suffix="" Style="aaBb" />
- <Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="s_" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="s_" Suffix="" Style="aaBb" />
- <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
- <Policy Inspect="False" Prefix="T" Suffix="" Style="AaBb" />
- <Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" />
- True
- True
- True
- True
- True
diff --git a/src/Avalonia.FreeDesktop/Automation/AtspiMainContext.cs b/src/Avalonia.FreeDesktop/Automation/AtspiMainContext.cs
index af53eb9422..4f4096255b 100644
--- a/src/Avalonia.FreeDesktop/Automation/AtspiMainContext.cs
+++ b/src/Avalonia.FreeDesktop/Automation/AtspiMainContext.cs
@@ -12,136 +12,154 @@ using Tmds.DBus.SourceGenerator;
namespace Avalonia.FreeDesktop.Automation;
-// internal class HandlerAtspiApplication : OrgA11yAtspiApplication
-// {
-// public const string RootPath = "/org/a11y/atspi/accessible/root";
-//
-// public HandlerAtspiApplication(Connection connection)
-// {
-// Connection = connection;
-// AtspiVersion = atspiVersion;
-// ToolkitName = "Avalonia";
-// Id = 0;
-// Version = typeof(HandlerAtspiApplication).Assembly.GetName().Version.ToString();
-// }
-//
-// private const string atspiVersion = "2.1";
-// protected override Connection Connection { get; }
-// public override string Path => RootPath;
-// protected override async ValueTask OnGetLocaleAsync(uint lctype)
-// {
-// return string.Empty;
-// }
-// }
-//
-// internal class AtspiAccessibleHandler : OrgA11yAtspiAccessible
-// {
-// public AtspiAccessibleHandler(Connection a11YConnection, Func peer, string path)
-// {
-// Name = Application.Current?.Name ?? "Avalonia Application";
-// Description = string.Empty;
-// Locale = Environment.GetEnvironmentVariable("LANG") ?? CultureInfo.CurrentCulture.Name;
-// ChildCount = peer()?.GetChildren()?.Count ?? 0;
-// Connection = a11YConnection;
-// Path = path;
-// }
-//
-// protected override Connection Connection { get; }
-// public override string Path { get; }
-// protected override ValueTask<(string, ObjectPath)> OnGetChildAtIndexAsync(int index)
-// {
-// return default;
-// }
-//
-// protected override ValueTask<(string, ObjectPath)[]> OnGetChildrenAsync()
-// {
-// return default;
-// }
-//
-// protected override ValueTask OnGetIndexInParentAsync()
-// {
-// return default;
-// }
-//
-// protected override ValueTask<(uint, (string, ObjectPath)[])[]> OnGetRelationSetAsync()
-// {
-// return default;
-// }
-//
-// protected override ValueTask OnGetRoleAsync()
-// {
-// return default;
-// }
-//
-// protected override ValueTask OnGetRoleNameAsync()
-// {
-// return default;
-// }
-//
-// protected override ValueTask OnGetLocalizedRoleNameAsync()
-// {
-// return default;
-// }
-//
-// protected override ValueTask OnGetStateAsync()
-// {
-// return default;
-// }
-//
-// protected override ValueTask> OnGetAttributesAsync()
-// {
-// return default;
-// }
-//
-// protected override ValueTask<(string, ObjectPath)> OnGetApplicationAsync()
-// {
-// return default;
-// }
-//
-// protected override ValueTask OnGetInterfacesAsync()
-// {
-// return default;
-// }
-// }
-
-
-
-
-internal class AtspiMainContext
+internal class HandlerAtspiApplication : OrgA11yAtspiApplication
{
- // private static bool s_instanceInitialized;
- // private static AtspiMainContext? _instance;
- // private readonly HandlerAtspiApplication _app;
- // private readonly Connection _connection;
+ public const string RootPath = "/org/a11y/atspi/accessible/root";
+
+ public HandlerAtspiApplication(Connection connection)
+ {
+ Connection = connection;
+ AtspiVersion = atspiVersion;
+ ToolkitName = "Avalonia";
+ Id = 0;
+ Version = typeof(HandlerAtspiApplication).Assembly.GetName().Version.ToString();
+ }
+
+ private const string atspiVersion = "2.1";
+ public override string Path => RootPath;
+
+ protected override Connection Connection { get; }
+
+ protected override async ValueTask OnGetLocaleAsync(uint lctype)
+ {
+ return String.Empty;
+ }
+
+ protected override async ValueTask OnRegisterEventListenerAsync(string @event)
+ {
+ }
+
+ protected override async ValueTask OnDeregisterEventListenerAsync(string @event)
+ {
+ }
+}
+
+internal class AtspiAccessibleHandler : OrgA11yAtspiAccessible
+{
+ public AtspiAccessibleHandler(Connection a11YConnection, Func peer, string path)
+ {
+ Name = Application.Current?.Name ?? "Avalonia Application";
+ Description = string.Empty;
+ Locale = Environment.GetEnvironmentVariable("LANG") ?? CultureInfo.CurrentCulture.Name;
+ ChildCount = 0; //peer()?.GetChildren()?.Count ?? 0;
+ Connection = a11YConnection;
+ Path = path;
+ }
+
+ protected override Connection Connection { get; }
+ public override string Path { get; }
+
+ protected override ValueTask<(string, ObjectPath)> OnGetChildAtIndexAsync(int index)
+ {
+ return default;
+ }
+
+ protected override ValueTask<(string, ObjectPath)[]> OnGetChildrenAsync()
+ {
+ return default;
+ }
+
+ protected override ValueTask OnGetIndexInParentAsync()
+ {
+ return default;
+ }
+
+ protected override ValueTask<(uint, (string, ObjectPath)[])[]> OnGetRelationSetAsync()
+ {
+ return default;
+ }
+
+ protected override ValueTask OnGetRoleAsync()
+ {
+ return default;
+ }
+
+ protected override ValueTask OnGetRoleNameAsync()
+ {
+ return default;
+ }
+
+ protected override ValueTask OnGetLocalizedRoleNameAsync()
+ {
+ return default;
+ }
+
+ protected override ValueTask OnGetStateAsync()
+ {
+ return default;
+ }
+
+ protected override ValueTask> OnGetAttributesAsync()
+ {
+ return default;
+ }
+
+ protected override ValueTask<(string, ObjectPath)> OnGetApplicationAsync()
+ {
+ return default;
+ }
+
+ protected override ValueTask OnGetInterfacesAsync()
+ {
+ return default;
+ }
+}
+
+internal class AtspiMainContext
+{
+ private static bool s_instanceInitialized;
+ private static AtspiMainContext? _instance;
+ private readonly HandlerAtspiApplication _app;
+ private readonly Connection _connection;
+
+ private readonly MethodHandlerMultiplexer _multiplex;
// private readonly List handlers = new List();
-
+
private AtspiMainContext(Connection a11yConnection)
{
-
- // _connection = a11yConnection;
- // _app = new HandlerAtspiApplication(_connection);
- }
+ _connection = a11yConnection;
+
+ _multiplex = new MethodHandlerMultiplexer(HandlerAtspiApplication.RootPath);
+
+ _connection.AddMethodHandler(_multiplex);
+
+ _app = new HandlerAtspiApplication(_connection);
+
+ _multiplex.AddHandler("org.a11y.atspi.Application", _app);
+
+ var rootAccessible = new AtspiAccessibleHandler(_connection, null, HandlerAtspiApplication.RootPath);
+
+ _multiplex.AddHandler("org.a11y.atspi.Accessible", rootAccessible);
+ }
public void RegisterRootPeer(Func peer)
{
- // var rootAccessible = new AtspiAccessibleHandler(_connection, peer, HandlerAtspiApplication.RootPath);
- // handlers.Add(rootAccessible);
- }
+ }
public static AtspiMainContext? Instance { get /*=> _instance*/; }
-
+
public static async void StartService()
{
- // if (s_instanceInitialized || DBusHelper.Connection is not { } sessionConnection) return;
- // var bus1 = new OrgA11yBus(sessionConnection, "org.a11y.Bus", "/org/a11y/bus");
- //
- // var address = await bus1.GetAddressAsync();
- //
- // if (DBusHelper.TryCreateNewConnection(address) is not { } a11YConnection) return;
- //
- // await a11YConnection.ConnectAsync();
- //
- // _instance = new AtspiMainContext(a11YConnection);
- // s_instanceInitialized = true;
- }
+ if (s_instanceInitialized || DBusHelper.Connection is not { } sessionConnection) return;
+ var bus1 = new OrgA11yBus(sessionConnection, "org.a11y.Bus", "/org/a11y/bus");
+
+ var address = await bus1.GetAddressAsync();
+
+ if (DBusHelper.TryCreateNewConnection(address) is not { } a11YConnection) return;
+
+ await a11YConnection.ConnectAsync();
+
+ _instance = new AtspiMainContext(a11YConnection);
+ s_instanceInitialized = true;
+ }
}
diff --git a/src/Avalonia.FreeDesktop/Automation/MethodHandlerMultiplexer.cs b/src/Avalonia.FreeDesktop/Automation/MethodHandlerMultiplexer.cs
new file mode 100644
index 0000000000..7ab77d5dc4
--- /dev/null
+++ b/src/Avalonia.FreeDesktop/Automation/MethodHandlerMultiplexer.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Avalonia.Controls.Shapes;
+using Tmds.DBus.Protocol;
+
+namespace Avalonia.FreeDesktop.Automation;
+
+internal class MethodHandlerMultiplexer(string rootPath) : IMethodHandler
+{
+ private Dictionary _handlers = new();
+
+ public void AddHandler(string @interface, IMethodHandler handler)
+ {
+ _handlers.Add(@interface, handler);
+ }
+
+ public string Path { get; } = rootPath;
+
+ private ReadOnlyMemory _introspectXml =
+ "\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n"u8
+ .ToArray();
+
+ public async ValueTask HandleMethodAsync(MethodContext context)
+ {
+ var reqInt = context.Request.InterfaceAsString;
+ switch (reqInt)
+ {
+ case "org.freedesktop.DBus.Properties":
+ switch (context.Request.MemberAsString)
+ {
+ case ("PropertiesChanged"):
+ case ("GetAll"):
+ case ("Get"):
+ case ("Set"):
+ Reply();
+
+ void Reply()
+ {
+ Reader reader = context.Request.GetBodyReader();
+ string intfc = reader.ReadString();
+
+ if (_handlers.TryGetValue(intfc, out var m2))
+ m2.HandleMethodAsync(context);
+
+ }
+ break;
+
+ }
+
+ break;
+
+ case "org.freedesktop.DBus.Introspectable":
+
+ switch (context.Request.MemberAsString, context.Request.SignatureAsString)
+ {
+ case ("Introspect", "" or null):
+ {
+ context.ReplyIntrospectXml(new[] { _introspectXml });
+ break;
+ }
+ }
+
+ break;
+ default:
+
+ if (_handlers.TryGetValue(reqInt, out var matchHandler))
+ matchHandler.HandleMethodAsync(context);
+
+ break;
+ }
+ }
+
+ public bool RunMethodHandlerSynchronously(Message message) => true;
+}
diff --git a/src/Avalonia.FreeDesktop/DBusXml/org.a11y.atspi.accessible.root.xml b/src/Avalonia.FreeDesktop/DBusXml/org.a11y.atspi.accessible.root.xml
index b4192e1839..88ed53933d 100644
--- a/src/Avalonia.FreeDesktop/DBusXml/org.a11y.atspi.accessible.root.xml
+++ b/src/Avalonia.FreeDesktop/DBusXml/org.a11y.atspi.accessible.root.xml
@@ -1,123 +1,108 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
+
+
-
+
-
-
+
+
-
+
-
+
-
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/src/Linux/Tmds.DBus.Protocol/DBusConnection.cs b/src/Linux/Tmds.DBus.Protocol/DBusConnection.cs
index 3ddcbb5a9d..6ca3336864 100644
--- a/src/Linux/Tmds.DBus.Protocol/DBusConnection.cs
+++ b/src/Linux/Tmds.DBus.Protocol/DBusConnection.cs
@@ -290,7 +290,7 @@ class DBusConnection : IDisposable
{
bool returnMessageToPool = true;
MessageHandler pendingCall = default;
- IMethodHandler? methodHandler = null;
+ IEnumerable? methodHandlers = null;
Action? monitor = null;
bool isMethodCall = message.MessageType == MessageType.MethodCall;
MethodContext? methodContext = null;
@@ -327,7 +327,7 @@ class DBusConnection : IDisposable
{
if (_pathNodes.TryGetValue(message.PathAsString!, out PathNode? node))
{
- methodHandler = node.MethodHandler;
+ methodHandlers = node.MethodHandlers;
bool isDBusIntrospect = message.Member.SequenceEqual("Introspect"u8) &&
message.Interface.SequenceEqual("org.freedesktop.DBus.Introspectable"u8);
@@ -372,23 +372,29 @@ class DBusConnection : IDisposable
if (isMethodCall)
{
Debug.Assert(methodContext is not null);
- if (methodHandler is not null)
+ if (methodHandlers is not null)
{
// Suppress methodContext nullability warnings.
#if NETSTANDARD2_0
#pragma warning disable CS8604
#endif
- bool runHandlerSynchronously = methodHandler.RunMethodHandlerSynchronously(message);
- if (runHandlerSynchronously)
- {
- await methodHandler.HandleMethodAsync(methodContext).ConfigureAwait(false);
- HandleNoReplySent(methodContext);
- }
- else
+
+ foreach (var methodHandler in methodHandlers)
{
- returnMessageToPool = false;
- RunMethodHandler(methodHandler, methodContext);
+
+ bool runHandlerSynchronously = methodHandler.RunMethodHandlerSynchronously(message);
+ if (runHandlerSynchronously)
+ {
+ await methodHandler.HandleMethodAsync(methodContext).ConfigureAwait(false);
+ HandleNoReplySent(methodContext);
+ }
+ else
+ {
+ returnMessageToPool = false;
+ RunMethodHandler(methodHandler, methodContext);
+ }
}
+
}
else
{
@@ -1287,4 +1293,4 @@ class DBusConnection : IDisposable
return writer.CreateMessage();
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Linux/Tmds.DBus.Protocol/PathNodeDictionary.cs b/src/Linux/Tmds.DBus.Protocol/PathNodeDictionary.cs
index 443a042104..ce8a51efcd 100644
--- a/src/Linux/Tmds.DBus.Protocol/PathNodeDictionary.cs
+++ b/src/Linux/Tmds.DBus.Protocol/PathNodeDictionary.cs
@@ -6,7 +6,7 @@ sealed class PathNode
// a string if there is a single child name
// a List List.Count child names
private object? _childNames;
- public IMethodHandler? MethodHandler;
+ public List? MethodHandlers = new();
public PathNode? Parent { get; set; }
public int ChildNameCount =>
@@ -178,7 +178,7 @@ sealed class PathNodeDictionary : IMethodHandlerDictionary
if (_dictionary.Remove(path, out PathNode? node))
{
nodes[j++] = (path, node);
- node.MethodHandler = null;
+ node.MethodHandlers.Clear();
}
}
count = j; j = 0;
@@ -217,7 +217,7 @@ sealed class PathNodeDictionary : IMethodHandlerDictionary
Debug.Assert(parent.ChildNameCount >= 1, "node is expected to be a known child");
if (parent.ChildNameCount == 1) // We're the only child.
{
- if (parent.MethodHandler is not null)
+ if (parent.MethodHandlers.Count > 0)
{
// Parent is still needed for the MethodHandler.
parent.ClearChildNames();
@@ -261,11 +261,11 @@ sealed class PathNodeDictionary : IMethodHandlerDictionary
PathNode node = GetOrCreateNode(path);
- if (node.MethodHandler is not null)
- {
- throw new InvalidOperationException($"A method handler is already registered for the path '{path}'.");
- }
- node.MethodHandler = methodHandler;
+ // if (node.MethodHandler is not null)
+ // {
+ // throw new InvalidOperationException($"A method handler is already registered for the path '{path}'.");
+ // }
+ node.MethodHandlers.Add(methodHandler);
}
public void RemoveMethodHandler(string path)
@@ -279,7 +279,7 @@ sealed class PathNodeDictionary : IMethodHandlerDictionary
if (node.ChildNameCount > 0)
{
// Node is still needed for its children.
- node.MethodHandler = null;
+ node.MethodHandlers.Clear();
_dictionary.Add(path, node);
}
else
@@ -308,4 +308,4 @@ sealed class PathNodeDictionary : IMethodHandlerDictionary
public int Compare((string Path, PathNode Node) x, (string Path, PathNode Node) y)
=> x.Path.Length - y.Path.Length;
}
-}
\ No newline at end of file
+}
diff --git a/src/Linux/Tmds.DBus.SourceGenerator/Properties/launchSettings.json b/src/Linux/Tmds.DBus.SourceGenerator/Properties/launchSettings.json
new file mode 100644
index 0000000000..1e7b7b4c72
--- /dev/null
+++ b/src/Linux/Tmds.DBus.SourceGenerator/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "Generator": {
+ "commandName": "DebugRoslynComponent",
+ "targetProject": "/var/home/strix/RiderProjects/Avalonia/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj"
+ }
+ }
+}