Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove unused dead code in ElementUtil, make class static #10680

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
@@ -1,316 +1,75 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Windows.Threading;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Automation;
using System.Windows.Automation.Peers;
using MS.Win32;
using MS.Internal.Media;
using System.Runtime.InteropServices;
using System.Windows.Automation;
using System.Windows.Threading;

using MS.Internal.PresentationCore;
namespace MS.Internal.Automation;

namespace MS.Internal.Automation
/// <summary>
/// Utility class for working with <see cref="AutomationPeer"/>.
/// </summary>
internal static class ElementUtil
{
// static class providing utility information for working with WCP elements
internal class ElementUtil
/// <summary>
/// Provides a helper to invoke work on the UI thread, re-throwing all exceptions on the thread that invoked this execution.
/// </summary>
internal static object Invoke(AutomationPeer peer, DispatcherOperationCallback work, object arg)
{
//------------------------------------------------------
//
// Constructors
//
//------------------------------------------------------

#region Constructors

// static class, so use private ctor
private ElementUtil() { }

#endregion Constructors


//------------------------------------------------------
//
// Internal Methods
//
//------------------------------------------------------

#region Internal Methods

internal static Visual GetParent( Visual el )
{
return VisualTreeHelper.GetParent(el) as Visual;
}

internal static Visual GetFirstChild( Visual el )
{
if (el == null)
{
return null;
}

return FindVisibleSibling ( el, 0, true );
}

internal static Visual GetLastChild( Visual el )
{
if (el == null)
{
return null;
}

return FindVisibleSibling ( el, el.InternalVisualChildrenCount - 1, false );
}

// Warning: Method is O(N). See FindVisibleSibling function for more information.
internal static Visual GetNextSibling( Visual el )
{
// To get next/previous sibling, have to find out where we
// are in our parent's children collection (ie. our siblings)
Visual parent = VisualTreeHelper.GetParent(el) as Visual;
// If parent is null, we're at root, so have no siblings
if (parent == null)
{
return null;
}
return FindVisibleSibling ( parent, el, searchForwards: true);
}

// Warning: Method is O(N). See FindVisibleSibling function for more information.
internal static Visual GetPreviousSibling( Visual el )
{
// To get next/previous sibling, have to find out where we
// are in our parent's children collection (ie. our siblings)
Visual parent = VisualTreeHelper.GetParent(el) as Visual;
// If parent is null, we're at root, so have no siblings
if (parent == null)
{
return null;
}

return FindVisibleSibling ( parent, el, searchForwards: false);
}

internal static Visual GetRoot( Visual el )
{
// Keep moving up parent chain till we reach the top...
Visual scan = el;
for( ; ; )
{
Visual test = VisualTreeHelper.GetParent(scan) as Visual;
if( test == null )
break;
scan = test;
}
return scan;
}

// Get bounding rectangle, in coords relative to root (not screen)
internal static Rect GetLocalRect( UIElement element )
{
// Get top-most visual.
Visual parent = GetRoot( element );

// Get the points for the rectangle and transform them.
double height = element.RenderSize.Height;
double width = element.RenderSize.Width;
Rect rect = new Rect(0, 0, width, height);

GeneralTransform g = element.TransformToAncestor(parent);
return g.TransformBounds(rect);
}

// Get bounding rectangle, relative to screen
internal static Rect GetScreenRect( IntPtr hwnd, UIElement el )
{
Rect rc = GetLocalRect( el );

// Map from local to screen coords...
NativeMethods.RECT rcWin32 = new NativeMethods.RECT( (int) rc.Left, (int) rc.Top, (int) rc.Right, (int) rc.Bottom );
try
{
SafeSecurityHelper.TransformLocalRectToScreen(new HandleRef(null, hwnd), ref rcWin32);
}
catch (System.ComponentModel.Win32Exception)
{
return Rect.Empty;
}

rc = new Rect( rcWin32.left, rcWin32.top, rcWin32.right - rcWin32.left, rcWin32.bottom - rcWin32.top );

return rc;
}
// Null dispatcher likely means the visual is in bad shape
Dispatcher dispatcher = peer.Dispatcher ?? throw new ElementNotAvailableException();

// Get element at given point (screen coords)
internal static Visual GetElementFromPoint( IntPtr hwnd, Visual root, Point pointScreen )
{
HwndSource hwndSource = HwndSource.CriticalFromHwnd(hwnd);

if(hwndSource == null)
return null;

Point pointClient = PointUtil.ScreenToClient( pointScreen, hwndSource );
Point pointRoot = PointUtil.ClientToRoot(pointClient, hwndSource);
PointHitTestResult result = VisualTreeUtils.AsNearestPointHitTestResult(VisualTreeHelper.HitTest(root, pointRoot));
Visual visual = result?.VisualHit;


return visual;
}
Exception remoteException = null;
bool completed = false;

// Ensures that an element is enabled; throws exception otherwise
internal static void CheckEnabled(Visual visual)
{
UIElement el = visual as UIElement;

if( el != null && ! el.IsEnabled )
object retVal = dispatcher.Invoke(
DispatcherPriority.Send,
TimeSpan.FromMinutes(3),
(DispatcherOperationCallback)delegate (object unused)
{
throw new ElementNotEnabledException();
}
}

internal static object Invoke(AutomationPeer peer, DispatcherOperationCallback work, object arg)
{
Dispatcher dispatcher = peer.Dispatcher;

// Null dispatcher likely means the visual is in bad shape!
if( dispatcher == null )
{
throw new ElementNotAvailableException();
}

Exception remoteException = null;
bool completed = false;

object retVal = dispatcher.Invoke(
DispatcherPriority.Send,
TimeSpan.FromMinutes(3),
(DispatcherOperationCallback) delegate(object unused)
try
{
try
{
return work(arg);
}
catch(Exception e)
{
remoteException = e;
return null;
}
catch //for non-CLS Compliant exceptions
{
remoteException = null;
return null;
}
finally
{
completed = true;
}
},
null);

if(completed)
{
if(remoteException != null)
return work(arg);
}
catch (Exception e)
{
throw remoteException;
remoteException = e;
return null;
}
}
else
{
bool dispatcherInShutdown = dispatcher.HasShutdownStarted;

if(dispatcherInShutdown)
catch //for non-CLS Compliant exceptions
{
throw new InvalidOperationException(SR.AutomationDispatcherShutdown);
remoteException = null;
return null;
}
else
finally
{
throw new TimeoutException(SR.AutomationTimeout);
completed = true;
}
}

return retVal;
}

#endregion Internal Methods

//------------------------------------------------------
//
// Private Methods
//
//------------------------------------------------------
},
null);

