CGDisplayioServicePortは、OS X>= 10.9、置き換える方法で推奨されていませんか?
-
21-12-2019 - |
質問
私は複数のモニターでの画面解像度をすばやく変更できるようにするために小さなアプリをしました。このコードを使って製品名を表示したい、このコードを使用して見つけるのは非常に簡単です。
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";
}
.
がOS X>= 10.9では推奨されていないため、Appleのドキュメントは交換がないと述べています。このメソッドを使用せずにサービスポートまたは製品名を見つける方法は?
IOレジストリを繰り返し、CGDisplayIOServicePort
メソッドを使用して表示サービスを見つけようとしましたが、IOレジストリにはあまり慣れていませんので、ソリューションが見つかりませんでした。
助けてくれてありがとう!
解決
@ Eunの投稿はこの議論を閉じるために情報を逃したようです。少し検索で、ioserviceportfromcgdisplayidがAppleが提供するAPIではないことがわかりました。むしろ、それはここで見つかったオープンソースコードです。 https://github.com/glfw/glfw/blob/e0a6772e5e4c672179fc69a90bcda3369792ed1f/src / Cocoa_Monitor.m
ioservicePortFromCgDisplayidをコピーし、それからの「getDisplayName」をコピーしました。 OS X 10.10で動作させるには2つの調整が必要でした。
- IOServicePortFromCgDisplayidのシリアル番号を処理するようにコードを削除します。 (CFDictionaryGetValue for. kdisplaySerialNumberは私にNULLを返します。)
- プロジェクトを削除します GetDisplayNameのエラー処理コード。
- 問題のトラッカー:github.com/glfw/glfw/issues/165
- コミット 解決策の場合: github.com/glfw/glfw/commit/e0a6772e5e4c672179fc69a90bcda3369792ed1f
もっと情報が必要な場合
私はそこにコードを提出したマシューヘンリーに感謝します。
他のヒント
これは私の問題を抱えています。また、GLFW 3.1、ファイルCocoa_Monitor.mからコードを始めました。
しかし、私はHiroshiが言った以上のようにそれを修正しなければなりませんでした、こんなよそ見:
// 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の組み込みディスプレイとThunderboltを介して接続されたAppleディスプレイをテストしました。
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];
}
.