If you’re a Mac developer you’re no doubt feeling that restlessness that comes when a major new OS release is nigh. Mac OS X 10.10 Yosemite has been cycling through “GM Candidate” releases for the past couple weeks, and many people seem to think it’s likely to be released to the public later this month.
One of the big user-facing visual changes is an optional “dark mode,” accessible from the General tab of System Preferences. When a user ticks this on, high level UI elements such as the menu bar and dock adopt a different style of drawing which you can roughly characterize as being white-on-black instead of the default black-on-white Mac appearance.
One hiccup for developers of third party apps is if you have an NSStatusItem or other custom menu bar item with a custom icon, you probably designed it so that it looks good on the white or light default menu bar.
Unfortunately, Apple has not provided a sanctioned method for detecting whether the user has switched to “dark mode,” so it’s non-trivial to tune your art to suit each of the modes at runtime. Instead, Apple recommends that all such icons should be designed such that Apple can effectively color them as appropriate for the current mode.
Luckily it’s pretty easy to get this behavior for custom status bar icons. You probably already call -[NSStatusItem setIcon:yourImage] with your custom image. Now, just make sure to call -[yourImage setTemplate:YES], and you’re done. The only caveat I would add here is that Mac OS X 10.9 and earlier do not seem to respect the “template” attribute when drawing status items, so I think the safest bet is to check for 10.10 at runtime, and omit the call to setTemplate if you’re running any earlier system:
BOOL oldBusted = (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_9) if (!oldBusted) { // 10.10 or higher, so setTemplate: is safe [myIcon setTemplate:YES] }
Now your status item icon looks great on 10.10, where in fact its coloring may even be slightly altered in light mode, and in 10.9, where it looks, well, like it always did. Update: thanks to Rick Fillion and Will Cosgrove for explaining that my problems on 10.9 are probably because my image is not designed right for use as a template. I’ll leave the solution to that as an exercise for the writer.
Unfortunately, this promise does not hold true for regular NSMenuItem items that are installed at the highest level in the menu bar. These are relatively uncommon, but for example you might find some apps with a gear icon, a script icon, or other similar graphic in lieu of a text-based menu title. When an icon is supplied to such a menu item, the template nature is not meaningfully respected in dark mode, so the icon draws more or less as-is, and is likely to almost disappear because of the lack of contrast. If you happen to be running 10.10 you can witness this problem by running iTunes and seeing that at least one script is in ~/Library/iTunes/Scripts. Its script menu icon appears right next to the “Help” menu.
I reported the issue to Apple and it came back as a duplicate. As of the latest 10.10 GM candidate, it has not been fixed, but I got a reassuring tweet from Apple’s own Eric Schlegel today:
@danielpunkass Now fixed in AppKit; best advice is just to use a template image. When the fix is available, template images will just work.
— Eric Schlegel (@ericsc) October 9, 2014
So in summary, if you use icons as the “titles” of menus either inside or outside of the status bar area of the menu bar, be sure to call setTemplate:YES on it when running on 10.10. If you happen to have a menu bar icon affected by the bug I reported, I recommend creating a test project that installs an NSStatusItem with the same icon, so you can get a sense for how it’s going to look in dark mode when its template nature is suitably handled.