314 lines
12 KiB
Diff
314 lines
12 KiB
Diff
|
commit 9b4fbe85d2e00c625c3d4abd975faf555000f685
|
||
|
Author: Giulio Camuffo <giuliocamuffo@gmail.com>
|
||
|
Date: Sun Aug 31 16:16:53 2014 +0300
|
||
|
|
||
|
Add a function for QPA plugins to explicitly destroy QScreens
|
||
|
|
||
|
Previously QPlatformScreen was automatically deleting its QScreen
|
||
|
in ~QPlatformScreen(). That means that we cannot use QScreen's
|
||
|
methods when the screen is being removed, because doing so would
|
||
|
call virtual methods of QPlatformScreen. By that point the
|
||
|
QPlatformScreen subclass object does not exist anymore, and we
|
||
|
call the default implementation instead of the subclassed one, or
|
||
|
get a crash for the pure virtual methods. This happens for example
|
||
|
when removing a screen which contains a QWindow with some QML item
|
||
|
using QQuickScreenAttached.
|
||
|
|
||
|
This patch adds a QPlatformIntegration::destroyScreen() function,
|
||
|
which deletes the QScreen and later the QPlatformScreen.
|
||
|
|
||
|
~QPlatformScreen will still delete the QScreen if it was not deleted
|
||
|
with destroyScreen(), so code not ported to the new approach
|
||
|
will continue to work as before, with only a warning added.
|
||
|
|
||
|
Task-number: QTBUG-41141
|
||
|
Change-Id: Ie4a03dee08ceb4c3e94a81875411f6f723273fe1
|
||
|
Reviewed-by: Jørgen Lind <jorgen.lind@theqtcompany.com>
|
||
|
Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
|
||
|
|
||
|
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
|
||
|
index 39b031e..93b1359 100644
|
||
|
--- a/src/gui/kernel/qplatformintegration.cpp
|
||
|
+++ b/src/gui/kernel/qplatformintegration.cpp
|
||
|
@@ -429,7 +429,7 @@ QList<int> QPlatformIntegration::possibleKeys(const QKeyEvent *) const
|
||
|
This adds the screen to QGuiApplication::screens(), and emits the
|
||
|
QGuiApplication::screenAdded() signal.
|
||
|
|
||
|
- The screen is automatically removed when the QPlatformScreen is destroyed.
|
||
|
+ The screen should be deleted by calling QPlatformIntegration::destroyScreen().
|
||
|
*/
|
||
|
void QPlatformIntegration::screenAdded(QPlatformScreen *ps)
|
||
|
{
|
||
|
@@ -439,6 +439,22 @@ void QPlatformIntegration::screenAdded(QPlatformScreen *ps)
|
||
|
emit qGuiApp->screenAdded(screen);
|
||
|
}
|
||
|
|
||
|
+/*!
|
||
|
+ Should be called by the implementation whenever a screen is removed.
|
||
|
+
|
||
|
+ This removes the screen from QGuiApplication::screens(), and deletes it.
|
||
|
+
|
||
|
+ Failing to call this and manually deleting the QPlatformScreen instead may
|
||
|
+ lead to a crash due to a pure virtual call.
|
||
|
+*/
|
||
|
+void QPlatformIntegration::destroyScreen(QPlatformScreen *screen)
|
||
|
+{
|
||
|
+ QGuiApplicationPrivate::screen_list.removeOne(screen->d_func()->screen);
|
||
|
+ delete screen->d_func()->screen;
|
||
|
+ screen->d_func()->screen = Q_NULLPTR;
|
||
|
+ delete screen;
|
||
|
+}
|
||
|
+
|
||
|
QStringList QPlatformIntegration::themeNames() const
|
||
|
{
|
||
|
return QStringList();
|
||
|
diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h
|
||
|
index d510240..9b7e2df 100644
|
||
|
--- a/src/gui/kernel/qplatformintegration.h
|
||
|
+++ b/src/gui/kernel/qplatformintegration.h
|
||
|
@@ -170,6 +170,7 @@ public:
|
||
|
|
||
|
protected:
|
||
|
void screenAdded(QPlatformScreen *screen);
|
||
|
+ void destroyScreen(QPlatformScreen *screen);
|
||
|
};
|
||
|
|
||
|
QT_END_NAMESPACE
|
||
|
diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp
|
||
|
index 71710d1..fa6d785 100644
|
||
|
--- a/src/gui/kernel/qplatformscreen.cpp
|
||
|
+++ b/src/gui/kernel/qplatformscreen.cpp
|
||
|
@@ -52,9 +52,11 @@ QPlatformScreen::QPlatformScreen()
|
||
|
QPlatformScreen::~QPlatformScreen()
|
||
|
{
|
||
|
Q_D(QPlatformScreen);
|
||
|
-
|
||
|
- QGuiApplicationPrivate::screen_list.removeOne(d->screen);
|
||
|
- delete d->screen;
|
||
|
+ if (d->screen) {
|
||
|
+ qWarning("Manually deleting a QPlatformScreen. Call QPlatformIntegration::destroyScreen instead.");
|
||
|
+ QGuiApplicationPrivate::screen_list.removeOne(d->screen);
|
||
|
+ delete d->screen;
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
|
||
|
index 72bd096..180cb23 100644
|
||
|
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
|
||
|
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
|
||
|
@@ -337,7 +337,7 @@ QCocoaIntegration::~QCocoaIntegration()
|
||
|
|
||
|
// Delete screens in reverse order to avoid crash in case of multiple screens
|
||
|
while (!mScreens.isEmpty()) {
|
||
|
- delete mScreens.takeLast();
|
||
|
+ destroyScreen(mScreens.takeLast());
|
||
|
}
|
||
|
|
||
|
clearToolbars();
|
||
|
@@ -397,7 +397,7 @@ void QCocoaIntegration::updateScreens()
|
||
|
// Now the leftovers in remainingScreens are no longer current, so we can delete them.
|
||
|
foreach (QCocoaScreen* screen, remainingScreens) {
|
||
|
mScreens.removeOne(screen);
|
||
|
- delete screen;
|
||
|
+ destroyScreen(screen);
|
||
|
}
|
||
|
// All screens in mScreens are siblings, because we ignored the mirrors.
|
||
|
foreach (QCocoaScreen* screen, mScreens)
|
||
|
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
|
||
|
index 461f160..ff4b753 100644
|
||
|
--- a/src/plugins/platforms/ios/qiosintegration.mm
|
||
|
+++ b/src/plugins/platforms/ios/qiosintegration.mm
|
||
|
@@ -120,7 +120,7 @@ QIOSIntegration::~QIOSIntegration()
|
||
|
m_inputContext = 0;
|
||
|
|
||
|
foreach (QScreen *screen, QGuiApplication::screens())
|
||
|
- delete screen->handle();
|
||
|
+ destroyScreen(screen->handle());
|
||
|
|
||
|
delete m_platformServices;
|
||
|
m_platformServices = 0;
|
||
|
diff --git a/src/plugins/platforms/kms/qkmsintegration.cpp b/src/plugins/platforms/kms/qkmsintegration.cpp
|
||
|
index d94d7d9..5ad58ba 100644
|
||
|
--- a/src/plugins/platforms/kms/qkmsintegration.cpp
|
||
|
+++ b/src/plugins/platforms/kms/qkmsintegration.cpp
|
||
|
@@ -74,7 +74,7 @@ QKmsIntegration::~QKmsIntegration()
|
||
|
delete device;
|
||
|
}
|
||
|
foreach (QPlatformScreen *screen, m_screens) {
|
||
|
- delete screen;
|
||
|
+ destroyScreen(screen);
|
||
|
}
|
||
|
delete m_fontDatabase;
|
||
|
delete m_vtHandler;
|
||
|
diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
|
||
|
index 777da98..4e83656 100644
|
||
|
--- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
|
||
|
+++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
|
||
|
@@ -57,7 +57,7 @@ QLinuxFbIntegration::QLinuxFbIntegration(const QStringList ¶mList)
|
||
|
|
||
|
QLinuxFbIntegration::~QLinuxFbIntegration()
|
||
|
{
|
||
|
- delete m_primaryScreen;
|
||
|
+ destroyScreen(m_primaryScreen);
|
||
|
}
|
||
|
|
||
|
void QLinuxFbIntegration::initialize()
|
||
|
diff --git a/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp b/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp
|
||
|
index 0b12e62..3fbed1e 100644
|
||
|
--- a/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp
|
||
|
+++ b/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp
|
||
|
@@ -60,7 +60,7 @@ QMinimalEglIntegration::QMinimalEglIntegration()
|
||
|
|
||
|
QMinimalEglIntegration::~QMinimalEglIntegration()
|
||
|
{
|
||
|
- delete mScreen;
|
||
|
+ destroyScreen(mScreen);
|
||
|
}
|
||
|
|
||
|
bool QMinimalEglIntegration::hasCapability(QPlatformIntegration::Capability cap) const
|
||
|
diff --git a/src/plugins/platforms/openwfd/qopenwfdintegration.cpp b/src/plugins/platforms/openwfd/qopenwfdintegration.cpp
|
||
|
index 1e29fcc..26bdd14 100644
|
||
|
--- a/src/plugins/platforms/openwfd/qopenwfdintegration.cpp
|
||
|
+++ b/src/plugins/platforms/openwfd/qopenwfdintegration.cpp
|
||
|
@@ -133,3 +133,8 @@ void QOpenWFDIntegration::addScreen(QOpenWFDScreen *screen)
|
||
|
{
|
||
|
screenAdded(screen);
|
||
|
}
|
||
|
+
|
||
|
+void QOpenWFDIntegration::destroyScreen(QOpenWFDScreen *screen)
|
||
|
+{
|
||
|
+ QPlatformIntegration::destroyScreen(screen);
|
||
|
+}
|
||
|
diff --git a/src/plugins/platforms/openwfd/qopenwfdintegration.h b/src/plugins/platforms/openwfd/qopenwfdintegration.h
|
||
|
index 6c086b7..9243205 100644
|
||
|
--- a/src/plugins/platforms/openwfd/qopenwfdintegration.h
|
||
|
+++ b/src/plugins/platforms/openwfd/qopenwfdintegration.h
|
||
|
@@ -63,6 +63,7 @@ public:
|
||
|
QPlatformPrinterSupport *printerSupport() const;
|
||
|
|
||
|
void addScreen(QOpenWFDScreen *screen);
|
||
|
+ void destroyScreen(QOpenWFDScreen *screen);
|
||
|
private:
|
||
|
QList<QPlatformScreen *> mScreens;
|
||
|
QList<QOpenWFDDevice *>mDevices;
|
||
|
diff --git a/src/plugins/platforms/openwfd/qopenwfdport.cpp b/src/plugins/platforms/openwfd/qopenwfdport.cpp
|
||
|
index 0bdc6b2..b643644 100644
|
||
|
--- a/src/plugins/platforms/openwfd/qopenwfdport.cpp
|
||
|
+++ b/src/plugins/platforms/openwfd/qopenwfdport.cpp
|
||
|
@@ -140,7 +140,7 @@ void QOpenWFDPort::detach()
|
||
|
mAttached = false;
|
||
|
mOn = false;
|
||
|
|
||
|
- delete mScreen;
|
||
|
+ mDevice->integration()->destroyScreen(mScreen);
|
||
|
|
||
|
wfdDestroyPipeline(mDevice->handle(),mPipeline);
|
||
|
mPipelineId = WFD_INVALID_PIPELINE_ID;
|
||
|
diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp
|
||
|
index 34b79b6..d47da01 100644
|
||
|
--- a/src/plugins/platforms/qnx/qqnxintegration.cpp
|
||
|
+++ b/src/plugins/platforms/qnx/qqnxintegration.cpp
|
||
|
@@ -554,7 +554,7 @@ void QQnxIntegration::removeDisplay(QQnxScreen *screen)
|
||
|
Q_CHECK_PTR(screen);
|
||
|
Q_ASSERT(m_screens.contains(screen));
|
||
|
m_screens.removeAll(screen);
|
||
|
- screen->deleteLater();
|
||
|
+ destroyScreen(screen);
|
||
|
}
|
||
|
|
||
|
void QQnxIntegration::destroyDisplays()
|
||
|
diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h
|
||
|
index d1617ea..7fb37bc 100644
|
||
|
--- a/src/plugins/platforms/windows/qwindowsintegration.h
|
||
|
+++ b/src/plugins/platforms/windows/qwindowsintegration.h
|
||
|
@@ -94,6 +94,7 @@ public:
|
||
|
static QWindowsIntegration *instance();
|
||
|
|
||
|
inline void emitScreenAdded(QPlatformScreen *s) { screenAdded(s); }
|
||
|
+ inline void emitDestroyScreen(QPlatformScreen *s) { destroyScreen(s); }
|
||
|
|
||
|
unsigned options() const;
|
||
|
|
||
|
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
|
||
|
index fd57d9e..79219e3 100644
|
||
|
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
|
||
|
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
|
||
|
@@ -462,7 +462,7 @@ void QWindowsScreenManager::removeScreen(int index)
|
||
|
if (movedWindowCount)
|
||
|
QWindowSystemInterface::flushWindowSystemEvents();
|
||
|
}
|
||
|
- delete m_screens.takeAt(index);
|
||
|
+ QWindowsIntegration::instance()->emitDestroyScreen(m_screens.takeAt(index));
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
@@ -497,4 +497,11 @@ bool QWindowsScreenManager::handleScreenChanges()
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
+void QWindowsScreenManager::clearScreens()
|
||
|
+{
|
||
|
+ // Delete screens in reverse order to avoid crash in case of multiple screens
|
||
|
+ while (!m_screens.isEmpty())
|
||
|
+ QWindowsIntegration::instance()->emitDestroyScreen(m_screens.takeLast());
|
||
|
+}
|
||
|
+
|
||
|
QT_END_NAMESPACE
|
||
|
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
|
||
|
index aa14083..924912d 100644
|
||
|
--- a/src/plugins/platforms/windows/qwindowsscreen.h
|
||
|
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
|
||
|
@@ -127,11 +127,7 @@ public:
|
||
|
|
||
|
QWindowsScreenManager();
|
||
|
|
||
|
- inline void clearScreens() {
|
||
|
- // Delete screens in reverse order to avoid crash in case of multiple screens
|
||
|
- while (!m_screens.isEmpty())
|
||
|
- delete m_screens.takeLast();
|
||
|
- }
|
||
|
+ void clearScreens();
|
||
|
|
||
|
bool handleScreenChanges();
|
||
|
bool handleDisplayChange(WPARAM wParam, LPARAM lParam);
|
||
|
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
|
||
|
index 5510c3b..ae59de5 100644
|
||
|
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
|
||
|
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
|
||
|
@@ -279,11 +279,12 @@ void QXcbConnection::updateScreens()
|
||
|
++xcbScreenNumber;
|
||
|
} // for each xcb screen
|
||
|
|
||
|
+ QXcbIntegration *integration = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration());
|
||
|
// Now activeScreens is the complete set of screens which are active at this time.
|
||
|
// Delete any existing screens which are not in activeScreens
|
||
|
for (int i = m_screens.count() - 1; i >= 0; --i) {
|
||
|
if (!activeScreens.contains(m_screens[i])) {
|
||
|
- delete m_screens[i];
|
||
|
+ integration->destroyScreen(m_screens.at(i));
|
||
|
m_screens.removeAt(i);
|
||
|
}
|
||
|
}
|
||
|
@@ -300,7 +301,7 @@ void QXcbConnection::updateScreens()
|
||
|
// Now that they are in the right order, emit the added signals for new screens only
|
||
|
foreach (QXcbScreen* screen, m_screens)
|
||
|
if (newScreens.contains(screen))
|
||
|
- ((QXcbIntegration*)QGuiApplicationPrivate::platformIntegration())->screenAdded(screen);
|
||
|
+ integration->screenAdded(screen);
|
||
|
}
|
||
|
|
||
|
QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, const char *displayName)
|
||
|
@@ -431,9 +432,10 @@ QXcbConnection::~QXcbConnection()
|
||
|
|
||
|
delete m_reader;
|
||
|
|
||
|
+ QXcbIntegration *integration = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration());
|
||
|
// Delete screens in reverse order to avoid crash in case of multiple screens
|
||
|
while (!m_screens.isEmpty())
|
||
|
- delete m_screens.takeLast();
|
||
|
+ integration->destroyScreen(m_screens.takeLast());
|
||
|
|
||
|
#ifdef XCB_USE_EGL
|
||
|
if (m_has_egl)
|