Skip to content

Commit

Permalink
[Windows] Improve performance in accessibility extensions (dotnet#22698)
Browse files Browse the repository at this point in the history
* AccessibilityExtensions: Add missing braces

* AccessibilityExtensions: Enable nullability and improve performance

* Update shipped & unshipped API

---------

Co-authored-by: Javier Suárez <javiersuarezruiz@hotmail.com>
  • Loading branch information
MartyIX and jsuarezruiz committed Jun 27, 2024
1 parent 51ad8f6 commit 3e3cd67
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#nullable disable
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Automation.Peers;
using NativeAutomationProperties = Microsoft.UI.Xaml.Automation.AutomationProperties;
Expand All @@ -7,112 +6,153 @@ namespace Microsoft.Maui.Controls.Platform
{
public static class AccessibilityExtensions
{
public static void SetAutomationPropertiesAutomationId(this FrameworkElement Control, string id)
public static void SetAutomationPropertiesAutomationId(this FrameworkElement Control, string? id)
{
Control.SetValue(NativeAutomationProperties.AutomationIdProperty, id);
}

public static string SetAutomationPropertiesName(this FrameworkElement Control, Element Element, string _defaultAutomationPropertiesName = null)
public static string? SetAutomationPropertiesName(this FrameworkElement Control, Element? Element, string? _defaultAutomationPropertiesName = null)
{
if (Element == null)
if (Element is null)
{
return _defaultAutomationPropertiesName;
}

string? currentValue = null;

if (_defaultAutomationPropertiesName == null)
_defaultAutomationPropertiesName = (string)Control.GetValue(NativeAutomationProperties.NameProperty);
if (_defaultAutomationPropertiesName is null)
{
_defaultAutomationPropertiesName = currentValue = (string)Control.GetValue(NativeAutomationProperties.NameProperty);
}

#pragma warning disable CS0618 // Type or member is obsolete
var elemValue = (string)Element.GetValue(AutomationProperties.NameProperty);
#pragma warning restore CS0618 // Type or member is obsolete

if (!string.IsNullOrWhiteSpace(elemValue))
Control.SetValue(NativeAutomationProperties.NameProperty, elemValue);
else
string newValue = !string.IsNullOrWhiteSpace(elemValue) ? elemValue : _defaultAutomationPropertiesName;

if (currentValue is null || currentValue != newValue)
{
Control.SetValue(NativeAutomationProperties.NameProperty, _defaultAutomationPropertiesName);
}

return _defaultAutomationPropertiesName;
}

public static AccessibilityView? SetAutomationPropertiesAccessibilityView(this FrameworkElement Control, Element Element, AccessibilityView? _defaultAutomationPropertiesAccessibilityView = null)
public static AccessibilityView? SetAutomationPropertiesAccessibilityView(this FrameworkElement Control, Element? Element, AccessibilityView? _defaultAutomationPropertiesAccessibilityView = null)
{
if (Element == null)
if (Element is null)
{
return _defaultAutomationPropertiesAccessibilityView;
}

AccessibilityView? currentValue = null;

if (!_defaultAutomationPropertiesAccessibilityView.HasValue)
_defaultAutomationPropertiesAccessibilityView = (AccessibilityView)Control.GetValue(NativeAutomationProperties.AccessibilityViewProperty);
{
_defaultAutomationPropertiesAccessibilityView = currentValue = (AccessibilityView)Control.GetValue(NativeAutomationProperties.AccessibilityViewProperty);
}

var newValue = _defaultAutomationPropertiesAccessibilityView;

var elemValue = (bool?)Element.GetValue(AutomationProperties.IsInAccessibleTreeProperty);

if (elemValue == true)
{
newValue = AccessibilityView.Content;
}
else if (elemValue == false)
{
newValue = AccessibilityView.Raw;
}

Control.SetValue(NativeAutomationProperties.AccessibilityViewProperty, newValue);
if (currentValue is null || currentValue != newValue)
{
Control.SetValue(NativeAutomationProperties.AccessibilityViewProperty, newValue);
}

return _defaultAutomationPropertiesAccessibilityView;

}
public static string SetAutomationPropertiesHelpText(this FrameworkElement Control, Element Element, string _defaultAutomationPropertiesHelpText = null)
public static string? SetAutomationPropertiesHelpText(this FrameworkElement Control, Element? Element, string? _defaultAutomationPropertiesHelpText = null)
{
if (Element == null)
{
return _defaultAutomationPropertiesHelpText;
}

if (_defaultAutomationPropertiesHelpText == null)
_defaultAutomationPropertiesHelpText = (string)Control.GetValue(NativeAutomationProperties.HelpTextProperty);
string? currentValue = null;

if (_defaultAutomationPropertiesHelpText is null)
{
_defaultAutomationPropertiesHelpText = currentValue = (string)Control.GetValue(NativeAutomationProperties.HelpTextProperty);
}

#pragma warning disable CS0618 // Type or member is obsolete
var elemValue = (string)Element.GetValue(AutomationProperties.HelpTextProperty);
#pragma warning restore CS0618 // Type or member is obsolete

if (!string.IsNullOrWhiteSpace(elemValue))
Control.SetValue(NativeAutomationProperties.HelpTextProperty, elemValue);
else
string newValue = !string.IsNullOrWhiteSpace(elemValue) ? elemValue : _defaultAutomationPropertiesHelpText;

if (currentValue is null || newValue != currentValue)
{
Control.SetValue(NativeAutomationProperties.HelpTextProperty, _defaultAutomationPropertiesHelpText);
}

return _defaultAutomationPropertiesHelpText;
}

public static UIElement SetAutomationPropertiesLabeledBy(
public static UIElement? SetAutomationPropertiesLabeledBy(
this FrameworkElement Control,
Element Element,
IMauiContext mauiContext,
UIElement _defaultAutomationPropertiesLabeledBy = null)
Element? Element,
IMauiContext? mauiContext,
UIElement? _defaultAutomationPropertiesLabeledBy = null)
{
if (Element == null)
if (Element is null)
{
return _defaultAutomationPropertiesLabeledBy;
}

// TODO Maui: this is a bit of a hack because Elements
// currently don't implement IView but they should
mauiContext ??= (Element as IView)?.Handler?.MauiContext;

if (_defaultAutomationPropertiesLabeledBy == null)
_defaultAutomationPropertiesLabeledBy = (UIElement)Control.GetValue(NativeAutomationProperties.LabeledByProperty);
UIElement? currentValue = null;

if (_defaultAutomationPropertiesLabeledBy is null)
{
_defaultAutomationPropertiesLabeledBy = currentValue = (UIElement)Control.GetValue(NativeAutomationProperties.LabeledByProperty);
}
#pragma warning disable CS0618 // Type or member is obsolete
var elemValue = (VisualElement)Element.GetValue(AutomationProperties.LabeledByProperty);
#pragma warning restore CS0618 // Type or member is obsolete
FrameworkElement nativeElement = null;
FrameworkElement? nativeElement = null;

if (mauiContext != null)
{
nativeElement = (elemValue as IView)?.ToHandler(mauiContext)?.PlatformView as FrameworkElement;
}

UIElement? newValue = nativeElement is not null ? nativeElement : _defaultAutomationPropertiesLabeledBy;

if (nativeElement != null)
if (currentValue is null || newValue != currentValue)
{
#pragma warning disable CS0618 // Type or member is obsolete
Control.SetValue(AutomationProperties.LabeledByProperty, nativeElement);
Control.SetValue(AutomationProperties.LabeledByProperty, newValue);
#pragma warning restore CS0618 // Type or member is obsolete
else
Control.SetValue(NativeAutomationProperties.LabeledByProperty, _defaultAutomationPropertiesLabeledBy);
}

return _defaultAutomationPropertiesLabeledBy;
}

// TODO MAUI: This is not having any effect on anything I've tested yet. See if we need it
// after we test the FP and NP w/ back button explicitly enabled.
public static void SetBackButtonTitle(this PageControl Control, Element Element)
public static void SetBackButtonTitle(this PageControl Control, Element? Element)
{
if (Element == null)
if (Element is null)
{
return;
}

var elemValue = ConcatenateNameAndHint(Element);

Expand All @@ -130,21 +170,23 @@ static string ConcatenateNameAndHint(Element Element)
#pragma warning restore CS0618 // Type or member is obsolete

if (string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(hint))
{
separator = "";

}
else
{
separator = ". ";

}

return string.Join(separator, name, hint);

}

public static void SetAutomationProperties(
this FrameworkElement frameworkElement,
Element element,
IMauiContext mauiContext,
string defaultName = null)
Element? element,
IMauiContext? mauiContext,
string? defaultName = null)
{
frameworkElement.SetAutomationPropertiesAutomationId(element?.AutomationId);
frameworkElement.SetAutomationPropertiesName(element, defaultName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2534,13 +2534,6 @@
~static Microsoft.Maui.Controls.OnPlatform<T>.implicit operator T(Microsoft.Maui.Controls.OnPlatform<T> onPlatform) -> T
~static Microsoft.Maui.Controls.PanGestureRecognizer.CurrentId.get -> Microsoft.Maui.Controls.Internals.AutoId
~static Microsoft.Maui.Controls.Picker.ControlsPickerMapper -> Microsoft.Maui.IPropertyMapper<Microsoft.Maui.IPicker, Microsoft.Maui.Handlers.PickerHandler>
~static Microsoft.Maui.Controls.Platform.AccessibilityExtensions.SetAutomationProperties(this Microsoft.UI.Xaml.FrameworkElement frameworkElement, Microsoft.Maui.Controls.Element element, Microsoft.Maui.IMauiContext mauiContext, string defaultName = null) -> void
~static Microsoft.Maui.Controls.Platform.AccessibilityExtensions.SetAutomationPropertiesAccessibilityView(this Microsoft.UI.Xaml.FrameworkElement Control, Microsoft.Maui.Controls.Element Element, Microsoft.UI.Xaml.Automation.Peers.AccessibilityView? _defaultAutomationPropertiesAccessibilityView = null) -> Microsoft.UI.Xaml.Automation.Peers.AccessibilityView?
~static Microsoft.Maui.Controls.Platform.AccessibilityExtensions.SetAutomationPropertiesAutomationId(this Microsoft.UI.Xaml.FrameworkElement Control, string id) -> void
~static Microsoft.Maui.Controls.Platform.AccessibilityExtensions.SetAutomationPropertiesHelpText(this Microsoft.UI.Xaml.FrameworkElement Control, Microsoft.Maui.Controls.Element Element, string _defaultAutomationPropertiesHelpText = null) -> string
~static Microsoft.Maui.Controls.Platform.AccessibilityExtensions.SetAutomationPropertiesLabeledBy(this Microsoft.UI.Xaml.FrameworkElement Control, Microsoft.Maui.Controls.Element Element, Microsoft.Maui.IMauiContext mauiContext, Microsoft.UI.Xaml.UIElement _defaultAutomationPropertiesLabeledBy = null) -> Microsoft.UI.Xaml.UIElement
~static Microsoft.Maui.Controls.Platform.AccessibilityExtensions.SetAutomationPropertiesName(this Microsoft.UI.Xaml.FrameworkElement Control, Microsoft.Maui.Controls.Element Element, string _defaultAutomationPropertiesName = null) -> string
~static Microsoft.Maui.Controls.Platform.AccessibilityExtensions.SetBackButtonTitle(this Microsoft.Maui.Controls.Platform.PageControl Control, Microsoft.Maui.Controls.Element Element) -> void
~static Microsoft.Maui.Controls.Platform.AccessKeyHelper.UpdateAccessKey(Microsoft.UI.Xaml.FrameworkElement control, Microsoft.Maui.Controls.VisualElement element) -> void
~static Microsoft.Maui.Controls.Platform.BrushExtensions.ToBrush(this Microsoft.Maui.Controls.Brush brush) -> Microsoft.UI.Xaml.Media.Brush
~static Microsoft.Maui.Controls.Platform.FontExtensions.ApplyFont(this Microsoft.UI.Xaml.Controls.Control self, Microsoft.Maui.Font font, Microsoft.Maui.IFontManager fontManager) -> void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommand.get -> S
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommand.set -> void
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommandParameter.get -> object!
Microsoft.Maui.Controls.PointerGestureRecognizer.PointerReleasedCommandParameter.set -> void
static Microsoft.Maui.Controls.Platform.AccessibilityExtensions.SetAutomationProperties(this Microsoft.UI.Xaml.FrameworkElement! frameworkElement, Microsoft.Maui.Controls.Element? element, Microsoft.Maui.IMauiContext? mauiContext, string? defaultName = null) -> void
static Microsoft.Maui.Controls.Platform.AccessibilityExtensions.SetAutomationPropertiesAccessibilityView(this Microsoft.UI.Xaml.FrameworkElement! Control, Microsoft.Maui.Controls.Element? Element, Microsoft.UI.Xaml.Automation.Peers.AccessibilityView? _defaultAutomationPropertiesAccessibilityView = null) -> Microsoft.UI.Xaml.Automation.Peers.AccessibilityView?
static Microsoft.Maui.Controls.Platform.AccessibilityExtensions.SetAutomationPropertiesAutomationId(this Microsoft.UI.Xaml.FrameworkElement! Control, string? id) -> void
static Microsoft.Maui.Controls.Platform.AccessibilityExtensions.SetAutomationPropertiesHelpText(this Microsoft.UI.Xaml.FrameworkElement! Control, Microsoft.Maui.Controls.Element? Element, string? _defaultAutomationPropertiesHelpText = null) -> string?
static Microsoft.Maui.Controls.Platform.AccessibilityExtensions.SetAutomationPropertiesLabeledBy(this Microsoft.UI.Xaml.FrameworkElement! Control, Microsoft.Maui.Controls.Element? Element, Microsoft.Maui.IMauiContext? mauiContext, Microsoft.UI.Xaml.UIElement? _defaultAutomationPropertiesLabeledBy = null) -> Microsoft.UI.Xaml.UIElement?
static Microsoft.Maui.Controls.Platform.AccessibilityExtensions.SetAutomationPropertiesName(this Microsoft.UI.Xaml.FrameworkElement! Control, Microsoft.Maui.Controls.Element? Element, string? _defaultAutomationPropertiesName = null) -> string?
static Microsoft.Maui.Controls.Platform.AccessibilityExtensions.SetBackButtonTitle(this Microsoft.Maui.Controls.Platform.PageControl! Control, Microsoft.Maui.Controls.Element? Element) -> void
static readonly Microsoft.Maui.Controls.KeyboardAccelerator.KeyProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.KeyboardAccelerator.ModifiersProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.DragGestureRecognizer.CanDragProperty -> Microsoft.Maui.Controls.BindableProperty!
Expand Down

0 comments on commit 3e3cd67

Please sign in to comment.