diff options
author | Liang Qi <liang.qi@qt.io> | 2019-03-06 12:31:50 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2019-03-06 12:31:50 +0100 |
commit | 2add2dbdaa9ff6ca6637ca22d6a9b7c7027751be (patch) | |
tree | 585628b0ceacfbdef5b9661c4043b9f71dfe9b01 | |
parent | f792fed2ff519ffac1436e41e47cc0504d253a77 (diff) | |
parent | 4eda22ea0db1fc571ae9f44a68825056e6245548 (diff) |
Merge remote-tracking branch 'origin/5.12' into 5.13
Conflicts:
src/network/access/http2/hpacktable_p.h
Change-Id: Ie0c296667dfdebba84f4858056a1ac80c24ee7df
24 files changed, 439 insertions, 444 deletions
diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index a855fcd0a5..16f9361d13 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -84,6 +84,7 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags) if (impexts.isEmpty()) impexts = project->values("QMAKE_EXTENSION_STATICLIB"); QList<QMakeLocalFileName> dirs; + int libidx = 0; for (const ProString &dlib : project->values("QMAKE_DEFAULT_LIBDIRS")) dirs.append(QMakeLocalFileName(dlib.toQString())); static const char * const lflags[] = { "LIBS", "LIBS_PRIVATE", @@ -96,11 +97,12 @@ Win32MakefileGenerator::findLibraries(bool linkPrl, bool mergeLflags) LibFlagType type = parseLibFlag(opt, &arg); if (type == LibFlagPath) { QMakeLocalFileName lp(arg.toQString()); - if (dirs.contains(lp)) { + int idx = dirs.indexOf(lp); + if (idx >= 0 && idx < libidx) { it = l.erase(it); continue; } - dirs.append(lp); + dirs.insert(libidx++, lp); (*it) = "-L" + lp.real(); } else if (type == LibFlagLib) { QString lib = arg.toQString(); diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index 7e3be9ef36..35bb465a04 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -912,16 +912,20 @@ QTemporaryFile *QTemporaryFile::createNativeFile(QFile &file) file.open(QIODevice::ReadOnly); //dump data QTemporaryFile *ret = new QTemporaryFile; - ret->open(); - file.seek(0); - char buffer[1024]; - while(true) { - qint64 len = file.read(buffer, 1024); - if(len < 1) - break; - ret->write(buffer, len); + if (ret->open()) { + file.seek(0); + char buffer[1024]; + while (true) { + qint64 len = file.read(buffer, 1024); + if (len < 1) + break; + ret->write(buffer, len); + } + ret->seek(0); + } else { + delete ret; + ret = nullptr; } - ret->seek(0); //restore if(wasOpen) file.seek(old_off); diff --git a/src/corelib/kernel/qcore_mac.cpp b/src/corelib/kernel/qcore_mac.cpp index e78b2d1171..b048576f5b 100644 --- a/src/corelib/kernel/qcore_mac.cpp +++ b/src/corelib/kernel/qcore_mac.cpp @@ -65,6 +65,19 @@ QCFString::operator CFStringRef() const #if defined(QT_USE_APPLE_UNIFIED_LOGGING) +bool AppleUnifiedLogger::willMirrorToStderr() +{ + // When running under Xcode or LLDB, one or more of these variables will + // be set, which triggers libsystem_trace.dyld to log messages to stderr + // as well, via_os_log_impl_mirror_to_stderr. Un-setting these variables + // is not an option, as that would silence normal NSLog or os_log calls, + // so instead we skip our own stderr output. See rdar://36919139. + static bool willMirror = qEnvironmentVariableIsSet("OS_ACTIVITY_DT_MODE") + || qEnvironmentVariableIsSet("ACTIVITY_LOG_STDERR") + || qEnvironmentVariableIsSet("CFLOG_FORCE_STDERR"); + return willMirror; +} + QT_MAC_WEAK_IMPORT(_os_log_default); bool AppleUnifiedLogger::messageHandler(QtMsgType msgType, const QMessageLogContext &context, const QString &message, const QString &optionalSubsystem) @@ -103,15 +116,7 @@ bool AppleUnifiedLogger::messageHandler(QtMsgType msgType, const QMessageLogCont // system from redacting our log message. os_log_with_type(log, logType, "%{public}s", qPrintable(message)); - // When running under Xcode or LLDB, one or more of these variables will - // be set, which triggers libsystem_trace.dyld to log messages to stderr - // as well, via_os_log_impl_mirror_to_stderr. Un-setting these variables - // is not an option, as that would silence normal NSLog or os_log calls, - // so instead we skip our own stderr output. See rdar://36919139. - static bool mirroredToStderr = qEnvironmentVariableIsSet("OS_ACTIVITY_DT_MODE") - || qEnvironmentVariableIsSet("ACTIVITY_LOG_STDERR") - || qEnvironmentVariableIsSet("CFLOG_FORCE_STDERR"); - return mirroredToStderr; + return willMirrorToStderr(); } os_log_type_t AppleUnifiedLogger::logTypeForMessageType(QtMsgType msgType) diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index acb87f8a3c..f96e7358a2 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -202,6 +202,7 @@ class Q_CORE_EXPORT AppleUnifiedLogger public: static bool messageHandler(QtMsgType msgType, const QMessageLogContext &context, const QString &message, const QString &subsystem = QString()); + static bool willMirrorToStderr(); private: static os_log_type_t logTypeForMessageType(QtMsgType msgType); static os_log_t cachedLog(const QString &subsystem, const QString &category); diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 05bc064005..b023ae9ed2 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -818,6 +818,16 @@ void QThread::quit() } +void QThread::exit(int returnCode) +{ + Q_D(QThread); + d->data->quitNow = true; + for (int i = 0; i < d->data->eventLoops.size(); ++i) { + QEventLoop *eventLoop = d->data->eventLoops.at(i); + eventLoop->exit(returnCode); + } +} + bool QThread::wait(unsigned long time) { Q_UNUSED(time); diff --git a/src/gui/Qt5GuiConfigExtras.cmake.in b/src/gui/Qt5GuiConfigExtras.cmake.in index 07869efd7d..84dbbfebd4 100644 --- a/src/gui/Qt5GuiConfigExtras.cmake.in +++ b/src/gui/Qt5GuiConfigExtras.cmake.in @@ -91,16 +91,29 @@ macro(_qt5gui_find_extra_libs Name Libs LibDir IncDirs) endforeach() !!ENDIF foreach(_lib ${Libs}) - string(REGEX REPLACE "[^_A-Za-z0-9]" "_" _cmake_lib_name ${_lib}) + if (IS_ABSOLUTE ${_lib}) + get_filename_component(_libFile ${_lib} NAME_WE) + if (_libFile MATCHES \"^${CMAKE_SHARED_LIBRARY_PREFIX}(.*)\") + set(_libFile ${CMAKE_MATCH_1}) + endif() + else() + set(_libFile ${_lib}) + endif() + + string(REGEX REPLACE "[^_A-Za-z0-9]" "_" _cmake_lib_name ${_libFile}) if (NOT TARGET Qt5::Gui_${_cmake_lib_name} AND NOT _Qt5Gui_${_cmake_lib_name}_LIBRARY_DONE) - find_library(Qt5Gui_${_cmake_lib_name}_LIBRARY ${_lib} + if (IS_ABSOLUTE ${_lib}) + set(Qt5Gui_${_cmake_lib_name}_LIBRARY ${_lib}) + else() + find_library(Qt5Gui_${_cmake_lib_name}_LIBRARY ${_lib} !!IF !isEmpty(CROSS_COMPILE) - PATHS \"${LibDir}\" + PATHS \"${LibDir}\" !!IF !mac - NO_DEFAULT_PATH + NO_DEFAULT_PATH !!ENDIF !!ENDIF - ) + ) + endif() !!IF mac set(Qt5Gui_${_cmake_lib_name}_LIBRARY "${Qt5Gui_${_cmake_lib_name}_LIBRARY}/${_lib}") if (NOT EXISTS "${Qt5Gui_${_cmake_lib_name}_LIBRARY}") diff --git a/src/gui/opengl/qopengltextureuploader.cpp b/src/gui/opengl/qopengltextureuploader.cpp index 90253546c8..b8b532b3d0 100644 --- a/src/gui/opengl/qopengltextureuploader.cpp +++ b/src/gui/opengl/qopengltextureuploader.cpp @@ -114,6 +114,18 @@ qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &imag externalFormat = GL_BGRA; internalFormat = GL_RGBA; pixelType = GL_UNSIGNED_INT_8_8_8_8_REV; +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN + // Without GL_UNSIGNED_INT_8_8_8_8_REV, BGRA only matches ARGB on little endian: + } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat) && !sRgbBinding) { + // The GL_EXT_texture_format_BGRA8888 extension requires the internal format to match the external. + externalFormat = internalFormat = GL_BGRA; + pixelType = GL_UNSIGNED_BYTE; + } else if (context->isOpenGLES() && context->hasExtension(QByteArrayLiteral("GL_APPLE_texture_format_BGRA8888"))) { + // Is only allowed as an external format like OpenGL. + externalFormat = GL_BGRA; + internalFormat = GL_RGBA; + pixelType = GL_UNSIGNED_BYTE; +#endif } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) { #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN GLint swizzle[4] = { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA }; @@ -125,25 +137,8 @@ qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &imag externalFormat = internalFormat = GL_RGBA; pixelType = GL_UNSIGNED_BYTE; } else { -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - // Without GL_UNSIGNED_INT_8_8_8_8_REV, BGRA only matches ARGB on little endian. - if (funcs->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat) && !sRgbBinding) { - // The GL_EXT_texture_format_BGRA8888 extension requires the internal format to match the external. - externalFormat = internalFormat = GL_BGRA; - pixelType = GL_UNSIGNED_BYTE; - } else if (context->isOpenGLES() && context->hasExtension(QByteArrayLiteral("GL_APPLE_texture_format_BGRA8888"))) { - // Is only allowed as an external format like OpenGL. - externalFormat = GL_BGRA; - internalFormat = GL_RGBA; - pixelType = GL_UNSIGNED_BYTE; - } else { - // No support for direct ARGB32 upload. - break; - } -#else - // Big endian requires GL_UNSIGNED_INT_8_8_8_8_REV for ARGB to match BGRA + // No support for direct ARGB32 upload. break; -#endif } targetFormat = image.format(); break; diff --git a/src/gui/painting/qbezier.cpp b/src/gui/painting/qbezier.cpp index a3dcb02e07..ddd1d997f2 100644 --- a/src/gui/painting/qbezier.cpp +++ b/src/gui/painting/qbezier.cpp @@ -333,7 +333,9 @@ static ShiftResult shift(const QBezier *orig, QBezier *shifted, qreal offset, qr *shifted = QBezier::fromPoints(points_shifted[map[0]], points_shifted[map[1]], points_shifted[map[2]], points_shifted[map[3]]); - return good_offset(orig, shifted, offset, threshold); + if (np > 2) + return good_offset(orig, shifted, offset, threshold); + return Ok; } // This value is used to determine the length of control point vectors @@ -432,7 +434,6 @@ redo: } else if (res == Ok) { ++o; --b; - continue; } else if (res == Circle && maxSegments - (o - curveSegments) >= 2) { // add semi circle if (addCircle(b, offset, o)) diff --git a/src/network/access/http2/hpacktable.cpp b/src/network/access/http2/hpacktable.cpp index a90ee72d52..fddb5feca5 100644 --- a/src/network/access/http2/hpacktable.cpp +++ b/src/network/access/http2/hpacktable.cpp @@ -42,6 +42,7 @@ #include <QtCore/qdebug.h> #include <algorithm> +#include <cstddef> #include <cstring> #include <limits> @@ -61,7 +62,7 @@ HeaderSize entry_size(const QByteArray &name, const QByteArray &value) // for counting the number of references to the name and value would have // 32 octets of overhead." - const unsigned sum = unsigned(name.size()) + value.size(); + const unsigned sum = unsigned(name.size() + value.size()); if (std::numeric_limits<unsigned>::max() - 32 < sum) return HeaderSize(); return HeaderSize(true, quint32(sum + 32)); @@ -75,7 +76,7 @@ int compare(const QByteArray &lhs, const QByteArray &rhs) if (const int minLen = std::min(lhs.size(), rhs.size())) { // We use memcmp, since strings in headers are allowed // to contain '\0'. - const int cmp = std::memcmp(lhs.constData(), rhs.constData(), minLen); + const int cmp = std::memcmp(lhs.constData(), rhs.constData(), std::size_t(minLen)); if (cmp) return cmp; } @@ -138,82 +139,6 @@ bool FieldLookupTable::SearchEntry::operator < (const SearchEntry &rhs)const return offset > rhs.offset; } -// This data is from HPACK's specs and it's quite -// conveniently sorted == works with binary search as it is. -// Later this can probably change and instead of simple -// vector we'll just reuse FieldLookupTable. -// TODO: it makes sense to generate this table while ... -// configuring/building Qt (some script downloading/parsing/generating -// would be quite handy). -const std::vector<HeaderField> &staticTable() -{ - static std::vector<HeaderField> table = { - {":authority", ""}, - {":method", "GET"}, - {":method", "POST"}, - {":path", "/"}, - {":path", "/index.html"}, - {":scheme", "http"}, - {":scheme", "https"}, - {":status", "200"}, - {":status", "204"}, - {":status", "206"}, - {":status", "304"}, - {":status", "400"}, - {":status", "404"}, - {":status", "500"}, - {"accept-charset", ""}, - {"accept-encoding", "gzip, deflate"}, - {"accept-language", ""}, - {"accept-ranges", ""}, - {"accept", ""}, - {"access-control-allow-origin", ""}, - {"age", ""}, - {"allow", ""}, - {"authorization", ""}, - {"cache-control", ""}, - {"content-disposition", ""}, - {"content-encoding", ""}, - {"content-language", ""}, - {"content-length", ""}, - {"content-location", ""}, - {"content-range", ""}, - {"content-type", ""}, - {"cookie", ""}, - {"date", ""}, - {"etag", ""}, - {"expect", ""}, - {"expires", ""}, - {"from", ""}, - {"host", ""}, - {"if-match", ""}, - {"if-modified-since", ""}, - {"if-none-match", ""}, - {"if-range", ""}, - {"if-unmodified-since", ""}, - {"last-modified", ""}, - {"link", ""}, - {"location", ""}, - {"max-forwards", ""}, - {"proxy-authenticate", ""}, - {"proxy-authorization", ""}, - {"range", ""}, - {"referer", ""}, - {"refresh", ""}, - {"retry-after", ""}, - {"server", ""}, - {"set-cookie", ""}, - {"strict-transport-security", ""}, - {"transfer-encoding", ""}, - {"user-agent", ""}, - {"vary", ""}, - {"via", ""}, - {"www-authenticate", ""} - }; - - return table; -} - FieldLookupTable::FieldLookupTable(quint32 maxSize, bool use) : maxTableSize(maxSize), tableCapacity(maxSize), @@ -296,12 +221,12 @@ void FieldLookupTable::evictEntry() quint32 FieldLookupTable::numberOfEntries() const { - return quint32(staticTable().size()) + nDynamic; + return quint32(staticPart().size()) + nDynamic; } quint32 FieldLookupTable::numberOfStaticEntries() const { - return quint32(staticTable().size()); + return quint32(staticPart().size()); } quint32 FieldLookupTable::numberOfDynamicEntries() const @@ -326,24 +251,18 @@ void FieldLookupTable::clearDynamicTable() bool FieldLookupTable::indexIsValid(quint32 index) const { - return index && index <= staticTable().size() + nDynamic; + return index && index <= staticPart().size() + nDynamic; } quint32 FieldLookupTable::indexOf(const QByteArray &name, const QByteArray &value)const { // Start from the static part first: - const auto &table = staticTable(); + const auto &table = staticPart(); const HeaderField field(name, value); - const auto staticPos = std::lower_bound(table.begin(), table.end(), field, - [](const HeaderField &lhs, const HeaderField &rhs) { - int cmp = compare(lhs.name, rhs.name); - if (cmp) - return cmp < 0; - return compare(lhs.value, rhs.value) < 0; - }); + const auto staticPos = findInStaticPart(field, CompareMode::nameAndValue); if (staticPos != table.end()) { if (staticPos->name == name && staticPos->value == value) - return staticPos - table.begin() + 1; + return quint32(staticPos - table.begin() + 1); } // Now we have to lookup in our dynamic part ... @@ -366,15 +285,12 @@ quint32 FieldLookupTable::indexOf(const QByteArray &name, const QByteArray &valu quint32 FieldLookupTable::indexOf(const QByteArray &name) const { // Start from the static part first: - const auto &table = staticTable(); + const auto &table = staticPart(); const HeaderField field(name, QByteArray()); - const auto staticPos = std::lower_bound(table.begin(), table.end(), field, - [](const HeaderField &lhs, const HeaderField &rhs) { - return compare(lhs.name, rhs.name) < 0; - }); + const auto staticPos = findInStaticPart(field, CompareMode::nameOnly); if (staticPos != table.end()) { if (staticPos->name == name) - return staticPos - table.begin() + 1; + return quint32(staticPos - table.begin() + 1); } // Now we have to lookup in our dynamic part ... @@ -402,7 +318,7 @@ bool FieldLookupTable::field(quint32 index, QByteArray *name, QByteArray *value) if (!indexIsValid(index)) return false; - const auto &table = staticTable(); + const auto &table = staticPart(); if (index - 1 < table.size()) { *name = table[index - 1].name; *value = table[index - 1].value; @@ -477,7 +393,7 @@ quint32 FieldLookupTable::keyToIndex(const SearchEntry &key) const Q_ASSERT(offset < ChunkSize); Q_ASSERT(chunkIndex || offset >= begin); - return quint32(offset + chunkIndex * ChunkSize - begin + 1 + staticTable().size()); + return quint32(offset + chunkIndex * ChunkSize - begin + 1 + staticPart().size()); } FieldLookupTable::SearchEntry FieldLookupTable::frontKey() const @@ -526,6 +442,103 @@ void FieldLookupTable::setMaxDynamicTableSize(quint32 size) updateDynamicTableSize(size); } +// This data is from the HPACK's specs and it's quite conveniently sorted, +// except ... 'accept' is in the wrong position, see how we handle it below. +const std::vector<HeaderField> &FieldLookupTable::staticPart() +{ + static std::vector<HeaderField> table = { + {":authority", ""}, + {":method", "GET"}, + {":method", "POST"}, + {":path", "/"}, + {":path", "/index.html"}, + {":scheme", "http"}, + {":scheme", "https"}, + {":status", "200"}, + {":status", "204"}, + {":status", "206"}, + {":status", "304"}, + {":status", "400"}, + {":status", "404"}, + {":status", "500"}, + {"accept-charset", ""}, + {"accept-encoding", "gzip, deflate"}, + {"accept-language", ""}, + {"accept-ranges", ""}, + {"accept", ""}, + {"access-control-allow-origin", ""}, + {"age", ""}, + {"allow", ""}, + {"authorization", ""}, + {"cache-control", ""}, + {"content-disposition", ""}, + {"content-encoding", ""}, + {"content-language", ""}, + {"content-length", ""}, + {"content-location", ""}, + {"content-range", ""}, + {"content-type", ""}, + {"cookie", ""}, + {"date", ""}, + {"etag", ""}, + {"expect", ""}, + {"expires", ""}, + {"from", ""}, + {"host", ""}, + {"if-match", ""}, + {"if-modified-since", ""}, + {"if-none-match", ""}, + {"if-range", ""}, + {"if-unmodified-since", ""}, + {"last-modified", ""}, + {"link", ""}, + {"location", ""}, + {"max-forwards", ""}, + {"proxy-authenticate", ""}, + {"proxy-authorization", ""}, + {"range", ""}, + {"referer", ""}, + {"refresh", ""}, + {"retry-after", ""}, + {"server", ""}, + {"set-cookie", ""}, + {"strict-transport-security", ""}, + {"transfer-encoding", ""}, + {"user-agent", ""}, + {"vary", ""}, + {"via", ""}, + {"www-authenticate", ""} + }; + + return table; +} + +std::vector<HeaderField>::const_iterator FieldLookupTable::findInStaticPart(const HeaderField &field, CompareMode mode) +{ + const auto &table = staticPart(); + const auto acceptPos = table.begin() + 18; + if (field.name == "accept") { + if (mode == CompareMode::nameAndValue && field.value != "") + return table.end(); + return acceptPos; + } + + auto predicate = [mode](const HeaderField &lhs, const HeaderField &rhs) { + const int cmp = compare(lhs.name, rhs.name); + if (cmp) + return cmp < 0; + else if (mode == CompareMode::nameAndValue) + return compare(lhs.value, rhs.value) < 0; + return false; + }; + + const auto staticPos = std::lower_bound(table.begin(), acceptPos, field, predicate); + if (staticPos != acceptPos) + return staticPos; + + return std::lower_bound(acceptPos + 1, table.end(), field, predicate); +} + } QT_END_NAMESPACE diff --git a/src/network/access/http2/hpacktable_p.h b/src/network/access/http2/hpacktable_p.h index 5eaccbffce..587d86f09c 100644 --- a/src/network/access/http2/hpacktable_p.h +++ b/src/network/access/http2/hpacktable_p.h @@ -173,6 +173,8 @@ public: bool updateDynamicTableSize(quint32 size); void setMaxDynamicTableSize(quint32 size); + static const std::vector<HeaderField> &staticPart(); + private: // Table's maximum size is controlled // by SETTINGS_HEADER_TABLE_SIZE (HTTP/2, 6.5.2). @@ -225,9 +227,16 @@ private: quint32 indexOfChunk(const Chunk *chunk) const; quint32 keyToIndex(const SearchEntry &key) const; + enum class CompareMode { + nameOnly, + nameAndValue + }; + + static std::vector<HeaderField>::const_iterator findInStaticPart(const HeaderField &field, CompareMode mode); + mutable QByteArray dummyDst; - Q_DISABLE_COPY_MOVE(FieldLookupTable); + Q_DISABLE_COPY_MOVE(FieldLookupTable) }; } diff --git a/src/network/access/qnetworkreplywasmimpl.cpp b/src/network/access/qnetworkreplywasmimpl.cpp index df4e034d97..b1e9853a50 100644 --- a/src/network/access/qnetworkreplywasmimpl.cpp +++ b/src/network/access/qnetworkreplywasmimpl.cpp @@ -265,7 +265,7 @@ qint64 QNetworkReplyWasmImpl::readData(char *data, qint64 maxlen) Q_D(QNetworkReplyWasmImpl); qint64 howMuch = qMin(maxlen, (d->downloadBuffer.size() - d->downloadBufferReadPosition)); - memcpy(data, d->downloadBuffer.constData(), howMuch); + memcpy(data, d->downloadBuffer.constData() + d->downloadBufferReadPosition, howMuch); d->downloadBufferReadPosition += howMuch; return howMuch; diff --git a/src/platformsupport/services/genericunix/qgenericunixservices.cpp b/src/platformsupport/services/genericunix/qgenericunixservices.cpp index 7fff50b2a1..734bdcaf75 100644 --- a/src/platformsupport/services/genericunix/qgenericunixservices.cpp +++ b/src/platformsupport/services/genericunix/qgenericunixservices.cpp @@ -179,7 +179,15 @@ static inline bool checkNeedPortalSupport() return !QStandardPaths::locate(QStandardPaths::RuntimeLocation, QLatin1String("flatpak-info")).isEmpty() || qEnvironmentVariableIsSet("SNAP"); } -static inline bool xdgDesktopPortalOpenFile(const QUrl &url) +static inline bool isPortalReturnPermanent(const QDBusError &error) +{ + // A service unknown error isn't permanent, it just indicates that we + // should fall back to the regular way. This check includes + // QDBusError::NoError. + return error.type() != QDBusError::ServiceUnknown; +} + +static inline QDBusMessage xdgDesktopPortalOpenFile(const QUrl &url) { // DBus signature: // OpenFile (IN s parent_window, @@ -198,23 +206,22 @@ static inline bool xdgDesktopPortalOpenFile(const QUrl &url) QLatin1String("org.freedesktop.portal.OpenURI"), QLatin1String("OpenFile")); - QDBusUnixFileDescriptor descriptor(fd); - qt_safe_close(fd); + QDBusUnixFileDescriptor descriptor; + descriptor.giveFileDescriptor(fd); // FIXME parent_window_id and handle writable option message << QString() << QVariant::fromValue(descriptor) << QVariantMap(); - QDBusPendingReply<QDBusObjectPath> reply = QDBusConnection::sessionBus().call(message); - return !reply.isError(); + return QDBusConnection::sessionBus().call(message); } #else Q_UNUSED(url) #endif - return false; + return QDBusMessage::createError(QDBusError::InternalError, qt_error_string()); } -static inline bool xdgDesktopPortalOpenUrl(const QUrl &url) +static inline QDBusMessage xdgDesktopPortalOpenUrl(const QUrl &url) { // DBus signature: // OpenURI (IN s parent_window, @@ -234,11 +241,10 @@ static inline bool xdgDesktopPortalOpenUrl(const QUrl &url) // FIXME parent_window_id and handle writable option message << QString() << url.toString() << QVariantMap(); - QDBusPendingReply<QDBusObjectPath> reply = QDBusConnection::sessionBus().call(message); - return !reply.isError(); + return QDBusConnection::sessionBus().call(message); } -static inline bool xdgDesktopPortalSendEmail(const QUrl &url) +static inline QDBusMessage xdgDesktopPortalSendEmail(const QUrl &url) { // DBus signature: // ComposeEmail (IN s parent_window, @@ -281,8 +287,7 @@ static inline bool xdgDesktopPortalSendEmail(const QUrl &url) // FIXME parent_window_id message << QString() << options; - QDBusPendingReply<QDBusObjectPath> reply = QDBusConnection::sessionBus().call(message); - return !reply.isError(); + return QDBusConnection::sessionBus().call(message); } #endif // QT_CONFIG(dbus) @@ -296,15 +301,23 @@ bool QGenericUnixServices::openUrl(const QUrl &url) { if (url.scheme() == QLatin1String("mailto")) { #if QT_CONFIG(dbus) - if (checkNeedPortalSupport()) - return xdgDesktopPortalSendEmail(url); + if (checkNeedPortalSupport()) { + QDBusError error = xdgDesktopPortalSendEmail(url); + if (isPortalReturnPermanent(error)) + return !error.isValid(); + + // service not running, fall back + } #endif return openDocument(url); } #if QT_CONFIG(dbus) - if (checkNeedPortalSupport()) - return xdgDesktopPortalOpenUrl(url); + if (checkNeedPortalSupport()) { + QDBusError error = xdgDesktopPortalOpenUrl(url); + if (isPortalReturnPermanent(error)) + return !error.isValid(); + } #endif if (m_webBrowser.isEmpty() && !detectWebBrowser(desktopEnvironment(), true, &m_webBrowser)) { @@ -317,8 +330,11 @@ bool QGenericUnixServices::openUrl(const QUrl &url) bool QGenericUnixServices::openDocument(const QUrl &url) { #if QT_CONFIG(dbus) - if (checkNeedPortalSupport()) - return xdgDesktopPortalOpenFile(url); + if (checkNeedPortalSupport()) { + QDBusError error = xdgDesktopPortalOpenFile(url); + if (isPortalReturnPermanent(error)) + return !error.isValid(); + } #endif if (m_documentLauncher.isEmpty() && !detectWebBrowser(desktopEnvironment(), false, &m_documentLauncher)) { diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index d86e935788..9c705616ba 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window"); Q_LOGGING_CATEGORY(lcQpaDrawing, "qt.qpa.drawing"); -Q_LOGGING_CATEGORY(lcQpaMouse, "qt.qpa.input.mouse"); +Q_LOGGING_CATEGORY(lcQpaMouse, "qt.qpa.input.mouse", QtCriticalMsg); Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen"); // diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 17063f6e92..5309449dce 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -137,22 +137,13 @@ { if ((self = [super initWithFrame:NSZeroRect])) { m_platformWindow = platformWindow; - m_buttons = Qt::NoButton; - m_acceptedMouseDowns = Qt::NoButton; - m_frameStrutButtons = Qt::NoButton; m_sendKeyEvent = false; - m_sendUpAsRightButton = false; m_inputSource = nil; - m_mouseMoveHelper = [[QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) alloc] initWithView:self]; m_resendKeyEvent = false; - m_scrolling = false; m_updatingDrag = false; m_currentlyInterpretedKeyEvent = nil; - m_dontOverrideCtrlLMB = qt_mac_resolveOption(false, platformWindow->window(), - "_q_platform_MacDontOverrideCtrlLMB", "QT_MAC_DONT_OVERRIDE_CTRL_LMB"); self.focusRingType = NSFocusRingTypeNone; - self.cursor = nil; self.previousSuperview = nil; self.previousWindow = nil; diff --git a/src/plugins/platforms/cocoa/qnsview_dragging.mm b/src/plugins/platforms/cocoa/qnsview_dragging.mm index 1c38c5326c..002cb3279e 100644 --- a/src/plugins/platforms/cocoa/qnsview_dragging.mm +++ b/src/plugins/platforms/cocoa/qnsview_dragging.mm @@ -57,9 +57,9 @@ NSFilesPromisePboardType, NSInkTextPboardType, NSMultipleTextSelectionPboardType, mimeTypeGeneric]]; - // Add custom types supported by the application. + // Add custom types supported by the application for (const QString &customType : qt_mac_enabledDraggedTypes()) - [supportedTypes addObject:customType.toNSString()]; + [supportedTypes addObject:customType.toNSString()]; [self registerForDraggedTypes:supportedTypes]; } @@ -79,11 +79,11 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin return target->mapFromGlobal(source->mapToGlobal(point)); } -- (NSDragOperation)draggingSession:(NSDraggingSession *)session - sourceOperationMaskForDraggingContext:(NSDraggingContext)context +- (NSDragOperation)draggingSession:(NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context { Q_UNUSED(session); Q_UNUSED(context); + QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); return qt_mac_mapDropActions(nativeDrag->currentDrag()->supportedActions()); } @@ -134,30 +134,29 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin if (pixmapCursor.isNull()) { switch (response.acceptedAction()) { - case Qt::CopyAction: - nativeCursor = [NSCursor dragCopyCursor]; - break; - case Qt::LinkAction: - nativeCursor = [NSCursor dragLinkCursor]; - break; - case Qt::IgnoreAction: - // Uncomment the next lines if forbiden cursor wanted on non droppable targets. - /*nativeCursor = [NSCursor operationNotAllowedCursor]; - break;*/ - case Qt::MoveAction: - default: - nativeCursor = [NSCursor arrowCursor]; - break; + case Qt::CopyAction: + nativeCursor = [NSCursor dragCopyCursor]; + break; + case Qt::LinkAction: + nativeCursor = [NSCursor dragLinkCursor]; + break; + case Qt::IgnoreAction: + // Uncomment the next lines if forbidden cursor is wanted on undroppable targets. + /*nativeCursor = [NSCursor operationNotAllowedCursor]; + break;*/ + case Qt::MoveAction: + default: + nativeCursor = [NSCursor arrowCursor]; + break; } - } - else { + } else { NSImage *nsimage = qt_mac_create_nsimage(pixmapCursor); nsimage.size = NSSizeFromCGSize((pixmapCursor.size() / pixmapCursor.devicePixelRatioF()).toCGSize()); nativeCursor = [[NSCursor alloc] initWithImage:nsimage hotSpot:NSZeroPoint]; [nsimage release]; } - // change the cursor + // Change the cursor [nativeCursor set]; // Make sure the cursor is updated correctly if the mouse does not move and window is under cursor @@ -169,39 +168,33 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin if (m_updatingDrag) return; - const QPoint mousePos(QCursor::pos()); - CGEventRef moveEvent(CGEventCreateMouseEvent( - NULL, kCGEventMouseMoved, - CGPointMake(mousePos.x(), mousePos.y()), + QCFType<CGEventRef> moveEvent = CGEventCreateMouseEvent( + nullptr, kCGEventMouseMoved, QCursor::pos().toCGPoint(), kCGMouseButtonLeft // ignored - )); + ); CGEventPost(kCGHIDEventTap, moveEvent); - CFRelease(moveEvent); } -- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender +- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender { - return [self handleDrag : sender]; + return [self handleDrag:(QEvent::DragEnter) sender:sender]; } -- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender +- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender { - m_updatingDrag = true; - const NSDragOperation ret([self handleDrag : sender]); - m_updatingDrag = false; - - return ret; + QScopedValueRollback<bool> rollback(m_updatingDrag, true); + return [self handleDrag:(QEvent::DragMove) sender:sender]; } // Sends drag update to Qt, return the action -- (NSDragOperation)handleDrag:(id <NSDraggingInfo>)sender +- (NSDragOperation)handleDrag:(QEvent::Type)dragType sender:(id<NSDraggingInfo>)sender { if (!m_platformWindow) return NSDragOperationNone; - NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil]; - QPoint qt_windowPoint(windowPoint.x, windowPoint.y); - Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations([sender draggingSourceOperationMask]); + QPoint windowPoint = QPointF::fromCGPoint([self convertPoint:sender.draggingLocation fromView:nil]).toPoint(); + + Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations(sender.draggingSourceOperationMask); QWindow *target = findEventTargetWindow(m_platformWindow->window()); if (!target) @@ -209,7 +202,12 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin const auto modifiers = [QNSView convertKeyModifiers:NSApp.currentEvent.modifierFlags]; const auto buttons = currentlyPressedMouseButtons(); - const auto point = mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint); + const auto point = mapWindowCoordinates(m_platformWindow->window(), target, windowPoint); + + if (dragType == QEvent::DragEnter) + qCDebug(lcQpaMouse) << dragType << self << "at" << windowPoint; + else + qCDebug(lcQpaMouse) << dragType << "at" << windowPoint << "with" << buttons; QPlatformDragQtResponse response(false, Qt::IgnoreAction, QRect()); QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); @@ -219,7 +217,7 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin point, qtAllowed, buttons, modifiers); [self updateCursorFromDragResponse:response drag:nativeDrag]; } else { - QCocoaDropData mimeData([sender draggingPasteboard]); + QCocoaDropData mimeData(sender.draggingPasteboard); response = QWindowSystemInterface::handleDrag(target, &mimeData, point, qtAllowed, buttons, modifiers); } @@ -227,7 +225,7 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin return qt_mac_mapDropAction(response.acceptedAction()); } -- (void)draggingExited:(id <NSDraggingInfo>)sender +- (void)draggingExited:(id<NSDraggingInfo>)sender { if (!m_platformWindow) return; @@ -236,17 +234,18 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin if (!target) return; - NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil]; - QPoint qt_windowPoint(windowPoint.x, windowPoint.y); + QPoint windowPoint = QPointF::fromCGPoint([self convertPoint:sender.draggingLocation fromView:nil]).toPoint(); + + qCDebug(lcQpaMouse) << QEvent::DragLeave << self << "at" << windowPoint; // Send 0 mime data to indicate drag exit QWindowSystemInterface::handleDrag(target, nullptr, - mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), + mapWindowCoordinates(m_platformWindow->window(), target, windowPoint), Qt::IgnoreAction, Qt::NoButton, Qt::NoModifier); } -// called on drop, send the drop to Qt and return if it was accepted. -- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender +// Called on drop, send the drop to Qt and return if it was accepted +- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender { if (!m_platformWindow) return false; @@ -255,31 +254,31 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin if (!target) return false; - NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil]; - QPoint qt_windowPoint(windowPoint.x, windowPoint.y); - Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations([sender draggingSourceOperationMask]); + QPoint windowPoint = QPointF::fromCGPoint([self convertPoint:sender.draggingLocation fromView:nil]).toPoint(); + + Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations(sender.draggingSourceOperationMask); QPlatformDropQtResponse response(false, Qt::IgnoreAction); QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); const auto modifiers = [QNSView convertKeyModifiers:NSApp.currentEvent.modifierFlags]; const auto buttons = currentlyPressedMouseButtons(); - const auto point = mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint); + const auto point = mapWindowCoordinates(m_platformWindow->window(), target, windowPoint); + + qCDebug(lcQpaMouse) << QEvent::Drop << "at" << windowPoint << "with" << buttons; if (nativeDrag->currentDrag()) { // The drag was started from within the application response = QWindowSystemInterface::handleDrop(target, nativeDrag->dragMimeData(), point, qtAllowed, buttons, modifiers); } else { - QCocoaDropData mimeData([sender draggingPasteboard]); + QCocoaDropData mimeData(sender.draggingPasteboard); response = QWindowSystemInterface::handleDrop(target, &mimeData, point, qtAllowed, buttons, modifiers); } return response.isAccepted(); } -- (void)draggingSession:(NSDraggingSession *)session - endedAtPoint:(NSPoint)screenPoint - operation:(NSDragOperation)operation +- (void)draggingSession:(NSDraggingSession *)session endedAtPoint:(NSPoint)screenPoint operation:(NSDragOperation)operation { Q_UNUSED(session); Q_UNUSED(screenPoint); @@ -295,6 +294,8 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin nativeDrag->setAcceptedAction(qt_mac_mapNSDragOperation(operation)); m_buttons = currentlyPressedMouseButtons(); + + qCDebug(lcQpaMouse) << "Drag session" << session << "ended, with" << m_buttons; } @end diff --git a/src/plugins/platforms/cocoa/qnsview_mouse.mm b/src/plugins/platforms/cocoa/qnsview_mouse.mm index 49c94f18db..6e3cff2b48 100644 --- a/src/plugins/platforms/cocoa/qnsview_mouse.mm +++ b/src/plugins/platforms/cocoa/qnsview_mouse.mm @@ -93,6 +93,7 @@ - (void)resetMouseButtons { + qCDebug(lcQpaMouse) << "Reseting mouse buttons"; m_buttons = Qt::NoButton; m_frameStrutButtons = Qt::NoButton; } @@ -145,6 +146,9 @@ QPoint qtScreenPoint = QCocoaScreen::mapFromNative(screenPoint).toPoint(); ulong timestamp = [theEvent timestamp] * 1000; + + auto eventType = cocoaEvent2QtMouseEvent(theEvent); + qCInfo(lcQpaMouse) << "Frame-strut" << eventType << "at" << qtWindowPoint << "with" << m_frameStrutButtons << "in" << self.window; QWindowSystemInterface::handleFrameStrutMouseEvent(m_platformWindow->window(), timestamp, qtWindowPoint, qtScreenPoint, m_frameStrutButtons); } @end @@ -153,6 +157,19 @@ - (void)initMouse { + m_buttons = Qt::NoButton; + m_acceptedMouseDowns = Qt::NoButton; + m_frameStrutButtons = Qt::NoButton; + + m_scrolling = false; + self.cursor = nil; + + m_sendUpAsRightButton = false; + m_dontOverrideCtrlLMB = qt_mac_resolveOption(false, m_platformWindow->window(), + "_q_platform_MacDontOverrideCtrlLMB", "QT_MAC_DONT_OVERRIDE_CTRL_LMB"); + + m_mouseMoveHelper = [[QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) alloc] initWithView:self]; + NSUInteger trackingOptions = NSTrackingActiveInActiveApp | NSTrackingMouseEnteredAndExited | NSTrackingCursorUpdate; @@ -241,6 +258,11 @@ button = Qt::RightButton; const auto eventType = cocoaEvent2QtMouseEvent(theEvent); + if (eventType == QEvent::MouseMove) + qCDebug(lcQpaMouse) << eventType << "at" << qtWindowPoint << "with" << buttons; + else + qCInfo(lcQpaMouse) << eventType << "of" << button << "at" << qtWindowPoint << "with" << buttons; + QWindowSystemInterface::handleMouseEvent(targetView->m_platformWindow->window(), timestamp, qtWindowPoint, qtScreenPoint, buttons, button, eventType, modifiers); @@ -446,16 +468,16 @@ - (void)cursorUpdate:(NSEvent *)theEvent { - qCDebug(lcQpaMouse) << "Updating cursor for" << self << "to" << self.cursor; - // Note: We do not get this callback when moving from a subview that // uses the legacy cursorRect API, so the cursor is reset to the arrow // cursor. See rdar://34183708 - if (self.cursor) + if (self.cursor && self.cursor != NSCursor.currentCursor) { + qCInfo(lcQpaMouse) << "Updating cursor for" << self << "to" << self.cursor; [self.cursor set]; - else + } else { [super cursorUpdate:theEvent]; + } } - (void)mouseMovedImpl:(NSEvent *)theEvent @@ -510,6 +532,8 @@ QPointF screenPoint; [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; m_platformWindow->m_enterLeaveTargetWindow = m_platformWindow->childWindowAt(windowPoint.toPoint()); + + qCInfo(lcQpaMouse) << QEvent::Enter << self << "at" << windowPoint << "with" << currentlyPressedMouseButtons(); QWindowSystemInterface::handleEnterEvent(m_platformWindow->m_enterLeaveTargetWindow, windowPoint, screenPoint); } @@ -528,6 +552,7 @@ if (!m_platformWindow->isContentView()) return; + qCInfo(lcQpaMouse) << QEvent::Leave << self; QWindowSystemInterface::handleLeaveEvent(m_platformWindow->m_enterLeaveTargetWindow); m_platformWindow->m_enterLeaveTargetWindow = 0; } @@ -626,8 +651,10 @@ // "isInverted": natural OS X scrolling, inverted from the Qt/other platform/Jens perspective. bool isInverted = [theEvent isDirectionInvertedFromDevice]; - qCDebug(lcQpaMouse) << "scroll wheel @ window pos" << qt_windowPoint << "delta px" << pixelDelta - << "angle" << angleDelta << "phase" << phase << (isInverted ? "inverted" : ""); + qCInfo(lcQpaMouse).nospace() << phase << " at " << qt_windowPoint + << " pixelDelta=" << pixelDelta << " angleDelta=" << angleDelta + << (isInverted ? " inverted=true" : ""); + QWindowSystemInterface::handleWheelEvent(m_platformWindow->window(), qt_timestamp, qt_windowPoint, qt_screenPoint, pixelDelta, angleDelta, m_currentWheelModifiers, phase, source, isInverted); } diff --git a/src/testlib/qappletestlogger.cpp b/src/testlib/qappletestlogger.cpp index 8e75da88f8..959ff6cf64 100644 --- a/src/testlib/qappletestlogger.cpp +++ b/src/testlib/qappletestlogger.cpp @@ -55,9 +55,8 @@ bool QAppleTestLogger::debugLoggingEnabled() return os_log_type_enabled(OS_LOG_DEFAULT, OS_LOG_TYPE_DEBUG); } -QAppleTestLogger::QAppleTestLogger(QAbstractTestLogger *logger) +QAppleTestLogger::QAppleTestLogger() : QAbstractTestLogger(nullptr) - , m_logger(logger) { } @@ -65,6 +64,8 @@ static QAppleLogActivity testFunctionActivity; void QAppleTestLogger::enterTestFunction(const char *function) { + Q_UNUSED(function); + // Re-create activity each time testFunctionActivity = QT_APPLE_LOG_ACTIVITY("Running test function").enter(); @@ -73,15 +74,12 @@ void QAppleTestLogger::enterTestFunction(const char *function) QString identifier = QString::fromLatin1(testIdentifier.data()); QMessageLogContext context(nullptr, 0, nullptr, "qt.test.enter"); QString message = identifier; - if (AppleUnifiedLogger::messageHandler(QtDebugMsg, context, message, identifier)) - return; // AUL already printed to stderr - m_logger->enterTestFunction(function); + AppleUnifiedLogger::messageHandler(QtDebugMsg, context, message, identifier); } void QAppleTestLogger::leaveTestFunction() { - m_logger->leaveTestFunction(); testFunctionActivity.leave(); } @@ -134,18 +132,12 @@ void QAppleTestLogger::addIncident(IncidentTypes type, const char *description, if (qstrlen(description)) message += QLatin1Char('\n') % QString::fromLatin1(description); - if (AppleUnifiedLogger::messageHandler(incidentClassification.first, context, message, subsystem)) - return; // AUL already printed to stderr - - m_logger->addIncident(type, description, file, line); + AppleUnifiedLogger::messageHandler(incidentClassification.first, context, message, subsystem); } void QAppleTestLogger::addMessage(QtMsgType type, const QMessageLogContext &context, const QString &message) { - if (AppleUnifiedLogger::messageHandler(type, context, message)) - return; // AUL already printed to stderr - - m_logger->addMessage(type, context, message); + AppleUnifiedLogger::messageHandler(type, context, message); } #endif // QT_USE_APPLE_UNIFIED_LOGGING diff --git a/src/testlib/qappletestlogger_p.h b/src/testlib/qappletestlogger_p.h index 5a45fad7a0..4217f4e6a2 100644 --- a/src/testlib/qappletestlogger_p.h +++ b/src/testlib/qappletestlogger_p.h @@ -63,12 +63,7 @@ class QAppleTestLogger : public QAbstractTestLogger public: static bool debugLoggingEnabled(); - QAppleTestLogger(QAbstractTestLogger *logger); - - void startLogging() override - { m_logger->startLogging(); } - void stopLogging() override - { m_logger->stopLogging(); } + QAppleTestLogger(); void enterTestFunction(const char *function) override; void leaveTestFunction() override; @@ -77,16 +72,12 @@ public: const char *file = 0, int line = 0) override; void addMessage(QtMsgType, const QMessageLogContext &, const QString &) override; - - void addBenchmarkResult(const QBenchmarkResult &result) override - { m_logger->addBenchmarkResult(result); } - void addMessage(MessageTypes type, const QString &message, const char *file = 0, int line = 0) override - { m_logger->addMessage(type, message, file, line); } + { Q_UNUSED(type); Q_UNUSED(message); Q_UNUSED(file); Q_UNUSED(line); Q_UNREACHABLE(); } -private: - QScopedPointer<QAbstractTestLogger> m_logger; + void addBenchmarkResult(const QBenchmarkResult &result) override + { Q_UNUSED(result); } }; #endif diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 3ee8094ddf..8d109113c4 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -78,6 +78,10 @@ #include <QtTest/private/qtestutil_macos_p.h> #endif +#if defined(Q_OS_DARWIN) +#include <QtTest/private/qappletestlogger_p.h> +#endif + #include <cmath> #include <numeric> #include <algorithm> @@ -511,7 +515,7 @@ static int qToInt(const char *str) Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, const char *const argv[], bool qml) { - QTestLog::LogMode logFormat = QTestLog::Plain; + int logFormat = -1; // Not set const char *logFilename = 0; QTest::testFunctions.clear(); @@ -679,7 +683,7 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, const char *const argv[], bool fprintf(stderr, "only one logger can log to stdout\n"); exit(1); } - QTestLog::addLogger(logFormat, filename); + QTestLog::addLogger(QTestLog::LogMode(logFormat), filename); } delete [] filename; delete [] format; @@ -841,10 +845,25 @@ Q_TESTLIB_EXPORT void qtest_qParseArgs(int argc, const char *const argv[], bool QTestLog::setInstalledTestCoverage(installedTestCoverage); // If no loggers were created by the long version of the -o command-line - // option, create a logger using whatever filename and format were - // set using the old-style command-line options. - if (QTestLog::loggerCount() == 0) - QTestLog::addLogger(logFormat, logFilename); + // option, but a logger was requested via the old-style option, add it. + const bool explicitLoggerRequested = logFormat != -1; + if (QTestLog::loggerCount() == 0 && explicitLoggerRequested) + QTestLog::addLogger(QTestLog::LogMode(logFormat), logFilename); + + bool addFallbackLogger = !explicitLoggerRequested; + +#if defined(QT_USE_APPLE_UNIFIED_LOGGING) + // Any explicitly requested loggers will be added by now, so we can check if they use stdout + const bool safeToAddAppleLogger = !AppleUnifiedLogger::willMirrorToStderr() || !QTestLog::loggerUsingStdout(); + if (safeToAddAppleLogger && QAppleTestLogger::debugLoggingEnabled()) { + QTestLog::addLogger(QTestLog::Apple, nullptr); + if (AppleUnifiedLogger::willMirrorToStderr() && !logFilename) + addFallbackLogger = false; // Prevent plain test logger fallback below + } +#endif + + if (addFallbackLogger) + QTestLog::addLogger(QTestLog::Plain, logFilename); } // Temporary, backwards compatibility, until qtdeclarative's use of it is converted diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp index 32be7f6f10..faef3912c4 100644 --- a/src/testlib/qtestlog.cpp +++ b/src/testlib/qtestlog.cpp @@ -60,6 +60,7 @@ #include <QtCore/qbytearray.h> #include <QtCore/QElapsedTimer> #include <QtCore/QVariant> +#include <QtCore/qvector.h> #if QT_CONFIG(regularexpression) #include <QtCore/QRegularExpression> #endif @@ -98,6 +99,8 @@ static void saveCoverageTool(const char * appname, bool testfailed, bool install static QElapsedTimer elapsedFunctionTime; static QElapsedTimer elapsedTotalTime; +#define FOREACH_TEST_LOGGER for (QAbstractTestLogger *logger : QTest::loggers) + namespace QTest { int fails = 0; @@ -165,109 +168,7 @@ namespace QTest { static IgnoreResultList *ignoreResultList = 0; - struct LoggerList - { - QAbstractTestLogger *logger; - LoggerList *next; - }; - - class TestLoggers - { - public: - static void addLogger(QAbstractTestLogger *logger) - { - LoggerList *l = new LoggerList; - l->logger = logger; - l->next = loggers; - loggers = l; - } - - static void destroyLoggers() - { - while (loggers) { - LoggerList *l = loggers; - loggers = loggers->next; - delete l->logger; - delete l; - } - } - -#define FOREACH_LOGGER(operation) \ - LoggerList *l = loggers; \ - while (l) { \ - QAbstractTestLogger *logger = l->logger; \ - Q_UNUSED(logger); \ - operation; \ - l = l->next; \ - } - - static void startLogging() - { - FOREACH_LOGGER(logger->startLogging()); - } - - static void stopLogging() - { - FOREACH_LOGGER(logger->stopLogging()); - } - - static void enterTestFunction(const char *function) - { - FOREACH_LOGGER(logger->enterTestFunction(function)); - } - - static void leaveTestFunction() - { - FOREACH_LOGGER(logger->leaveTestFunction()); - } - - static void enterTestData(QTestData *data) - { - FOREACH_LOGGER(logger->enterTestData(data)); - } - - static void addIncident(QAbstractTestLogger::IncidentTypes type, const char *description, - const char *file = 0, int line = 0) - { - FOREACH_LOGGER(logger->addIncident(type, description, file, line)); - } - - static void addBenchmarkResult(const QBenchmarkResult &result) - { - FOREACH_LOGGER(logger->addBenchmarkResult(result)); - } - - static void addMessage(QtMsgType type, const QMessageLogContext &context, - const QString &message) - { - FOREACH_LOGGER(logger->addMessage(type, context, message)); - } - - static void addMessage(QAbstractTestLogger::MessageTypes type, const QString &message, - const char *file = 0, int line = 0) - { - FOREACH_LOGGER(logger->addMessage(type, message, file, line)); - } - - static void outputString(const char *msg) - { - FOREACH_LOGGER(logger->outputString(msg)); - } - - static int loggerCount() - { - int count = 0; - FOREACH_LOGGER(++count); - return count; - } - - private: - static LoggerList *loggers; - }; - -#undef FOREACH_LOGGER - - LoggerList *TestLoggers::loggers = 0; + static QVector<QAbstractTestLogger*> loggers; static bool loggerUsingStdout = false; static int verbosity = 0; @@ -306,10 +207,10 @@ namespace QTest { { static QBasicAtomicInt counter = Q_BASIC_ATOMIC_INITIALIZER(QTest::maxWarnings); - if (QTest::TestLoggers::loggerCount() == 0) { + if (QTestLog::loggerCount() == 0) { // if this goes wrong, something is seriously broken. qInstallMessageHandler(oldMessageHandler); - QTEST_ASSERT(QTest::TestLoggers::loggerCount() != 0); + QTEST_ASSERT(QTestLog::loggerCount() != 0); } if (handleIgnoredMessage(type, message)) { @@ -322,13 +223,16 @@ namespace QTest { return; if (!counter.deref()) { - QTest::TestLoggers::addMessage(QAbstractTestLogger::QSystem, + FOREACH_TEST_LOGGER { + logger->addMessage(QAbstractTestLogger::QSystem, QStringLiteral("Maximum amount of warnings exceeded. Use -maxwarnings to override.")); + } return; } } - QTest::TestLoggers::addMessage(type, context, message); + FOREACH_TEST_LOGGER + logger->addMessage(type, context, message); if (type == QtFatalMsg) { /* Right now, we're inside the custom message handler and we're @@ -351,13 +255,16 @@ void QTestLog::enterTestFunction(const char* function) QTEST_ASSERT(function); - QTest::TestLoggers::enterTestFunction(function); + FOREACH_TEST_LOGGER + logger->enterTestFunction(function); } void QTestLog::enterTestData(QTestData *data) { QTEST_ASSERT(data); - QTest::TestLoggers::enterTestData(data); + + FOREACH_TEST_LOGGER + logger->enterTestData(data); } int QTestLog::unhandledIgnoreMessages() @@ -376,7 +283,8 @@ void QTestLog::leaveTestFunction() if (printAvailableTags) return; - QTest::TestLoggers::leaveTestFunction(); + FOREACH_TEST_LOGGER + logger->leaveTestFunction(); } void QTestLog::printUnhandledIgnoreMessages() @@ -391,7 +299,8 @@ void QTestLog::printUnhandledIgnoreMessages() message = QStringLiteral("Did not receive any message matching: \"") + list->pattern.toRegularExpression().pattern() + QLatin1Char('"'); #endif } - QTest::TestLoggers::addMessage(QAbstractTestLogger::Info, message); + FOREACH_TEST_LOGGER + logger->addMessage(QAbstractTestLogger::Info, message); list = list->next; } @@ -411,7 +320,8 @@ void QTestLog::addPass(const char *msg) ++QTest::passes; - QTest::TestLoggers::addIncident(QAbstractTestLogger::Pass, msg); + FOREACH_TEST_LOGGER + logger->addIncident(QAbstractTestLogger::Pass, msg); } void QTestLog::addFail(const char *msg, const char *file, int line) @@ -420,7 +330,8 @@ void QTestLog::addFail(const char *msg, const char *file, int line) ++QTest::fails; - QTest::TestLoggers::addIncident(QAbstractTestLogger::Fail, msg, file, line); + FOREACH_TEST_LOGGER + logger->addIncident(QAbstractTestLogger::Fail, msg, file, line); } void QTestLog::addXFail(const char *msg, const char *file, int line) @@ -428,7 +339,8 @@ void QTestLog::addXFail(const char *msg, const char *file, int line) QTEST_ASSERT(msg); QTEST_ASSERT(file); - QTest::TestLoggers::addIncident(QAbstractTestLogger::XFail, msg, file, line); + FOREACH_TEST_LOGGER + logger->addIncident(QAbstractTestLogger::XFail, msg, file, line); } void QTestLog::addXPass(const char *msg, const char *file, int line) @@ -438,7 +350,8 @@ void QTestLog::addXPass(const char *msg, const char *file, int line) ++QTest::fails; - QTest::TestLoggers::addIncident(QAbstractTestLogger::XPass, msg, file, line); + FOREACH_TEST_LOGGER + logger->addIncident(QAbstractTestLogger::XPass, msg, file, line); } void QTestLog::addBPass(const char *msg) @@ -447,7 +360,8 @@ void QTestLog::addBPass(const char *msg) ++QTest::blacklists; - QTest::TestLoggers::addIncident(QAbstractTestLogger::BlacklistedPass, msg); + FOREACH_TEST_LOGGER + logger->addIncident(QAbstractTestLogger::BlacklistedPass, msg); } void QTestLog::addBFail(const char *msg, const char *file, int line) @@ -457,7 +371,8 @@ void QTestLog::addBFail(const char *msg, const char *file, int line) ++QTest::blacklists; - QTest::TestLoggers::addIncident(QAbstractTestLogger::BlacklistedFail, msg, file, line); + FOREACH_TEST_LOGGER + logger->addIncident(QAbstractTestLogger::BlacklistedFail, msg, file, line); } void QTestLog::addBXPass(const char *msg, const char *file, int line) @@ -467,7 +382,8 @@ void QTestLog::addBXPass(const char *msg, const char *file, int line) ++QTest::blacklists; - QTest::TestLoggers::addIncident(QAbstractTestLogger::BlacklistedXPass, msg, file, line); + FOREACH_TEST_LOGGER + logger->addIncident(QAbstractTestLogger::BlacklistedXPass, msg, file, line); } void QTestLog::addBXFail(const char *msg, const char *file, int line) @@ -477,7 +393,8 @@ void QTestLog::addBXFail(const char *msg, const char *file, int line) ++QTest::blacklists; - QTest::TestLoggers::addIncident(QAbstractTestLogger::BlacklistedXFail, msg, file, line); + FOREACH_TEST_LOGGER + logger->addIncident(QAbstractTestLogger::BlacklistedXFail, msg, file, line); } void QTestLog::addSkip(const char *msg, const char *file, int line) @@ -487,27 +404,33 @@ void QTestLog::addSkip(const char *msg, const char *file, int line) ++QTest::skips; - QTest::TestLoggers::addMessage(QAbstractTestLogger::Skip, QString::fromUtf8(msg), file, line); + FOREACH_TEST_LOGGER + logger->addMessage(QAbstractTestLogger::Skip, QString::fromUtf8(msg), file, line); } void QTestLog::addBenchmarkResult(const QBenchmarkResult &result) { - QTest::TestLoggers::addBenchmarkResult(result); + FOREACH_TEST_LOGGER + logger->addBenchmarkResult(result); } void QTestLog::startLogging() { elapsedTotalTime.start(); elapsedFunctionTime.start(); - QTest::TestLoggers::startLogging(); + FOREACH_TEST_LOGGER + logger->startLogging(); QTest::oldMessageHandler = qInstallMessageHandler(QTest::messageHandler); } void QTestLog::stopLogging() { qInstallMessageHandler(QTest::oldMessageHandler); - QTest::TestLoggers::stopLogging(); - QTest::TestLoggers::destroyLoggers(); + FOREACH_TEST_LOGGER { + logger->stopLogging(); + delete logger; + } + QTest::loggers.clear(); QTest::loggerUsingStdout = false; saveCoverageTool(QTestResult::currentAppName(), failCount() != 0, QTestLog::installedTestCoverage()); } @@ -542,6 +465,11 @@ void QTestLog::addLogger(LogMode mode, const char *filename) case QTestLog::TAP: logger = new QTapTestLogger(filename); break; +#if defined(QT_USE_APPLE_UNIFIED_LOGGING) + case QTestLog::Apple: + logger = new QAppleTestLogger; + break; +#endif #if defined(HAVE_XCTEST) case QTestLog::XCTest: logger = new QXcodeTestLogger; @@ -549,21 +477,13 @@ void QTestLog::addLogger(LogMode mode, const char *filename) #endif } -#if defined(QT_USE_APPLE_UNIFIED_LOGGING) - // Logger that also feeds messages to AUL. It needs to wrap the existing - // logger, as it needs to be able to short circuit the existing logger - // in case AUL prints to stderr. - if (QAppleTestLogger::debugLoggingEnabled()) - logger = new QAppleTestLogger(logger); -#endif - QTEST_ASSERT(logger); - QTest::TestLoggers::addLogger(logger); + QTest::loggers.append(logger); } int QTestLog::loggerCount() { - return QTest::TestLoggers::loggerCount(); + return QTest::loggers.size(); } bool QTestLog::loggerUsingStdout() @@ -575,15 +495,16 @@ void QTestLog::warn(const char *msg, const char *file, int line) { QTEST_ASSERT(msg); - if (QTest::TestLoggers::loggerCount() > 0) - QTest::TestLoggers::addMessage(QAbstractTestLogger::Warn, QString::fromUtf8(msg), file, line); + FOREACH_TEST_LOGGER + logger->addMessage(QAbstractTestLogger::Warn, QString::fromUtf8(msg), file, line); } void QTestLog::info(const char *msg, const char *file, int line) { QTEST_ASSERT(msg); - QTest::TestLoggers::addMessage(QAbstractTestLogger::Info, QString::fromUtf8(msg), file, line); + FOREACH_TEST_LOGGER + logger->addMessage(QAbstractTestLogger::Info, QString::fromUtf8(msg), file, line); } void QTestLog::setVerboseLevel(int level) diff --git a/src/testlib/qtestlog_p.h b/src/testlib/qtestlog_p.h index 0bdd6290e1..e63e89a78e 100644 --- a/src/testlib/qtestlog_p.h +++ b/src/testlib/qtestlog_p.h @@ -53,6 +53,10 @@ #include <QtTest/qttestglobal.h> +#if defined(Q_OS_DARWIN) +#include <QtCore/private/qcore_mac_p.h> +#endif + QT_BEGIN_NAMESPACE class QBenchmarkResult; @@ -63,9 +67,12 @@ class Q_TESTLIB_EXPORT QTestLog { public: enum LogMode { - Plain = 0, XML, LightXML, XunitXML, CSV, TeamCity, TAP, + Plain = 0, XML, LightXML, XunitXML, CSV, TeamCity, TAP +#if defined(QT_USE_APPLE_UNIFIED_LOGGING) + , Apple +#endif #if defined(HAVE_XCTEST) - XCTest + , XCTest #endif }; diff --git a/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro b/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro index 5efe68f4af..18c9c8d198 100644 --- a/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro +++ b/tests/auto/corelib/plugin/qpluginloader/qpluginloader.pro @@ -10,7 +10,7 @@ SUBDIRS = lib \ tst.depends += almostplugin SUBDIRS += almostplugin } -macos:qtConfig(private_tests) { +macos:qtConfig(private_tests):qtHaveModule(gui) { tst.depends += machtest SUBDIRS += machtest } diff --git a/tests/auto/network/access/hpack/tst_hpack.cpp b/tests/auto/network/access/hpack/tst_hpack.cpp index 810745a065..d5e359db57 100644 --- a/tests/auto/network/access/hpack/tst_hpack.cpp +++ b/tests/auto/network/access/hpack/tst_hpack.cpp @@ -57,7 +57,6 @@ private Q_SLOTS: void lookupTableConstructor(); - void lookupTableStatic_data(); void lookupTableStatic(); void lookupTableDynamic(); @@ -126,7 +125,7 @@ void tst_Hpack::bitstreamConstruction() // 'Read' some data back: for (int i = 0; i < size; ++i) { uchar bitPattern = 0; - const auto bitsRead = in.peekBits(i * 8, 8, &bitPattern); + const auto bitsRead = in.peekBits(quint64(i * 8), 8, &bitPattern); QVERIFY(bitsRead == 8); QVERIFY(bitPattern == bytes[i]); } @@ -282,7 +281,7 @@ void tst_Hpack::bitstreamCompression() const auto start = QRandomGenerator::global()->bounded(uint(bytes.length()) / 2); auto end = start * 2; if (!end) - end = bytes.length() / 2; + end = unsigned(bytes.length() / 2); strings.push_back(bytes.substr(start, end - start)); const auto &s = strings.back(); totalStringBytes += s.size(); @@ -384,43 +383,21 @@ void tst_Hpack::lookupTableConstructor() } } -void tst_Hpack::lookupTableStatic_data() -{ - QTest::addColumn<QByteArray>("expectedName"); - QTest::addColumn<QByteArray>("expectedValue"); - - // Some predefined fields to find - // (they are always defined/required by HPACK). - QTest::newRow(":authority|") << QByteArray(":authority") << QByteArray(""); - QTest::newRow(":method|GET") << QByteArray(":method") << QByteArray("GET"); - QTest::newRow(":method|POST") << QByteArray(":method") << QByteArray("POST"); - QTest::newRow(":path|/") << QByteArray(":path") << QByteArray("/"); - QTest::newRow(":path|/index.html") << QByteArray(":path") << QByteArray("/index.html"); - QTest::newRow(":scheme|http") << QByteArray(":scheme") << QByteArray("http"); - QTest::newRow(":scheme|https") << QByteArray(":scheme") << QByteArray("https"); - QTest::newRow(":status|200") << QByteArray(":status") << QByteArray("200"); - QTest::newRow(":status|204") << QByteArray(":status") << QByteArray("204"); - QTest::newRow(":status|206") << QByteArray(":status") << QByteArray("206"); - QTest::newRow(":status|304") << QByteArray(":status") << QByteArray("304"); - QTest::newRow(":status|400") << QByteArray(":status") << QByteArray("400"); - QTest::newRow(":status|404") << QByteArray(":status") << QByteArray("404"); - QTest::newRow(":status|500") << QByteArray(":status") << QByteArray("500"); -} - void tst_Hpack::lookupTableStatic() { const FieldLookupTable table(0, false /*all static, no need in 'search index'*/); - - QFETCH(QByteArray, expectedName); - QFETCH(QByteArray, expectedValue); - - const quint32 index = table.indexOf(expectedName, expectedValue); - QVERIFY(index != 0); - + const auto &staticTable = FieldLookupTable::staticPart(); QByteArray name, value; - QVERIFY(table.field(index, &name, &value)); - QCOMPARE(name, expectedName); - QCOMPARE(value, expectedValue); + quint32 currentIndex = 1; // HPACK is indexing starting from 1. + for (const HeaderField &field : staticTable) { + const quint32 index = table.indexOf(field.name, field.value); + QVERIFY(index != 0); + QCOMPARE(index, currentIndex); + QVERIFY(table.field(index, &name, &value)); + QCOMPARE(name, field.name); + QCOMPARE(value, field.value); + ++currentIndex; + } } void tst_Hpack::lookupTableDynamic() diff --git a/tests/auto/other/other.pro b/tests/auto/other/other.pro index 378750472d..c5426202e8 100644 --- a/tests/auto/other/other.pro +++ b/tests/auto/other/other.pro @@ -56,7 +56,7 @@ winrt|!qtHaveModule(gui)|!qtConfig(accessibility): SUBDIRS -= qaccessibility !qtConfig(process): SUBDIRS -= qprocess_and_guieventloop -!mac: SUBDIRS -= \ +!macos|!qtHaveModule(gui): SUBDIRS -= \ macgui \ macnativeevents \ macplist \ |