Investigating a high resolution / retina utility for MacBook Pro 1x and 2x modes

I am thoroughly enjoying the pixels on the new MacBook Pro. Can pretty much do all multi-monitor configurations I need/use/want on a Mac using the one screen. Only problem is this is using a combination of +/- 1.5x 1920×1200 (my default workable resolution for years — previous MBP was a 17″ and prior to that I was on a combination of Wintel laptops with similar) and all-out 1x 2880×1800 (which is fucking wonderful) and having to switch between the two (the latter not having a convenient system preference). So, I set about investigating the possibility of writing an OS X utility / menu bar app to help do the work for me…

Enumerating NSScreen gets interesting results. E.g. this:

1 2 3 4 5 6 7 8 9 10 11
NSArray *screens=[NSScreen screens];
for(NSScreen *s in screens)
{
NSLog(@"\n");
NSLog(@"description: %@", s.description);
NSLog(@"backing scale factor: %f", s.backingScaleFactor);
NSLog(@"frame %@", NSStringFromRect(s.frame));
NSLog(@"visibleFrame %@", NSStringFromRect(s.visibleFrame));
NSLog(@"device description: %@", s.deviceDescription);
NSLog(@"------------------------------------\n\n");
}
view raw gistfile1.m hosted with ❤ by GitHub

Nets this:

1 2 3 4 5 6 7 8 9 10 11 12 13
2012-07-01 21:16:37.979 Retina Resolution Menu[72064:403]
2012-07-01 21:16:37.979 Retina Resolution Menu[72064:403] description: <NSScreen: 0x7f870a903730>
2012-07-01 21:16:37.981 Retina Resolution Menu[72064:403] backing scale factor: 2.000000
2012-07-01 21:16:37.981 Retina Resolution Menu[72064:403] frame {{-1920, 240}, {1920, 1200}}
2012-07-01 21:16:37.981 Retina Resolution Menu[72064:403] visibleFrame {{-1916, 240}, {1916, 1200}}
2012-07-01 21:16:37.982 Retina Resolution Menu[72064:403] device description: {
NSDeviceBitsPerSample = 8;
NSDeviceColorSpaceName = NSCalibratedRGBColorSpace;
NSDeviceIsScreen = YES;
NSDeviceResolution = "NSSize: {144, 144}";
NSDeviceSize = "NSSize: {1920, 1200}";
NSScreenNumber = 69731264;
}
view raw gistfile1.txt hosted with ❤ by GitHub

However, inspecting from CGDisplayMode isn’t so fruitful:

(Based pretty much entirely on the Quartz Display Services doc here)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
CGDirectDisplayID displays[MAX_DISPLAYS];
uint32_t numDisplays;
uint32_t i;
CGGetActiveDisplayList(MAX_DISPLAYS, displays, &numDisplays);
for(i=0; i<numDisplays; i++)
{
CGDisplayModeRef mode;
CFIndex index, count;
CFArrayRef modeList;
modeList=CGDisplayCopyAllDisplayModes(displays[i], NULL);
count=CFArrayGetCount(modeList);
NSLog(@"\n\nmode --");
for(index=0;index<count;index++)
{
mode=(CGDisplayModeRef)CFArrayGetValueAtIndex(modeList, index);
long h=0, w=0;
h=CGDisplayModeGetHeight(mode);
w=CGDisplayModeGetWidth(mode);
uint32_t flags=CGDisplayModeGetIOFlags(mode);
NSLog(@"flags: %d", flags);
NSLog(@"w, h: %ld, %ld", w, h);
//test mode here against required params and set, using:
//CGDisplaySetDisplayMode(displays[i], mode, NULL);
}
CFRelease(modeList);
}
view raw gistfile1.m hosted with ❤ by GitHub

Nets this:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
2012-07-01 21:20:11.693 Retina Resolution Menu[72088:403] w, h: 2880, 1800
2012-07-01 21:20:11.693 Retina Resolution Menu[72088:403] w, h: 2880, 1800
2012-07-01 21:20:11.694 Retina Resolution Menu[72088:403] w, h: 1440, 900
2012-07-01 21:20:11.694 Retina Resolution Menu[72088:403] w, h: 1440, 900
2012-07-01 21:20:11.694 Retina Resolution Menu[72088:403] w, h: 2560, 1600
2012-07-01 21:20:11.695 Retina Resolution Menu[72088:403] w, h: 2560, 1600
2012-07-01 21:20:11.695 Retina Resolution Menu[72088:403] w, h: 2048, 1280
2012-07-01 21:20:11.695 Retina Resolution Menu[72088:403] w, h: 2048, 1280
2012-07-01 21:20:11.696 Retina Resolution Menu[72088:403] w, h: 1024, 768
2012-07-01 21:20:11.696 Retina Resolution Menu[72088:403] w, h: 1024, 768
2012-07-01 21:20:11.696 Retina Resolution Menu[72088:403] w, h: 800, 600
2012-07-01 21:20:11.703 Retina Resolution Menu[72088:403] w, h: 800, 600
2012-07-01 21:20:11.703 Retina Resolution Menu[72088:403] w, h: 640, 480
2012-07-01 21:20:11.704 Retina Resolution Menu[72088:403] w, h: 640, 480
2012-07-01 21:20:11.704 Retina Resolution Menu[72088:403] w, h: 1680, 1050
2012-07-01 21:20:11.704 Retina Resolution Menu[72088:403] w, h: 1680, 1050
2012-07-01 21:20:11.705 Retina Resolution Menu[72088:403] w, h: 1280, 800
2012-07-01 21:20:11.705 Retina Resolution Menu[72088:403] w, h: 1280, 800
view raw gistfile1.txt hosted with ❤ by GitHub

