The Strange Case of the OS X System Preferences Window Width

The OS X System Preferences app is something like a wrapper app. In itself, it doesn’t do more than to present all installed system preference panes and these panes then allow you to configure your OS X installation. In addition to system-provided preference panes that come with OS X, additional preference panes can be installed by the user, or by applications.

Xcode comes with a template for such custom preference panes and there is a Preference Pane Programming Guide. Custom preference panes aren’t full-scale applications but rather a user interface to adjust some settings, wrapped in a bundle, so they can’t be distributed via the Mac App Store as such, but could only be an accessory to an application. It might be for this reason that custom preference panes don’t seem to be too popular nowadays.

When I prepared a preference-pane-only app recently, I stumbled upon one inconsistency in Apple’s Preference Pane Programming Guide. The guide states in its section “The Preference Application”, as does the Xcode template, that the

System Preferences window has a fixed width (668 pixels)[.]

and fancies to also give another value in its section “Creating a Preference Pane Bundle”:

For System Preferences, the window should not be more than 595 pixels wide.

Both values didn’t match with what I saw on my computer, so I investigated the issue. Apparently, the System Preferences window on my computer running OS X El Capitan was considerably wider than 668 (or even 595) pixels. Some research later it turned out that the width of the System Preferences window depends on the system language: The window will be 668 pixels wide when English is the primary language, but will have a different width for other languages. For example, with German set as primary language, as it is on my computer, the window is 762 pixels wide:

prefpanewidth

Setting the language to Russian, it is 780 pixels wide, setting it to Italian, it is 750 pixels wide etc. I checked previous OS X versions and found that this flexible-width approach is around since OS X Yosemite, but is still not mentioned in any Apple documentation. While Apple’s preference panes that come with OS X dynamically adjust their width to the actual width of the System Preferences window, this is not true for any custom preference pane, that will instead be displayed centered with more or less wide blank margins. For example, the popular Growl app comes with a custom preference pane that on my computer with German system language displays like this:

growl

This doesn’t look too professional so I thought of making my preference pane dynamically resize itself, as do the system-provided preference panes. As the Preference Pane Programming Guide still assumes that preference panes have a fixed width (while it isn’t too sure about which width this is, see above), it naturally doesn’t mention any way how to achieve this. Also, the NSPreferencePane class that is to be used to implement a custom preference pane doesn’t offer any way to retrieve the actual width of the system preferences window.

I then came up with a solution which takes advantage of the fact that the code of the custom preference pane will be executed by the System Preferences app and will therefore also have its process identifier. We can now use this process identifier to read out the width of its window from the obscure Quartz Window Services CGWindowListCopyWindowInfo function. This is what below snippet does:

-(float)preferenceWindowWidth
{
    float result = 668.0; // default in case something goes wrong
    NSMutableArray *windows = (NSMutableArray *)CFBridgingRelease(CGWindowListCopyWindowInfo
      (kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID));
    int myProcessIdentifier = [[NSProcessInfo processInfo] processIdentifier];
    BOOL foundWidth = NO;
    for (NSDictionary *window in windows) {
        int windowProcessIdentifier = [[window objectForKey:@"kCGWindowOwnerPID"] intValue];
        if ((myProcessIdentifier == windowProcessIdentifier) && (!foundWidth)) {
            foundWidth = YES;
            NSDictionary *bounds = [window objectForKey:@"kCGWindowBounds"];
            result = [[bounds valueForKey:@"Width"] floatValue];
        }
    }
    return result;
}

In the mainViewDidLoad method of the custom preference pane code we can use the retrieved width value to resize the width of our preference pane’s main view:

-(void)mainViewDidLoad
{
    NSSize size = self.mainView.frame.size;
    size.width = [self preferenceWindowWidth];
    [[self mainView] setFrameSize:size];
}

I’ve filed a bug report with Apple to at least update the Preference Pane Programming Guide.

Apps without Interfaces

Software without user interfaces is cool. This is about minimalism and “one thing well” and “keep it simple” and “less is more” and about less distraction: If we assume that software typically presents at least some information to the user, it follows that applications without real user interfaces will have to use UI elements which are already present, provided either by the operating system or by other running applications.

Continue reading “Apps without Interfaces”

Brow: Programming in the Age of the Sandbox

On June 1, Apple will enforce Sandboxing for all new apps on the Mac App Store. It has been already widely discussed how this will affect developers and especially certain types of apps. Not least Utility apps which need to have a wide file system access or which are a kind of system service without a real user interface will have hard times making it in the Mac App Store now. I found it a fascinating idea to start a new programming project with exactly this kind of app in mind, just for the reason of testing the limits of how far one can go inside the sandbox. And for the reason that my two existing apps still need to be migrated to the sandbox.

Continue reading “Brow: Programming in the Age of the Sandbox”

Things I don’t like about feed readers

Mac RSS feed reader apps are a booming software genre. Every few months a new powerful app is published, with a polished interface and lots of cool functions. I argue that feed reader apps shouldn’t be designed as if they had to cover complicated issues but that they should be tiny and neat tools giving me the information I need, as fast as possible and as easily as possible. I don’t like rocket-science, sophisticated readers, I’m looking for a really, really simple reader app which holds the balance between “too sophisticated” and “too minimalistic”, which is just functional (and beautiful).

Continue reading “Things I don’t like about feed readers”

Strange Kind of Focus Ring

According to Apple’s Human Interface Guidelines for OS X (HIG), a focus ring is “Highlighting around onscreen area that is ready to accept user input.”. It is shown as a blue bezel around that control which has the keyboard focus. As I tried to implement a secondary source list today with a gradient button bar resembling this example (no, there is no focus ring visible in the picture):

Continue reading “Strange Kind of Focus Ring”