问题
I want to set a certain window, from an external app (for example textedit), to be front most.
I can successfully get a reference to the app itself using GetFrontProcess, and check whether it is front most. If it is not, I can use setFrontProcess to make it focussed.
I can then use the the accessibility API to examine all the windows under that application. I am checking that a certain window exists, and if so I compare it against the front most window of the application:
//get the front window of textEditApp and store it in 'currentFrontWindow'
AXUIElementCopyAttributeValue(textEditApp, kAXFocusedWindowAttribute, (CFTypeRef *)¤tFrontWindow);
If the window I am interested in is not frontmost, I need to set it so. I thought that I could use AXUIElement Set AttributeValue to do this but I am not getting any success. Below is how I have tried to do it.
//set the front window of textEditApp to be desiredFrontWindow
AXUIElementSetAttributeValue(textEditApp, kAXFocusedUIElementAttribute, desiredFrontWindow);
I have checked that the window exists, and the application is 'switched to' successfully. But why doesn't this line of code bring the specified window to the front?
Thanks.
回答1:
But why doesn't this line of code bring the specified window to the front?
Because you tried to set a read-only attribute.
In order to make a window frontmost, you need to set the appropriate property of the window. The same goes for an application: To make an application frontmost, you need to set the appropriate property of the application.
The Cocoa/Mac OS X name for the frontmost window is “the main window”. (See, for example, NSApplication's and NSWindow's methods relating to that concept.) Accessibility uses the same name, so to make a single window frontmost, set the value of its kAXMainAttribute
to kCFBooleanTrue
.
The way to make the application frontmost is similar: Set the value of its kAXFrontmostAttribute
to kCFBooleanTrue
. You'll need to do both of these to both set the frontmost window of the application and make the application active.
As far as I can tell, there is no way to bring only a single window of an application frontmost and give it session focus.
回答2:
I was able to accomplish this in an app I worked on by bringing the application to the front, then bringing a single window to the front.
First bringing the app to the front:
let currentPid = NSRunningApplication.currentApplication().processIdentifier
if let pid = (the pid of the app in question) where pid != currentPid {
NSRunningApplication(processIdentifier: pid)?.activateWithOptions(.ActivateIgnoringOtherApps)
}
Then sending the window to the front:
let window = (window AXUIElement)
AXUIElementSetAttributeValue(window, NSAccessibilityMainAttribute, true)
回答3:
I recently discovered that, if you don't mind some Carbon, you can use SetFrontProcessWithOptions to bring a window to the front and give it focus if you pass kSetFrontProcessFrontWindowOnly as the second argument.
来源:https://stackoverflow.com/questions/2114283/setting-the-front-most-window-using-accessibility-api