diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-10-22 01:00:49 +0200 |
---|---|---|
committer | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-10-22 01:00:49 +0200 |
commit | 563dc21c517647e72785247bbbf07d1b6553f59c (patch) | |
tree | 6c96f317da30520d1ad253a3785878abc4ec1cf1 /src | |
parent | 35adb74ddd915831789f0175423660f8e898942e (diff) | |
parent | aa4b0f5cb7e84046530fbc26581f777506fea658 (diff) | |
download | qtbase-563dc21c517647e72785247bbbf07d1b6553f59c.tar.gz |
Merge remote-tracking branch 'origin/5.14' into 5.15
Change-Id: Ic062a5bd62621877b17cc0d47303b3c879241385
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/kernel/qguiapplication.cpp | 23 | ||||
-rw-r--r-- | src/gui/kernel/qguiapplication_p.h | 2 | ||||
-rw-r--r-- | src/gui/kernel/qwindowsysteminterface.cpp | 6 | ||||
-rw-r--r-- | src/gui/kernel/qwindowsysteminterface.h | 3 | ||||
-rw-r--r-- | src/gui/kernel/qwindowsysteminterface_p.h | 3 | ||||
-rw-r--r-- | src/gui/rhi/qrhi.cpp | 26 | ||||
-rw-r--r-- | src/gui/text/qtextengine.cpp | 24 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm | 49 | ||||
-rw-r--r-- | src/plugins/platforms/haiku/qhaikuapplication.cpp | 5 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbsessionmanager.cpp | 5 | ||||
-rw-r--r-- | src/tools/uic/cpp/cppwriteinitialization.cpp | 2 | ||||
-rw-r--r-- | src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc | 4 | ||||
-rw-r--r-- | src/widgets/kernel/qapplication.cpp | 19 |
13 files changed, 104 insertions, 67 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index b4c4231910..f09f7e941b 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1865,7 +1865,20 @@ bool QGuiApplication::event(QEvent *e) { if(e->type() == QEvent::LanguageChange) { setLayoutDirection(qt_detectRTLLanguage()?Qt::RightToLeft:Qt::LeftToRight); + } else if (e->type() == QEvent::Quit) { + // Close open windows. This is done in order to deliver de-expose + // events while the event loop is still running. + for (QWindow *topLevelWindow : QGuiApplication::topLevelWindows()) { + // Already closed windows will not have a platform window, skip those + if (!topLevelWindow->handle()) + continue; + if (!topLevelWindow->close()) { + e->ignore(); + return true; + } + } } + return QCoreApplication::event(e); } @@ -1942,6 +1955,9 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv QWindowSystemInterfacePrivate::ApplicationStateChangedEvent * changeEvent = static_cast<QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *>(e); QGuiApplicationPrivate::setApplicationState(changeEvent->newState, changeEvent->forcePropagate); } break; + case QWindowSystemInterfacePrivate::ApplicationTermination: + QGuiApplicationPrivate::processApplicationTermination(e); + break; case QWindowSystemInterfacePrivate::FlushEvents: { QWindowSystemInterfacePrivate::FlushEventsEvent *flushEventsEvent = static_cast<QWindowSystemInterfacePrivate::FlushEventsEvent *>(e); QWindowSystemInterface::deferredFlushWindowSystemEvents(flushEventsEvent->flags); } @@ -3491,6 +3507,13 @@ bool QGuiApplicationPrivate::tryCloseRemainingWindows(QWindowList processedWindo return true; } +void QGuiApplicationPrivate::processApplicationTermination(QWindowSystemInterfacePrivate::WindowSystemEvent *windowSystemEvent) +{ + QEvent event(QEvent::Quit); + QGuiApplication::sendSpontaneousEvent(QGuiApplication::instance(), &event); + windowSystemEvent->eventAccepted = event.isAccepted(); +} + /*! \since 5.2 \fn Qt::ApplicationState QGuiApplication::applicationState() diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index e28607bad6..26f65b2f16 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -141,6 +141,8 @@ public: static void processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e); + static void processApplicationTermination(QWindowSystemInterfacePrivate::WindowSystemEvent *e); + static void updateFilteredScreenOrientation(QScreen *screen); static void reportScreenOrientationChange(QScreen *screen); static void processScreenOrientationChange(QWindowSystemInterfacePrivate::ScreenOrientationEvent *e); diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 5f61853a6d..4f1056e906 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -285,6 +285,12 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleApplicationStateChanged, Qt::Application QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); } +QT_DEFINE_QPA_EVENT_HANDLER(bool, handleApplicationTermination) +{ + auto *e = new QWindowSystemInterfacePrivate::WindowSystemEvent(QWindowSystemInterfacePrivate::ApplicationTermination); + return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); +} + QWindowSystemInterfacePrivate::GeometryChangeEvent::GeometryChangeEvent(QWindow *window, const QRect &newGeometry) : WindowSystemEvent(GeometryChange) , window(window) diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index 4a0bc858a9..d5a4ad30d8 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -215,6 +215,9 @@ public: template<typename Delivery = QWindowSystemInterface::DefaultDelivery> static void handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate = false); + template<typename Delivery = QWindowSystemInterface::DefaultDelivery> + static bool handleApplicationTermination(); + #if QT_CONFIG(draganddrop) #if QT_DEPRECATED_SINCE(5, 11) QT_DEPRECATED static QPlatformDragQtResponse handleDrag(QWindow *window, const QMimeData *dropData, diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h index 55fd181ef0..6e4bce607e 100644 --- a/src/gui/kernel/qwindowsysteminterface_p.h +++ b/src/gui/kernel/qwindowsysteminterface_p.h @@ -99,7 +99,8 @@ public: ApplicationStateChanged = 0x19, FlushEvents = 0x20, WindowScreenChanged = 0x21, - SafeAreaMarginsChanged = 0x22 + SafeAreaMarginsChanged = 0x22, + ApplicationTermination = 0x23 }; class WindowSystemEvent { diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp index dabad35688..8ef98d2e42 100644 --- a/src/gui/rhi/qrhi.cpp +++ b/src/gui/rhi/qrhi.cpp @@ -3518,14 +3518,36 @@ QRhiResource::Type QRhiSwapChain::resourceType() const \c{currentPixelSize() != surfacePixelSize()} then the swapchain needs to be resized. + \note Typical rendering logic will call this function to get the output + size when starting to prepare a new frame, and base dependent calculations + (such as, the viewport) on the size returned from this function. + + While in many cases the value is the same as \c{QWindow::size() * + QWindow::devicePixelRatio()}, relying on the QWindow-reported size is not + guaranteed to be correct on all platforms and graphics API implementations. + Using this function is therefore strongly recommended whenever there is a + need to identify the dimensions, in pixels, of the output layer or surface. + + This also has the added benefit of avoiding potential data races when QRhi + is used on a dedicated rendering thread, because the need to call QWindow + functions, that may then access data updated on the main thread, is + avoided. + \sa surfacePixelSize() */ /*! \fn QSize QRhiSwapChain::surfacePixelSize() - \return The size of the window's associated surface or layer. Do not assume - this is the same as QWindow::size() * QWindow::devicePixelRatio(). + \return The size of the window's associated surface or layer. + + \warning Do not assume this is the same as \c{QWindow::size() * + QWindow::devicePixelRatio()}. With some graphics APIs and windowing system + interfaces (for example, Vulkan) there is a theoretical possibility for a + surface to assume a size different from the associated window. To support + these cases, rendering logic must always base size-derived calculations + (such as, viewports) on the size reported from QRhiSwapChain, and never on + the size queried from QWindow. \note Can also be called before buildOrResize(), if at least window() is already set) This in combination with currentPixelSize() allows to detect diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index b37353bf2c..209433dac5 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -2125,22 +2125,7 @@ void QTextEngine::itemize() const } #if QT_CONFIG(harfbuzz) analysis = scriptAnalysis.data(); - if (qt_useHarfbuzzNG()) { - // ### pretend HB-old behavior for now - for (int i = 0; i < length; ++i) { - switch (analysis[i].script) { - case QChar::Script_Latin: - case QChar::Script_Hiragana: - case QChar::Script_Katakana: - case QChar::Script_Bopomofo: - case QChar::Script_Han: - analysis[i].script = QChar::Script_Common; - break; - default: - break; - } - } - } else { + if (!qt_useHarfbuzzNG()) { for (int i = 0; i < length; ++i) analysis[i].script = hbscript_to_script(script_to_hbscript(analysis[i].script)); } @@ -3619,7 +3604,12 @@ int QTextEngine::positionInLigature(const QScriptItem *si, int end, int clusterLength = 0; if (si->analysis.script != QChar::Script_Common && - si->analysis.script != QChar::Script_Greek) { + si->analysis.script != QChar::Script_Greek && + si->analysis.script != QChar::Script_Latin && + si->analysis.script != QChar::Script_Hiragana && + si->analysis.script != QChar::Script_Katakana && + si->analysis.script != QChar::Script_Bopomofo && + si->analysis.script != QChar::Script_Han) { if (glyph_pos == -1) return si->position + end; else { diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm index 33a45985a8..9b0a6b1b86 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm @@ -88,10 +88,13 @@ #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 { - bool startedQuit; NSObject <NSApplicationDelegate> *reflectionDelegate; bool inLaunch; } @@ -140,46 +143,30 @@ QT_USE_NAMESPACE return [[self.dockMenu retain] autorelease]; } -- (BOOL)canQuit -{ - QCloseEvent ev; - QGuiApplication::sendEvent(qGuiApp, &ev); - return ev.isAccepted(); -} - // This function will only be called when NSApp is actually running. - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { if ([reflectionDelegate respondsToSelector:_cmd]) return [reflectionDelegate applicationShouldTerminate:sender]; - if ([self canQuit]) { - if (!startedQuit) { - startedQuit = true; - // Close open windows. This is done in order to deliver de-expose - // events while the event loop is still running. - const QWindowList topLevels = QGuiApplication::topLevelWindows(); - for (int i = 0; i < topLevels.size(); ++i) { - QWindow *topLevelWindow = topLevels.at(i); - // Already closed windows will not have a platform window, skip those - if (topLevelWindow->handle()) - QWindowSystemInterface::handleCloseEvent(topLevelWindow); - } - QWindowSystemInterface::flushWindowSystemEvents(); - - QGuiApplication::exit(0); - startedQuit = false; - } - } - if (QGuiApplicationPrivate::instance()->threadData->eventLoops.isEmpty()) { - // INVARIANT: No event loop is executing. This probably - // means that Qt is used as a plugin, or as a part of a native - // Cocoa application. In any case it should be fine to - // terminate now: + // No event loop is executing. This probably means that Qt is used as a plugin, + // or as a part of a native Cocoa application. In any case it should be fine to + // terminate now. + qCDebug(lcQpaApplication) << "No running event loops, terminating now"; return NSTerminateNow; } + if (!QWindowSystemInterface::handleApplicationTermination<QWindowSystemInterface::SynchronousDelivery>()) { + qCDebug(lcQpaApplication) << "Application termination canceled"; + return NSTerminateCancel; + } + + // Even if the application termination was accepted by the application we can't + // return NSTerminateNow, as that would trigger AppKit to ultimately call exit(). + // We need to ensure that the runloop continues spinning so that we can return + // from our own event loop back to main(), and exit from there. + qCDebug(lcQpaApplication) << "Termination accepted, but returning to runloop for exit through main()"; return NSTerminateCancel; } diff --git a/src/plugins/platforms/haiku/qhaikuapplication.cpp b/src/plugins/platforms/haiku/qhaikuapplication.cpp index b75810c453..de4acdfd4a 100644 --- a/src/plugins/platforms/haiku/qhaikuapplication.cpp +++ b/src/plugins/platforms/haiku/qhaikuapplication.cpp @@ -42,6 +42,8 @@ #include <QCoreApplication> #include <QFileOpenEvent> +#include <qpa/qwindowsysteminterface.h> + #include <Entry.h> #include <Path.h> @@ -52,8 +54,7 @@ QHaikuApplication::QHaikuApplication(const char *signature) bool QHaikuApplication::QuitRequested() { - QEvent quitEvent(QEvent::Quit); - QCoreApplication::sendEvent(QCoreApplication::instance(), &quitEvent); + QWindowSystemInterface::handleApplicationTermination<QWindowSystemInterface::SynchronousDelivery>(); return true; } diff --git a/src/plugins/platforms/xcb/qxcbsessionmanager.cpp b/src/plugins/platforms/xcb/qxcbsessionmanager.cpp index 2303ccf806..f880d4d722 100644 --- a/src/plugins/platforms/xcb/qxcbsessionmanager.cpp +++ b/src/plugins/platforms/xcb/qxcbsessionmanager.cpp @@ -42,6 +42,8 @@ #ifndef QT_NO_SESSIONMANAGER +#include <qpa/qwindowsysteminterface.h> + #include <qguiapplication.h> #include <qdatetime.h> #include <qfileinfo.h> @@ -289,8 +291,7 @@ static void sm_dieCallback(SmcConn smcConn, SmPointer /* clientData */) if (smcConn != smcConnection) return; resetSmState(); - QEvent quitEvent(QEvent::Quit); - QGuiApplication::sendEvent(qApp, &quitEvent); + QWindowSystemInterface::handleApplicationTermination<QWindowSystemInterface::SynchronousDelivery>(); } static void sm_shutdownCancelledCallback(SmcConn smcConn, SmPointer clientData) diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp index fd5f8c9017..717bff4a51 100644 --- a/src/tools/uic/cpp/cppwriteinitialization.cpp +++ b/src/tools/uic/cpp/cppwriteinitialization.cpp @@ -1680,7 +1680,7 @@ static void writeResourceIcon(QTextStream &output, "Selected", "Off"); } if (i->hasElementSelectedOn()) { - writeIconAddFile(output, indent, iconName, i->elementSelectedOff()->text(), + writeIconAddFile(output, indent, iconName, i->elementSelectedOn()->text(), "Selected", "On"); } } diff --git a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc index 00323eace6..84233e4b62 100644 --- a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc +++ b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc @@ -549,6 +549,10 @@ If the property references an enum declared with Q_ENUMS, you should reference its constants by name, i.e., not their numeric value. + \note Use the qproperty syntax with care, as it modifies the + widget that is being painted. Also, the qproperty syntax is evaluated only + once, which is when the widget is polished by the style. This means that any + attempt to use them in pseudo-states such as QPushButton:hover, will not work. */ /*! diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 3223781b63..dfa1bc23b1 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -1866,22 +1866,19 @@ void QApplication::aboutQt() bool QApplication::event(QEvent *e) { Q_D(QApplication); - if(e->type() == QEvent::Close) { - QCloseEvent *ce = static_cast<QCloseEvent*>(e); - ce->accept(); + if (e->type() == QEvent::Quit) { closeAllWindows(); - - const QWidgetList list = topLevelWidgets(); - for (auto *w : list) { + for (auto *w : topLevelWidgets()) { if (w->isVisible() && !(w->windowType() == Qt::Desktop) && !(w->windowType() == Qt::Popup) && (!(w->windowType() == Qt::Dialog) || !w->parentWidget())) { - ce->ignore(); - break; + e->ignore(); + return true; } } - if (ce->isAccepted()) { - return true; - } + // Explicitly call QCoreApplication instead of QGuiApplication so that + // we don't let QGuiApplication close any windows we skipped earlier in + // closeAllWindows(). FIXME: Unify all this close magic through closeAllWindows. + return QCoreApplication::event(e); #ifndef Q_OS_WIN } else if (e->type() == QEvent::LocaleChange) { // on Windows the event propagation is taken care by the |