Browse Source

Implement -accessibilityPlaceholderValue on macOS

macOS uses a unique -accessibilityPlaceholderValue property for the
placeholder of a text field; -accessibilityHelp has different meaning from
HelpText on Windows. Map TextBox.PlaceholderText to be returned by
-accessibilityPlaceholderValue.

Ref: https://www.w3.org/TR/core-aam-1.2/#ariaPlaceholder
pull/20714/head
Adam Demasi 1 month ago
parent
commit
8593ef3038
No known key found for this signature in database GPG Key ID: C645138D382EA6A5
  1. 5
      native/Avalonia.Native/src/OSX/automation.mm
  2. 2
      samples/IntegrationTestApp/Pages/AutomationPage.axaml
  3. 20
      src/Avalonia.Controls/Automation/Peers/AutomationPeer.cs
  4. 1
      src/Avalonia.Controls/Automation/Peers/InteropAutomationPeer.cs
  5. 2
      src/Avalonia.Controls/Automation/Peers/TextBoxAutomationPeer.cs
  6. 1
      src/Avalonia.Native/AvnAutomationPeer.cs
  7. 1
      src/Avalonia.Native/avn.idl

5
native/Avalonia.Native/src/OSX/automation.mm

@ -220,6 +220,11 @@
return GetNSStringAndRelease(_peer->GetHelpText());
}
- (NSString *)accessibilityPlaceholderValue
{
return GetNSStringAndRelease(_peer->GetPlaceholderText());
}
- (id)accessibilityValue
{
if (_peer->IsRangeValueProvider())

2
samples/IntegrationTestApp/Pages/AutomationPage.axaml

@ -10,7 +10,7 @@
TextBlockWithNameAndAutomationId
</TextBlock>
<TextBlock Name="TextBlockAsLabel">Label for TextBox</TextBlock>
<TextBox Name="LabeledByTextBox" AutomationProperties.LabeledBy="{Binding #TextBlockAsLabel}">
<TextBox Name="LabeledByTextBox" AutomationProperties.LabeledBy="{Binding #TextBlockAsLabel}" PlaceholderText="Placeholder for TextBox">
Foo
</TextBox>
<TextBlock Name="TextBlockWithHeader1" AutomationProperties.ControlTypeOverride="Header" AutomationProperties.HeadingLevel="1">

20
src/Avalonia.Controls/Automation/Peers/AutomationPeer.cs

@ -283,12 +283,29 @@ namespace Avalonia.Automation.Peers
/// </remarks>
public string GetHelpText() => GetHelpTextCore() ?? string.Empty;
/// <summary>
/// Gets text that provides a placeholder for the element that is associated with this automation peer.
/// </summary>
/// <remarks>
/// <list type="table">
/// <item>
/// <term>Windows</term>
/// <description>No mapping.</description>
/// </item>
/// <item>
/// <term>macOS</term>
/// <description><c>NSAccessibilityProtocol.accessibilityPlaceholderValue</c></description>
/// </item>
/// </list>
/// </remarks>
public string GetPlaceholderText() => GetPlaceholderTextCore() ?? string.Empty;
/// <summary>
/// Gets the control type for the element that is associated with the UI Automation peer.
/// </summary>
/// <remarks>
/// Gets the type of the element.
///
///
/// <list type="table">
/// <item>
/// <term>Windows</term>
@ -595,6 +612,7 @@ namespace Avalonia.Automation.Peers
protected abstract AutomationPeer? GetLabeledByCore();
protected abstract string? GetNameCore();
protected virtual string? GetHelpTextCore() => null;
protected virtual string? GetPlaceholderTextCore() => null;
protected virtual AutomationLandmarkType? GetLandmarkTypeCore() => null;
protected virtual int GetHeadingLevelCore() => 0;
protected virtual string? GetItemTypeCore() => null;

1
src/Avalonia.Controls/Automation/Peers/InteropAutomationPeer.cs

@ -29,6 +29,7 @@ internal class InteropAutomationPeer : AutomationPeer
protected override AutomationPeer? GetLabeledByCore() => throw new NotImplementedException();
protected override string? GetNameCore() => throw new NotImplementedException();
protected override string? GetHelpTextCore() => throw new NotImplementedException();
protected override string? GetPlaceholderTextCore() => throw new NotImplementedException();
protected override IReadOnlyList<AutomationPeer> GetOrCreateChildrenCore() => throw new NotImplementedException();
protected override AutomationPeer? GetParentCore() => _parent;
protected override bool HasKeyboardFocusCore() => throw new NotImplementedException();

2
src/Avalonia.Controls/Automation/Peers/TextBoxAutomationPeer.cs

@ -21,6 +21,8 @@ namespace Avalonia.Automation.Peers
return AutomationControlType.Edit;
}
protected override string? GetPlaceholderTextCore() => Owner.PlaceholderText;
protected virtual void OwnerPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
{
if(e.Property == TextBox.TextProperty)

1
src/Avalonia.Native/AvnAutomationPeer.cs

@ -46,6 +46,7 @@ namespace Avalonia.Native
public IAvnAutomationPeer? LabeledBy => Wrap(_inner.GetLabeledBy());
public IAvnString? Name => _inner.GetName().ToAvnString();
public IAvnString? HelpText => _inner.GetHelpText().ToAvnString();
public IAvnString? PlaceholderText => _inner.GetPlaceholderText().ToAvnString();
public AvnLandmarkType LandmarkType => (AvnLandmarkType?)_inner.GetLandmarkType() ?? AvnLandmarkType.LandmarkNone;
public int HeadingLevel => _inner.GetHeadingLevel();
public IAvnAutomationPeer? Parent => Wrap(_inner.GetParent());

1
src/Avalonia.Native/avn.idl

@ -1328,6 +1328,7 @@ interface IAvnAutomationPeer : IUnknown
void ValueProvider_SetValue([const] char* value);
IAvnString* GetHelpText();
IAvnString* GetPlaceholderText();
AvnLandmarkType GetLandmarkType();
int GetHeadingLevel();

Loading…
Cancel
Save