a programmer's thoughts

Menu

Exploring Apple’s customization of titlebar in Xcode 4

As you may have noticed, Xcode’s NSWindow does not actually have a single representedURL; it has two, the project and the current in-project file.

So how did Apple achieve that?

First things first, you can start figuring that out by yourself by asking your window’s contentView for its superview. Although undocumented, enough apps seem to be playing around with this (including Xcode) that I presume Apple would be reluctant to change something important here.

Second, I’m not going to actually show you any code just yet. Perhaps in a future blog post; I did start writing something, but it’s unfinished.

Third, there is no third: let’s get to it.

Hacking tools

Playing with contentView‘s superviews can only get you so far (although, you may be able to hack something anyway). Injecting code in form of plugins into Xcode is possible, as proven by JugglerShu’s XVim.

But there’s a nicer way.

Say hello to F-Script. It’s a nice scripting language and let’s-call-it mini-IDE in itself, but there’s something far more powerful it can do.

On F-Script

It has a full fledged object browser that uses introspection to figure out what the hell exists in the view hierarchy. It also has a nice view picker so you can easily access the exact view that you’re playing with. Python may be neat for programming, but this one is just smashing for debugging GUI apps.

F-Script is not intended to be used as a standalone dev environment however; you’re supposed to put it into your app and use it at runtime. Kind of like what you can do with Python already… except this one comes with a runtime debugging GUI out of the box (and the aforementioned view picker!), and is pretty dedicated to playing with Cocoa and Objective-C (while Python can play with it through its PyObjC bridge – powerful, but not the best way to do it; also, method names become lengthy and weird when written in Python).

Note that I, for now, have absolutely no experience with F-Script as a programming language, and I don’t intend to learn it too much for now, just as I don’t intend to learn all nuts and bolts of GDB. It may be nice, but for now, it’s far, far, far more amazing as a debugging tool.

Okay, so where does playing with Xcode come in?

Unfortunately, not in the form of injecting the debugging code into Xcode and playing with it. This is the loveliest part of F-Script, however; you can inject it into any app and inspect how it works, see runtime class definitions, send messages to existing objects, etc. But not with Xcode, because of some magic that Xcode is doing causing F-Script to crash Xcode.

Finding the beast

Let’s get back to business. Although Xcode crashes, view inspector of F-Script works long enough to let us know the name of the class implementing the custom view Apple uses in the titlebar for displaying two “represented URLs”. A-ha! DVTDualProxyWindowTitleView, we’ve found you!

Now, where could this be defined? Let’s explore various private frameworks found in Xcode using class-dump (install it from MacPorts). And voila! Xcode.app/Contents/SharedFrameworks/DVTKit.framework. Using class-dump we can also see that it’s used in… DVTDualProxyWindow, a subclass of NSWindow. Wonderful!

Now, just trying to load this framework into standalone F-Script.app fails miserably and returns NO. At least for me. otool -L told me which frameworks this one depends on… so I loaded them first.

About the beast

Finally, DVTDualProxyWindow is a subclass of NSWindow which apparently overrides -setTitle: to do nothing, overrides -setRepresentedURL: to be used for the ‘project’ URL, and defines new method -setSecondaryRepresentedURL: to add the ‘document’ URL. Both of these methods are just talking to DVTDualProxyWindowTitleView. We don’t really care what happens behind the scenes; it’s just a regular view. But let’s see if it works.

Open F-Script app. Right click on the toolbar and choose ‘Customize’. Aside from customization sheet, a new window appears titled ‘Custom Buttons’. Pick one of ‘CustomX’ buttons, and select ‘Block…’. (Of course, prior to that, in the toolbar customization sheet, drag the picked button to the toolbar… you know, so you can click it.)

IMPORTANT! To be able to proceed, you need to solve the following simple math (so we know that you are a human) :-)

Support me!

Need a host with root access over SSH where you can deploy a blank machine within 60 seconds? Need a host billed per hour, that costs only $5/month (that's less than a cent per hour)? Try Digital Ocean!