diff options
author | Stephen Kelly <stephen.kelly@kdab.com> | 2012-02-11 01:33:55 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-02-16 01:56:27 +0100 |
commit | 66603985f2de74ac5f3bd5d259f0e65f710f62d7 (patch) | |
tree | 65049a5d31f1e8a978f60f5fc12d1dd26be73284 /src | |
parent | 90feedb6429df225b81bc279093ae1ca1278b391 (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.cpp | 10 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication_p.h | 4 | ||||
-rw-r--r-- | src/gui/kernel/qguiapplication.cpp | 11 | ||||
-rw-r--r-- | src/gui/kernel/qguiapplication_p.h | 2 | ||||
-rw-r--r-- | src/gui/kernel/qwindow.cpp | 24 | ||||
-rw-r--r-- | src/widgets/kernel/qapplication.cpp | 15 | ||||
-rw-r--r-- | src/widgets/kernel/qapplication_p.h | 2 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget.cpp | 20 |
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(); + } } |