Search code examples
objective-ccocoaquartz-graphics

How to Get the Display Name with the Display ID in Mac OS X?


I was wondering if you could help me figure out how to progmatically get the Display Name for a monitor by using its Display ID number in Mac OS X (10.5)? A requirement is if I give a function the Display ID, it'll provide the Display Name in return (or vice versa).

Display Name looks something like this: "Color LCD", "SAMSUNG"

Display ID looks something like this: "69671872", "893830283"

NSScreen in Cocoa (Obj-C), or CGGetActiveDisplayList in Quartz (C), allow you to get the Display ID number for a monitor. Neither appear to have a method to get the Display Name. Oh no! Here's the code for NSScreen to get the Display ID:

NSArray *screenArray = [NSScreen screens];
NSDictionary *screenDescription = [[screenArray objectAtIndex:0] deviceDescription];
NSLog(@"Device ID: %@", [screenDescription objectForKey:@"NSScreenNumber"]);

System Profiler, and Displays under System Preferences, reference displays by Display Name, not Display ID.

I'm asking as I want to run an AppleScript, and it requires a Display Name rather than a Display ID. Any help is MUCH appreciated! :)


Solution

  • This gives you the localized display name:

    static void KeyArrayCallback(const void* key, const void* value, void* context) { CFArrayAppendValue(context, key);  }
    
    - (NSString*)localizedDisplayProductName
    {
        NSDictionary* screenDictionary = [[NSScreen mainScreen] deviceDescription];
        NSNumber* screenID = [screenDictionary objectForKey:@"NSScreenNumber"];
        CGDirectDisplayID aID = [screenID unsignedIntValue];            
        CFStringRef localName = NULL;
        io_connect_t displayPort = CGDisplayIOServicePort(aID);
        CFDictionaryRef dict = (CFDictionaryRef)IODisplayCreateInfoDictionary(displayPort, 0);
        CFDictionaryRef names = CFDictionaryGetValue(dict, CFSTR(kDisplayProductName));
        if(names)
        {
            CFArrayRef langKeys = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
            CFDictionaryApplyFunction(names, KeyArrayCallback, (void*)langKeys);
            CFArrayRef orderLangKeys = CFBundleCopyPreferredLocalizationsFromArray(langKeys);
            CFRelease(langKeys);
            if(orderLangKeys && CFArrayGetCount(orderLangKeys))
            {
                CFStringRef langKey = CFArrayGetValueAtIndex(orderLangKeys, 0);
                localName = CFDictionaryGetValue(names, langKey);
                CFRetain(localName);
            }
            CFRelease(orderLangKeys);
        }
        CFRelease(dict);
        return [(NSString*)localName autorelease];
    }