Leopard CGWindowList* APIs

Leopard brings new APIs at the CoreGraphics layer to gather information about windows on the system. These functions let you find windows relative to a known window, find all windows on the system, including those offscreen, and obtain images of one or more windows as composited by the Window Server.

However, these API’s have an interesting peculiarity: when the documentation says “a CFArray of CGWindowID values” they mean a CFArray of uint32s, not CFNumbers as programmers familiar with CoreFoundation might expect. This holds true for the CGWindowListCreate(), CGWindowListCreateDescriptionFromArray(), and CGWindowListCreateImageFromArray functions, but the two functions that return window information (CGWindowListCopyWindowInfo() and CGWindowListCreateDescriptionFromArray()) wrap all numeric values in CFNumbers.

To create such an array, you’ll have to create it with CFArrayCreateMutable(), such as the following:

/* Make an array with no callbacks */
CFMutableArrayRef windows = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);

/* myWindow is a NSWindow */
CFArrayAppendValue(windows, (void *)[myWindow windowNumber]);

To get the CGWindowID of a NSWindow, you’ll want to use -[NSWindow windowNumber]. Even though the documentation specifies that this isn’t the same number as assigned by the WindowServer, it turns out that it works fine with the CGWindow* APIs.

Posted in Leopard, Programming | 1 Comment

Time Machine Menu

The Time Machine application, when in the dock, enables access to functions for showing Time Machine, backing up now, stopping an existing backup, browsing other Time Machine disks and showing Time Machine preferences. If you’re like me, you’d like access to these features without the app in the dock; unfortunately, you can’t — by default.

I’ve done a bit of digging and was able to implement all but one of these features in a menu extra. Download it and the source here.

And yes, the menu icon doesn’t scale nicely :)

Posted in Leopard, Programming | 4 Comments

Time Machine Exclusions

So Time Machine is a pretty convenient way to backup your machine, and I use it to backup my laptop to an external FireWire drive. Although Time Machine backs up the “whole system,” I assumed there had to be some exclusions, such as cache files or /dev, for example. After a short bit of digging, I discovered that these paths are specified in a standard property list at /System/Library/CoreServices/backupd.bundle/Contents/Resources/StdExclusions.plist

The full list is some 57 items, and is available below. Besides the expected cache items, the list includes some items I thought interesting:

/home
*/Library/Logs
/Users/Guest
/Library/Safari/Icons.db
/.Spotlight-V100

Of these, the only one I find odd is the exclusion of logs. If your system goes haywire such that you restore it completely from a backup, it might be nice to see what went wrong.

[Update] Fixed the path to the StdExclusions.plist file.

Continue reading

Posted in Leopard | 39 Comments

Quicksilver Plugins

As the Quicksilver site seems to be down right as everyone is reinstalling for Leopard, I’ve packaged the plugins I have into a zip available here. Quicksilver itself is available here. To install, just put the PlugIns folder in your Library/Application Support/Quicksilver folder or double click the plugins.

[Update] Zon Wakest was nice enough to upload additional plugins. Thanks Zon! These are now added into my archive and the combined list is below. If you got the old archive, download just the additional plugins.

[Update2] Quicksilver now links to 3814 instead of 3813.

The plugins included are as follows:

Continue reading

Posted in General | 51 Comments

Pointless Optimization

The other day I needed to write a function to give me a formatted string representation of a quantity of bytes. Pretty trivial function, but nontheless, I found myself optimizing it. I ended up with the following:

static uint64_t count = 7;
static NSString *suffixes[7] = 
    { @"B", @"KiB", @"MiB", @"GiB", @"TiB", @"PiB", @"EiB"};
uint64_t i, c;
for (i = 1024, c = 0; i < (count << 60); i <<= 10, c++) {
    if (bytes < i) 
        return [NSString stringWithFormat:  @"%0.2f%@", 
                                            (double)bytes / (double)(i >> 10), 
                                            suffixes[c]];
}
return @"Big";

Now, optimizing away divisions (except for the final conversion to string) really doesn’t save any time at all. The creation and subsequent autorelease of a NSString will take far longer than the division operations, even for large byte counts. Thus, I believe this code sample qualifies as pointless optimization, although it was entertaining to write.

Posted in Programming | Leave a comment

Color Setting Performance

If you’re looking to eek some extra performance out of your drawing code, take a look at how you’re setting your fill and stroke colors. Setting the color using CGContextSetRGBFillColor() or creating a new CGColorRef/NSColor object each time you set the color is quite expensive to do each time you draw. Depending on how many colors you use in your drawing, consider caching the CGColorRef objects and using CGContextSetFillColorWithColor() or -[NSColor setFill] instead.

A CGColorRef is 48 bytes for a RGB color. A NSColor is 32 bytes for a RGB color, plus 48 bytes for a CGColorRef. If you can afford the memory hit, you’ll see quite a bit of speed improvement from caching colors.

Below is the output from a small test app (source available here) that tests various color setting methods: (Each test is 1,000,000 iterations.)

CGContextSetRGBFillColor: 4.368422 seconds
CGContextSetFillColorWithColor, static CGColorRef: 0.599552 seconds
-[NSColor setFillColor], static NSColor: 0.832328 seconds
-[NSColor setFillColor], dynamic NSColor: 5.847799 seconds

Posted in Programming | Leave a comment

It’s all about the bits

So the idea here is to talk about programming, all the way down to the nitty-gritty: the bits we all know and love. In particular, I intend to focus on lower-level topics, such as what a piece of code actually does, rather than architecture and design. I’m passionate about performance, so you’ll find both rants about performance problems I come across and discussions of work I’ve done to speed things up when I can. A lot can be done with a computer, but to keep it real, it’s all about the bits :)

Posted in General | Leave a comment