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

[Servicing 3.1] Fixing regression in Control.AccessibleName property #3600

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,17 @@ public override bool RaiseLiveRegionChanged()
internal override bool IsIAccessibleExSupported()
=> Owner is IAutomationLiveRegion ? true : base.IsIAccessibleExSupported();

internal override bool IsPatternSupported(int patternId)
{
// Override this, in your derived class, if you implement UIAutomation patterns
if (patternId == NativeMethods.UIA_LegacyIAccessiblePatternId)
{
return true;
}

return base.IsPatternSupported(patternId);
}

internal override object GetPropertyValue(int propertyID)
{
if (propertyID == NativeMethods.UIA_LiveSettingPropertyId && Owner is IAutomationLiveRegion)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ internal FormAccessibleObject(Form owner) : base(owner)

internal override Rectangle BoundingRectangle => _owner.Bounds;

internal override object GetPropertyValue(int propertyID)
Tanya-Solyanik marked this conversation as resolved.
Show resolved Hide resolved
{
return propertyID == NativeMethods.UIA_NamePropertyId
? Name
Tanya-Solyanik marked this conversation as resolved.
Show resolved Hide resolved
: base.GetPropertyValue(propertyID);
}

internal override bool IsIAccessibleExSupported()
{
if (_owner != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,8 @@ internal override object GetPropertyValue(int propertyID)
return NativeMethods.UIA_GroupControlTypeId;
case NativeMethods.UIA_IsKeyboardFocusablePropertyId:
return true;
case NativeMethods.UIA_NamePropertyId:
return Name;
}

return base.GetPropertyValue(propertyID);
Expand Down
7 changes: 5 additions & 2 deletions src/System.Windows.Forms/src/System/Windows/Forms/Label.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1744,9 +1744,12 @@ public override AccessibleRole Role

internal override object GetPropertyValue(int propertyID)
{
if (propertyID == NativeMethods.UIA_ControlTypePropertyId)
switch (propertyID)
{
return NativeMethods.UIA_TextControlTypeId;
case NativeMethods.UIA_ControlTypePropertyId:
return NativeMethods.UIA_TextControlTypeId;
case NativeMethods.UIA_NamePropertyId:
return Name;
}

return base.GetPropertyValue(propertyID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,7 @@ internal override bool IsIAccessibleExSupported()
internal override bool IsPatternSupported(int patternId)
{
if (patternId == NativeMethods.UIA_ScrollPatternId ||
patternId == NativeMethods.UIA_SelectionPatternId ||
patternId == NativeMethods.UIA_LegacyIAccessiblePatternId)
Tanya-Solyanik marked this conversation as resolved.
Show resolved Hide resolved
patternId == NativeMethods.UIA_SelectionPatternId)
{
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -581,8 +581,7 @@ internal override bool IsPatternSupported(int patternId) =>
var p when
p == NativeMethods.UIA_ValuePatternId ||
p == NativeMethods.UIA_GridPatternId ||
p == NativeMethods.UIA_TablePatternId ||
p == NativeMethods.UIA_LegacyIAccessiblePatternId => true,
p == NativeMethods.UIA_TablePatternId => true,
Tanya-Solyanik marked this conversation as resolved.
Show resolved Hide resolved
_ => base.IsPatternSupported(patternId)
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,28 +313,19 @@ internal override object GetPropertyValue(int propertyID)
}
}

/// <summary>
/// Indicates whether the specified pattern is supported.
/// </summary>
/// <param name="patternId">The pattern ID.</param>
/// <returns>True if specified pattern is supported, otherwise false.</returns>
internal override bool IsPatternSupported(int patternId)
Tanya-Solyanik marked this conversation as resolved.
Show resolved Hide resolved
{
if (patternId == NativeMethods.UIA_LegacyIAccessiblePatternId)
{
return true;
}

return base.IsPatternSupported(patternId);
}

/// <summary>
/// Gets the accessible role.
/// </summary>
public override AccessibleRole Role
{
get
{
AccessibleRole role = Owner.AccessibleRole;
if (role != AccessibleRole.Default)
Tanya-Solyanik marked this conversation as resolved.
Show resolved Hide resolved
{
return role;
}

return AccessibleRole.PushButton;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5593,9 +5593,12 @@ internal override UnsafeNativeMethods.IRawElementProviderFragment FragmentNaviga

internal override object GetPropertyValue(int propertyID)
{
if (propertyID == NativeMethods.UIA_ControlTypePropertyId)
switch (propertyID)
{
return NativeMethods.UIA_ToolBarControlTypeId;
case NativeMethods.UIA_ControlTypePropertyId:
return NativeMethods.UIA_ToolBarControlTypeId;
case NativeMethods.UIA_NamePropertyId:
return Name;
}

return base.GetPropertyValue(propertyID);
Expand Down
10 changes: 10 additions & 0 deletions src/System.Windows.Forms/src/System/Windows/Forms/ToolStripItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4727,6 +4727,16 @@ internal override void SetFocus()
Owner.Select();
}

internal override bool IsPatternSupported(int patternId)
{
if (patternId == NativeMethods.UIA_LegacyIAccessiblePatternId)
{
return true;
}

return base.IsPatternSupported(patternId);
}

internal void RaiseFocusChanged()
{
ToolStrip root = ownerItem.RootToolStrip;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -856,9 +856,12 @@ public ToolStripTextBoxControlAccessibleObject(Control toolStripHostedControl, T

internal override object GetPropertyValue(int propertyID)
{
if (propertyID == NativeMethods.UIA_ControlTypePropertyId)
switch (propertyID)
{
return NativeMethods.UIA_EditControlTypeId;
case NativeMethods.UIA_ControlTypePropertyId:
return NativeMethods.UIA_EditControlTypeId;
case NativeMethods.UIA_NamePropertyId:
return Name;
}

return base.GetPropertyValue(propertyID);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// 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.Collections.Generic;
using System.Linq;
using System.Reflection;
using Xunit;

namespace System.Windows.Forms.Tests.AccessibleObjects
{
public class Control_ControlAccessibleObjectTests
{
[Theory]
[MemberData(nameof(ControlObject_TestData))]
public void ControlAccessibleObject_LegacyIAccessible_Custom_Role_ReturnsExpected(Type type)
{
Control control = GetControl(type);

if (control == null || !control.SupportsUiaProviders)
SergeySmirnov-Akvelon marked this conversation as resolved.
Show resolved Hide resolved
{
return;
}

control.AccessibleRole = AccessibleRole.Link;
AccessibleObject controlAccessibleObject = control.AccessibilityObject;

var accessibleObjectRole = controlAccessibleObject.Role;

Assert.Equal(AccessibleRole.Link, accessibleObjectRole);
}

[Theory]
[MemberData(nameof(ControlObject_TestData))]
public void ControlAccessibleObject_IsPatternSupported_LegacyIAccessible_ReturnsTrue(Type type)
{
Control control = GetControl(type);

if (control == null || !control.SupportsUiaProviders)
SergeySmirnov-Akvelon marked this conversation as resolved.
Show resolved Hide resolved
{
return;
}

AccessibleObject controlAccessibleObject = control.AccessibilityObject;

bool supportsLegacyIAccessiblePatternId = controlAccessibleObject.IsPatternSupported(NativeMethods.UIA_LegacyIAccessiblePatternId);

Assert.True(supportsLegacyIAccessiblePatternId);
}

[Theory]
[MemberData(nameof(ControlObject_TestData))]
public void ControlAccessibleObject_LegacyIAccessible_Custom_Description_ReturnsExpected(Type type)
{
Control control = GetControl(type);

if (control == null || !control.SupportsUiaProviders)
SergeySmirnov-Akvelon marked this conversation as resolved.
Show resolved Hide resolved
{
return;
}

control.AccessibleDescription = "Test Accessible Description";
AccessibleObject controlAccessibleObject = control.AccessibilityObject;

var accessibleObjectDescription = controlAccessibleObject.Description;

Assert.Equal("Test Accessible Description", accessibleObjectDescription);
}

[Theory]
[MemberData(nameof(ControlObject_TestData))]
public void ToolStripItemAccessibleObject_GetPropertyValue_Custom_Name_ReturnsExpected(Type type)
Tanya-Solyanik marked this conversation as resolved.
Show resolved Hide resolved
{
Control control = GetControl(type);

if (control == null || !control.SupportsUiaProviders)
{
return;
}

control.Name = "Name1";
control.AccessibleName = "Test Name";
Tanya-Solyanik marked this conversation as resolved.
Show resolved Hide resolved

AccessibleObject controlAccessibleObject = control.AccessibilityObject;
var accessibleName = controlAccessibleObject.GetPropertyValue(NativeMethods.UIA_NamePropertyId);

Assert.Equal("Test Name", accessibleName);
}

public static IEnumerable<object[]> ControlObject_TestData()
{
var types = typeof(Control).Assembly.GetTypes().Where(type => !type.IsAbstract && type != typeof(WebBrowser));
RussKie marked this conversation as resolved.
Show resolved Hide resolved
foreach (var type in types)
{
yield return new object[] { type };
}
}

private Control GetControl(Type type)
{
if (!typeof(Control).IsAssignableFrom(type))
RussKie marked this conversation as resolved.
Show resolved Hide resolved
{
return null;
}

var ctor = type.GetConstructor(
Tanya-Solyanik marked this conversation as resolved.
Show resolved Hide resolved
bindingAttr: BindingFlags.Public | BindingFlags.Instance,
binder: null,
types: Array.Empty<Type>(),
modifiers: null);

if (ctor == null)
{
return null;
}

return (Control)ctor.Invoke(new object[0]);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace System.Windows.Forms.Tests.AccessibleObjects
public class DataGridViewAccessibleObjectTests
{
[Fact]
public void PropertyGridAccessibleObject_Ctor_Default()
public void DataGridViewAccessibleObject_Ctor_Default()
Tanya-Solyanik marked this conversation as resolved.
Show resolved Hide resolved
{
DataGridView dataGridView = new DataGridView();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
// 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.
// See the LICENSE file in the project root for more information.

using System.Drawing;
using Moq;
using Xunit;

namespace System.Windows.Forms.Tests
Expand Down Expand Up @@ -38,6 +37,60 @@ public void ToolStripItemAccessibleObject_Ctor_NullOwnerItem_ThrowsArgumentNullE
Assert.Throws<ArgumentNullException>("ownerItem", () => new ToolStripItem.ToolStripItemAccessibleObject(null));
}

[WinFormsFact]
RussKie marked this conversation as resolved.
Show resolved Hide resolved
public void ToolStripItemAccessibleObject_GetPropertyValue_Custom_Name_ReturnsExpected()
{
using var toolStripItem = new SubToolStripItem()
{
Name = "Name1",
AccessibleName = "Test Name"
};

AccessibleObject toolStripItemAccessibleObject = toolStripItem.AccessibilityObject;
var accessibleName = toolStripItemAccessibleObject.GetPropertyValue(NativeMethods.UIA_NamePropertyId);

Assert.Equal("Test Name", accessibleName);
}

[WinFormsFact]
public void ToolStripItemAccessibleObject_IsPatternSupported_LegacyIAccessible_ReturnsTrue()
{
using var toolStripItem = new SubToolStripItem();
AccessibleObject toolStripItemAccessibleObject = toolStripItem.AccessibilityObject;

bool supportsLegacyIAccessiblePatternId = toolStripItemAccessibleObject.IsPatternSupported(NativeMethods.UIA_LegacyIAccessiblePatternId);

Assert.True(supportsLegacyIAccessiblePatternId);
}

[WinFormsFact]
public void ToolStripItemAccessibleObject_LegacyIAccessible_Custom_Role_ReturnsExpected()
{
using var toolStripItem = new SubToolStripItem()
{
AccessibleRole = AccessibleRole.Link
};

AccessibleObject toolStripItemAccessibleObject = toolStripItem.AccessibilityObject;
var accessibleObjectRole = toolStripItemAccessibleObject.Role;

Assert.Equal(AccessibleRole.Link, accessibleObjectRole);
}

[WinFormsFact]
public void ToolStripItemAccessibleObject_LegacyIAccessible_Custom_Description_ReturnsExpected()
{
using var toolStripItem = new SubToolStripItem()
{
AccessibleDescription = "Test Description"
};

AccessibleObject toolStripItemAccessibleObject = toolStripItem.AccessibilityObject;
var accessibleObjectDescription = toolStripItemAccessibleObject.Description;

Assert.Equal("Test Description", accessibleObjectDescription);
}

private class SubToolStripItem : ToolStripItem
{
public SubToolStripItem() : base()
Expand Down
Loading