Cocoa: Fix zombie NSScreen crash

While the Cocoa documentation says we should not cache [NSScreen screens],
it seems that we should not cache its referenced objects either. This
caused a crash in desktop components when using Dial because, given
the way it is being rendered, we need to know the screen pixel ratio.

Task-number: QTCOMPONENTS-1279
Change-Id: If5c3c6f14d04925215b9dca011143a2056a68846
Reviewed-by: J-P Nurmi <jpnurmi@digia.com>
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@digia.com>
This commit is contained in:
Gabriel de Dietrich 2013-01-02 16:42:16 +01:00 committed by The Qt Project
parent d75b217901
commit f415d86d1e
2 changed files with 14 additions and 9 deletions

View File

@ -80,11 +80,11 @@ public:
// ---------------------------------------------------- // ----------------------------------------------------
// Additional methods // Additional methods
void setVirtualSiblings(QList<QPlatformScreen *> siblings) { m_siblings = siblings; } void setVirtualSiblings(QList<QPlatformScreen *> siblings) { m_siblings = siblings; }
NSScreen *osScreen() const { return m_screen; } NSScreen *osScreen() const;
void updateGeometry(); void updateGeometry();
public: public:
NSScreen *m_screen; int m_screenIndex;
QRect m_geometry; QRect m_geometry;
QRect m_availableGeometry; QRect m_availableGeometry;
QDpi m_logicalDpi; QDpi m_logicalDpi;

View File

@ -70,9 +70,8 @@ static void initResources()
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
QCocoaScreen::QCocoaScreen(int screenIndex) : QCocoaScreen::QCocoaScreen(int screenIndex) :
QPlatformScreen(), m_refreshRate(60.0) QPlatformScreen(), m_screenIndex(screenIndex), m_refreshRate(60.0)
{ {
m_screen = [[NSScreen screens] objectAtIndex:screenIndex];
updateGeometry(); updateGeometry();
m_cursor = new QCocoaCursor; m_cursor = new QCocoaCursor;
} }
@ -82,19 +81,25 @@ QCocoaScreen::~QCocoaScreen()
delete m_cursor; delete m_cursor;
} }
NSScreen *QCocoaScreen::osScreen() const
{
return [[NSScreen screens] objectAtIndex:m_screenIndex];
}
void QCocoaScreen::updateGeometry() void QCocoaScreen::updateGeometry()
{ {
NSRect frameRect = [m_screen frame]; NSScreen *nsScreen = osScreen();
NSRect frameRect = [nsScreen frame];
m_geometry = QRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width, frameRect.size.height); m_geometry = QRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width, frameRect.size.height);
NSRect visibleRect = [m_screen visibleFrame]; NSRect visibleRect = [nsScreen visibleFrame];
m_availableGeometry = QRect(visibleRect.origin.x, m_availableGeometry = QRect(visibleRect.origin.x,
frameRect.size.height - (visibleRect.origin.y + visibleRect.size.height), // invert y frameRect.size.height - (visibleRect.origin.y + visibleRect.size.height), // invert y
visibleRect.size.width, visibleRect.size.height); visibleRect.size.width, visibleRect.size.height);
m_format = QImage::Format_RGB32; m_format = QImage::Format_RGB32;
m_depth = NSBitsPerPixelFromDepth([m_screen depth]); m_depth = NSBitsPerPixelFromDepth([nsScreen depth]);
NSDictionary *devDesc = [m_screen deviceDescription]; NSDictionary *devDesc = [nsScreen deviceDescription];
CGDirectDisplayID dpy = [[devDesc objectForKey:@"NSScreenNumber"] unsignedIntValue]; CGDirectDisplayID dpy = [[devDesc objectForKey:@"NSScreenNumber"] unsignedIntValue];
CGSize size = CGDisplayScreenSize(dpy); CGSize size = CGDisplayScreenSize(dpy);
m_physicalSize = QSizeF(size.width, size.height); m_physicalSize = QSizeF(size.width, size.height);
@ -119,7 +124,7 @@ qreal QCocoaScreen::devicePixelRatio() const
{ {
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) { if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
return qreal([m_screen backingScaleFactor]); return qreal([osScreen() backingScaleFactor]);
} else } else
#endif #endif
{ {