Plumb application quit through platform plugin

If we have a platform plugin we ask the platform to quit, and if
not we fall back to the base implementation of QCoreApplication
that sends Quit events directly.

This allows the platform to involve the rest of the system in the
process. The platform will then come back with a spontaneous quit
via QWSI::handleApplicationTermination(), which will then send
the corresponding Quit even from QGuiApplication like normal.

Task-number: QTBUG-45262
Task-number: QTBUG-33235
Task-number: QTBUG-72013
Task-number: QTBUG-59782
Change-Id: I0000aaf7192e4b905933c5da0e53901c6c88f26a
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Tor Arne Vestbø 2019-10-15 14:18:40 +02:00
parent cc570ce2fe
commit 0c02f133f3
11 changed files with 45 additions and 7 deletions

View File

@ -1975,11 +1975,18 @@ void QCoreApplication::quit()
if (!self)
return;
if (QThread::currentThread() == self->d_func()->mainThread()) {
self->d_func()->quit();
}
void QCoreApplicationPrivate::quit()
{
Q_Q(QCoreApplication);
if (QThread::currentThread() == mainThread()) {
QEvent quitEvent(QEvent::Quit);
QCoreApplication::sendEvent(self, &quitEvent);
QCoreApplication::sendEvent(q, &quitEvent);
} else {
QCoreApplication::postEvent(self, new QEvent(QEvent::Quit));
QCoreApplication::postEvent(q, new QEvent(QEvent::Quit));
}
}

View File

@ -135,6 +135,8 @@ public:
virtual bool shouldQuit() {
return true;
}
virtual void quit();
void maybeQuit();
static QBasicAtomicPointer<QThread> theMainThread;

View File

@ -3641,6 +3641,14 @@ bool QGuiApplicationPrivate::shouldQuitInternal(const QWindowList &processedWind
return true;
}
void QGuiApplicationPrivate::quit()
{
if (auto *platformIntegration = QGuiApplicationPrivate::platformIntegration())
platformIntegration->quit();
else
QCoreApplicationPrivate::quit();
}
void QGuiApplicationPrivate::processApplicationTermination(QWindowSystemInterfacePrivate::WindowSystemEvent *windowSystemEvent)
{
QEvent event(QEvent::Quit);

View File

@ -105,6 +105,7 @@ public:
void addQtOptions(QList<QCommandLineOption> *options) override;
#endif
virtual bool shouldQuit() override;
void quit() override;
bool shouldQuitInternal(const QWindowList &processedWindows);

View File

@ -529,6 +529,20 @@ void QPlatformIntegration::beep() const
{
}
/*!
\since 6.0
Asks the platform to terminate the application.
Overrides should ensure there's a callback into the QWSI
function handleApplicationTermination so that the quit can
be propagated to QtGui and the application.
*/
void QPlatformIntegration::quit() const
{
QWindowSystemInterface::handleApplicationTermination<QWindowSystemInterface::SynchronousDelivery>();
}
#ifndef QT_NO_OPENGL
/*!
Platform integration function for querying the OpenGL implementation type.

View File

@ -220,6 +220,7 @@ public:
virtual void setApplicationIcon(const QIcon &icon) const;
virtual void beep() const;
virtual void quit() const;
#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
virtual QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const;

View File

@ -92,10 +92,6 @@
#include <qpa/qwindowsysteminterface.h>
#include <qwindowdefs.h>
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQpaApplication, "qt.qpa.application");
QT_END_NAMESPACE
QT_USE_NAMESPACE
@implementation QCocoaApplicationDelegate {

View File

@ -72,6 +72,7 @@ Q_DECLARE_LOGGING_CATEGORY(lcQpaWindow)
Q_DECLARE_LOGGING_CATEGORY(lcQpaDrawing)
Q_DECLARE_LOGGING_CATEGORY(lcQpaMouse)
Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen)
Q_DECLARE_LOGGING_CATEGORY(lcQpaApplication)
class QPixmap;
class QString;

View File

@ -59,6 +59,7 @@ Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window");
Q_LOGGING_CATEGORY(lcQpaDrawing, "qt.qpa.drawing");
Q_LOGGING_CATEGORY(lcQpaMouse, "qt.qpa.input.mouse", QtCriticalMsg);
Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen", QtCriticalMsg);
Q_LOGGING_CATEGORY(lcQpaApplication, "qt.qpa.application");
//
// Conversion Functions

View File

@ -132,6 +132,7 @@ public:
void setApplicationIcon(const QIcon &icon) const override;
void beep() const override;
void quit() const override;
void closePopups(QWindow *forWindow = nullptr);

View File

@ -488,6 +488,12 @@ void QCocoaIntegration::beep() const
NSBeep();
}
void QCocoaIntegration::quit() const
{
qCDebug(lcQpaApplication) << "Terminating application";
[NSApp terminate:nil];
}
void QCocoaIntegration::closePopups(QWindow *forWindow)
{
for (auto it = m_popupWindowStack.begin(); it != m_popupWindowStack.end();) {