From bcc8876e8e434210b3c725ce88a6525ed9ab359f Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 26 Mar 2021 22:16:30 +0100 Subject: [PATCH] Handle children changing. And map all the automation control types to roles. --- native/Avalonia.Native/src/OSX/automation.mm | 68 ++++++++++++++------ native/Avalonia.Native/src/OSX/window.mm | 5 ++ src/Avalonia.Native/AutomationNode.cs | 5 +- src/Avalonia.Native/avn.idl | 1 + 4 files changed, 54 insertions(+), 25 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/automation.mm b/native/Avalonia.Native/src/OSX/automation.mm index 064b414094..32230ff5b7 100644 --- a/native/Avalonia.Native/src/OSX/automation.mm +++ b/native/Avalonia.Native/src/OSX/automation.mm @@ -21,6 +21,11 @@ public: _node = [[AvnAutomationNode alloc] initWithPeer: peer]; } + virtual void ChildrenChanged() override + { + NSAccessibilityPostNotification(_node, NSAccessibilityLayoutChangedNotification); + } + virtual NSObject* GetNSAccessibility() override { return _node; @@ -50,25 +55,46 @@ public: auto controlType = _peer->GetAutomationControlType(); switch (controlType) { - case AutomationButton: - return NSAccessibilityButtonRole; - case AutomationCheckBox: - return NSAccessibilityCheckBoxRole; - case AutomationComboBox: - return NSAccessibilityPopUpButtonRole; - case AutomationGroup: - case AutomationPane: - return NSAccessibilityGroupRole; - case AutomationSlider: - return NSAccessibilitySliderRole; - case AutomationTab: - return NSAccessibilityTabGroupRole; - case AutomationTabItem: - return NSAccessibilityRadioButtonRole; - case AutomationWindow: - return NSAccessibilityWindowRole; - default: - return NSAccessibilityUnknownRole; + case AutomationButton: return NSAccessibilityButtonRole; + case AutomationCalendar: return NSAccessibilityGridRole; + case AutomationCheckBox: return NSAccessibilityCheckBoxRole; + case AutomationComboBox: return NSAccessibilityPopUpButtonRole; + case AutomationEdit: return NSAccessibilityTextFieldRole; + case AutomationHyperlink: return NSAccessibilityLinkRole; + case AutomationImage: return NSAccessibilityImageRole; + case AutomationListItem: return NSAccessibilityRowRole; + case AutomationList: return NSAccessibilityTableRole; + case AutomationMenu: return NSAccessibilityMenuBarRole; + case AutomationMenuBar: return NSAccessibilityMenuBarRole; + case AutomationMenuItem: return NSAccessibilityMenuItemRole; + case AutomationProgressBar: return NSAccessibilityProgressIndicatorRole; + case AutomationRadioButton: return NSAccessibilityRadioButtonRole; + case AutomationScrollBar: return NSAccessibilityScrollBarRole; + case AutomationSlider: return NSAccessibilitySliderRole; + case AutomationSpinner: return NSAccessibilityIncrementorRole; + case AutomationStatusBar: return NSAccessibilityTableRole; + case AutomationTab: return NSAccessibilityTabGroupRole; + case AutomationTabItem: return NSAccessibilityRadioButtonRole; + case AutomationText: return NSAccessibilityTextFieldRole; + case AutomationToolBar: return NSAccessibilityToolbarRole; + case AutomationToolTip: return NSAccessibilityPopoverRole; + case AutomationTree: return NSAccessibilityOutlineRole; + case AutomationTreeItem: return NSAccessibilityOutlineRowSubrole; + case AutomationCustom: return NSAccessibilityUnknownRole; + case AutomationGroup: return NSAccessibilityGroupRole; + case AutomationThumb: return NSAccessibilityHandleRole; + case AutomationDataGrid: return NSAccessibilityGridRole; + case AutomationDataItem: return NSAccessibilityCellRole; + case AutomationDocument: return NSAccessibilityStaticTextRole; + case AutomationSplitButton: return NSAccessibilityPopUpButtonRole; + case AutomationWindow: return NSAccessibilityWindowRole; + case AutomationPane: return NSAccessibilityGroupRole; + case AutomationHeader: return NSAccessibilityGroupRole; + case AutomationHeaderItem: return NSAccessibilityButtonRole; + case AutomationTable: return NSAccessibilityTableRole; + case AutomationTitleBar: return NSAccessibilityGroupRole; + case AutomationSeparator: return NSAccessibilityUnknownRole; + default: return NSAccessibilityUnknownRole; } } @@ -188,13 +214,13 @@ public: - (AvnWindow*) getAvnWindow { auto window = [self getWindow]; - return dynamic_cast(window)->GetNSWindow(); + return window != nullptr ? dynamic_cast(window)->GetNSWindow() : nullptr; } - (AvnView*) getAvnView { auto window = [self getWindow]; - return dynamic_cast(window)->GetNSView(); + return window != nullptr ? dynamic_cast(window)->GetNSView() : nullptr; } @end diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm index dc009dc5a0..456a2db3ee 100644 --- a/native/Avalonia.Native/src/OSX/window.mm +++ b/native/Avalonia.Native/src/OSX/window.mm @@ -509,6 +509,11 @@ public: return S_OK; } + virtual void ChildrenChanged() override + { + NSAccessibilityPostNotification(Window, NSAccessibilityLayoutChangedNotification); + } + protected: virtual NSWindowStyleMask GetStyle() { diff --git a/src/Avalonia.Native/AutomationNode.cs b/src/Avalonia.Native/AutomationNode.cs index c45ade520a..c0e46b52b9 100644 --- a/src/Avalonia.Native/AutomationNode.cs +++ b/src/Avalonia.Native/AutomationNode.cs @@ -18,10 +18,7 @@ namespace Avalonia.Native public IAvnAutomationNode Native { get; } public IAutomationNodeFactory Factory { get; } - public void ChildrenChanged() - { - // TODO - } + public void ChildrenChanged() => Native.ChildrenChanged(); public void PropertyChanged(AutomationProperty property, object? oldValue, object? newValue) { diff --git a/src/Avalonia.Native/avn.idl b/src/Avalonia.Native/avn.idl index 8357742f55..5697665545 100644 --- a/src/Avalonia.Native/avn.idl +++ b/src/Avalonia.Native/avn.idl @@ -820,4 +820,5 @@ interface IAvnAutomationPeerArray : IUnknown [uuid(004dc40b-e435-49dc-bac5-6272ee35382a)] interface IAvnAutomationNode : IUnknown { + void ChildrenChanged(); }