summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDyami Caliri <dyami@dragonframe.com>2014-08-27 09:27:50 -0700
committerDyami Caliri <dyami@dragonframe.com>2014-08-28 23:48:56 +0200
commit9c3a58a913a7e59359146264ee59d40d703d4db2 (patch)
tree622106939650b8302023d422f4a02aac283f7282
parent3da75b05841e503c146a326c15b9065eebfe35b7 (diff)
Recreate child windows when changing screens
When setting a new screen, the code calls QWindow::destroy(), which recursively destroys all child windows. It then calls create() on the top-level window, leaving child windows destroyed. This causes crashes if you have embedded native widgets. Task-number: QTBUG-40817 Change-Id: Iaace2589f48bbfd5faaf5ff95357ff43b310504a Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com> Reviewed-by: Laszlo Agocs <laszlo.agocs@digia.com>
-rw-r--r--src/gui/kernel/qwindow.cpp34
-rw-r--r--src/gui/kernel/qwindow_p.h1
-rwxr-xr-x[-rw-r--r--]tests/auto/widgets/kernel/qwidget_window/qwidget_window.pro2
-rwxr-xr-x[-rw-r--r--]tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp37
4 files changed, 60 insertions, 14 deletions
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index d6f9fad070..6724d68c95 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -367,12 +367,31 @@ void QWindowPrivate::setScreen(QScreen *newScreen, bool recreate)
if (newScreen) {
q->connect(screen, SIGNAL(destroyed(QObject*)), q, SLOT(screenDestroyed(QObject*)));
if (shouldRecreate)
- q->create();
+ create(true);
}
emit q->screenChanged(newScreen);
}
}
+void QWindowPrivate::create(bool recursive)
+{
+ Q_Q(QWindow);
+ if (!platformWindow) {
+ platformWindow = QGuiApplicationPrivate::platformIntegration()->createPlatformWindow(q);
+ QObjectList childObjects = q->children();
+ for (int i = 0; i < childObjects.size(); i ++) {
+ QObject *object = childObjects.at(i);
+ if (object->isWindowType()) {
+ QWindow *window = static_cast<QWindow *>(object);
+ if (recursive)
+ window->d_func()->create(true);
+ if (window->d_func()->platformWindow)
+ window->d_func()->platformWindow->setParent(platformWindow);
+ }
+ }
+ }
+}
+
void QWindowPrivate::clearFocusObject()
{
}
@@ -490,18 +509,7 @@ bool QWindow::isVisible() const
void QWindow::create()
{
Q_D(QWindow);
- if (!d->platformWindow) {
- d->platformWindow = QGuiApplicationPrivate::platformIntegration()->createPlatformWindow(this);
- QObjectList childObjects = children();
- for (int i = 0; i < childObjects.size(); i ++) {
- QObject *object = childObjects.at(i);
- if(object->isWindowType()) {
- QWindow *window = static_cast<QWindow *>(object);
- if (window->d_func()->platformWindow)
- window->d_func()->platformWindow->setParent(d->platformWindow);
- }
- }
- }
+ d->create(false);
}
/*!
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h
index 4305edea51..51d78bb9cd 100644
--- a/src/gui/kernel/qwindow_p.h
+++ b/src/gui/kernel/qwindow_p.h
@@ -132,6 +132,7 @@ public:
void _q_clearAlert();
void setScreen(QScreen *newScreen, bool recreate);
+ void create(bool recursive);
virtual void clearFocusObject();
diff --git a/tests/auto/widgets/kernel/qwidget_window/qwidget_window.pro b/tests/auto/widgets/kernel/qwidget_window/qwidget_window.pro
index baa2823f9a..d61681d5cb 100644..100755
--- a/tests/auto/widgets/kernel/qwidget_window/qwidget_window.pro
+++ b/tests/auto/widgets/kernel/qwidget_window/qwidget_window.pro
@@ -1,7 +1,7 @@
CONFIG += testcase
CONFIG += parallel_test
TARGET = tst_qwidget_window
-QT += widgets testlib
+QT += widgets testlib core-private gui-private
SOURCES += tst_qwidget_window.cpp
x11 {
diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
index d6b7fc20ed..87e1c7a4f3 100644..100755
--- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
+++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
@@ -52,6 +52,9 @@
#include <qlistwidget.h>
#include <qpushbutton.h>
#include <qboxlayout.h>
+#include <qtabwidget.h>
+#include <qlabel.h>
+#include <private/qwindow_p.h>
static inline void setFrameless(QWidget *w)
{
@@ -96,6 +99,8 @@ private slots:
#endif
void tst_qtbug35600();
+ void tst_recreateWindow_QTBUG40817();
+
};
void tst_QWidget_window::initTestCase()
@@ -598,5 +603,37 @@ void tst_QWidget_window::tst_qtbug35600()
// QTBUG-35600: program may crash here or on exit
}
+void tst_QWidget_window::tst_recreateWindow_QTBUG40817()
+{
+ QTabWidget tab;
+
+ QWidget *w = new QWidget;
+ tab.addTab(w, "Tab1");
+ QVBoxLayout *vl = new QVBoxLayout(w);
+ QLabel *lbl = new QLabel("HELLO1");
+ lbl->setObjectName("label1");
+ vl->addWidget(lbl);
+ w = new QWidget;
+ tab.addTab(w, "Tab2");
+ vl = new QVBoxLayout(w);
+ lbl = new QLabel("HELLO2");
+ lbl->setAttribute(Qt::WA_NativeWindow);
+ lbl->setObjectName("label2");
+ vl->addWidget(lbl);
+
+ tab.show();
+
+ QVERIFY(QTest::qWaitForWindowExposed(&tab));
+
+ QWindow *win = tab.windowHandle();
+ win->destroy();
+ QWindowPrivate *p = qt_window_private(win);
+ p->create(true);
+ win->show();
+
+ tab.setCurrentIndex(1);
+}
+
+
QTEST_MAIN(tst_QWidget_window)
#include "tst_qwidget_window.moc"