Fix ref counted window close handling.
Instead of refcounting QWindow visibility, we ask the Application subclass whether quitting is appropriate. Task-Id: QTBUG-24120 Change-Id: Idd19cc1a3e5742fddded89c7638aaaa5e47c568d Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com> Reviewed-by: Robin Burchell <robin+qt@viroteck.net>
This commit is contained in:
parent
90feedb642
commit
66603985f2
@ -1506,8 +1506,14 @@ void QCoreApplicationPrivate::ref()
|
||||
|
||||
void QCoreApplicationPrivate::deref()
|
||||
{
|
||||
if (!quitLockRef.deref() && in_exec && quitLockRefEnabled)
|
||||
QCoreApplication::postEvent(qApp, new QEvent(QEvent::Quit));
|
||||
if (!quitLockRef.deref())
|
||||
maybeQuit();
|
||||
}
|
||||
|
||||
void QCoreApplicationPrivate::maybeQuit()
|
||||
{
|
||||
if (quitLockRef.load() == 0 && in_exec && quitLockRefEnabled && shouldQuit())
|
||||
QCoreApplication::postEvent(QCoreApplication::instance(), new QEvent(QEvent::Quit));
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -92,6 +92,10 @@ public:
|
||||
QAtomicInt quitLockRef;
|
||||
void ref();
|
||||
void deref();
|
||||
virtual bool shouldQuit() {
|
||||
return true;
|
||||
}
|
||||
void maybeQuit();
|
||||
|
||||
static QThread *theMainThread;
|
||||
static QThread *mainThread();
|
||||
|
@ -1477,6 +1477,17 @@ void QGuiApplicationPrivate::emitLastWindowClosed()
|
||||
}
|
||||
}
|
||||
|
||||
bool QGuiApplicationPrivate::shouldQuit()
|
||||
{
|
||||
/* if there is no visible top-level window left, we allow the quit */
|
||||
QWindowList list = QGuiApplication::topLevelWindows();
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
QWindow *w = list.at(i);
|
||||
if (w->visible())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\property QGuiApplication::layoutDirection
|
||||
|
@ -74,6 +74,8 @@ public:
|
||||
virtual void notifyLayoutDirectionChange();
|
||||
virtual void notifyActiveWindowChange(QWindow *previous);
|
||||
|
||||
virtual bool shouldQuit();
|
||||
|
||||
static Qt::KeyboardModifiers modifier_buttons;
|
||||
static Qt::MouseButtons mouse_buttons;
|
||||
|
||||
|
@ -165,14 +165,6 @@ void QWindow::setVisible(bool visible)
|
||||
return;
|
||||
d->visible = visible;
|
||||
emit visibleChanged(visible);
|
||||
if (QCoreApplication::instance() && !transientParent()) {
|
||||
QCoreApplicationPrivate *applicationPrivate = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance()));
|
||||
if (visible) {
|
||||
applicationPrivate->ref();
|
||||
} else {
|
||||
applicationPrivate->deref();
|
||||
}
|
||||
}
|
||||
|
||||
if (!d->platformWindow)
|
||||
create();
|
||||
@ -514,15 +506,6 @@ void QWindow::setTransientParent(QWindow *parent)
|
||||
QWindow *previousParent = d->transientParent;
|
||||
|
||||
d->transientParent = parent;
|
||||
|
||||
if (QCoreApplication::instance() && d->visible) {
|
||||
QCoreApplicationPrivate *applicationPrivate = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance()));
|
||||
if (parent && !previousParent) {
|
||||
applicationPrivate->deref();
|
||||
} else if (!parent && previousParent) {
|
||||
applicationPrivate->ref();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QWindow *QWindow::transientParent() const
|
||||
@ -1116,13 +1099,16 @@ void QWindowPrivate::maybeQuitOnLastWindowClosed()
|
||||
bool lastWindowClosed = true;
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
QWindow *w = list.at(i);
|
||||
if (!w->visible() || w->parent())
|
||||
if (!w->visible())
|
||||
continue;
|
||||
lastWindowClosed = false;
|
||||
break;
|
||||
}
|
||||
if (lastWindowClosed)
|
||||
if (lastWindowClosed) {
|
||||
QGuiApplicationPrivate::emitLastWindowClosed();
|
||||
QCoreApplicationPrivate *applicationPrivate = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance()));
|
||||
applicationPrivate->maybeQuit();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -67,6 +67,7 @@
|
||||
#include "private/qstylesheetstyle_p.h"
|
||||
#include "private/qstyle_p.h"
|
||||
#include "qmessagebox.h"
|
||||
#include "qwidgetwindow_qpa_p.h"
|
||||
#include <QtWidgets/qgraphicsproxywidget.h>
|
||||
#include <QtGui/qstylehints.h>
|
||||
#include <QtGui/qinputmethod.h>
|
||||
@ -3289,6 +3290,20 @@ int QApplication::exec()
|
||||
return QGuiApplication::exec();
|
||||
}
|
||||
|
||||
bool QApplicationPrivate::shouldQuit()
|
||||
{
|
||||
/* if there is no non-withdrawn primary window left (except
|
||||
the ones without QuitOnClose), we emit the lastWindowClosed
|
||||
signal */
|
||||
QWidgetList list = QApplication::topLevelWidgets();
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
QWidget *w = list.at(i);
|
||||
if (w->isVisible() && !w->parentWidget() && w->testAttribute(Qt::WA_QuitOnClose))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! \reimp
|
||||
*/
|
||||
bool QApplication::notify(QObject *receiver, QEvent *e)
|
||||
|
@ -178,6 +178,8 @@ public:
|
||||
virtual void notifyLayoutDirectionChange();
|
||||
virtual void notifyActiveWindowChange(QWindow *);
|
||||
|
||||
virtual bool shouldQuit();
|
||||
|
||||
#if defined(Q_WS_X11)
|
||||
#ifndef QT_NO_SETTINGS
|
||||
static bool x11_apply_settings();
|
||||
|
@ -7410,8 +7410,24 @@ bool QWidgetPrivate::close_helper(CloseMode mode)
|
||||
// Attempt to close the application only if this has WA_QuitOnClose set and a non-visible parent
|
||||
quitOnClose = quitOnClose && (parentWidget.isNull() || !parentWidget->isVisible());
|
||||
|
||||
if (quitOnClose && q->windowHandle()) {
|
||||
static_cast<QWindowPrivate*>(QObjectPrivate::get(q->windowHandle()))->maybeQuitOnLastWindowClosed();
|
||||
if (quitOnClose) {
|
||||
/* if there is no non-withdrawn primary window left (except
|
||||
the ones without QuitOnClose), we emit the lastWindowClosed
|
||||
signal */
|
||||
QWidgetList list = QApplication::topLevelWidgets();
|
||||
bool lastWindowClosed = true;
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
QWidget *w = list.at(i);
|
||||
if (!w->isVisible() || w->parentWidget() || !w->testAttribute(Qt::WA_QuitOnClose))
|
||||
continue;
|
||||
lastWindowClosed = false;
|
||||
break;
|
||||
}
|
||||
if (lastWindowClosed) {
|
||||
QGuiApplicationPrivate::emitLastWindowClosed();
|
||||
QCoreApplicationPrivate *applicationPrivate = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance()));
|
||||
applicationPrivate->maybeQuit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -137,16 +137,7 @@ private slots:
|
||||
void touchEventPropagation();
|
||||
|
||||
void qtbug_12673();
|
||||
|
||||
void testQuitLockRef();
|
||||
void testQuitLock1();
|
||||
void testQuitLock2();
|
||||
void testQuitLock3();
|
||||
void testQuitLock4();
|
||||
void testQuitLock5();
|
||||
void testQuitLock6();
|
||||
void testQuitLock7();
|
||||
void testQuitLock8();
|
||||
void noQuitOnHide();
|
||||
|
||||
void globalStaticObjectDestruction(); // run this last
|
||||
|
||||
@ -2060,506 +2051,30 @@ void tst_QApplication::qtbug_12673()
|
||||
QCOMPARE(testProcess.exitStatus(), QProcess::NormalExit);
|
||||
}
|
||||
|
||||
class JobObject : public QObject
|
||||
class NoQuitOnHideWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
JobObject(int milliseconds, QObject *parent = 0)
|
||||
: QObject(parent)
|
||||
NoQuitOnHideWidget(QWidget *parent = 0)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QTimer::singleShot(milliseconds, this, SLOT(timeout()));
|
||||
}
|
||||
|
||||
JobObject(QObject *parent = 0)
|
||||
: QObject(parent)
|
||||
{
|
||||
QTimer::singleShot(1000, this, SLOT(timeout()));
|
||||
QTimer::singleShot(0, this, SLOT(hide()));
|
||||
QTimer::singleShot(500, this, SLOT(exitApp()));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void timeout()
|
||||
{
|
||||
emit done();
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
signals:
|
||||
void done();
|
||||
|
||||
private:
|
||||
QEventLoopLocker locker;
|
||||
};
|
||||
|
||||
class QuitLockRefTester : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QuitLockRefTester(QObject *parent = 0)
|
||||
: QObject(parent)
|
||||
{
|
||||
QTimer::singleShot(0, this, SLOT(doTest()));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void doTest()
|
||||
{
|
||||
QApplicationPrivate *privateClass = static_cast<QApplicationPrivate*>(QObjectPrivate::get(qApp));
|
||||
|
||||
{
|
||||
QDialog *win1 = new QDialog;
|
||||
|
||||
// Test with a lock active so that the refcount doesn't drop to zero during these tests, causing a quit.
|
||||
// (until we exit the scope)
|
||||
QEventLoopLocker locker;
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 1);
|
||||
|
||||
win1->show();
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 2);
|
||||
|
||||
QDialog *win2 = new QDialog;
|
||||
|
||||
win2->show();
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 3);
|
||||
|
||||
delete win1;
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 2);
|
||||
|
||||
delete win2;
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 1);
|
||||
|
||||
win1 = new QDialog;
|
||||
|
||||
win1->show();
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 2);
|
||||
|
||||
JobObject *job1 = new JobObject(this);
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 3);
|
||||
|
||||
delete win1;
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 2);
|
||||
|
||||
delete job1;
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 1);
|
||||
|
||||
QWidget *w1 = new QWidget;
|
||||
|
||||
w1->show();
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 2);
|
||||
|
||||
QWidget *w2 = new QMainWindow;
|
||||
|
||||
w2->show();
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 3);
|
||||
|
||||
QWidget *w3 = new QWidget(0, Qt::Dialog);
|
||||
|
||||
w3->show();
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 4);
|
||||
|
||||
delete w3;
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 3);
|
||||
|
||||
delete w2;
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 2);
|
||||
|
||||
QWidget *subWidget1 = new QWidget(w1, Qt::Window);
|
||||
|
||||
// Even though We create a new widget and show it,
|
||||
// the ref count does not go up because it is a child of
|
||||
// w1, which is the top-level, and what we are actually
|
||||
// refcounting.
|
||||
subWidget1->show();
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 2);
|
||||
|
||||
// When we use setParent(0) and re-show, the
|
||||
// ref count does increase:
|
||||
QCOMPARE(subWidget1->isVisible(), true);
|
||||
subWidget1->setParent(0);
|
||||
QCOMPARE(subWidget1->isVisible(), false);
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 2);
|
||||
|
||||
subWidget1->show();
|
||||
QCOMPARE(subWidget1->isVisible(), true);
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 3);
|
||||
|
||||
subWidget1->setParent(w1);
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 2);
|
||||
|
||||
QWidget *subWidget2 = new QWidget(w1);
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 2);
|
||||
|
||||
subWidget2->show();
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 2);
|
||||
|
||||
delete subWidget2;
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 2);
|
||||
|
||||
QWidget *subWidget3 = new QWidget(w1);
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 2);
|
||||
|
||||
subWidget3->show();
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 2);
|
||||
|
||||
subWidget3->hide();
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 2);
|
||||
|
||||
delete subWidget3;
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 2);
|
||||
|
||||
QWidget *subWidget4 = new QWidget(subWidget1);
|
||||
QWidget *subWidget5 = new QWidget(subWidget1);
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 2);
|
||||
|
||||
QWidget *subWidget6 = new QWidget(subWidget4, Qt::Window);
|
||||
|
||||
subWidget6->show();
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 2);
|
||||
|
||||
delete w1;
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 1);
|
||||
|
||||
w1 = new QWidget;
|
||||
w2 = new QWidget;
|
||||
w3 = new QWidget;
|
||||
|
||||
QHBoxLayout *layout = new QHBoxLayout(w1);
|
||||
|
||||
layout->addWidget(w2);
|
||||
layout->addWidget(w3);
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 1);
|
||||
|
||||
w1->show();
|
||||
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 2);
|
||||
|
||||
w1->hide();
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 1);
|
||||
|
||||
delete w1;
|
||||
|
||||
}
|
||||
QCOMPARE(privateClass->quitLockRef.load(), 0);
|
||||
void exitApp() {
|
||||
qApp->exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
void tst_QApplication::testQuitLockRef()
|
||||
void tst_QApplication::noQuitOnHide()
|
||||
{
|
||||
int argc = 1;
|
||||
char *argv[] = { "tst_qapplication" };
|
||||
QApplication app(argc, argv);
|
||||
|
||||
QuitLockRefTester tester;
|
||||
|
||||
app.exec();
|
||||
}
|
||||
|
||||
void tst_QApplication::testQuitLock1()
|
||||
{
|
||||
int argc = 1;
|
||||
char *argv[] = { "tst_qcoreapplication" };
|
||||
QApplication app(argc, argv);
|
||||
|
||||
QWidget *w = new QWidget;
|
||||
|
||||
w->show();
|
||||
|
||||
QMetaObject::invokeMethod(w, "close", Qt::QueuedConnection);
|
||||
|
||||
app.exec();
|
||||
|
||||
// No hang = pass.
|
||||
}
|
||||
|
||||
void tst_QApplication::testQuitLock2()
|
||||
{
|
||||
int argc = 1;
|
||||
char *argv[] = { "tst_qcoreapplication" };
|
||||
QApplication app(argc, argv);
|
||||
|
||||
QWidget *w1 = new QWidget;
|
||||
|
||||
w1->show();
|
||||
|
||||
QWidget *w2 = new QWidget;
|
||||
|
||||
w2->show();
|
||||
|
||||
QMetaObject::invokeMethod(w1, "deleteLater", Qt::QueuedConnection);
|
||||
QMetaObject::invokeMethod(w2, "hide", Qt::QueuedConnection);
|
||||
|
||||
app.exec();
|
||||
|
||||
// No hang = pass.
|
||||
}
|
||||
|
||||
class Result : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Result(QObject *parent = 0)
|
||||
: QObject(parent), m_passes(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool result() const
|
||||
{
|
||||
return m_passes;
|
||||
}
|
||||
|
||||
public slots:
|
||||
|
||||
void setPasses()
|
||||
{
|
||||
setResult(true);
|
||||
}
|
||||
|
||||
void setFails()
|
||||
{
|
||||
setResult(false);
|
||||
}
|
||||
|
||||
void setResult(bool result)
|
||||
{
|
||||
m_passes = result;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_passes;
|
||||
};
|
||||
|
||||
void tst_QApplication::testQuitLock3()
|
||||
{
|
||||
int argc = 1;
|
||||
char *argv[] = { "tst_qcoreapplication" };
|
||||
QApplication app(argc, argv);
|
||||
|
||||
Result *result = new Result(&app);
|
||||
|
||||
JobObject *job = new JobObject(&app);
|
||||
|
||||
QObject::connect(job, SIGNAL(done()), result, SLOT(setPasses()));
|
||||
|
||||
app.exec();
|
||||
|
||||
QVERIFY(result->result());
|
||||
}
|
||||
|
||||
void tst_QApplication::testQuitLock4()
|
||||
{
|
||||
int argc = 1;
|
||||
char *argv[] = { "tst_qcoreapplication" };
|
||||
QApplication app(argc, argv);
|
||||
|
||||
QWidget *w = new QWidget;
|
||||
|
||||
w->show();
|
||||
|
||||
Result *result = new Result(&app);
|
||||
JobObject *job = new JobObject(1000, &app);
|
||||
|
||||
QTimer::singleShot(500, w, SLOT(deleteLater()));
|
||||
|
||||
QObject::connect(w, SIGNAL(destroyed()), result, SLOT(setFails()));
|
||||
QObject::connect(job, SIGNAL(done()), result, SLOT(setPasses()));
|
||||
|
||||
app.exec();
|
||||
|
||||
QVERIFY(result->result());
|
||||
}
|
||||
|
||||
class JobBeforeWindowRunner : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
JobBeforeWindowRunner(QObject *parent = 0)
|
||||
: QObject(parent), m_result(new Result(this))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
JobObject *job = new JobObject(this);
|
||||
connect(job, SIGNAL(done()), m_result, SLOT(setFails()));
|
||||
connect(job, SIGNAL(destroyed()), SLOT(showWindowDelayed()), Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
bool result() const { return m_result->result(); }
|
||||
|
||||
private slots:
|
||||
void showWindowDelayed()
|
||||
{
|
||||
qApp->setQuitLockEnabled(true);
|
||||
QTimer::singleShot(500, this, SLOT(showWindow()));
|
||||
}
|
||||
|
||||
void showWindow()
|
||||
{
|
||||
QWidget *w = new QWidget;
|
||||
w->show();
|
||||
w->deleteLater();
|
||||
connect(w, SIGNAL(destroyed()), m_result, SLOT(setPasses()));
|
||||
}
|
||||
|
||||
private:
|
||||
Result * const m_result;
|
||||
};
|
||||
|
||||
void tst_QApplication::testQuitLock5()
|
||||
{
|
||||
int argc = 1;
|
||||
char *argv[] = { "tst_qcoreapplication" };
|
||||
QApplication app(argc, argv);
|
||||
app.setQuitLockEnabled(false);
|
||||
// Run a job before showing a window, and only enable the refcounting
|
||||
// after doing so.
|
||||
// Although the job brings the refcount to zero, the app does not exit
|
||||
// until setQuitLockEnabled is called and the feature re-enabled.
|
||||
|
||||
JobBeforeWindowRunner *eventRunner = new JobBeforeWindowRunner(&app);
|
||||
|
||||
eventRunner->start();
|
||||
|
||||
app.exec();
|
||||
|
||||
QVERIFY(eventRunner->result());
|
||||
}
|
||||
|
||||
class JobDuringWindowRunner : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
JobDuringWindowRunner(QObject *parent = 0)
|
||||
: QObject(parent), m_result(new Result(this))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
JobObject *job = new JobObject(this);
|
||||
|
||||
QWidget *w = new QWidget;
|
||||
w->show();
|
||||
w->deleteLater();
|
||||
|
||||
QObject::connect(w, SIGNAL(destroyed()), m_result, SLOT(setFails()));
|
||||
QObject::connect(job, SIGNAL(done()), m_result, SLOT(setPasses()));
|
||||
}
|
||||
|
||||
bool result() const { return m_result->result(); }
|
||||
|
||||
private:
|
||||
Result * const m_result;
|
||||
};
|
||||
|
||||
void tst_QApplication::testQuitLock6()
|
||||
{
|
||||
int argc = 1;
|
||||
char *argv[] = { "tst_qcoreapplication" };
|
||||
QApplication app(argc, argv);
|
||||
|
||||
// A job runs, and while it is running, a window is shown and closed,
|
||||
// then the job ends, which causes the quit.
|
||||
|
||||
JobDuringWindowRunner *eventRunner = new JobDuringWindowRunner(&app);
|
||||
|
||||
eventRunner->start();
|
||||
|
||||
app.exec();
|
||||
|
||||
QVERIFY(eventRunner->result());
|
||||
}
|
||||
class JobWindowJobWindowRunner : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
JobWindowJobWindowRunner(QObject *parent = 0)
|
||||
: QObject(parent), m_result(new Result(this))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
JobObject *job = new JobObject(500, this);
|
||||
|
||||
QWidget *w = new QWidget;
|
||||
w->show();
|
||||
QTimer::singleShot(1000, w, SLOT(deleteLater()));
|
||||
|
||||
QObject::connect(w, SIGNAL(destroyed()), m_result, SLOT(setPasses()));
|
||||
QObject::connect(job, SIGNAL(done()), m_result, SLOT(setFails()));
|
||||
}
|
||||
|
||||
bool result() const { return m_result->result(); }
|
||||
private:
|
||||
Result * const m_result;
|
||||
};
|
||||
|
||||
void tst_QApplication::testQuitLock7()
|
||||
{
|
||||
int argc = 1;
|
||||
char *argv[] = { "tst_qcoreapplication" };
|
||||
QApplication app(argc, argv);
|
||||
|
||||
// A job runs, and while it is running, a window is shown
|
||||
// then the job ends, then the window is closed, which causes the quit.
|
||||
|
||||
JobWindowJobWindowRunner *eventRunner = new JobWindowJobWindowRunner(&app);
|
||||
|
||||
eventRunner->start();
|
||||
|
||||
app.exec();
|
||||
|
||||
QVERIFY(eventRunner->result());
|
||||
}
|
||||
|
||||
void tst_QApplication::testQuitLock8()
|
||||
{
|
||||
int argc = 1;
|
||||
char *argv[] = { "tst_qcoreapplication" };
|
||||
QApplication app(argc, argv);
|
||||
|
||||
QMainWindow *mw1 = new QMainWindow;
|
||||
mw1->show();
|
||||
QMainWindow *mw2 = new QMainWindow;
|
||||
mw2->show();
|
||||
|
||||
QMetaObject::invokeMethod(mw1, "close", Qt::QueuedConnection);
|
||||
QMetaObject::invokeMethod(mw2, "close", Qt::QueuedConnection);
|
||||
|
||||
app.exec();
|
||||
|
||||
// No hang = pass
|
||||
int argc = 0;
|
||||
QApplication app(argc, 0);
|
||||
QWidget *window1 = new NoQuitOnHideWidget(false);
|
||||
window1->show();
|
||||
QCOMPARE(app.exec(), 1);
|
||||
}
|
||||
|
||||
class ShowCloseShowWidget : public QWidget
|
||||
|
Loading…
Reference in New Issue
Block a user