macOS: Unregister screen notification handlers on QGuiApplication shutdown

In the case of a plugin, the plugin might be unloaded, and destroy its
QGuiApplication. We don't want the screen notification handlers to outlive
the application, as that results in crashes.

Fixes: QTBUG-91919
Pick-to: 6.2 6.1 5.15
Done-with: Yang Yang
Change-Id: I3a4c0fcf97b785357516d1dac34489511400f154
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This commit is contained in:
Tor Arne Vestbø 2021-06-22 11:43:18 +02:00
parent d0676874d6
commit 96469ae338
2 changed files with 16 additions and 3 deletions

View File

@ -43,6 +43,7 @@
#include "qcocoacursor.h"
#include <qpa/qplatformintegration.h>
#include <QtCore/private/qcore_mac_p.h>
#include <CoreGraphics/CoreGraphics.h>
#include <CoreVideo/CoreVideo.h>
@ -102,6 +103,9 @@ private:
static void updateScreens();
static void cleanupScreens();
static QMacNotificationObserver s_screenParameterObserver;
static CGDisplayReconfigurationCallBack s_displayReconfigurationCallBack;
static bool updateScreensIfNeeded();
static NSArray *s_screenConfigurationBeforeUpdate;

View File

@ -75,12 +75,14 @@ namespace CoreGraphics {
}
NSArray *QCocoaScreen::s_screenConfigurationBeforeUpdate = nil;
QMacNotificationObserver QCocoaScreen::s_screenParameterObserver;
CGDisplayReconfigurationCallBack QCocoaScreen::s_displayReconfigurationCallBack = nullptr;
void QCocoaScreen::initializeScreens()
{
updateScreens();
CGDisplayRegisterReconfigurationCallback([](CGDirectDisplayID displayId, CGDisplayChangeSummaryFlags flags, void *userInfo) {
s_displayReconfigurationCallBack = [](CGDirectDisplayID displayId, CGDisplayChangeSummaryFlags flags, void *userInfo) {
Q_UNUSED(userInfo);
// Displays are reconfigured in batches, and we want to update our screens
@ -131,9 +133,10 @@ void QCocoaScreen::initializeScreens()
updateScreensIfNeeded();
}
}
}, nullptr);
};
CGDisplayRegisterReconfigurationCallback(s_displayReconfigurationCallBack, nullptr);
static QMacNotificationObserver screenParameterObserver(NSApplication.sharedApplication,
s_screenParameterObserver = QMacNotificationObserver(NSApplication.sharedApplication,
NSApplicationDidChangeScreenParametersNotification, [&]() {
qCDebug(lcQpaScreen) << "Received screen parameter change notification";
updateScreensIfNeeded(); // As a last resort we update screens here
@ -241,6 +244,12 @@ void QCocoaScreen::cleanupScreens()
// Remove screens in reverse order to avoid crash in case of multiple screens
for (QScreen *screen : backwards(QGuiApplication::screens()))
static_cast<QCocoaScreen*>(screen->handle())->remove();
Q_ASSERT(s_displayReconfigurationCallBack);
CGDisplayRemoveReconfigurationCallback(s_displayReconfigurationCallBack, nullptr);
s_displayReconfigurationCallBack = nullptr;
s_screenParameterObserver.remove();
}
void QCocoaScreen::remove()