summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2019-03-06 12:31:50 +0100
committerLiang Qi <liang.qi@qt.io>2019-03-06 12:31:50 +0100
commit2add2dbdaa9ff6ca6637ca22d6a9b7c7027751be (patch)
tree585628b0ceacfbdef5b9661c4043b9f71dfe9b01 /src
parentf792fed2ff519ffac1436e41e47cc0504d253a77 (diff)
parent4eda22ea0db1fc571ae9f44a68825056e6245548 (diff)
Merge remote-tracking branch 'origin/5.12' into 5.13
Conflicts: src/network/access/http2/hpacktable_p.h Change-Id: Ie0c296667dfdebba84f4858056a1ac80c24ee7df
Diffstat (limited to 'src')
-rw-r--r--src/corelib/io/qtemporaryfile.cpp22
-rw-r--r--src/corelib/kernel/qcore_mac.cpp23
-rw-r--r--src/corelib/kernel/qcore_mac_p.h1
-rw-r--r--src/corelib/thread/qthread.cpp10
-rw-r--r--src/gui/Qt5GuiConfigExtras.cmake.in23
-rw-r--r--src/gui/opengl/qopengltextureuploader.cpp31
-rw-r--r--src/gui/painting/qbezier.cpp5
-rw-r--r--src/network/access/http2/hpacktable.cpp209
-rw-r--r--src/network/access/http2/hpacktable_p.h11
-rw-r--r--src/network/access/qnetworkreplywasmimpl.cpp2
-rw-r--r--src/platformsupport/services/genericunix/qgenericunixservices.cpp52
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm2
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm9
-rw-r--r--src/plugins/platforms/cocoa/qnsview_dragging.mm111
-rw-r--r--src/plugins/platforms/cocoa/qnsview_mouse.mm39
-rw-r--r--src/testlib/qappletestlogger.cpp20
-rw-r--r--src/testlib/qappletestlogger_p.h17
-rw-r--r--src/testlib/qtestcase.cpp31
-rw-r--r--src/testlib/qtestlog.cpp195
-rw-r--r--src/testlib/qtestlog_p.h11
20 files changed, 420 insertions, 404 deletions
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
};