summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStephen Kelly <stephen.kelly@kdab.com>2012-02-11 01:33:55 +0100
committerQt by Nokia <qt-info@nokia.com>2012-02-16 01:56:27 +0100
commit66603985f2de74ac5f3bd5d259f0e65f710f62d7 (patch)
tree65049a5d31f1e8a978f60f5fc12d1dd26be73284 /src
parent90feedb6429df225b81bc279093ae1ca1278b391 (diff)
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>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp10
-rw-r--r--src/corelib/kernel/qcoreapplication_p.h4
-rw-r--r--src/gui/kernel/qguiapplication.cpp11
-rw-r--r--src/gui/kernel/qguiapplication_p.h2
-rw-r--r--src/gui/kernel/qwindow.cpp24
-rw-r--r--src/widgets/kernel/qapplication.cpp15
-rw-r--r--src/widgets/kernel/qapplication_p.h2
-rw-r--r--src/widgets/kernel/qwidget.cpp20
8 files changed, 65 insertions, 23 deletions
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index cf3ae1b7c5..80e42336d6 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -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));
}
/*!
diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h
index 861a046f16..112b313129 100644
--- a/src/corelib/kernel/qcoreapplication_p.h
+++ b/src/corelib/kernel/qcoreapplication_p.h
@@ -92,6 +92,10 @@ public:
QAtomicInt quitLockRef;
void ref();
void deref();
+ virtual bool shouldQuit() {
+ return true;
+ }
+ void maybeQuit();
static QThread *theMainThread;
static QThread *mainThread();
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 4d80aafea5..5f50fe343a 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -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
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index 7fafe0336d..f86d8264fa 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -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;
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 61ae2a2438..d15198c505 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -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();
+ }
}
}
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 4387d2a287..b04925d85d 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -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)
diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h
index 790176afe3..e728868182 100644
--- a/src/widgets/kernel/qapplication_p.h
+++ b/src/widgets/kernel/qapplication_p.h
@@ -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();
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index f98f7fbe66..f095e475af 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -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();
+ }
}