views:

191

answers:

2

I'm facing a problem for an application I'm writing (http://code.google.com/p/blazingstars/issues/detail?id=25), where my program is a menulet (menu bar) application that uses the Accessibility API to interact with and control another program. I do the usual things like registering for the API notifications and getting the window list through API calls, etc., but I realized a while ago that if my program is started in a second Space (virtual desktop) after the program I'm interacting with is started in the first, my program will crash and burn because it can't access any information about its target. (Is there a way around that problem I'm missing?)

A simple solution would be to popup a dialog asking the user to restart the program in the correct Space, but for the life of me I can't figure out how to tell which Space my target is in, either through NSWorkspace or the Accessibility API, so that I can compare it to the Space that I'm in. Any ideas?

Note that setting the collection behaviour to NSWindowCollectionBehaviorCanJoinAllSpaces isn't going to do me any good because I have to do a bunch of work upon launch, so I have to be in the same space as my target right from the start.

A: 

You should probably redesign your app so that it delays its initialization until the app you want to control is in the current space.

There is no easy way to do this under Leopard because there are no official "space change" notifications, but the blog post and comments on this page may help.

Rob Keniger
Rob,That's more or less what I want to do (I'll actually quit until the user starts the two programs together). But unless I'm missing something, the blog post you link to doesn't answer my question: how do I tell what space *another* app (not my own) is in?
Winawer
Ah, I see what you mean. I am not sure if that's even possible, I'm pretty certain it's not possible with public APIs.
Rob Keniger
+2  A: 

I think you can do this with the APIs in CGWindow.h. Specifically see CGWindowListCopyWindowInfo() and kCGWindowWorkspace.

I've used these APIs to do all types of things like getting window contents, window frames, etc...

If that doesn't work then you might want to try this private API: extern CGSError CGSGetWindowWorkspace(const CGSConnectionID cid, CGSWindowID wid, CGSWorkspaceID *workspace); The trick would be getting the connection ID of the target process.

Leibowitzn
This sounds like the best shot to me. I *really* hate working with these APIs, but I guess I'll have to just suck it up. :-) Thanks, Leibowitzn.
Winawer