In Mac OS X, every display gets a unique CGDirectDisplayID
number assigned to it. You can use CGGetActiveDisplayList(
) or [NSScreen screens]
I have found no conceputally better way than what you list as "Tried". But I found a solution for the ambiguity issue of comparing only vendor id and product id.
oldInfoDict
and newInfoDict
in your code contain an additional entry for key kIODisplayEDIDKey
(defined in IOGraphicsTypes.h) which contains the EDID of each connected display. My observations show that this data as a whole stays persistent between GPU switches. For example:
CGDirectDisplayID displayId = [[[screen deviceDescription] valueForKey:@"NSScreenNumber"] unsignedIntValue];
io_service_t displayPort = CGDisplayIOServicePort(displayId);
if (displayPort == MACH_PORT_NULL)
return nil; // No physical device to get a name from.
CFDictionaryRef infoDict = IODisplayCreateInfoDictionary(displayPort, kIODisplayOnlyPreferredName);
NSData *displayEdid = (NSData *)CFDictionaryGetValue(infoDict, CFSTR(kIODisplayEDIDKey));
NSLog(@"EDID: %@", displayEdid);
CFRelease(infoDict);
Looking at the data description of EDID in Wikipedia, this blob already contains manufacturer, product id and serial. So it's enough to compare displays by using the EDID data (or for example a hash of it if you only want to compare a shorter number).