Browse Source

Fix missing root automation peer in x11/atspi (#20775)

* Fix missing root automation peer in x11/atspi

* Root nodes are special case; fix GetIndexInParentAsync to handle root nodes since their parents == null.
pull/19747/merge
Jumar Macato 3 weeks ago
committed by GitHub
parent
commit
d957cb391e
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 16
      src/Avalonia.FreeDesktop.AtSpi/Handlers/AtSpiAccessibleHandler.cs
  2. 7
      src/Avalonia.X11/X11AtSpiAccessibility.cs
  3. 12
      src/Avalonia.X11/X11Window.cs

16
src/Avalonia.FreeDesktop.AtSpi/Handlers/AtSpiAccessibleHandler.cs

@ -63,6 +63,22 @@ namespace Avalonia.FreeDesktop.AtSpi.Handlers
public ValueTask<int> GetIndexInParentAsync() public ValueTask<int> GetIndexInParentAsync()
{ {
// Window nodes are children of the ApplicationAtSpiNode, but their
// internal Parent field is null (they are attached with parent: null).
// Mirror the Parent property's special case so that backward path
// walks (e.g. accerciser's get_index_in_parent) work correctly.
if (node is RootAtSpiNode { AppRoot: { } appRoot })
{
var windows = appRoot.WindowChildren;
for (var i = 0; i < windows.Count; i++)
{
if (ReferenceEquals(windows[i], node))
return ValueTask.FromResult(i);
}
return ValueTask.FromResult(-1);
}
var parent = node.Parent; var parent = node.Parent;
if (parent is null) if (parent is null)
return ValueTask.FromResult(-1); return ValueTask.FromResult(-1);

7
src/Avalonia.X11/X11AtSpiAccessibility.cs

@ -142,8 +142,11 @@ namespace Avalonia.X11
{ {
try try
{ {
if (window.InputRoot.RootElement is Control control) if (window.InputRoot.FocusRoot is Control control)
return ControlAutomationPeer.CreatePeerForElement(control); {
var peer = ControlAutomationPeer.CreatePeerForElement(control);
return peer?.GetAutomationRoot() ?? peer;
}
} }
catch (Exception e) catch (Exception e)
{ {

12
src/Avalonia.X11/X11Window.cs

@ -1029,9 +1029,10 @@ namespace Avalonia.X11
// Remove from AT-SPI tree before closing // Remove from AT-SPI tree before closing
_platform.UntrackWindow(this); _platform.UntrackWindow(this);
if (_platform.AtSpiServer is { } atSpiServer if (_platform.AtSpiServer is { } atSpiServer
&& _inputRoot?.RootElement is Control atSpiControl) && _inputRoot?.FocusRoot is Control atSpiControl)
{ {
var atSpiPeer = atSpiControl.GetAutomationPeer(); var atSpiPeer = atSpiControl.GetAutomationPeer()?.GetAutomationRoot()
?? atSpiControl.GetAutomationPeer();
if (atSpiPeer is not null) if (atSpiPeer is not null)
atSpiServer.RemoveWindow(atSpiPeer); atSpiServer.RemoveWindow(atSpiPeer);
} }
@ -1125,11 +1126,12 @@ namespace Avalonia.X11
_platform.TrackWindow(this); _platform.TrackWindow(this);
if (_platform.AtSpiServer is { } server if (_platform.AtSpiServer is { } server
&& _inputRoot?.RootElement is Control c) && _inputRoot?.FocusRoot is Control c)
{ {
var peer = Avalonia.Automation.Peers.ControlAutomationPeer.CreatePeerForElement(c); var peer = Avalonia.Automation.Peers.ControlAutomationPeer.CreatePeerForElement(c);
if (peer is not null) var rootPeer = peer?.GetAutomationRoot() ?? peer;
server.AddWindow(peer); if (rootPeer is not null)
server.AddWindow(rootPeer);
} }
} }

Loading…
Cancel
Save