Carbon Accessibility API - Retrieving Windows Information Through Spaces

I have the following (minor) problem that I want to solve programmatically. Whenever I disconnect my secondary monitor from my laptop, all windows are now visible at a lower resolution. When I reconnect the external monitor, I need to manually replace the windows with the correct position. I have to do this every morning (sigh).

Now I decided to write a simple command line program that could save the position of all open windows and move them when I want to restore their positions.

I was able to do something that works great using the Accessibility API, which allows me to manage windows that are not part of my process space. I have a problem: the program can only see windows that are in my current space (I'm talking about the OSX Spaces feature here).

In other words, when I run my program to save positions in windows, it will only be able to save window positions in the space I am currently in.

More information about my program:

  • It goes through all running processes and gets their PIDs.
  • It creates app items from these PIDs ( AXUIElementCreateApplication

    )
  • It gets the windows associated with this application and then their positions

When getting window elements from an application element, AXUIElementCopyAttributeValues

only returns the windows of the current space to me.

Now, is there a way to manage any windows (in different spaces)? If not, I wouldn't mind changing the spaces programmatically to get all windows, but that is not possible.

Any help would be appreciated!

+2


a source to share


2 answers


I don't know of a documented way to switch spaces.



You probably want CGSPrivate.h - CGSSetWorkspace

et al. Just be aware that these are SPI functions and may interrupt without warning even in version 10.6.x.

+1


a source


If you want to avoid using private APIs, you can take advantage of the fact that Mission Control has keyboard shortcuts to navigate to different locations, and you can programmatically send keycodes to activate them. I wrote a blog post about this ( http://ianyh.com/blog/2013/06/05/accessibility/ ) for a window pane manager I was working on named Amethyst which has some example code you can check in -[AMWindow moveToSpace:]

.

The short version moves to a space similar to using the default ctrl + arrow key

to move to adjacent spaces:

CGEventRef keyboardDownEvent = CGEventCreateKeyboardEvent(NULL, kVK_RightArrow, true);
CGEventRef keyboardUpEvent = CGEventCreateKeyboardEvent(NULL, kVK_RightArrow, false);

CGEventSetFlags(keyboardDownEvent, kCGEventFlagMaskControl);
CGEventSetFlags(keyboardUpEvent, 0);

CGEventPost(kCGHIDEventTap, keyboardDownEvent);
CGEventPost(kCGHIDEventTap, keyboardUpEvent);

CFRelease(keyboardEvent);
CFRelease(keyboardEventUp);

      



You can combine this with NSWorkspaceActiveSpaceDidChangeNotification

to traverse all gaps and collect window data.

Also, as a potentially interesting note, the accessibility APIs can actually give you windows in all spaces at the same time, but this will only give you windows in the spaces you went through, starting with the process using the running APIs. I have no idea why this is, but it looks like.

0


a source







All Articles