Which doesn’t seem to relate to anything useful — in fact it really doesn’t. It’s a list of the 1x resolutions you can force the display into. Setting one of those (using CGDisplaySetDisplayMode or CGConfigureDisplayWithDisplayMode) will switch the display into a 1x mode with the specified resolution. A great way of getting it into native 2880×1800 mode (though I was already using SetResX for that).

Next thing I stumbled upon was that if you go to /System/Library/Displays/Overrides/DisplayVendorID-610 and grep ‘ 2x’ * you see this:

1 2 3 4 5 6 7 8 9 10 11 12 13 14
DisplayProductID-a00e: <data>AAAPAAAACWAAAAAJAKAAAA==</data> <!-- 3840x2400 mirror external panels to internal (include 2x) -->
DisplayProductID-a00e: <data>AAANIAAACDQAAAAJAKAAAA==</data> <!-- 3360x2100 mirror external panels to internal (include 2x) -->
DisplayProductID-a00e: <data>AAALQAAABwgAAAAJAKAAAA==</data> <!-- 2880x1800 mirror external panels to internal (include 2x) -->
DisplayProductID-a00e: <data>AAAKAAAABkAAAAAJAKAAAA==</data> <!-- 2650x1600 mirror external panels to internal (include 2x) -->
DisplayProductID-a00e: <data>AAAHgAAABLAAAAAJAKAAAA==</data> <!-- 1920x1200 mirror external panels to internal (include 2x) -->
DisplayProductID-a00e: <data>AAAHgAAABDgAAAAJACAAAA==</data> <!-- 1920x1080 mirror external panels to internal 1080p (no 2x) -->
DisplayProductID-a00e: <data>AAAFAAAAAtAAAAAJACAAAA==</data> <!-- 1280x720 mirror external panels to internal 720p (no 2x) -->
DisplayProductID-a00f: <data>AAAPAAAACWAAAAAJAKAAAA==</data> <!-- 3840x2400 mirror external panels to internal (include 2x) -->
DisplayProductID-a00f: <data>AAANIAAACDQAAAAJAKAAAA==</data> <!-- 3360x2100 mirror external panels to internal (include 2x) -->
DisplayProductID-a00f: <data>AAALQAAABwgAAAAJAKAAAA==</data> <!-- 2880x1800 mirror external panels to internal (include 2x) -->
DisplayProductID-a00f: <data>AAAKAAAABkAAAAAJAKAAAA==</data> <!-- 2650x1600 mirror external panels to internal (include 2x) -->
DisplayProductID-a00f: <data>AAAHgAAABLAAAAAJAKAAAA==</data> <!-- 1920x1200 mirror external panels to internal (include 2x) -->
DisplayProductID-a00f: <data>AAAHgAAABDgAAAAJACAAAA==</data> <!-- 1920x1080 mirror external panels to internal 1080p (no 2x) -->
DisplayProductID-a00f: <data>AAAFAAAAAtAAAAAJACAAAA==</data> <!-- 1280x720 mirror external panels to internal 720p (no 2x) -->
view raw gistfile1.xml hosted with ❤ by GitHub

Which is more interesting if you look at the content of one of those files, e.g.:

1 2 3 4 5 6 7 8 9
<plist version="1.0">
<dict>
<key>IOGFlags</key>
<integer>4</integer>
<key>scale-resolutions</key>
<array>
<!-- internal panel modes AND modes mirroring external panels (but not kDisplayModeValidForMirroringFlag) " -->
<!-- This list includes sizes that overlap between and preferred sizes the internal panel and common matches for external displays" -->
<!-- If the internal panel does not need a sizes then set kDisplayModeValidForMirroringFlag and move them down to that list " -->
view raw gistfile1.xml hosted with ❤ by GitHub

e.g. — (being) that those are specifically IOFlags.

In this thread on macrumours.com it’s noted that SwitchResX caused issues because one of the above files vanished — and the system was subsequently not able to provide anything other than 1x resolutions.

Presumption (certainly not a conclusion — this the first bit of under the hood poking around I’ve done in OS X) is that there’s something happening that’s not publically exposed, but for legacy support (games that set full screen device resolution modes spring to mind), the old behaviour of CGDisplay… is retained. NSScreen (and window, etc) obviously have extensive support — it’s just presented around CGDisplay. NSUserDefaults in the NSGlobalDomain also fails to provide access to whatever it is that System Preferences is doing.

And then…

I found the updated version of SetResX on reddit, now called RetinaDisplay Menu and conveniently including source code (thanks
http://www.phoenix-dev.com/). Above presumption is pretty much confirmed — it seems to be dynamically linking to the private API method CGSGetDisplayModeDescriptionOfLength and building the structure required to contain the results (including the particularly pertinent float density — e.g. scale). Then using CGSConfigureDisplayMode to actually make the mode change (instead of CGConfigureDisplayWithDisplayMode).

Conclusion?

Go get Retina DisplayMenu (linked from reddit). It does what I set about doing, and it seems to work right now. Unlikely we’ll see it on the Mac App Store due to the private API calls (which is what I was hoping to be able to do with a utility in the first place), but it’s no major hassle to download, place somewhere convenient and add it to your user/login items preferences.

Additional resources

For the application level stuff, best resources so far are:

No comments yet.

Add Comment