I want to use MacOS accessibility feature with my application which renders its own custom UI (i.e. not using Cocoa). For this I implement a tree of subclassed NSAccessibilityElements associated with each widget I draw.
The root UI container is hosted inside an NSView provided to my application externally (my application is a plugin). Now I need to attach my tree of NSAccessibilityElements to the existing NSView provided by the host.
Apple documentation recommends two ways to achieve this:
accessibilityChildren property to include custom elements (Qt uses this method for example). Unfortunately I do not create the parent NSView myself, it gets injected externally.accessibilityAddChildElement convenience method. But when I call it on provided NSView object, I get an exception that it does not respond to this method.What would be the right way to attach a tree of NSAccessibilityElements to an exiting NSView?
So I ended up subclassing NSView to capture the top level NSAccessibilityElement. Overridden - (NSArray*) accessibilityChildren method returns that captured accessibility element as one of its children:
@interface AccessibilityRootView : NSView
- (instancetype)initWithAccessibilityElement: (NSAccessibilityElement*)anElement;
@end
@implementation AccessibilityRootView
{
NSAccessibilityElement* element;
}
- (instancetype) initWithAccessibilityElement: (NSAccessibilityElement*)anElement
{
self = [super init];
if (self)
element = anElement;
return self;
}
- (NSArray*) accessibilityChildren
{
NSArray<NSAccessibilityElement*> *children = [super accessibilityChildren];
int numKids = (int)[children count] + 1;
NSMutableArray<NSAccessibilityElement*> *kids = [NSMutableArray<NSAccessibilityElement*> arrayWithCapacity:numKids];
for (id object in children)
[kids addObject:object];
[kids addObject: element];
return NSAccessibilityUnignoredChildren (kids);
}
@end
I then attach this subclassed view of zero size to the parent NSView provided by the host:
NSView* hostView = /* host-provided NSView */;
AccessibilityRootView* accessibilityRootView = [[AccessibilityRootView alloc] initWithAccessibilityElement:(NSAccessibilityElement*)topLevelAccessibilityElement];
[hostView addSubview:accessibilityRootView];
[accessibilityRootView release];
At this point all my NSAccessibilityElements are attached to that zero-size view that lives in the host-provided view, and MacOS can successfully query the items.
Additionally each NSAccessibilityElement had to implement correctly its
- (NSRect)accessibilityFrame and
- (id) accessibilityHitTest:(NSPoint)point
to match the screen position of my custom drawn UI widgets.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With