Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting the front most window using accessibility API

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 *)&currentFrontWindow);

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.

like image 279
Ben Packard Avatar asked Jan 22 '10 01:01

Ben Packard


2 Answers

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.

like image 112
Peter Hosey Avatar answered Sep 21 '22 06:09

Peter Hosey


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)
like image 30
Keith Smiley Avatar answered Sep 17 '22 06:09

Keith Smiley