From beca19ee5092a394362d628af4b3db2c64e50734 Mon Sep 17 00:00:00 2001 From: Jumar Macato <16554748+jmacato@users.noreply.github.com> Date: Wed, 18 Mar 2026 19:54:47 +0800 Subject: [PATCH] add InitializePeerAsync to AtSpiServer for P2P automation mode --- src/Avalonia.FreeDesktop.AtSpi/AtSpiServer.cs | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/Avalonia.FreeDesktop.AtSpi/AtSpiServer.cs b/src/Avalonia.FreeDesktop.AtSpi/AtSpiServer.cs index 16d36eb590..d831fc2d35 100644 --- a/src/Avalonia.FreeDesktop.AtSpi/AtSpiServer.cs +++ b/src/Avalonia.FreeDesktop.AtSpi/AtSpiServer.cs @@ -15,6 +15,11 @@ namespace Avalonia.FreeDesktop.AtSpi { /// /// Manages the AT-SPI D-Bus connection, node registration, and event emission. + /// Can operate in two modes: + /// + /// — connects to the Linux accessibility bus (screen reader mode). + /// — accepts an existing peer-to-peer D-Bus connection (automation mode). + /// /// internal sealed class AtSpiServer : IAsyncDisposable { @@ -82,6 +87,46 @@ namespace Avalonia.FreeDesktop.AtSpi _ = InitializeRegistryTrackerAsync(_registryTracker); } + /// + /// Initializes the AT-SPI server on an existing peer-to-peer D-Bus connection. + /// Unlike , this does not connect to the accessibility bus + /// or embed with the AT-SPI registry — the caller supplies the connection directly. + /// Suitable for automation scenarios where the transport is a named pipe or socket. + /// + /// An already-connected peer-to-peer . + /// + /// A unique name for this server instance (e.g. ":auto.1234"). + /// Used in AT-SPI object references returned to the client. + /// + /// + /// Optional synchronization context for marshaling handler calls. + /// Pass the UI thread's context when requires dispatcher access. + /// When , an is created automatically. + /// + internal async Task InitializePeerAsync( + DBusConnection connection, + string uniqueName, + SynchronizationContext? syncContext = null) + { + ArgumentNullException.ThrowIfNull(connection); + ArgumentException.ThrowIfNullOrEmpty(uniqueName); + + _a11yConnection = connection; + _uniqueName = uniqueName; + _syncContext = syncContext ?? new AvaloniaSynchronizationContext(DispatcherPriority.Normal); + + _appRoot = new ApplicationAtSpiNode(null); + _cacheHandler = new AtSpiCacheHandler(); + + await BuildAndRegisterAppRootAsync(); + await RegisterCachePathAsync(); + + // No registry embedding or event tracker in peer-to-peer mode — + // the client is the only consumer and receives all signals directly. + lock (_embedSync) + _isEmbedded = true; + } + /// /// Adds a window to the AT-SPI tree. ///