After replacing Big Sur OSX 11.0 with the latest 11.5, my app's AXObserverAddNotification methods fails. Here is sample code I tested:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSLog(@"Hello world");
AXUIElementRef frontMostApp = AXUIElementCreateApplication(82695); // '82695' is the PID reference to my Xcode 12.5.1 app running at front
NSLog(@"frontMostApp: %@",frontMostApp);
CFTypeRef frontMostWindow = NULL;
AXError error = AXUIElementCopyAttributeValue(frontMostApp, kAXFocusedWindowAttribute, (CFTypeRef *)&frontMostWindow);
if (error != kAXErrorSuccess) {
NSLog(@"failed with error: %i",error);
}
'frontMostWindow' reference is never created and I get the error number -25204. It seems like the latest Big Sur 11.5 has revised the Accessibility API or perhaps there is some permission switch I am unaware of that would make things work. What am I doing wrong?
CodePudding user response:
Using similar code to the one posted, I am able to get the observer call-back mechanism to work only upon the main application's set of windows. When I attempt to evoke a callback on another app's windows, I get an error showing -25204 ("A fundamental error has occurred")--even when I provide this application Accessability permission within the Security and Privacy preferences. This problem has occurred as a result of installing the latest macOS Big Sur, version 11.5.2.
I suspect that Apple no longer will support Accessibility programming outside one's own application for security reasons, unless this they have created a bug in the new OS.
The following code works on an app that posts two windows, but does not work when evoking the windows of an external application such as TextEdit:
@interface AppDelegate : NSObject <NSApplicationDelegate>{
IBOutlet NSWindow *window1;
IBOutlet NSWindow *window2;
}
@end
@implementation AppDelegate
NSWorkspace *workspace;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
[self installFocusedWindowChangedAXObserver];
}
static void focusedWindowChangedCallback(AXObserverRef observer, AXUIElementRef element, CFStringRef notification, void *self){
NSLog(@"mainWindowChangedCallback");
NSBeep();
}
- (AXError)installFocusedWindowChangedAXObserver {
usleep(100000); // This pause allows me time to click on another application besides this one to test observer call-back mechanism if I wish. Otherwise, this test application will post window1 and window2 that will trigger the kAXFocusedWindowChangedNotification mechanism when they are alternately clicked upon and thus change the window focus.
NSRunningApplication* frontMostApp = [[NSWorkspace sharedWorkspace] frontmostApplication];
pid_t pid = [frontMostApp processIdentifier];
NSLog(@"pid: %i",pid);
AXObserverRef observer = NULL;
AXError axErr = AXObserverCreate(pid, focusedWindowChangedCallback, &observer); // Note that the 2nd param is a 'AXObserverCallback' method (see documentation for method signature strictures)
NSLog(@"axErr: %i",axErr);
NSLog(@"observer: %@",observer);
CFRunLoopAddSource(CFRunLoopGetCurrent(),
AXObserverGetRunLoopSource(observer),
kCFRunLoopDefaultMode);
AXUIElementRef element = AXUIElementCreateApplication(pid); // pid of this app (the observer watcher)
NSLog(@"element: %@",element);
axErr = AXObserverAddNotification(observer, element, kAXFocusedWindowChangedNotification, (__bridge void *)(self));
NSLog(@"axErr: %i",axErr);
return axErr;
}
@end
CodePudding user response:
Try switching this line:
CFTypeRef frontMostWindow = NULL;
to:
AXUIElementRef frontMostWindow = NULL;
Internally, I bet AXUIElementCopyAttributeValue
is doing a sizeof
operation with the pointer you pass in to calculate the right amount of memory to allocate for the result (which is returned in a __AXUIElement
struct, according to the header file).
My guess is that doing a sizeof()
of a CFTypeRef
does not give you the right size, so it doesn't work and you get that memory allocation error code.