Taming Snow Leopard: CGDisplayBestModeForParameters deprecation

We used to have a cool function that would give us the best match for a given resolution, it’s deprecated so let’s work around it. Again Apple failed to provide a documented example so here is one:

struct screenMode {
    size_t width;
    size_t height;
    size_t bitsPerPixel;
};

- (size_t) displayBitsPerPixelForMode: (CGDisplayModeRef) mode {
	
	size_t depth = 0;
	
	CFStringRef pixEnc = CGDisplayModeCopyPixelEncoding(mode);
	if(CFStringCompare(pixEnc, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
		depth = 32;
	else if(CFStringCompare(pixEnc, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
		depth = 16;
	else if(CFStringCompare(pixEnc, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
		depth = 8;
	
	return depth;
}

- (CGDisplayModeRef) bestMatchForMode: (struct screenMode) screenMode {
	
	bool exactMatch = false;
	
    // Get a copy of the current display mode
	CGDisplayModeRef displayMode = CGDisplayCopyDisplayMode(kCGDirectMainDisplay);
	
    // Loop through all display modes to determine the closest match.
    // CGDisplayBestModeForParameters is deprecated on 10.6 so we will emulate it's behavior
    // Try to find a mode with the requested depth and equal or greater dimensions first.
    // If no match is found, try to find a mode with greater depth and same or greater dimensions.
    // If still no match is found, just use the current mode.
    CFArrayRef allModes = CGDisplayCopyAllDisplayModes(kCGDirectMainDisplay, NULL);
    for(int i = 0; i < CFArrayGetCount(allModes); i++)	{
		CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i);

		if([self displayBitsPerPixelForMode: mode] != screenMode.bitsPerPixel)
			continue;
		
		if((CGDisplayModeGetWidth(mode) >= screenMode.width) && (CGDisplayModeGetHeight(mode) >= screenMode.height))
		{
			displayMode = mode;
			exactMatch = true;
			break;
		}
	}
	
    // No depth match was found
    if(!exactMatch)
	{
		for(int i = 0; i < CFArrayGetCount(allModes); i++)
		{
			CGDisplayModeRef mode = (CGDisplayModeRef)CFArrayGetValueAtIndex(allModes, i);
			if([self displayBitsPerPixelForMode: mode] >= screenMode.bitsPerPixel)
				continue;
			
			if((CGDisplayModeGetWidth(mode) >= screenMode.width) && (CGDisplayModeGetHeight(mode) >= screenMode.height))
			{
				displayMode = mode;
				break;
			}
		}
	}
	return displayMode;
}

Now, now Apple, this was a lot easier before

Advertisements
Tagged with: ,
Posted in Code
3 comments on “Taming Snow Leopard: CGDisplayBestModeForParameters deprecation
  1. Tom says:

    Your code is leaking the return value from CGDisplayCopyDisplayMode()

  2. lukassen says:

    You’re absolutely right, i call this code only on startup so i hadn’t noticed since there were more significant parts to fix.

    Thanks for the pointer!

  3. […] Taming Snow Leopard: CGDisplayBestModeForParameters deprecation January 2010 2 comments […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories
%d bloggers like this: