Change Space grows up


At the end of August I posted about Change, which seeks to replace the sorely missed 2D grid spaces feature that was in Snow Leopard for those unlucky enough to be using OSX Lion.

Now it’s two and a half months and over 50 commits later, and I have just released version 2.2.0. I think the app is getting pretty usable.

The last post I mentioned how I was using MacRuby to write the app, and indeed this was a pretty quick and easy way to get it off the ground.

But there are a couple of issues with MacRuby. Firstly, you need to set your Xcode up to include the MacRuby framework and runtime in the .app file otherwise users will have to install it themselves. And the runtime adds about 10Mb to your app size.

Secondly, when integrating with other libraries and certain calls to the Cocoa libraries and other APIs you find yourself having to write bridge code where the structures you are dealing with do not map easily to ruby objects.

Given these issues, I decided to rewrite the app completely in Objective C.

By mid October I had the App running nicely in the new language, and it was coming in at about half a meg as opposed to just under ten.

Some great libraries helped with the features I needed. Shortcutrecorder provided an ability to change the global hotkeys.

Change Space also displays the current desktop number in the status bar at the top of your screen.

At this time, rather than fade the desktop number out as I had been doing previously, the number was shown in the status bar permanently by polling the system for which desktop was active each second. I was to find a better way to do this though – it turns out that there is a notification for desktop change, so I can just subscribe to that and remove the polling altogether.

NSNotificationCenter *notCenter;    notCenter = [[NSWorkspace sharedWorkspace] notificationCenter];    [notCenter addObserver:self               selector:@selector(workspaceObserver:)               name:NSWorkspaceActiveSpaceDidChangeNotification object:nil];

I also wanted to add central screen notifications of the direction of movement between your spaces, and which you went from and to.

I started off with a simple arrow, but it would be far nicer to see an entire grid of the right dimensions. Step in Harry Groover, who provided code for a very nice looking grid. I added the arrow, and we had a really great looking result.


Next up I wanted the desktops to move in the right direction.

The importan APIs are defined like this:

extern OSStatus CGSNewTransition(const CGSConnection cid,   const CGSTransitionSpec* spec, int *pTransitionHandle);        extern OSStatus CGSInvokeTransition(const CGSConnection cid,   int transitionHandle, float duration);

The reverse engineering has already been done for us by previous apps such as DesktopManager, so the enum documentation can be found.

Not everything seems to work in Lion, but we have enough to work with. Calling CGSNewTransition will freeze the existing desktop, and wait for a transition to be invoked.

CGSInvokeTransition will perform the specified transition.

Unfortunately I do not have (as yet) a way to disable the standard left or right lion transitions, so when I want the desktop to move up or down I need to wait for the left or right transition to happen between creating the new transition and invoking it. Experimentation tells me that 0.3s is a long enough wait for that.

So the vertical transitions have a slight delay before they activate, but I think it’s worth it to preserve illusion of a grid.

For those who can’t stand the extra wait, I added a preference option to allow these transitions to be turned off.

So now, I think Change has come of age.

There are still a few problems to iron out, in particular the space 1 issue (I must use the AppleScript bridge to navigate to it, which is slower and is affected by which modifier keys you are holding down).

I hope to have this problem licked soon though.

Download Change v2.2.0 here.