CGDISPlayIosErvicePort는 OS X>= 10.9에서 사용되지 않습니다. 교체 방법은 무엇입니까?

StackOverflow https://stackoverflow.com//questions/20025868

문제

여러 개의 모니터에서 화면 해상도를 신속하게 변경할 수 있도록 작은 앱을 사용했습니다.제품 이름을 모니터의 제목으로 표시 하고이 코드를 사용하는 것은 매우 간단합니다.

NSDictionary *deviceInfo = (__bridge NSDictionary *)IODisplayCreateInfoDictionary(CGDisplayIOServicePort(dispID), kIODisplayOnlyPreferredName);

NSDictionary *localizedNames = [deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];

if([localizedNames count] > 0) {
    _title = [localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]];
} else {
    _title = @"Unknown display";
}
.

그러나 CGDisplayIOServicePort는 OS X>= 10.9에서 사용되지 않으며 Apple의 문서는 교체가 없다고합니다.이 방법을 사용하지 않고 서비스 포트 또는 제품 이름을 찾는 방법은 무엇입니까?

io-registry를 통해 반복하려고 시도하고 IOServiceGetMatchingServices 메소드를 사용하여 디스플레이 서비스를 찾으려고하지만 솔루션을 찾을 수 없도록 IO 레지스트리에 익숙하지 않으므로 IO 레지스트리에 익숙하지 않습니다.

도움말 감사드립니다!

도움이 되었습니까?

해결책

@ eun의 게시물 이이 토론을 닫으려면 정보를 놓친 것처럼 보입니다. 조금 수색으로 ioservicePortFromCgDisplayID가 Apple이 제공하는 API가 아니라는 것을 발견했습니다. 오히려 여기에있는 오픈 소스 코드의 조각입니다. https://github.com/glfw/glfw/blob/e0a6772e5e4c672179fc69a90bcda3369792ed1f/src /cocoaa_monitor.m

ioserviceportFromCgDisplayID와 'GetDisplayName'을 복사했습니다. OS X 10.10에서 작업 할 두 가지 조정이 필요했습니다.

  1. IOSERVICEPortFromCgDisplayID에서 일련 번호를 처리하는 코드를 제거합니다. (CFDictionaryGetValue KDISPlaySerialNumber는 나를 위해 null을 반환합니다.)
  2. 프로젝트 제거 getDisplayName에서 코드 처리 코드.
  3. 더 많은 정보가 필요하면

    • 이슈 추적기 문제 추적기 : github.com/glfw/glfw/issues/165
    • commit. 솔루션의 경우 : github.com/glfw/glfw/commit/e0a6772e5e4c672179fc69a90bcda3369792ed1f

    나는 그곳에 코드를 제출 한 Matthew Henry에게 감사드립니다.

다른 팁

여기에이 문제가 발생합니다.GLFW 3.1, COCOA_MONITOR.M 파일에서 코드를 시작했습니다.
그러나 히로시가 말한 것처럼 다른 방식으로 그것을 수정해야했습니다. 그래서 여기에 간다 :

// Get the name of the specified display
- (NSString*) screenNameForDisplay: (NSNumber*) screen_id
{
    CGDirectDisplayID displayID = [screen_id unsignedIntValue];

    io_service_t serv = [self IOServicePortFromCGDisplayID: displayID];
    if (serv == 0)
        return @"unknown";

    CFDictionaryRef info = IODisplayCreateInfoDictionary(serv, kIODisplayOnlyPreferredName);
    IOObjectRelease(serv);

    CFStringRef display_name;
    CFDictionaryRef names = CFDictionaryGetValue(info, CFSTR(kDisplayProductName));

    if ( !names ||
         !CFDictionaryGetValueIfPresent(names, CFSTR("en_US"), (const void**) & display_name)  )
    {
        // This may happen if a desktop Mac is running headless
        CFRelease( info );
        return @"unknown";
    }

    NSString * displayname = [NSString stringWithString: (__bridge NSString *) display_name];
    CFRelease(info);
    return displayname;
}


// Returns the io_service_t (an int) corresponding to a CG display ID, or 0 on failure.
// The io_service_t should be released with IOObjectRelease when not needed.

- (io_service_t) IOServicePortFromCGDisplayID: (CGDirectDisplayID) displayID
{
    io_iterator_t iter;
    io_service_t serv, servicePort = 0;

    CFMutableDictionaryRef matching = IOServiceMatching("IODisplayConnect");

    // releases matching for us
    kern_return_t err = IOServiceGetMatchingServices( kIOMasterPortDefault, matching, & iter );
    if ( err )
        return 0;

    while ( (serv = IOIteratorNext(iter)) != 0 )
    {
        CFDictionaryRef displayInfo;
        CFNumberRef vendorIDRef;
        CFNumberRef productIDRef;
        CFNumberRef serialNumberRef;

        displayInfo = IODisplayCreateInfoDictionary( serv, kIODisplayOnlyPreferredName );

        Boolean success;
        success =  CFDictionaryGetValueIfPresent( displayInfo, CFSTR(kDisplayVendorID),  (const void**) & vendorIDRef );
        success &= CFDictionaryGetValueIfPresent( displayInfo, CFSTR(kDisplayProductID), (const void**) & productIDRef );

        if ( !success )
        {
            CFRelease(displayInfo);
            continue;
        }

        SInt32 vendorID;
        CFNumberGetValue( vendorIDRef, kCFNumberSInt32Type, &vendorID );
        SInt32 productID;
        CFNumberGetValue( productIDRef, kCFNumberSInt32Type, &productID );

        // If a serial number is found, use it.
        // Otherwise serial number will be nil (= 0) which will match with the output of 'CGDisplaySerialNumber'
        SInt32 serialNumber = 0;
        if ( CFDictionaryGetValueIfPresent(displayInfo, CFSTR(kDisplaySerialNumber), (const void**) & serialNumberRef) )
        {
            CFNumberGetValue( serialNumberRef, kCFNumberSInt32Type, &serialNumber );
        }

        // If the vendor and product id along with the serial don't match
        // then we are not looking at the correct monitor.
        // NOTE: The serial number is important in cases where two monitors
        //       are the exact same.
        if( CGDisplayVendorNumber(displayID) != vendorID ||
            CGDisplayModelNumber(displayID)  != productID ||
            CGDisplaySerialNumber(displayID) != serialNumber )
        {
            CFRelease(displayInfo);
            continue;
        }

        servicePort = serv;
        CFRelease(displayInfo);
        break;
    }

    IOObjectRelease(iter);
    return servicePort;
}
.

이것은 MacOS 10.11 (El Capitan)에서 쓴 스크린 세이버에서 나에게 잘 작동합니다. 나는 MACBookPro의 내장 디스플레이와 Apple 디스플레이를 통해 Thunderbolt를 통해 연결된 것을 테스트했습니다.

NSString* screenNameForDisplay(CGDirectDisplayID displayID)
{
    NSString *screenName = nil;
    io_service_t service = IOServicePortFromCGDisplayID(displayID);
    if (service)
    {
        NSDictionary *deviceInfo = (NSDictionary *)IODisplayCreateInfoDictionary(service, kIODisplayOnlyPreferredName);
        NSDictionary *localizedNames = [deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];

        if ([localizedNames count] > 0) {
            screenName = [[localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]] retain];
        }

        [deviceInfo release];
    }
    return [screenName autorelease];
}
.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top