7 changed files with 205 additions and 125 deletions
@ -0,0 +1,122 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Avalonia.Logging; |
|||
using Tmds.DBus.Protocol; |
|||
using Tmds.DBus.SourceGenerator; |
|||
|
|||
namespace Avalonia.FreeDesktop.AtSpi; |
|||
|
|||
internal abstract class Accessible : OrgA11yAtspiAccessible |
|||
{ |
|||
private readonly Accessible? _internalParent; |
|||
public Guid InternalGuid { get; protected set; } |
|||
public CacheEntry InternalCacheEntry { get; } = new(); |
|||
public string DbusPath { get; } |
|||
public string ServiceName { get; } |
|||
|
|||
public Accessible? InternalParent => _internalParent; |
|||
|
|||
protected Accessible(string serviceName, Accessible? internalParent) |
|||
{ |
|||
_internalParent = internalParent; |
|||
ServiceName = serviceName; |
|||
InternalGuid = new Guid(); |
|||
DbusPath = Path.Combine(AtSpiConstants.AvaloniaPathPrefix, InternalGuid.ToString("N")); |
|||
} |
|||
|
|||
public (string, ObjectPath) Convert() => (ServiceName, (ObjectPath)DbusPath); |
|||
|
|||
|
|||
private readonly List<Accessible> _internalChildren = new(); |
|||
|
|||
public void AddChild(Accessible accessible) |
|||
{ |
|||
if (AtSpiContext.Cache != null && AtSpiContext.Cache.TryAddEntry(accessible)) |
|||
{ |
|||
_internalChildren.Add(accessible); |
|||
ChildCount = _internalChildren.Count; |
|||
} |
|||
else |
|||
{ |
|||
Logger.TryGet(LogEventLevel.Error, LogArea.FreeDesktopPlatform)?.Log(this, |
|||
$"Unable to add Accessible object to the root AT-SPI cache. {accessible.InternalGuid}"); |
|||
|
|||
} |
|||
} |
|||
|
|||
public void RemoveChild(Accessible accessible) |
|||
{ |
|||
_internalChildren.Remove(accessible); |
|||
ChildCount = _internalChildren.Count; |
|||
} |
|||
|
|||
public IList<Accessible> InternalChildren => _internalChildren; |
|||
|
|||
|
|||
protected override ValueTask<(string, ObjectPath)> OnGetChildAtIndexAsync(int index) |
|||
{ |
|||
var accessible = InternalChildren.ElementAtOrDefault(index); |
|||
if (accessible is not null) |
|||
{ |
|||
return ValueTask.FromResult(accessible.Convert()); |
|||
} |
|||
|
|||
return ValueTask.FromResult<(string, ObjectPath)>((":0.0", "/org/a11y/atspi/accessible/null")); |
|||
} |
|||
|
|||
protected override ValueTask<(string, ObjectPath)[]> OnGetChildrenAsync() |
|||
{ |
|||
return ValueTask.FromResult(InternalChildren.Select(x => x.Convert()).ToArray()); |
|||
} |
|||
|
|||
protected override ValueTask<int> OnGetIndexInParentAsync() |
|||
{ |
|||
if (_internalParent is null) return ValueTask.FromResult(-1); |
|||
return ValueTask.FromResult(_internalParent.InternalChildren.IndexOf(this)); |
|||
} |
|||
|
|||
protected override ValueTask<(uint, (string, ObjectPath)[])[]> OnGetRelationSetAsync() |
|||
{ |
|||
return ValueTask.FromResult<(uint, (string, ObjectPath)[])[]>(default!); |
|||
} |
|||
|
|||
protected override ValueTask<uint> OnGetRoleAsync() |
|||
{ |
|||
return ValueTask.FromResult((uint)InternalCacheEntry.Role); |
|||
} |
|||
|
|||
protected override ValueTask<string> OnGetRoleNameAsync() |
|||
{ |
|||
return ValueTask.FromResult(InternalCacheEntry.RoleName); |
|||
} |
|||
|
|||
protected override ValueTask<string> OnGetLocalizedRoleNameAsync() |
|||
{ |
|||
return ValueTask.FromResult(InternalCacheEntry.LocalizedName); |
|||
} |
|||
|
|||
protected override ValueTask<uint[]> OnGetStateAsync() |
|||
{ |
|||
return ValueTask.FromResult(InternalCacheEntry.ApplicableStates); |
|||
} |
|||
|
|||
protected override ValueTask<Dictionary<string, string>> OnGetAttributesAsync() |
|||
{ |
|||
return ValueTask.FromResult<Dictionary<string, string>>(new() { { "toolkit", "Avalonia" } }); |
|||
} |
|||
|
|||
protected override ValueTask<(string, ObjectPath)> OnGetApplicationAsync() |
|||
{ |
|||
return ValueTask.FromResult(InternalCacheEntry.Application); |
|||
} |
|||
|
|||
protected override ValueTask<string[]> OnGetInterfacesAsync() |
|||
{ |
|||
return ValueTask.FromResult(InternalCacheEntry.ApplicableInterfaces); |
|||
} |
|||
} |
|||
|
|||
|
|||
@ -0,0 +1,38 @@ |
|||
using Tmds.DBus.Protocol; |
|||
|
|||
namespace Avalonia.FreeDesktop.AtSpi; |
|||
|
|||
public class CacheEntry |
|||
{ |
|||
public (string, ObjectPath) Accessible = (":0.0", "/org/a11y/atspi/accessible/object"); |
|||
public (string, ObjectPath) Application = (":0.0", "/org/a11y/atspi/accessible/application"); |
|||
public (string, ObjectPath) Parent = (":0.0", "/org/a11y/atspi/accessible/parent"); |
|||
public int IndexInParent = 0; |
|||
public int ChildCount = 0; |
|||
public string[] ApplicableInterfaces = ["org.a11y.atspi.Accessible"]; |
|||
public string LocalizedName = string.Empty; |
|||
public AtSpiConstants.Role Role = default; |
|||
public string RoleName = string.Empty; |
|||
public uint[] ApplicableStates = []; |
|||
|
|||
public ( |
|||
(string, ObjectPath), |
|||
(string, ObjectPath), |
|||
(string, ObjectPath), |
|||
int, |
|||
int, |
|||
string[], |
|||
string, |
|||
uint, |
|||
string, |
|||
uint[]) Convert() => (Accessible, |
|||
Application, |
|||
Parent, |
|||
IndexInParent, |
|||
ChildCount, |
|||
ApplicableInterfaces, |
|||
LocalizedName, |
|||
(uint)Role, |
|||
RoleName, |
|||
ApplicableStates); |
|||
} |
|||
@ -1,79 +1,29 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Tmds.DBus.Protocol; |
|||
using Tmds.DBus.SourceGenerator; |
|||
|
|||
namespace Avalonia.FreeDesktop.AtSpi; |
|||
|
|||
internal class RootAccessible : OrgA11yAtspiAccessible |
|||
internal class RootAccessible : Accessible |
|||
{ |
|||
public override Connection Connection { get; } |
|||
public RootCache.CacheEntry CacheEntry { get; } = new(); |
|||
|
|||
public RootAccessible() |
|||
{ |
|||
CacheEntry.Accessible = (AtSpiContext.ServiceName, AtSpiContext.RootPath)!; |
|||
CacheEntry.Application = (AtSpiContext.ServiceName, AtSpiContext.RootPath)!; |
|||
CacheEntry.ApplicableInterfaces = ["org.a11y.atspi.Accessible", "org.a11y.atspi.Application"]; |
|||
CacheEntry.Role = AtSpiConstants.Role.Application; |
|||
CacheEntry.LocalizedName = AtSpiConstants.RoleNames[(int)CacheEntry.Role]; |
|||
CacheEntry.RoleName = AtSpiConstants.RoleNames[(int)CacheEntry.Role]; |
|||
CacheEntry.ChildCount = 0; //TODO
|
|||
CacheEntry.ApplicableStates = [0, 0]; |
|||
} |
|||
|
|||
protected override async ValueTask<(string, ObjectPath)> OnGetChildAtIndexAsync(int index) |
|||
{ |
|||
return (":0.0", "/org/a11y/atspi/accessible/null"); |
|||
} |
|||
|
|||
protected override async ValueTask<(string, ObjectPath)[]> OnGetChildrenAsync() |
|||
{ |
|||
return default; |
|||
} |
|||
|
|||
protected override async ValueTask<int> OnGetIndexInParentAsync() |
|||
{ |
|||
return -1; |
|||
} |
|||
|
|||
protected override async ValueTask<(uint, (string, ObjectPath)[])[]> OnGetRelationSetAsync() |
|||
{ |
|||
return default; |
|||
} |
|||
|
|||
protected override async ValueTask<uint> OnGetRoleAsync() |
|||
{ |
|||
return (uint)CacheEntry.Role; |
|||
} |
|||
|
|||
protected override async ValueTask<string> OnGetRoleNameAsync() |
|||
{ |
|||
return CacheEntry.RoleName; |
|||
} |
|||
|
|||
protected override async ValueTask<string> OnGetLocalizedRoleNameAsync() |
|||
{ |
|||
return CacheEntry.LocalizedName; |
|||
} |
|||
|
|||
protected override async ValueTask<uint[]> OnGetStateAsync() |
|||
{ |
|||
return CacheEntry.ApplicableStates; |
|||
} |
|||
|
|||
protected override async ValueTask<Dictionary<string, string>> OnGetAttributesAsync() |
|||
{ |
|||
return new() { { "toolkit", "Avalonia" } }; |
|||
} |
|||
|
|||
protected override async ValueTask<(string, ObjectPath)> OnGetApplicationAsync() |
|||
{ |
|||
return CacheEntry.Application; |
|||
} |
|||
|
|||
protected override async ValueTask<string[]> OnGetInterfacesAsync() |
|||
{ |
|||
return CacheEntry.ApplicableInterfaces; |
|||
} |
|||
} |
|||
public RootAccessible(Connection connection, string serviceName) : base(serviceName, null) |
|||
{ |
|||
Connection = connection; |
|||
InternalCacheEntry.Accessible = (serviceName, AtSpiContext.RootPath)!; |
|||
InternalCacheEntry.Application = (serviceName, AtSpiContext.RootPath)!; |
|||
InternalCacheEntry.ApplicableInterfaces = ["org.a11y.atspi.Accessible", "org.a11y.atspi.Application"]; |
|||
InternalCacheEntry.Role = AtSpiConstants.Role.Application; |
|||
InternalCacheEntry.LocalizedName = AtSpiConstants.RoleNames[(int)InternalCacheEntry.Role]; |
|||
InternalCacheEntry.RoleName = AtSpiConstants.RoleNames[(int)InternalCacheEntry.Role]; |
|||
InternalCacheEntry.ChildCount = 0; //TODO
|
|||
InternalCacheEntry.ApplicableStates = [0, 0]; |
|||
|
|||
this.InternalGuid = Guid.Empty; |
|||
} |
|||
|
|||
} |
|||
|
|||
Loading…
Reference in new issue