В Mac OS X каждому дисплею присваивается уникальный номер CGDirectDisplayID
. Вы можете использовать CGGetActiveDisplayList(
) или [NSScreen screens]
для доступа к ним, среди прочего. За документы Apple :
Идентификатор дисплея может сохраняться через
процессы и перезагрузка системы, и
как правило, остается постоянным, пока
определенные параметры дисплея не
изменить.
На новых MacBook Pro середины 2010 года Apple начала использовать автоматическое переключение графики Intel / nVidia. Ноутбуки имеют два графических процессора, маломощный Intel и мощный nVidia. Предыдущие ноутбуки с двумя графическими процессорами (модели 2009 года) не имели автоматического переключения графических процессоров и требовали от пользователя изменения настроек, выхода из системы и повторного входа в систему для переключения графического процессора. Даже в старых системах был только один графический процессор.
Существует проблема с моделями середины 2010 года, когда CGDirectDisplayID не остаются неизменными, когда дисплей переключается с одного графического процессора на другое. Например:
- Ноутбук включается.
- Встроенный ЖК
Экран управляется чипсетом Intel.
Идентификатор дисплея: 30002
- Внешний
Дисплей подключен.
- Встроенный
ЖК-экран переключается на nVidia
Набор микросхем. Это изменения ID дисплея:
30004
- Внешний дисплей управляется
от чипсета nVidia.
- ... на данный момент,
чипсет Intel не работает ...
- Пользователь отключает Внешний дисплей .
- Встроенный ЖК-экран переключается обратно на
Чипсет Intel. Это идентификатор дисплея
возвращается к оригиналу: 30002
У меня вопрос: как сопоставить старый идентификатор дисплея новому идентификатору дисплея, если они меняются из-за смены графического процессора?
Мысли о:
Я заметил, что идентификатор дисплея меняется только на 2, но у меня недостаточно тестовых Mac, чтобы определить, является ли это общим для всех новых MacBook Pro или только для меня. В любом случае это своего рода клочок, если «просто проверьте идентификаторы дисплея, которые находятся +/- 2 друг от друга».
Пробовал:
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()
не возвращает YES, если тот же дисплей изменил GPU. Вот пример сравнения словаря (посмотрите на ключ 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
изменяется при переключении графических процессоров, поэтому IODisplayMatchDictionaries()
не работает.
Теоретически я могу сравнить только клавиши DisplayProductID
и DisplayVendorID
, но я пишу программное обеспечение для конечного пользователя, и меня беспокоит ситуация, когда у пользователей есть два или более одинаковых монитора, то есть будут ли оба одинаковых DisplayProductID / DisplayVendorID). Другими словами, это не идеальное решение, открытое для потенциальных сбоев.
Любая помощь очень ценится! :)