Mac / Cocoa - Getting a list of windows using Accessibility API
I want to use the Accessibility API to get a list of all windows for a given application (external).
The goal is to check if a certain window is open. First I check that 开发者_运维知识库the application is running (using [NSWorkspace runningApplications] and checking each one), and then I want to check the title bar text of each window that is open for that application.
PS
So I can create an element for the app using the PID:
AXUIElementRef app = AXUIElementCreateApplication(pid);
but what do I do with it? Am I even going in the right direction? Can't beleive it's so hard to find examples on this.
I don't know a way to get window ID and PID from the Accessibility API.
The NSWindow method Laurent mentioned only provides Window IDs but not the PID of the window owning application.
I would use the CGWindowList methods that are available since 10.5.
To get a list of window IDs and the PID of the owner you can try the following:
CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
for (NSMutableDictionary* entry in (NSArray*)windowList)
{
NSString* ownerName = [entry objectForKey:(id)kCGWindowOwnerName];
NSInteger ownerPID = [[entry objectForKey:(id)kCGWindowOwnerPID] integerValue];
NSLog(@"%@:%d", ownerName, ownerPID);
}
CFRelease(windowList);
You can control if you want all windows (including offscreen, ...) with the option paramter.
Also the entry objects contain a lot more information. Documentation link
This works for me in Swift 5.1:
let windowList: CFArray? = CGWindowListCopyWindowInfo(.optionOnScreenOnly, kCGNullWindowID)
for entry in windowList! as Array {
let ownerName: String = entry.object(forKey: kCGWindowName) as? String ?? "N/A"
let ownerPID: Int = entry.object(forKey: kCGWindowOwnerPID) as? Int ?? 0
print("ownerName: \(ownerName), ownerPID:\(ownerPID)")
}
Use AXUIElementCopyAttributeValues
to copy the value for kAXWindowsAttribute
, which should be an array of AXUIElement objects representing the application's windows.
As you can guess from its function name, it follows the copy rule.
You can use windowNumbersWithOptions:. It lists all the windows from all the applications by their number. But I can't find how to get a NSWindow from a window number...
If you get kAXErrorCannotComplete
it is likely because you used a newer project where XCode automatically added the App Sandbox
or Hardened Runtime
capabilities. Delete them from the Signing and Capabilities
tab and it should start working.
精彩评论