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) if (!self)
return; 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); QEvent quitEvent(QEvent::Quit);
QCoreApplication::sendEvent(self, &quitEvent); QCoreApplication::sendEvent(q, &quitEvent);
} else { } 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() { virtual bool shouldQuit() {
return true; return true;
} }
virtual void quit();
void maybeQuit(); void maybeQuit();
static QBasicAtomicPointer<QThread> theMainThread; static QBasicAtomicPointer<QThread> theMainThread;

View File

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

View File

@ -105,6 +105,7 @@ public:
void addQtOptions(QList<QCommandLineOption> *options) override; void addQtOptions(QList<QCommandLineOption> *options) override;
#endif #endif
virtual bool shouldQuit() override; virtual bool shouldQuit() override;
void quit() override;
bool shouldQuitInternal(const QWindowList &processedWindows); 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 #ifndef QT_NO_OPENGL
/*! /*!
Platform integration function for querying the OpenGL implementation type. 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 setApplicationIcon(const QIcon &icon) const;
virtual void beep() const; virtual void beep() const;
virtual void quit() const;
#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC) #if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
virtual QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const; virtual QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const;

View File

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

View File

@ -72,6 +72,7 @@ Q_DECLARE_LOGGING_CATEGORY(lcQpaWindow)
Q_DECLARE_LOGGING_CATEGORY(lcQpaDrawing) Q_DECLARE_LOGGING_CATEGORY(lcQpaDrawing)
Q_DECLARE_LOGGING_CATEGORY(lcQpaMouse) Q_DECLARE_LOGGING_CATEGORY(lcQpaMouse)
Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen) Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen)
Q_DECLARE_LOGGING_CATEGORY(lcQpaApplication)
class QPixmap; class QPixmap;
class QString; 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(lcQpaDrawing, "qt.qpa.drawing");
Q_LOGGING_CATEGORY(lcQpaMouse, "qt.qpa.input.mouse", QtCriticalMsg); Q_LOGGING_CATEGORY(lcQpaMouse, "qt.qpa.input.mouse", QtCriticalMsg);
Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen", QtCriticalMsg); Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen", QtCriticalMsg);
Q_LOGGING_CATEGORY(lcQpaApplication, "qt.qpa.application");
// //
// Conversion Functions // Conversion Functions

View File

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

View File

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