From 9fcccb94a9d42f76fb7a790496506638e6c60491 Mon Sep 17 00:00:00 2001 From: Jumar Macato <16554748+jmacato@users.noreply.github.com> Date: Thu, 2 Apr 2026 16:07:11 +0800 Subject: [PATCH] AvnAccessibilityElement fixes (#21062) --- native/Avalonia.Native/src/OSX/automation.mm | 33 ++++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/automation.mm b/native/Avalonia.Native/src/OSX/automation.mm index 005eaf0b50..6eee49f619 100644 --- a/native/Avalonia.Native/src/OSX/automation.mm +++ b/native/Avalonia.Native/src/OSX/automation.mm @@ -317,7 +317,30 @@ - (id)accessibilityParent { auto parentPeer = _peer->GetParent(); - return parentPeer ? [AvnAccessibilityElement acquire:parentPeer] : [NSApplication sharedApplication]; + + if (parentPeer == nullptr) + return [NSApplication sharedApplication]; + + // When the parent is a root provider, return the AvnView (content view) + // rather than the AvnWindow. macOS accessibility requires that the parent + // chain is consistent with the children chain: AvnView exposes these + // elements as its accessibilityChildren, so the elements must report + // AvnView as their accessibilityParent. A mismatch causes macOS to be + // unable to resolve AXUIElementRefs back to the correct object, which + // makes setter calls like AXUIElementSetAttributeValue silently land on + // AvnView instead of the target AvnAccessibilityElement. + if (parentPeer->IsRootProvider()) + { + auto window = parentPeer->RootProvider_GetWindow(); + if (window != nullptr) + { + auto holder = dynamic_cast(window); + if (holder != nullptr) + return holder->GetNSView(); + } + } + + return [AvnAccessibilityElement acquire:parentPeer]; } - (id)accessibilityTopLevelUIElement @@ -403,7 +426,11 @@ - (BOOL)isAccessibilitySelectorAllowed:(SEL)selector { - if (selector == @selector(accessibilityPerformShowMenu)) + if (selector == @selector(setAccessibilityValue:)) + { + return _peer->IsValueProvider() || _peer->IsRangeValueProvider(); + } + else if (selector == @selector(accessibilityPerformShowMenu)) { return _peer->IsExpandCollapseProvider() && _peer->ExpandCollapseProvider_GetShowsMenu(); } @@ -422,7 +449,7 @@ { return _peer->IsRangeValueProvider(); } - + return [super isAccessibilitySelectorAllowed:selector]; }