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.Collections.Generic; |
||||
|
using System.Linq; |
||||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||||
using Tmds.DBus.Protocol; |
using Tmds.DBus.Protocol; |
||||
using Tmds.DBus.SourceGenerator; |
using Tmds.DBus.SourceGenerator; |
||||
|
|
||||
namespace Avalonia.FreeDesktop.AtSpi; |
namespace Avalonia.FreeDesktop.AtSpi; |
||||
|
|
||||
internal class RootAccessible : OrgA11yAtspiAccessible |
internal class RootAccessible : Accessible |
||||
{ |
{ |
||||
public override Connection Connection { get; } |
public override Connection Connection { get; } |
||||
public RootCache.CacheEntry CacheEntry { get; } = new(); |
|
||||
|
|
||||
public RootAccessible() |
public RootAccessible(Connection connection, string serviceName) : base(serviceName, null) |
||||
{ |
{ |
||||
CacheEntry.Accessible = (AtSpiContext.ServiceName, AtSpiContext.RootPath)!; |
Connection = connection; |
||||
CacheEntry.Application = (AtSpiContext.ServiceName, AtSpiContext.RootPath)!; |
InternalCacheEntry.Accessible = (serviceName, AtSpiContext.RootPath)!; |
||||
CacheEntry.ApplicableInterfaces = ["org.a11y.atspi.Accessible", "org.a11y.atspi.Application"]; |
InternalCacheEntry.Application = (serviceName, AtSpiContext.RootPath)!; |
||||
CacheEntry.Role = AtSpiConstants.Role.Application; |
InternalCacheEntry.ApplicableInterfaces = ["org.a11y.atspi.Accessible", "org.a11y.atspi.Application"]; |
||||
CacheEntry.LocalizedName = AtSpiConstants.RoleNames[(int)CacheEntry.Role]; |
InternalCacheEntry.Role = AtSpiConstants.Role.Application; |
||||
CacheEntry.RoleName = AtSpiConstants.RoleNames[(int)CacheEntry.Role]; |
InternalCacheEntry.LocalizedName = AtSpiConstants.RoleNames[(int)InternalCacheEntry.Role]; |
||||
CacheEntry.ChildCount = 0; //TODO
|
InternalCacheEntry.RoleName = AtSpiConstants.RoleNames[(int)InternalCacheEntry.Role]; |
||||
CacheEntry.ApplicableStates = [0, 0]; |
InternalCacheEntry.ChildCount = 0; //TODO
|
||||
} |
InternalCacheEntry.ApplicableStates = [0, 0]; |
||||
|
|
||||
protected override async ValueTask<(string, ObjectPath)> OnGetChildAtIndexAsync(int index) |
this.InternalGuid = Guid.Empty; |
||||
{ |
} |
||||
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; |
|
||||
} |
|
||||
} |
|
||||
|
|||||
Loading…
Reference in new issue