Move your application’s windows between spaces

I puzzled for a few hours over this the other night — it’s something that used to work in VirtueDesktops, and for some reason I just assumed it no longer functioned under Mac OS X 10.5. Aside from an embarrassing bout of forgetting to get the window number properly, this turned out to be remarkably simple.

Prerequisites

You’ll need a copy of the CGSPrivate header in your project.

How to

Simply use the following code, where ibo_window is an Interface Builder outlet to an NSWindow in your XIB file:

CGSWindowID windowId = (CGSWindowID)[ibo_window windowNumber];
// The following integer represents the space you want to move the window to - the array is not zero-based - Space 1 == 1, Space 2 == 2, etc
NSInteger spaceToMoveTo = 2;
// Window count can be more than one, but for this example we're using a single window
NSInteger windowCount = 1;
// Now for the magical call:
CGSMoveWorkspaceWindowList(_CGSDefaultConnection(), &windowId, windowCount, spaceToMoveTo);

// If you want to check which space a window is on, simple use the following code:
NSInteger windowId = -1;  
CGSGetWindowWorkspace(_CGSDefaultConnection(), windowId, &workspaceID);
NSLog(@"Your window is now on space %i", windowId);

Easy, huh? I’m pretty sure this won’t work across processes (that’s why all the old desktop managers insert code into the running Dock application — it’s one of the only applications that has permission to muck about with other application’s windows). You should also probably try to intercept any errors thrown by the CGS* methods, but I’ll leave that as an exercise to you, gentle reader.

Comments

Gravatar for Chris.

Great tip. I was won­der­ing how to do this. I have a ques­tion for you though. I’m a devel­oper and have just recently started look­ing into OSX devel­op­ment and came across your hyper­spaces app. I’m curi­ous as to what you wrote it in, and whether that was a design deci­sion, or if you were forced into that lan­guage because of what you were try­ing to do on the oper­at­ing sys­tem. Thanks!

Posted by Chris on

Gravatar for Tony Arnold.

Hi Chris,

Hyper­spaces is writ­ten in Objective-​C, using the Cocoa frame­work. There’s a sprin­kling of the older Car­bon frame­work in my hotkey helper appli­ca­tion, only because it’s not cur­rently pos­si­ble to set global hotkeys directly using Cocoa.

There are also a few straight C func­tions — these are mainly around the pri­vate SPIs that I use to access infor­ma­tion about the cur­rent state of the user’s work­spaces (just like the one in this post).

I gave some thought to using an alter­na­tive lan­guage ear­lier on such as Ruby using the MacRuby bridges, but if you’re devel­op­ing on the mac you’d be kind of silly to use any­thing but Cocoa. UI toolkits/​frameworks such as Trolltech’s Qt and other “uni­ver­sal” UI toolk­its gen­er­ally look out of place and don’t respond in quite the same way as a native Cocoa application.

I guess I could have used Objective-​C++ as the lan­guage, but I don’t really know C++ all that well to start with. I guess there were a few places where I was “forced” to use straight C, but given the nature of Objective-​C you’d be hard pressed to avoid it in even the most straight-​laced of applications.

Does that answer your question?

Posted by Tony Arnold on

Gravatar for Danny Espinoza.

Tony: thank you, thank you, thank you. This is exactly what we needed to solve a major prob­lem with Stain­less (our multi-​process browser à la Google Chrome) and Spaces. You will def­i­nitely get a credit in our app.

Posted by Danny Espinoza on

Gravatar for Tony Arnold.

@Danny — not a prob­lem at all — I’m glad it came to be some use! I have a few other tricks up my sleeve I’m writ­ing up at the moment, so let me know if there’s any­thing else you’re stuck on.

Posted by Tony Arnold on

Gravatar for Rowan Lewis.

If I try to interact with the code block (scroll, select text), then it becomes mostly transparent.

Using Chrome 5.0.366.2 on Windows 7 (oh the horror)

Posted by Rowan Lewis on

Gravatar for Tony Arnold.

Ugh, way to go Chrome. This is what happens when Google half asses their implementation. Looks like the -webkit-mask-image is getting screwed up — I’ll look for a fix.

It seems to me that shit like this shouldn’t happen when Google are using WebKit, but noooo — they have to muck about and make it NotQuiteWebKit. Dicks.

</rant>

Posted by Tony Arnold on

Gravatar for tribalvibes.

Tony, thanks very much for this pointer. Is there also a call to create one or a list of newly opened windows in a designated Space?

Posted by tribalvibes on

Gravatar for Tony Arnold.

A call to create a new Space? You can adjust the number of rows/​columns via the scripting bridge framework. Controlling where individual windows isn’t possible without private API usage right now, but you can also set the application bindings via the scripting bridge. I hope that helps.

Posted by Tony Arnold on

Sorry, this conversation has finished.

This post is a bit old now, so I've closed the conversation. If you're keen to keep talking about it, please email me directly.