macOS: Replace deprecated CGDisplayIOServicePort function

There's no replacement function from Apple's side, so we have to iterate
the available displays and pick the right one based on the vendor, product
and serial number.

Change-Id: I437bee06bc6826c3214a701cd2c65f6109eeb3e7
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
bb10
Tor Arne Vestbø 2017-11-02 20:52:47 +01:00
parent f1aa2ee512
commit bfcad18526
3 changed files with 61 additions and 6 deletions

View File

@ -193,6 +193,19 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSPanelContentsWrapper);
// -------------------------------------------------------------------------
// QAppleRefCounted expects the retain function to return the object
io_object_t q_IOObjectRetain(io_object_t obj);
// QAppleRefCounted expects the release function to return void
void q_IOObjectRelease(io_object_t obj);
template <typename T>
class QIOType : public QAppleRefCounted<T, io_object_t, q_IOObjectRetain, q_IOObjectRelease>
{
using QAppleRefCounted<T, io_object_t, q_IOObjectRetain, q_IOObjectRelease>::QAppleRefCounted;
};
// -------------------------------------------------------------------------
// Depending on the ABI of the platform, we may need to use objc_msgSendSuper_stret:
// - http://www.sealiesoftware.com/blog/archive/2008/10/30/objc_explain_objc_msgSend_stret.html
// - https://lists.apple.com/archives/cocoa-dev/2008/Feb/msg02338.html

View File

@ -408,4 +408,19 @@ QT_END_NAMESPACE
[super layout];
}
// -------------------------------------------------------------------------
io_object_t q_IOObjectRetain(io_object_t obj)
{
kern_return_t ret = IOObjectRetain(obj);
Q_ASSERT(!ret);
return obj;
}
void q_IOObjectRelease(io_object_t obj)
{
kern_return_t ret = IOObjectRelease(obj);
Q_ASSERT(!ret);
}
@end

View File

@ -103,6 +103,38 @@ QRectF QCocoaScreen::flipCoordinate(const QRectF &rect) const
return QRectF(flipCoordinate(rect.topLeft() + QPoint(0, rect.height())), rect.size());
}
static QString displayName(CGDirectDisplayID displayID)
{
QIOType<io_iterator_t> iterator;
if (IOServiceGetMatchingServices(kIOMasterPortDefault,
IOServiceMatching("IODisplayConnect"), &iterator))
return QString();
QIOType<io_service_t> display;
while ((display = IOIteratorNext(iterator)) != 0)
{
NSDictionary *info = [(__bridge NSDictionary*)IODisplayCreateInfoDictionary(
display, kIODisplayOnlyPreferredName) autorelease];
if ([[info objectForKey:@kDisplayVendorID] longValue] != CGDisplayVendorNumber(displayID))
continue;
if ([[info objectForKey:@kDisplayProductID] longValue] != CGDisplayModelNumber(displayID))
continue;
if ([[info objectForKey:@kDisplaySerialNumber] longValue] != CGDisplaySerialNumber(displayID))
continue;
NSDictionary *localizedNames = [info objectForKey:@kDisplayProductName];
if (![localizedNames count])
break; // Correct screen, but no name in dictionary
return QString::fromNSString([localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]]);
}
return QString();
}
void QCocoaScreen::updateGeometry()
{
NSScreen *nsScreen = nativeScreen();
@ -139,12 +171,7 @@ void QCocoaScreen::updateGeometry()
if (refresh > 0)
m_refreshRate = refresh;
// Get m_name (brand/model of the monitor)
NSDictionary *deviceInfo = (NSDictionary *)IODisplayCreateInfoDictionary(CGDisplayIOServicePort(dpy), kIODisplayOnlyPreferredName);
NSDictionary *localizedNames = [deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];
if ([localizedNames count] > 0)
m_name = QString::fromUtf8([[localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]] UTF8String]);
[deviceInfo release];
m_name = displayName(dpy);
QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry());
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(), m_logicalDpi.first, m_logicalDpi.second);