Programatically Controlling Spaces

March 22nd, 2008 by Joe Ranieri

There’s been a lot of questions on mailing lists about how to control Spaces programatically. So far, there’s been no results from these discussions. Well, fortunately accomplishing this is quite simple, if you’re comfortable using private APIs.

Functions to query the current settings:

CGError CGSGetWorkspace(CGSConnectionID cid, CGSWorkspaceID *outWorkspace);
extern bool CoreDockGetWorkspacesEnabled();
extern void CoreDockGetWorkspacesCount(int *rows, int *columns);

You’ll probably also want to switch spaces. You can accomplish this by using a distributed notification. This tells the Dock to switch spaces, giving you all of the normal animations:

- (void)switchToSpace:(CGSWorkspaceID)spaceNumber {
  // note that the notification is 1 based, but CGSWorkspaceID is zero based!
  [[NSDistributedNotificationCenter defaultCenter] postNotificationName:@"com.apple.switchSpaces"
                                                                 object:[NSString stringWithFormat:@"%i", spaceNumber + 1]];
}

And lastly, you’ll probably want to get notified when things change:

//! Gets called when the current space changes.
void SpaceChangedCallback(CGSNotificationType type, CGSWorkspaceID *workspace, unsigned int dataLength, Controller *self) {
  if(*workspace != kCGSTransitioningWorkspaceID) {
    // do something
  }
}
 
//! Gets called when the user enables or disables Spaces.
- (void)spacesEnabledChanged:(NSNotification *)notification {
  // do something
}
 
//! Start listening for workspace related changes.
- (void)registerForNotifications {
  // listen for when Spaces is enabled or disabled
  [[NSDistributedNotificationCenter defaultCenter] addObserver:self
                                                      selector:@selector(spacesEnabledChanged:)
                                                          name:@"SpacesEnableChange"
                                                        object:nil
                                            suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately];
 
  // listen for when the current space changes
  CGSRegisterNotifyProc((CGSNotifyProcPtr)SpaceChangedCallback, kCGSNotificationWorkspaceChanged, self);
}

You can find a full code example in the CGSInternal svn repository under Examples/SpacesSwitchingMenu, which mimics the Spaces menu extra.

Happy hacking!


Toys for Christmas

December 25th, 2007 by Ryan Govostes

Dear readers, gather ’round, we’ve got something to share:
Click on Toybox above and see what’s in there.
We’re sure you’ll enjoy at least one of these things,
Our greatest inventions, fit for you kings.

There’s one to label your episodes of M*A*S*H,
And another, a CGS private function stash.
And a third, if you’re not yet licking your lips:
We’ll give you a way to make Dashboard web clips!

We’ll be away for the week, but please let us know
How you all liked the teasers we’ve had to show.
Even if you didn’t, post a comment anyways.
Well, we’re out — Happy Holidays.