summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa/qcocoascreen.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoascreen.mm')
-rw-r--r--src/plugins/platforms/cocoa/qcocoascreen.mm100
1 files changed, 23 insertions, 77 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoascreen.mm b/src/plugins/platforms/cocoa/qcocoascreen.mm
index d326d149f1..e419492202 100644
--- a/src/plugins/platforms/cocoa/qcocoascreen.mm
+++ b/src/plugins/platforms/cocoa/qcocoascreen.mm
@@ -74,7 +74,6 @@ namespace CoreGraphics {
Q_ENUM_NS(DisplayChange)
}
-NSArray *QCocoaScreen::s_screenConfigurationBeforeUpdate = nil;
QMacNotificationObserver QCocoaScreen::s_screenParameterObserver;
CGDisplayReconfigurationCallBack QCocoaScreen::s_displayReconfigurationCallBack = nullptr;
@@ -85,83 +84,23 @@ void QCocoaScreen::initializeScreens()
s_displayReconfigurationCallBack = [](CGDirectDisplayID displayId, CGDisplayChangeSummaryFlags flags, void *userInfo) {
Q_UNUSED(userInfo);
- // Displays are reconfigured in batches, and we want to update our screens
- // once a batch ends, so that all the states of the displays are up to date.
- static int displayReconfigurationsInProgress = 0;
-
const bool beforeReconfigure = flags & kCGDisplayBeginConfigurationFlag;
- qCDebug(lcQpaScreen).verbosity(0).nospace() << "Display " << displayId
- << (beforeReconfigure ? " about to reconfigure" : " was ")
- << QFlags<CoreGraphics::DisplayChange>(flags)
- << " with " << displayReconfigurationsInProgress
- << " display configuration(s) in progress";
-
- if (!flags) {
- // CGDisplayRegisterReconfigurationCallback has been observed to be called
- // with flags unset. This seems like a bug. The callback is not paired with
- // a matching "completion" callback either, so we don't know whether to treat
- // it as a begin or end of reconfigure.
- return;
- }
+ qCDebug(lcQpaScreen).verbosity(0) << "Display" << displayId
+ << (beforeReconfigure ? "beginning" : "finished") << "reconfigure"
+ << QFlags<CoreGraphics::DisplayChange>(flags);
- if (beforeReconfigure) {
- if (!displayReconfigurationsInProgress++) {
- // There might have been a screen reconfigure before this that
- // we didn't process yet, so do that now if that's the case.
- updateScreensIfNeeded();
-
- Q_ASSERT(!s_screenConfigurationBeforeUpdate);
- s_screenConfigurationBeforeUpdate = NSScreen.screens;
- qCDebug(lcQpaScreen, "Display reconfigure transaction started"
- " with screen configuration %p", s_screenConfigurationBeforeUpdate);
-
- static void (^tryScreenUpdate)();
- tryScreenUpdate = ^void () {
- qCDebug(lcQpaScreen) << "Attempting screen update from runloop block";
- if (!updateScreensIfNeeded())
- CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopCommonModes, tryScreenUpdate);
- };
- CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopCommonModes, tryScreenUpdate);
- }
- } else {
- Q_ASSERT_X(displayReconfigurationsInProgress, "QCococaScreen",
- "Display configuration transactions are expected to be balanced");
-
- if (!--displayReconfigurationsInProgress) {
- qCDebug(lcQpaScreen) << "Display reconfigure transaction completed";
- // We optimistically update now, in case the NSScreens have changed
- updateScreensIfNeeded();
- }
- }
+ if (!beforeReconfigure)
+ updateScreens();
};
CGDisplayRegisterReconfigurationCallback(s_displayReconfigurationCallBack, nullptr);
s_screenParameterObserver = QMacNotificationObserver(NSApplication.sharedApplication,
NSApplicationDidChangeScreenParametersNotification, [&]() {
qCDebug(lcQpaScreen) << "Received screen parameter change notification";
- updateScreensIfNeeded(); // As a last resort we update screens here
+ updateScreens();
});
}
-bool QCocoaScreen::updateScreensIfNeeded()
-{
- if (!s_screenConfigurationBeforeUpdate) {
- qCDebug(lcQpaScreen) << "QScreens have already been updated, all good";
- return true;
- }
-
- if (s_screenConfigurationBeforeUpdate == NSScreen.screens) {
- qCDebug(lcQpaScreen) << "Still waiting for NSScreen configuration change";
- return false;
- }
-
- qCDebug(lcQpaScreen, "NSScreen configuration changed to %p", NSScreen.screens);
- updateScreens();
-
- s_screenConfigurationBeforeUpdate = nil;
- return true;
-}
-
/*
Update the list of available QScreens, and the properties of existing screens.
@@ -321,15 +260,18 @@ void QCocoaScreen::update(CGDirectDisplayID displayId)
Q_ASSERT(isOnline());
+ // Some properties are only available via NSScreen
+ NSScreen *nsScreen = nativeScreen();
+ if (!nsScreen) {
+ qCDebug(lcQpaScreen) << "Corresponding NSScreen not yet available. Deferring update";
+ return;
+ }
+
const QRect previousGeometry = m_geometry;
const QRect previousAvailableGeometry = m_availableGeometry;
const QDpi previousLogicalDpi = m_logicalDpi;
const qreal previousRefreshRate = m_refreshRate;
- // Some properties are only available via NSScreen
- NSScreen *nsScreen = nativeScreen();
- Q_ASSERT(nsScreen);
-
// The reference screen for the geometry is always the primary screen
QRectF primaryScreenGeometry = QRectF::fromCGRect(CGDisplayBounds(CGMainDisplayID()));
m_geometry = qt_mac_flip(QRectF::fromCGRect(nsScreen.frame), primaryScreenGeometry).toRect();
@@ -759,13 +701,17 @@ QList<QPlatformScreen*> QCocoaScreen::virtualSiblings() const
QCocoaScreen *QCocoaScreen::get(NSScreen *nsScreen)
{
- if (s_screenConfigurationBeforeUpdate) {
- qCWarning(lcQpaScreen) << "Trying to resolve screen while waiting for screen reconfigure!";
- if (!updateScreensIfNeeded())
- qCWarning(lcQpaScreen) << "Failed to do last minute screen update. Expect crashes.";
+ auto displayId = nsScreen.qt_displayId;
+ auto *cocoaScreen = get(displayId);
+ if (!cocoaScreen) {
+ qCWarning(lcQpaScreen) << "Failed to map" << nsScreen
+ << "to QCocoaScreen. Doing last minute update.";
+ updateScreens();
+ cocoaScreen = get(displayId);
+ if (!cocoaScreen)
+ qCWarning(lcQpaScreen) << "Last minute update failed!";
}
-
- return get(nsScreen.qt_displayId);
+ return cocoaScreen;
}
QCocoaScreen *QCocoaScreen::get(CGDirectDisplayID displayId)