Skip to content

Commit c1645ca

Browse files
committed
Allow an AutomationPeer to override its visual root.
This is needed for example when a UI framework hosts a peer in the automation tree of a main window whose control is actually hosted in a popup. It allows the bounding rectangle to be calculated correctly in that case. s
1 parent eb1f784 commit c1645ca

File tree

2 files changed

+25
-14
lines changed

2 files changed

+25
-14
lines changed

src/Avalonia.Controls/Automation/Peers/AutomationPeer.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,14 @@ public abstract class AutomationPeer
115115
/// <summary>
116116
/// Gets the <see cref="AutomationPeer"/> that is the parent of this <see cref="AutomationPeer"/>.
117117
/// </summary>
118-
/// <returns></returns>
119118
public AutomationPeer? GetParent() => GetParentCore();
120119

120+
/// <summary>
121+
/// Gets the <see cref="AutomationPeer"/> that is the root of this <see cref="AutomationPeer"/>'s
122+
/// visual tree.
123+
/// </summary>
124+
public AutomationPeer? GetVisualRoot() => GetVisualRootCore();
125+
121126
/// <summary>
122127
/// Gets a value that indicates whether the element that is associated with this automation
123128
/// peer currently has keyboard focus.
@@ -247,6 +252,22 @@ protected virtual AutomationControlType GetControlTypeOverrideCore()
247252
return GetAutomationControlTypeCore();
248253
}
249254

255+
protected virtual AutomationPeer? GetVisualRootCore()
256+
{
257+
var parent = GetParent();
258+
259+
while (parent != null)
260+
{
261+
var nextParent = parent.GetParent();
262+
if (nextParent == null)
263+
return parent;
264+
parent = nextParent;
265+
}
266+
267+
return null;
268+
}
269+
270+
250271
protected virtual bool IsContentElementOverrideCore()
251272
{
252273
return IsControlElement() && IsContentElementCore();

src/Windows/Avalonia.Win32/Automation/AutomationNode.cs

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public Rect BoundingRectangle
7575

7676
public virtual IRawElementProviderFragmentRoot? FragmentRoot
7777
{
78-
get => InvokeSync(() => GetRoot()) as IRawElementProviderFragmentRoot;
78+
get => InvokeSync(() => GetRoot());
7979
}
8080

8181
public virtual IRawElementProviderSimple? HostRawElementProvider => null;
@@ -243,20 +243,10 @@ protected void RaiseFocusChanged(AutomationNode? focused)
243243
(int)UiaEventId.AutomationFocusChanged);
244244
}
245245

246-
private AutomationNode? GetRoot()
246+
private RootAutomationNode? GetRoot()
247247
{
248248
Dispatcher.UIThread.VerifyAccess();
249-
250-
var peer = Peer;
251-
var parent = peer.GetParent();
252-
253-
while (peer.GetProvider<AAP.IRootProvider>() is null && parent is object)
254-
{
255-
peer = parent;
256-
parent = peer.GetParent();
257-
}
258-
259-
return peer is object ? GetOrCreate(peer) : null;
249+
return GetOrCreate(Peer.GetVisualRoot()) as RootAutomationNode;
260250
}
261251

262252
private void OnPeerChildrenChanged(object? sender, EventArgs e)

0 commit comments

Comments
 (0)