Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CGDisplayCopyAllDisplayModes leaves out one valid mode

When programmatically working with display modes in OS X (documentation), I've found that the CGDisplayCopyAllDisplayModes leaves out the rightmost option that is presented in System Preferences.

A simple utility that prints the size of the current display mode and all available display mode sizes outputs this

current size: 1920x1200
available sizes:
2880x1800
1440x900
2560x1600
2048x1280
1024x768
800x600
640x480
1680x1050
1280x800

1920x1200 is a valid option enter image description here

All of the other options that System Preferences gives are represented in the list. Does anyone have any idea why 1920x1200 may not be included? I have tried changing to another one of the pre-defined values in system prefs, but it did not cause 1920x1200 to be included.

Edit (the accepted answer is much better than these shenanigans, but I'm leaving this info just in case)

The "scaled" display modes can be found by referencing a private API.

You can create a header file that makes the private methods available: see this gist that I borrowed from this project.

Then you can see all modes, including the scaled ones like this

print("Private modes:\n")

var numDisplayModes: Int32 = 0
CGSGetNumberOfDisplayModes(mainDisplayID, &numDisplayModes)
print("Num modes \(numDisplayModes)")

for i in 0...(numDisplayModes-1) {
    var pmode: CGPrivDisplayMode = CGPrivDisplayMode()
    CGSGetDisplayModeDescriptionOfLength(mainDisplayID, CInt(i), &pmode, CInt(sizeof(CGPrivDisplayMode)))
    
    print("\t\(pmode.modeNumber): \(pmode.width)x\(pmode.height) -- \(pmode.density)  \n")
}
like image 757
wmarbut Avatar asked Jun 16 '15 05:06

wmarbut


1 Answers

There's public API that's only documented in the header. CGDisplayCopyAllDisplayModes() takes an options parameter, which is a dictionary. The docs (and even the headers) say that it's unused and you must pass NULL, but you can pass a dictionary with the key kCGDisplayShowDuplicateLowResolutionModes and value kCFBooleanTrue.

The option name is not really clear. It includes a bunch of extra modes.

Also, you may need to use CGDisplayModeGetPixelWidth() and CGDisplayModeGetPixelHeight() to distinguish between the point size and the pixel size of the backing store. (CGDisplayModeGetWidth() and CGDisplayModeGetHeight() return point size. By comparing those values, you can determine if the mode is scaled.)

like image 59
Ken Thomases Avatar answered Nov 18 '22 04:11

Ken Thomases