Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@
<Compile Include="System\Windows\Automation\Peers\GenericRootAutomationPeer.cs" />
<Compile Include="System\Windows\Automation\Peers\UIElement3DAutomationPeer.cs" />
<Compile Include="System\Windows\Automation\Peers\UIElementAutomationPeer.cs" />
<Compile Include="System\Windows\Automation\Peers\UIElementAutomationUtils.cs" />
<Compile Include="System\Windows\Diagnostics\VisualDiagnostics.cs" />
<Compile Include="System\Windows\Diagnostics\VisualTreeChangeEventArgs.cs" />
<Compile Include="System\Windows\Diagnostics\XamlSourceInfo.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Windows.Input;
Expand Down Expand Up @@ -54,61 +54,31 @@ public static AutomationPeer FromElement(UIElement3D element)

return element.GetAutomationPeer();
}

///
override protected List<AutomationPeer> GetChildrenCore()

#nullable enable

/// <summary>
/// Retrieves the automation peers for the <see cref="UIElement"/> / <see cref="UIElement3D"/> children of this <see cref="_owner"/>.
/// </summary>
/// <returns>
/// Returns <see langword="null"/> if the <see cref="_owner"/> has no children of given type, otherwise a list of children.
/// </returns>
protected override List<AutomationPeer>? GetChildrenCore()
{
List<AutomationPeer> children = null;
List<AutomationPeer>? children = null;

iterate(_owner,
(IteratorCallback)delegate(AutomationPeer peer)
{
if (children == null)
children = new List<AutomationPeer>();
UIElementAutomationUtils.Iterate(_owner, ref children, static (ref List<AutomationPeer>? children, AutomationPeer peer) =>
{
children ??= new List<AutomationPeer>();
children.Add(peer);

children.Add(peer);
return (false);
});
return false;
});

return children;
}

private delegate bool IteratorCallback(AutomationPeer peer);

//
private static bool iterate(DependencyObject parent, IteratorCallback callback)
{
bool done = false;

if(parent != null)
{
AutomationPeer peer = null;
int count = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < count && !done; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);

if( child != null
&& child is UIElement
&& (peer = UIElementAutomationPeer.CreatePeerForElement((UIElement)child)) != null )
{
done = callback(peer);
}
else if ( child != null
&& child is UIElement3D
&& (peer = CreatePeerForElement(((UIElement3D)child))) != null )
{
done = callback(peer);
}
else
{
done = iterate(child, callback);
}
}
}

return done;
}
#nullable disable

///
override public object GetPattern(PatternInterface patternInterface)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Windows.Input;
Expand Down Expand Up @@ -52,81 +52,51 @@ public static AutomationPeer FromElement(UIElement element)

return element.GetAutomationPeer();
}

///
override protected List<AutomationPeer> GetChildrenCore()

#nullable enable

/// <summary>
/// Retrieves the automation peers for the <see cref="UIElement"/> / <see cref="UIElement3D"/> children of this <see cref="_owner"/>.
/// </summary>
/// <returns>
/// Returns <see langword="null"/> if the <see cref="_owner"/> has no children of given type, otherwise a list of children.
/// </returns>
protected override List<AutomationPeer>? GetChildrenCore()
{
List<AutomationPeer> children = null;
List<AutomationPeer>? children = null;

iterate(_owner,
(IteratorCallback)delegate(AutomationPeer peer)
{
if (children == null)
children = new List<AutomationPeer>();
UIElementAutomationUtils.Iterate(_owner, ref children, static (ref List<AutomationPeer>? children, AutomationPeer peer) =>
{
children ??= new List<AutomationPeer>();
children.Add(peer);

children.Add(peer);
return (false);
});
return false;
});

return children;
}

///
internal static AutomationPeer GetRootAutomationPeer(Visual rootVisual, IntPtr hwnd)
internal static AutomationPeer? GetRootAutomationPeer(Visual rootVisual, IntPtr hwnd)
{
AutomationPeer root = null;
AutomationPeer? root = null;

iterate(rootVisual,
(IteratorCallback)delegate(AutomationPeer peer)
{
root = peer;
return (true);
});
UIElementAutomationUtils.Iterate(rootVisual, ref root, static (ref AutomationPeer? root, AutomationPeer peer) =>
{
root = peer;

return true;
});

if (root != null)
if (root is not null)
{
root.Hwnd = hwnd;
}

return root;
}

private delegate bool IteratorCallback(AutomationPeer peer);

//
private static bool iterate(DependencyObject parent, IteratorCallback callback)
{
bool done = false;

if(parent != null)
{
AutomationPeer peer = null;
int count = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < count && !done; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);

if( child != null
&& child is UIElement
&& (peer = CreatePeerForElement((UIElement)child)) != null )
{
done = callback(peer);
}
else if ( child != null
&& child is UIElement3D
&& (peer = UIElement3DAutomationPeer.CreatePeerForElement(((UIElement3D)child))) != null )
{
done = callback(peer);
}
else
{
done = iterate(child, callback);
}
}
}

return done;
}
#nullable disable

///
override public object GetPattern(PatternInterface patternInterface)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#nullable enable

using System.Windows.Media;

namespace System.Windows.Automation.Peers;

/// <summary>
/// Provides utility methods shared by <see cref="UIElementAutomationPeer"/> and <see cref="UIElement3DAutomationPeer"/>.
/// </summary>
internal static class UIElementAutomationUtils
{
/// <summary>
/// Generic callback for the <see cref="Iterate{T}"/> function.
/// </summary>
internal delegate bool UIElementIteratorCallback<T>(ref T? capture, AutomationPeer peer);

/// <summary>
/// Iterates through the children of the given <paramref name="parent"/> and either attempts to create
/// or retrieve the current <see cref="AutomationPeer"/> for the given <see cref="UIElement"/> / <see cref="UIElement3D"/>.
/// </summary>
internal static bool Iterate<T>(DependencyObject? parent, ref T? callbackParameter, UIElementIteratorCallback<T> callback)
{
bool done = false;

if (parent is not null)
{
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);

for (int i = 0; i < childrenCount && !done; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
AutomationPeer? peer;

if ((child is UIElement uiElement && (peer = uiElement.CreateAutomationPeer()) is not null) ||
(child is UIElement3D uiElement3D && (peer = uiElement3D.CreateAutomationPeer()) is not null))
{
done = callback(ref callbackParameter, peer);
}
else
{
done = Iterate(child, ref callbackParameter, callback);
}
}
}

return done;
}
}