Skip to content

Commit d71c3ce

Browse files
authored
Replace boxing ArrayLists in UIAutomationClientSideProviders (ClickablePoint) (#9430)
* replace boxing ArrayList with generic List<CPRect> * make fields readonly * rename "al" params as "list" params to reflect reality * use pattern matching where applicable * add readonly constraint to CPRect bool methods * adjust comments from "Program" to "Progman" * Resolve post-merge issues
1 parent 416ba88 commit d71c3ce

File tree

2 files changed

+61
-62
lines changed

2 files changed

+61
-62
lines changed

src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/AutomationProxies/ClickablePoint.cs

Lines changed: 54 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
3-
// See the LICENSE file in the project root for more information.
43

5-
using System;
6-
using System.Collections;
4+
using System.Collections.Generic;
75
using MS.Win32;
6+
using System;
87

98
namespace MS.Internal.AutomationProxies
109
{
1110
static internal class ClickablePoint
1211
{
1312
/// <summary>
14-
/// Static Constructor. Retrieve and keeps the hwnd for "Program"
15-
/// The Windows Rectangle for "Program" is the union for the real
13+
/// Static Constructor. Retrieve and keeps the hwnd for "Progman"
14+
/// The Windows Rectangle for "Progman" is the union for the real
1615
/// Estate for all the monitors.
1716
/// </summary>
1817
static ClickablePoint()
1918
{
19+
_hwndDesktop = UnsafeNativeMethods.GetDesktopWindow();
2020
_hwndProgman = Misc.FindWindowEx(IntPtr.Zero, IntPtr.Zero, "Progman", null);
2121
if (_hwndProgman == IntPtr.Zero)
2222
{
2323
_hwndProgman = _hwndDesktop;
2424
}
2525
}
26-
26+
2727
//------------------------------------------------------
2828
//
2929
// Internal Methods
@@ -46,11 +46,11 @@ static ClickablePoint()
4646
/// But makes it a bit more efficent.
4747
/// </summary>
4848
/// <param name="hwnd">Window Handle</param>
49-
/// <param name="alIn">Input list of Rectangles to check GetPoint against</param>
50-
/// <param name="alOut">Output list of Rectangles after the exclusion test</param>
49+
/// <param name="listIn">Input list of Rectangles to check GetPoint against</param>
50+
/// <param name="listOut">Output list of Rectangles after the exclusion test</param>
5151
/// <param name="pt">Clickable Point</param>
5252
/// <returns>True if there is a clickable in ro</returns>
53-
static internal bool GetPoint(IntPtr hwnd, ArrayList alIn, ArrayList alOut, ref NativeMethods.Win32Point pt)
53+
static internal bool GetPoint(IntPtr hwnd, List<CPRect> listIn, List<CPRect> listOut, ref NativeMethods.Win32Point pt)
5454
{
5555
IntPtr hwndStart = hwnd;
5656
IntPtr hwndCurrent = hwnd;
@@ -61,7 +61,7 @@ static internal bool GetPoint(IntPtr hwnd, ArrayList alIn, ArrayList alOut, ref
6161
{
6262
// For siblings, the element bounding rectangle must not be covered by the
6363
// bounding rect of its siblings
64-
if (!ClickableInRect(hwnd, ref pt, true, alIn, alOut))
64+
if (!ClickableInRect(hwnd, ref pt, true, listIn, listOut))
6565
{
6666
return false;
6767
}
@@ -103,7 +103,7 @@ static internal bool GetPoint(IntPtr hwnd, ArrayList alIn, ArrayList alOut, ref
103103
// Substitute the Desktop with the Progman hwnd for clipping calculation
104104
IntPtr hwndClip = hwnd == _hwndDesktop ? _hwndProgman : hwnd;
105105

106-
if (!ClickableInRect(hwndClip, ref pt, false, alIn, alOut))
106+
if (!ClickableInRect(hwndClip, ref pt, false, listIn, listOut))
107107
{
108108
return false;
109109
}
@@ -115,7 +115,7 @@ static internal bool GetPoint(IntPtr hwnd, ArrayList alIn, ArrayList alOut, ref
115115

116116
// For siblings, the element bounding rectangle must not be covered by the
117117
// bounding rect of its siblings
118-
if (!ClickableInRect(hwnd, ref pt, true, alIn, alOut))
118+
if (!ClickableInRect(hwnd, ref pt, true, listIn, listOut))
119119
{
120120
return false;
121121
}
@@ -131,9 +131,9 @@ static internal bool GetPoint(IntPtr hwnd, ArrayList alIn, ArrayList alOut, ref
131131
/// be performed. There is no easy way out.
132132
/// </summary>
133133
/// <param name="fragment"></param>
134-
/// <param name="alIn"></param>
135-
/// <param name="alOut"></param>
136-
internal static void ExcludeChildren(ProxyFragment fragment, ArrayList alIn, ArrayList alOut)
134+
/// <param name="listIn"></param>
135+
/// <param name="listOut"></param>
136+
internal static void ExcludeChildren(ProxyFragment fragment, List<CPRect> listIn, List<CPRect> listOut)
137137
{
138138
// First go through all the children to exclude whatever is on top
139139
for (ProxySimple simple = fragment.GetFirstChild(); simple != null; simple = fragment.GetNextSibling(simple))
@@ -145,18 +145,18 @@ internal static void ExcludeChildren(ProxyFragment fragment, ArrayList alIn, Arr
145145
}
146146

147147
// Copy the output bits
148-
alIn.Clear();
149-
alIn.AddRange(alOut);
148+
listIn.Clear();
149+
listIn.AddRange(listOut);
150150

151151
NativeMethods.Win32Rect rc = new NativeMethods.Win32Rect(simple.BoundingRectangle);
152152
CPRect rcp = new CPRect(ref rc, false);
153153

154-
ClickablePoint.SplitRect(alIn, ref rcp, alOut, true);
154+
SplitRect(listIn, ref rcp, listOut, true);
155155

156156
// recurse on the children
157-
if (simple is ProxyFragment)
157+
if (simple is ProxyFragment proxyFrag)
158158
{
159-
ExcludeChildren((ProxyFragment)simple, alIn, alOut);
159+
ExcludeChildren(proxyFrag, listIn, listOut);
160160
}
161161
}
162162
}
@@ -206,13 +206,13 @@ internal CPRect(ref NativeMethods.Win32Rect rc, bool fRiAsInsideRect)
206206
}
207207

208208
// return true if the 2 rectangle intersects
209-
internal bool Intersect(ref CPRect ri)
209+
internal readonly bool Intersect(ref CPRect ri)
210210
{
211211
return !(_top >= ri._bottom || ri._top >= _bottom || _left >= ri._right || ri._left >= _right);
212212
}
213213

214214
// return true if ri completely covers this
215-
internal bool Overlap(ref CPRect ri)
215+
internal readonly bool Overlap(ref CPRect ri)
216216
{
217217
return (ri._left <= _left && ri._right >= _right && ri._top <= _top && ri._bottom >= _bottom);
218218
}
@@ -228,7 +228,7 @@ internal bool Overlap(ref CPRect ri)
228228

229229
#region Private Methods
230230

231-
private static bool ClickableInRect(IntPtr hwnd, ref NativeMethods.Win32Point pt, bool fRiAsInsideRect, ArrayList alIn, ArrayList alOut)
231+
private static bool ClickableInRect(IntPtr hwnd, ref NativeMethods.Win32Point pt, bool fRiAsInsideRect, List<CPRect> listIn, List<CPRect> listOut)
232232
{
233233
if (!SafeNativeMethods.IsWindowVisible(hwnd))
234234
{
@@ -270,13 +270,13 @@ private static bool ClickableInRect(IntPtr hwnd, ref NativeMethods.Win32Point pt
270270
}
271271

272272
// Copy the output bits
273-
alIn.Clear();
274-
alIn.AddRange(alOut);
273+
listIn.Clear();
274+
listIn.AddRange(listOut);
275275

276276
CPRect rcp = new CPRect(ref rc, false);
277277

278-
ClickablePoint.SplitRect(alIn, ref rcp, alOut, fRiAsInsideRect);
279-
if (!GetClickablePoint(alOut, out pt.x, out pt.y))
278+
SplitRect(listIn, ref rcp, listOut, fRiAsInsideRect);
279+
if (!GetClickablePoint(listOut, out pt.x, out pt.y))
280280
{
281281
return false;
282282
}
@@ -294,9 +294,9 @@ private static bool ClickableInRect(IntPtr hwnd, ref NativeMethods.Win32Point pt
294294
/// <param name="ri">Inside Rectangle</param>
295295
/// <param name="left">Left Margin for the resulting rectangles</param>
296296
/// <param name="right">Right Margin for the resulting rectangles</param>
297-
/// <param name="alRect">Array of resulting rectangles</param>
297+
/// <param name="rectList">Array of resulting rectangles</param>
298298
/// <param name="fRiAsInsideRect">Covered flag</param>
299-
static private void SplitVertical(ref CPRect ro, ref CPRect ri, int left, int right, ArrayList alRect, bool fRiAsInsideRect)
299+
static private void SplitVertical(ref CPRect ro, ref CPRect ri, int left, int right, List<CPRect> rectList, bool fRiAsInsideRect)
300300
{
301301
// bottom clip
302302
if (ri._bottom > ro._bottom)
@@ -309,21 +309,21 @@ static private void SplitVertical(ref CPRect ro, ref CPRect ri, int left, int ri
309309

310310
if (bottom > top)
311311
{
312-
alRect.Add(new CPRect(left, top, right, bottom, ro._fNotCovered));
312+
rectList.Add(new CPRect(left, top, right, bottom, ro._fNotCovered));
313313
top = bottom;
314314
}
315315

316316
bottom = ri._bottom;
317317
if (bottom > top)
318318
{
319-
alRect.Add(new CPRect(left, top, right, bottom, ro._fNotCovered & fRiAsInsideRect));
319+
rectList.Add(new CPRect(left, top, right, bottom, ro._fNotCovered & fRiAsInsideRect));
320320
top = bottom;
321321
}
322322

323323
bottom = ro._bottom;
324324
if (bottom > top)
325325
{
326-
alRect.Add(new CPRect(left, top, right, bottom, ro._fNotCovered));
326+
rectList.Add(new CPRect(left, top, right, bottom, ro._fNotCovered));
327327
}
328328
}
329329

@@ -350,20 +350,20 @@ static private void SplitVertical(ref CPRect ro, ref CPRect ri, int left, int ri
350350
/// <param name="ri">Inside Rectangle</param>
351351
/// <param name="alRect">Collection of resulting rectangles</param>
352352
/// <param name="fRiAsInsideRect"></param>
353-
static private void SplitRect(ref CPRect ro, CPRect ri, ArrayList alRect, bool fRiAsInsideRect)
353+
static private void SplitRect(ref CPRect ro, CPRect ri, List<CPRect> rectList, bool fRiAsInsideRect)
354354
{
355355
// If ri is fully outside easy way out.
356356
if (!ro._fNotCovered || !ro.Intersect(ref ri))
357357
{
358358
ro._fNotCovered &= fRiAsInsideRect;
359-
alRect.Add(ro);
359+
rectList.Add(ro);
360360
return;
361361
}
362362

363363
if (ro.Overlap(ref ri))
364364
{
365365
ro._fNotCovered &= !fRiAsInsideRect;
366-
alRect.Add(ro);
366+
rectList.Add(ro);
367367
return;
368368
}
369369

@@ -384,21 +384,21 @@ static private void SplitRect(ref CPRect ro, CPRect ri, ArrayList alRect, bool f
384384

385385
if (right > left)
386386
{
387-
alRect.Add(new CPRect(left, ro._top, right, ro._bottom, ro._fNotCovered & fRiAsInsideRect));
387+
rectList.Add(new CPRect(left, ro._top, right, ro._bottom, ro._fNotCovered & fRiAsInsideRect));
388388
left = right;
389389
}
390390

391391
right = ri._right;
392392
if (right > left)
393393
{
394-
SplitVertical(ref ro, ref ri, left, right, alRect, !fRiAsInsideRect);
394+
SplitVertical(ref ro, ref ri, left, right, rectList, !fRiAsInsideRect);
395395
left = right;
396396
}
397397

398398
right = ro._right;
399399
if (right > left)
400400
{
401-
alRect.Add(new CPRect(left, ro._top, right, ro._bottom, ro._fNotCovered & fRiAsInsideRect));
401+
rectList.Add(new CPRect(left, ro._top, right, ro._bottom, ro._fNotCovered & fRiAsInsideRect));
402402
}
403403
}
404404

@@ -408,19 +408,19 @@ static private void SplitRect(ref CPRect ro, CPRect ri, ArrayList alRect, bool f
408408
/// marked as covered or not.
409409
///
410410
/// </summary>
411-
/// <param name="alIn">List of input rectangle</param>
411+
/// <param name="listIn">List of input rectangle</param>
412412
/// <param name="ri">Overlapping Rectangle</param>
413-
/// <param name="alOut">New sets of reactangle</param>
413+
/// <param name="listOut">New sets of reactangle</param>
414414
/// <param name="fRiAsInsideRect">Input Rectangle is rectangle covering alIn Rects or everything
415415
/// outside of ri must be marked as covered</param>
416-
static private void SplitRect(ArrayList alIn, ref CPRect ri, ArrayList alOut, bool fRiAsInsideRect)
416+
static private void SplitRect(List<CPRect> listIn, ref CPRect ri, List<CPRect> listOut, bool fRiAsInsideRect)
417417
{
418-
alOut.Clear();
419-
for (int i = 0, c = alIn.Count; i < c; i++)
418+
listOut.Clear();
419+
for (int i = 0; i < listIn.Count; i++)
420420
{
421-
CPRect ro = (CPRect)alIn[i];
421+
CPRect ro = listIn[i];
422422

423-
SplitRect(ref ro, ri, alOut, fRiAsInsideRect);
423+
SplitRect(ref ro, ri, listOut, fRiAsInsideRect);
424424
}
425425
}
426426

@@ -429,15 +429,15 @@ static private void SplitRect(ArrayList alIn, ref CPRect ri, ArrayList alOut, bo
429429
/// Goes through the list of rectangle, stops on the first rectangle that is not covered
430430
/// and returns the mid point
431431
/// </summary>
432-
/// <param name="al">list of ractangle</param>
432+
/// <param name="rectList">list of ractangle</param>
433433
/// <param name="x">X coordinate for a clickable point</param>
434434
/// <param name="y">Y coordinate for a clickable point</param>
435435
/// <returns>Clickable point found</returns>
436-
static private bool GetClickablePoint(ArrayList al, out int x, out int y)
436+
static private bool GetClickablePoint(List<CPRect> rectList, out int x, out int y)
437437
{
438-
for (int i = 0, c = al.Count; i < c; i++)
438+
for (int i = 0; i < rectList.Count; i++)
439439
{
440-
CPRect r = (CPRect)al[i];
440+
CPRect r = rectList[i];
441441

442442
if (r._fNotCovered == true && (r._right - r._left) * (r._bottom - r._top) > 0)
443443
{
@@ -457,16 +457,16 @@ static private bool GetClickablePoint(ArrayList al, out int x, out int y)
457457
}
458458

459459
#endregion
460-
460+
461461
#region Private fields
462-
462+
463463
// Top level Desktop window
464-
private static IntPtr _hwndDesktop = UnsafeNativeMethods.GetDesktopWindow();
464+
private static readonly IntPtr _hwndDesktop;
465465

466-
/// The WindowsRect for "Program" is the union for the real
466+
/// The WindowsRect for "Progman" is the union for the real
467467
/// estate for all the monitors. Instead of doing clipping against the root of the hwnd
468468
/// tree that is the desktop. The last clipping should be done against the Progman hwnd.
469-
private static IntPtr _hwndProgman;
469+
private static readonly IntPtr _hwndProgman;
470470

471471
#endregion Private fields
472472

src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClientSideProviders/MS/Internal/AutomationProxies/ProxySimple.cs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
using System;
3030
using System.Windows.Automation;
3131
using System.Windows.Automation.Provider;
32-
using System.Collections;
32+
using System.Collections.Generic;
3333
using Accessibility;
3434
using System.Windows;
3535
using MS.Win32;
@@ -585,22 +585,21 @@ internal bool GetClickablePoint(out NativeMethods.Win32Point pt, bool fClipClien
585585
}
586586
}
587587

588-
ArrayList alIn = new ArrayList(100);
589-
ArrayList alOut = new ArrayList(100);
588+
List<ClickablePoint.CPRect> listIn = new(100);
589+
List<ClickablePoint.CPRect> listOut = new(100);
590590

591591
// Get the mid point to start with
592592
pt.x = (rcItem.right - 1 + rcItem.left) / 2;
593593
pt.y = (rcItem.bottom - 1 + rcItem.top) / 2;
594-
alOut.Add(new ClickablePoint.CPRect(ref rcItem, true));
594+
listOut.Add(new ClickablePoint.CPRect(ref rcItem, true));
595595

596596
// First go through all the children to exclude whatever is on top
597-
ProxyFragment proxyFrag = this as ProxyFragment;
598-
if (proxyFrag != null)
597+
if (this is ProxyFragment proxyFrag)
599598
{
600-
ClickablePoint.ExcludeChildren(proxyFrag, alIn, alOut);
599+
ClickablePoint.ExcludeChildren(proxyFrag, listIn, listOut);
601600
}
602601

603-
return ClickablePoint.GetPoint(_hwnd, alIn, alOut, ref pt);
602+
return ClickablePoint.GetPoint(_hwnd, listIn, listOut, ref pt);
604603
}
605604

606605
internal string GetAccessibleName(int item)

0 commit comments

Comments
 (0)