// Potential enhancement: Consider Visual3Ds in this walk?
// Does this walk need to continue through the Visual3D tree once
// we have UIElement3D?
private static Visual FindVisibleSibling ( Visual parent, int start, bool searchForwards)
if (completed)
{
int index = start;
int childrenCount = parent.InternalVisualChildrenCount;

while ( index >= 0 && index < childrenCount )
if (remoteException is not null)
{
Visual sibling = parent.InternalGetVisualChild(index);

// if its visible or something other than a UIElement keep it
if ( !(sibling is UIElement) || (((UIElement)sibling).Visibility == Visibility.Visible ) )
return sibling;

index += searchForwards ? 1 : -1;
throw remoteException;
}

return null;
}

// Potential enhancement - Consider Visual3Ds in this walk?
// Does this walk need to continue through the Visual3D tree once
// we have UIElement3D?
//
// WARNING: This method is O(N) and can therefore lead to O(N^2) algorithms.
private static Visual FindVisibleSibling(Visual parent, Visual child, bool searchForwards)
else
{
//
// First we figure out the index of the specified child Visual. This is why the runtime
// of this method is O(n).

int childrenCount = parent.InternalVisualChildrenCount;
int childIndex;
bool dispatcherInShutdown = dispatcher.HasShutdownStarted;

for (childIndex = 0; childIndex < childrenCount; childIndex++)
if (dispatcherInShutdown)
{
Visual current = parent.InternalGetVisualChild(childIndex);
if (current == child)
{
// Found the child.
break;
}
throw new InvalidOperationException(SR.AutomationDispatcherShutdown);
}

//
// Now that we have the child index, we can go and lookup the sibling.
if(searchForwards)
return FindVisibleSibling(parent, childIndex+1, searchForwards); // (FindVisibleSibling can deal with out of range indices).
else
return FindVisibleSibling(parent, childIndex-1, searchForwards); // (FindVisibleSibling can deal with out of range indices).
{
throw new TimeoutException(SR.AutomationTimeout);
}
}

//------------------------------------------------------
//
// Private Fields
//
//------------------------------------------------------

#region Private Fields

// static class, so no private fields

#endregion Private Fields
return retVal;
}
}