Mac OS Xでは、すべてのディスプレイに一意のCGDirectDisplayID
番号が割り当てられます。)を使用するCGGetActiveDisplayList(
か[NSScreen screens]
、それらにアクセスすることができます。Appleのドキュメントによると:
表示IDは、プロセス間およびシステムの再起動後も保持でき、特定の表示パラメーターが変更されない限り、通常は一定のままです。
新しい2010年半ばのMacBookProでは、Appleは自動切り替えのIntel/nVidiaグラフィックスの使用を開始しました。ラップトップには、2つのGPU、低電力のIntelと高電力のnVidiaがあります。以前のデュアルGPUラップトップ(2009モデル)には自動GPU切り替えがなく、GPU切り替えを行うには、ユーザーが設定を変更し、ログオフしてから再度ログオンする必要がありました。古いシステムでもGPUは1つしかありませんでした。
2010年半ばのモデルには、ディスプレイが1つのGPUから次のGPUに切り替わるときにCGDirectDisplayIDが同じままにならないという問題があります。例えば:
- ノートパソコンの電源がオンになります。
- 内蔵LCDスクリーンはIntelチップセットによって駆動されます。ディスプレイID: 30002
- 外部ディスプレイが接続されています。
- 内蔵 LCDスクリーンはnVidiaチップセットに切り替わります。表示IDの変更: 30004
- 外部ディスプレイはnVidiaチップセットによって駆動されます。
- ...この時点で、Intelチップセットは休止しています...
- ユーザーが外部ディスプレイのプラグを抜きます。
- 内蔵LCDスクリーンがIntelチップセットに戻ります。表示IDが元に戻ります:30002
私の質問は、GPUの変更によって変更されたときに、古いディスプレイIDを新しいディスプレイIDに一致させるにはどうすればよいですか?
について考えた:
ディスプレイIDが2だけ変わることに気づきましたが、これがすべての新しいMacBook Proに共通するのか、それとも私のものだけなのかを判断するのに十分なテストMacがありません。とにかく、「互いに+/- 2のディスプレイIDをチェックするだけ」が機能する場合は、一種の応急修理です。
試した:
CGDisplayRegisterReconfigurationCallback()
表示が変更される前後に通知する、には、一致するロジックがありません。登録されているメソッド内にこのようなものを入れても機能しません。
// Run before display settings change:
CGDirectDisplayID directDisplayID = ...;
io_service_t servicePort = CGDisplayIOServicePort(directDisplayID);
CFDictionaryRef oldInfoDict = IODisplayCreateInfoDictionary(servicePort, kIODisplayMatchingInfo);
// ...display settings change...
// Run after display settings change:
CGDirectDisplayID directDisplayID = ...;
io_service_t servicePort = CGDisplayIOServicePort(directDisplayID);
CFDictionaryRef newInfoDict = IODisplayCreateInfoDictionary(servicePort, kIODisplayMatchingInfo);
BOOL match = IODisplayMatchDictionaries(oldInfoDict, newInfoDict, 0);
if (match)
NSLog(@"Displays are a match");
else
NSLog(@"Displays are not a match");
上で起こっていることは次のとおりです。
- 表示設定が変更される前にoldInfoDictをキャッシュしています。
- 表示設定が変更されるのを待っています
- 次に、を使用してoldInfoDictをnewInfoDictと比較します。
IODisplayMatchDictionaries()
IODisplayMatchDictionaries()
BOOLを返します。「はい」は同じか、「いいえ」は異なります。
残念ながら、IODisplayMatchDictionaries()
同じディスプレイがGPUを変更した場合、YESは返されません。比較している辞書の例を次に示します(IODisplayLocation
キーを見てください)。
// oldInfoDict (Display ID: 30002)
oldInfoDict: {
DisplayProductID = 40144;
DisplayVendorID = 1552;
IODisplayLocation = "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/IGPU@2/AppleIntelFramebuffer/display0/AppleBacklightDisplay";
}
// newInfoDict (Display ID: 30004)
newInfoDict: {
DisplayProductID = 40144;
DisplayVendorID = 1552;
IODisplayLocation = "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/P0P2@1/IOPCI2PCIBridge/GFX0@0/NVDA,Display-A@0/NVDA/display0/AppleBacklightDisplay";
}
ご覧IODisplayLocation
のとおり、GPUを切り替えるとキーが変わるため、IODisplayMatchDictionaries()
機能しません。
DisplayProductID
理論的には、キーとキーだけを比較できDisplayVendorID
ますが、エンドユーザーソフトウェアを作成していて、ユーザーが2つ以上の同一のモニターを接続している(つまり、両方に同じDisplayProductID / DisplayVendorIDがある)状況が心配です。 。言い換えれば、それは潜在的なグリッチに開かれた完全ではない解決策です。
どんな助けでも大歓迎です!:)