WindowWarp
Update 7/26: Someone used the screenshot below to make some fake screenshots of OSX Leopard.
I thought I might post this while there are still a number of OSX developers running around the blog. There is a nice undocumented window manager call, CGSSetWindowWarp, which lets you twist and bend windows. I played around with a few years ago, but never got around to using it for anything.
![]()
![]()
The warped windows are fully functional, with the exception that mouse input is not remapped. Still some work to do there.
Some suggestions for things to do with it:
- 3D Exposé replacement: "rotate" the screen, so can you can see windows from the side and pick one out
- Fish-eye window manager: keep full-sized windows in the center of the screen; shrink and warp when they reach the edge
- Rotational virtual desktops: something similar to the FrontRow menu, where the windows would be on the outside of a cylinder. You could zoom out slightly, then spin the cylinder to get to the windws you want.
- Wobbly windows: pretend that the windows are only pinned to the desktop at the top, and use the motion sensor and some simple physics to wobble the windows.
If you do something cool, please post a link here!
Full-size screenshots after the fold.
Full size screenshots:

Two browsers and a terminal.

As you can see, the windows can overlap themselves, though only in one direction.
May 22, 2006
SmackBook Pro
Updates below the fold
I usually keep two 20" screens side by side on my desk, so I can code
on one and test on the other. I find I can work much faster if I can
just make a change in Eclipse, and by the time I turn my head to
the other screen, the tests have already run. My new laptop, however, has a 15" screen, which feels a bit cramped when I'm
working away from the office. I've been using the fancy Desktop Manager by
Richard Wareham, which is a very nice utility to let you keep several
virtual desktops, and change between them easily.
Of course, if you're using something like Emacs or Butler, all your keys will be taken already, so you'll need to use some sort of Command-Ctrl-Shift-4 keystroke for the actual desktop switching.
Turns out, the laptop has a built-in motion sensor. Nominally, it's there to protect the internal hard drive. The basic idea is this: If the accelerometer suddenly notices that the gravitational pull of earth is no longer present, the most likely explanation is that the laptop, sensor and all, is currently accelerating at 9.81 m/s² towards said earth. In that case, it will (wisely) try to turn the hard drive off in preparation for impact.
It can, however, also be used in situations not involving lobbing the laptop across the room, fun though that may be.
7/30: And now, the "official" IBM version for ThinkPad, which lets you use "shave-and-a-haircut" as your screen-saver password.
6/29: Smack your Nokia phone
6/27: Smack the penguin: GTollina.
6/17: Less violent (light sensor based) version now out.
6/7: Tom Merritt at c|net has posted a tutorial video of sorts. Thanks!
6/5: Here comes the SmackPad - courtesy of Michele Campeotto, you can shake your IBM ThinkPad to bits too.
5/31: Lincoln Ramsay has released UniMotion, a small open source library for reading the motion sensor. It supports iBook, PowerBook and MacBook Pro, old and new. Go Lincoln!
The latest release of VirtueDesktops supports the NSRemoteNotificationCenter protocol detailed below, so steps 1-7 of Dave's illustrated instructions have been superseded by "Install VirtueDesktop."
5/26: Any OSX developers looking for a fun hacking project? CGSSetWindowWarp is still virtually unused.
If you're on a PowerBook or iBook, see comment #136. For sensitivity issues, see #152.
All code in this post is released under the GPL.
Desktop Manager patch
First, you'll need to be able to control Desktop Manager from
outside. Cocoa has a nice class called NSDistributedNotificationCenter
which can handle simple message passing between applications. DM uses
a notification center internally to send "next desktop", "previous
desktop" commands to itself, so the patch just replaces the normal
version with the distributed version. I added the following to WorkspaceController.m, inside the init method:
[[NSDistributedNotificationCenter defaultCenter] addObserver: self
selector: @selector(selectNextWorkspace)
name: NOTIFICATION_NEXTWORKSPACE
object: nil
];
[[NSDistributedNotificationCenter defaultCenter] addObserver: self
selector: @selector(selectPreviousWorkspace)
name: NOTIFICATION_PREVWORKSPACE
object: nil
];
To control all the windows in the system, an application needs to have access to
the CGSUniversalConnection; only one application can have that at a
given time, and the Dock tends to win the battle. Desktop Manager sneakily uses
mach_inject to inject its own code into the Dock
application. There's still no x86 version of the sweet, sweet mach_inject library (Wolf! Help us!), so
not all the Desktop Manager features will not work on Intel.
Reading the sensor
For the actual sensor reading, I used amstracker by Amit Singh. He does not allow redistribution, so you'll have to get it directly from the source.
notify: Remote control for Desktop Manager
This 15-line program lets you send random notifications to any running application.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
[[NSAutoreleasePool alloc] init];
if(argc != 2) {
NSLog(@"Use: %s notification-name", argv[0]);
return 1;
}
[[NSDistributedNotificationCenter defaultCenter]
postNotificationName: [NSString stringWithCString: argv[1]]
object: nil];
return 0;
}
Compile it with gcc -framework Foundation -o notify notify.m, then call it with
./notify SwitchToNextWorkspace.
Actual motion interpreter
You can do arbitrarily fancy stuff here; this 10-line Perl script
just checks to see if the horizontal acceleration exceeds some threshold in
either direction, and calls the notify program.
use strict;
my $stable;
open F,"./AMSTracker -s -u0.01 |";
while(<F>) {
my @a = /(-?\d+)/g;
print, next if @a != 3;
# we get a signed short written as two unsigned bytes
$a[0] += 256 if $a[0] < 0;
my $x = $a[1]*256 + $a[0];
if(abs($x) < 20) {
$stable++;
}
if(abs($x) > 30 && $stable > 30) {
$stable = 0;
my $foo = $x < 0 ? 'Prev' : 'Next';
system "./notify SwitchTo${foo}Workspace\n";
}
}
Summary
Here's a self-contained zip file of the above patches.- Install and run the patched DesktopManager
- Download and unzip the zip file above (I just updated it with a binary version of
notify, so you'll have to re-download it) - Download
amstrackerfrom osxbook.com (I'm not allowed to redistribute it) - Place the
amstrackerbinary in the directory where you unzipped smackbook.zip. - You should have a directory with the files
amstracker,notifyandsmack.pl. From the terminal, in that directory, run the commandperl smack.pl