aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/3rdparty/masm/assembler/LinkBuffer.h8
-rw-r--r--src/qml/compiler/qqmlpropertycachecreator_p.h40
-rw-r--r--src/qml/compiler/qv4compileddata.cpp8
-rw-r--r--src/qml/compiler/qv4compilercontext_p.h1
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp27
-rw-r--r--src/qml/jsruntime/qv4engine.cpp4
-rw-r--r--src/qml/jsruntime/qv4global_p.h3
-rw-r--r--src/qml/jsruntime/qv4identifiertable.cpp2
-rw-r--r--src/qml/jsruntime/qv4internalclass_p.h2
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp1
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp3
-rw-r--r--src/qml/qml/qqmlimport.cpp2
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp29
-rw-r--r--src/qml/types/qqmlmodelsmodule.cpp2
-rw-r--r--src/qmltest/doc/src/qtquicktest-index.qdoc8
-rw-r--r--src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc12
-rw-r--r--src/quick/handlers/qquickdraghandler.cpp7
-rw-r--r--src/quick/items/qquickwindow.cpp18
-rw-r--r--src/quick/items/qquickwindow.h1
-rw-r--r--src/quick/scenegraph/qsgdefaultcontext.cpp10
-rw-r--r--src/quickwidgets/qquickwidget.cpp31
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp28
-rw-r--r--tests/auto/qml/qmlmin/tst_qmlmin.cpp1
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp17
-rw-r--r--tests/auto/qml/qqmllanguage/data/cyclicAlias.errors.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/cyclicAlias.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/fuzzed.1.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/fuzzed.1.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/fuzzed.2.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/fuzzed.2.qmlbin0 -> 404 bytes
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp7
-rw-r--r--tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp23
-rw-r--r--tests/auto/qml/qv4assembler/tst_qv4assembler.cpp22
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/data/dragMargin.qml36
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp33
-rw-r--r--tests/auto/quick/qquicklistview/BLACKLIST3
-rw-r--r--tests/auto/quick/qquicklistview/data/delegateWithMouseArea.qml29
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp34
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/BLACKLIST2
-rw-r--r--tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp4
-rw-r--r--tools/qml/main.cpp7
-rw-r--r--tools/qml/qml.icnsbin196156 -> 0 bytes
-rw-r--r--tools/qml/qml.pro10
-rw-r--r--tools/qml/qml.qrc1
-rw-r--r--tools/qml/resources/Info.plist (renamed from tools/qml/Info.plist)0
-rw-r--r--tools/qml/resources/qml-64.pngbin0 -> 2304 bytes
-rw-r--r--tools/qml/resources/qml.icnsbin0 -> 194026 bytes
-rw-r--r--tools/qml/resources/qml.icobin0 -> 124455 bytes
-rw-r--r--tools/qmlscene/main.cpp7
49 files changed, 408 insertions, 87 deletions
diff --git a/src/3rdparty/masm/assembler/LinkBuffer.h b/src/3rdparty/masm/assembler/LinkBuffer.h
index c79b0663c8..7f9979302e 100644
--- a/src/3rdparty/masm/assembler/LinkBuffer.h
+++ b/src/3rdparty/masm/assembler/LinkBuffer.h
@@ -243,7 +243,7 @@ protected:
inline void linkCode(void* ownerUID, JITCompilationEffort);
- inline void performFinalization();
+ virtual void performFinalization();
#if DUMP_LINK_STATISTICS
static void dumpLinkStatistics(void* code, size_t initialSize, size_t finalSize);
@@ -342,7 +342,7 @@ inline void LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::linkCode
}
template <typename MacroAssembler, template <typename T> class ExecutableOffsetCalculator>
-inline void LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::performFinalization()
+void LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::performFinalization()
{
// NOTE: This function is specialized in LinkBuffer<MacroAssemblerARMv7>
#ifndef NDEBUG
@@ -388,7 +388,7 @@ public:
linkCode(ownerUID, effort);
}
- inline void performFinalization();
+ virtual void performFinalization() override final;
inline void linkCode(void* ownerUID, JITCompilationEffort);
@@ -412,7 +412,7 @@ private:
};
template <typename MacroAssembler>
-inline void BranchCompactingLinkBuffer<MacroAssembler>::performFinalization()
+void BranchCompactingLinkBuffer<MacroAssembler>::performFinalization()
{
#ifndef NDEBUG
ASSERT(!m_completed);
diff --git a/src/qml/compiler/qqmlpropertycachecreator_p.h b/src/qml/compiler/qqmlpropertycachecreator_p.h
index 6bee599c0a..074dc98648 100644
--- a/src/qml/compiler/qqmlpropertycachecreator_p.h
+++ b/src/qml/compiler/qqmlpropertycachecreator_p.h
@@ -692,11 +692,6 @@ inline QQmlCompileError QQmlPropertyCacheAliasCreator<ObjectContainer>::property
const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *minorVersion,
QQmlPropertyData::Flags *propertyFlags)
{
- const int targetObjectIndex = objectForId(component, alias.targetObjectId);
- Q_ASSERT(targetObjectIndex >= 0);
-
- const CompiledObject &targetObject = *objectContainer->objectAt(targetObjectIndex);
-
*type = 0;
bool writable = false;
bool resettable = false;
@@ -704,11 +699,36 @@ inline QQmlCompileError QQmlPropertyCacheAliasCreator<ObjectContainer>::property
propertyFlags->isAlias = true;
if (alias.aliasToLocalAlias) {
- auto targetAlias = targetObject.aliasesBegin();
- for (uint i = 0; i < alias.localAliasIndex; ++i)
- ++targetAlias;
- return propertyDataForAlias(component, *targetAlias, type, minorVersion, propertyFlags);
- } else if (alias.encodedMetaPropertyIndex == -1) {
+ const QV4::CompiledData::Alias *lastAlias = &alias;
+ QVarLengthArray<const QV4::CompiledData::Alias *, 4> seenAliases({lastAlias});
+
+ do {
+ const CompiledObject *targetObject = objectContainer->objectAt(
+ objectForId(component, lastAlias->targetObjectId));
+ Q_ASSERT(targetObject);
+
+ auto nextAlias = targetObject->aliasesBegin();
+ for (uint i = 0; i < lastAlias->localAliasIndex; ++i)
+ ++nextAlias;
+
+ const QV4::CompiledData::Alias *targetAlias = &(*nextAlias);
+ if (seenAliases.contains(targetAlias)) {
+ return QQmlCompileError(targetAlias->location,
+ QQmlPropertyCacheCreatorBase::tr("Cyclic alias"));
+ }
+
+ seenAliases.append(targetAlias);
+ lastAlias = targetAlias;
+ } while (lastAlias->aliasToLocalAlias);
+
+ return propertyDataForAlias(component, *lastAlias, type, minorVersion, propertyFlags);
+ }
+
+ const int targetObjectIndex = objectForId(component, alias.targetObjectId);
+ Q_ASSERT(targetObjectIndex >= 0);
+ const CompiledObject &targetObject = *objectContainer->objectAt(targetObjectIndex);
+
+ if (alias.encodedMetaPropertyIndex == -1) {
Q_ASSERT(alias.flags & QV4::CompiledData::Alias::AliasPointsToPointerObject);
auto *typeRef = objectContainer->resolvedType(targetObject.inheritedTypeNameIndex);
if (!typeRef) {
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 9ffcb81fa2..9fb91e9140 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -470,8 +470,10 @@ Heap::Module *CompilationUnit::instantiate(ExecutionEngine *engine)
ScopedString importName(scope);
const uint importCount = data->importEntryTableSize;
- imports = new const Value *[importCount];
- memset(imports, 0, importCount * sizeof(Value *));
+ if (importCount > 0) {
+ imports = new const Value *[importCount];
+ memset(imports, 0, importCount * sizeof(Value *));
+ }
for (uint i = 0; i < importCount; ++i) {
const CompiledData::ImportEntry &entry = data->importEntryTable()[i];
auto dependentModuleUnit = engine->loadModule(QUrl(stringAt(entry.moduleRequest)), this);
@@ -895,6 +897,8 @@ bool ResolvedTypeReference::addToHash(QCryptographicHash *hash, QQmlEngine *engi
hash->addData(createPropertyCache(engine)->checksum(&ok));
return ok;
}
+ if (!compilationUnit)
+ return false;
hash->addData(compilationUnit->unitData()->md5Checksum, sizeof(compilationUnit->unitData()->md5Checksum));
return true;
}
diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h
index 8f3b60e395..020b403bc4 100644
--- a/src/qml/compiler/qv4compilercontext_p.h
+++ b/src/qml/compiler/qv4compilercontext_p.h
@@ -215,7 +215,6 @@ struct Context {
bool usesThis = false;
bool innerFunctionAccessesThis = false;
bool innerFunctionAccessesNewTarget = false;
- bool hasTry = false;
bool returnsClosure = false;
mutable bool argumentsCanEscape = false;
bool requiresExecutionContext = false;
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index 04593f202a..8984b6931e 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -741,9 +741,9 @@ void ScanFunctions::calcEscapingVariables()
if (c->contextType != ContextType::ESModule)
continue;
for (const auto &entry: c->exportEntries) {
- auto m = c->members.find(entry.localName);
- if (m != c->members.end())
- m->canEscape = true;
+ auto mIt = c->members.constFind(entry.localName);
+ if (mIt != c->members.constEnd())
+ mIt->canEscape = true;
}
break;
}
@@ -759,8 +759,8 @@ void ScanFunctions::calcEscapingVariables()
}
Q_ASSERT(c != inner);
while (c) {
- Context::MemberMap::const_iterator it = c->members.find(var);
- if (it != c->members.end()) {
+ Context::MemberMap::const_iterator it = c->members.constFind(var);
+ if (it != c->members.constEnd()) {
if (c->parent || it->isLexicallyScoped()) {
it->canEscape = true;
c->requiresExecutionContext = true;
@@ -816,15 +816,17 @@ void ScanFunctions::calcEscapingVariables()
// add an escaping 'this' variable
c->addLocalVar(QStringLiteral("this"), Context::VariableDefinition, VariableScope::Let);
c->requiresExecutionContext = true;
- auto m = c->members.find(QStringLiteral("this"));
- m->canEscape = true;
+ auto mIt = c->members.constFind(QStringLiteral("this"));
+ Q_ASSERT(mIt != c->members.constEnd());
+ mIt->canEscape = true;
}
if (c->innerFunctionAccessesNewTarget) {
// add an escaping 'new.target' variable
c->addLocalVar(QStringLiteral("new.target"), Context::VariableDefinition, VariableScope::Let);
c->requiresExecutionContext = true;
- auto m = c->members.find(QStringLiteral("new.target"));
- m->canEscape = true;
+ auto mIt = c->members.constFind(QStringLiteral("new.target"));
+ Q_ASSERT(mIt != c->members.constEnd());
+ mIt->canEscape = true;
}
if (c->allVarsEscape && c->contextType == ContextType::Block && c->members.isEmpty())
c->allVarsEscape = false;
@@ -845,8 +847,9 @@ void ScanFunctions::calcEscapingVariables()
}
if (c->contextType == ContextType::Block && c->isCatchBlock) {
c->requiresExecutionContext = true;
- auto m = c->members.find(c->caughtVariable);
- m->canEscape = true;
+ auto mIt = c->members.constFind(c->caughtVariable);
+ Q_ASSERT(mIt != c->members.constEnd());
+ mIt->canEscape = true;
}
const QLatin1String exprForOn("expression for on");
if (c->contextType == ContextType::Binding && c->name.length() > exprForOn.size() &&
@@ -855,7 +858,7 @@ void ScanFunctions::calcEscapingVariables()
// we don't know if the code is a signal handler or not.
c->requiresExecutionContext = true;
if (c->allVarsEscape) {
- for (auto &m : c->members)
+ for (const auto &m : qAsConst(c->members))
m.canEscape = true;
}
}
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index bcd577c24d..bd1124beb6 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -1537,6 +1537,10 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
case QMetaType::QLocale:
return QQmlLocale::wrap(this, *reinterpret_cast<const QLocale*>(ptr));
#endif
+ case QMetaType::QPixmap:
+ case QMetaType::QImage:
+ // Scarce value types
+ return QV4::Encode(newVariantObject(variant));
default:
break;
}
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index 162fb66cba..58bffdf2d1 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -94,7 +94,8 @@ inline double trunc(double d) { return d > 0 ? floor(d) : ceil(d); }
#elif defined(Q_PROCESSOR_X86_64) && (QT_POINTER_SIZE == 8) \
&& (defined(Q_OS_WIN) || defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_MAC) || defined(Q_OS_FREEBSD))
# define V4_ENABLE_JIT
-#elif defined(Q_PROCESSOR_ARM_32) && (QT_POINTER_SIZE == 4)
+#elif defined(Q_PROCESSOR_ARM_32) && (QT_POINTER_SIZE == 4) \
+ && (defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_FREEBSD) || defined(Q_OS_INTEGRITY))
# if defined(thumb2) || defined(__thumb2__) || ((defined(__thumb) || defined(__thumb__)) && __TARGET_ARCH_THUMB-0 == 4)
# define V4_ENABLE_JIT
# elif defined(__ARM_ARCH_ISA_THUMB) && __ARM_ARCH_ISA_THUMB == 2 // clang 3.5 and later will set this if the core supports the Thumb-2 ISA.
diff --git a/src/qml/jsruntime/qv4identifiertable.cpp b/src/qml/jsruntime/qv4identifiertable.cpp
index e476baa886..4305bc4647 100644
--- a/src/qml/jsruntime/qv4identifiertable.cpp
+++ b/src/qml/jsruntime/qv4identifiertable.cpp
@@ -70,7 +70,7 @@ IdentifierTable::~IdentifierTable()
{
free(entriesByHash);
free(entriesById);
- for (auto &h : idHashes)
+ for (const auto &h : qAsConst(idHashes))
h->identifierTable = nullptr;
}
diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h
index 42b61218a5..7bb10f47a3 100644
--- a/src/qml/jsruntime/qv4internalclass_p.h
+++ b/src/qml/jsruntime/qv4internalclass_p.h
@@ -457,7 +457,7 @@ private:
InternalClass *addMemberImpl(PropertyKey identifier, PropertyAttributes data, InternalClassEntry *entry);
void removeChildEntry(InternalClass *child);
- friend struct ExecutionEngine;
+ friend struct ::QV4::ExecutionEngine;
};
inline
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 85d06bcabe..6a242ba5f6 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -1942,6 +1942,7 @@ ReturnedValue Runtime::method_div(const Value &left, const Value &right)
int lval = left.integerValue();
int rval = right.integerValue();
if (rval != 0 // division by zero should result in a NaN
+ && !(lval == std::numeric_limits<int>::min() && rval == -1) // doesn't fit in int
&& (lval % rval == 0) // fractions can't be stored in an int
&& !(lval == 0 && rval < 0)) // 0 / -something results in -0.0
return Encode(int(lval / rval));
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index dee6a67792..6afa6d36d6 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -765,9 +765,8 @@ static void appendReplacementString(QString *result, const QString &input, const
i += skip;
if (substStart != JSC::Yarr::offsetNoMatch && substEnd != JSC::Yarr::offsetNoMatch)
*result += input.midRef(substStart, substEnd - substStart);
- else {
+ else if (skip == 0) // invalid capture reference. Taken as literal value
*result += replaceValue.at(i);
- }
} else {
*result += replaceValue.at(i);
}
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index a79d4d074c..5a1364473e 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -867,7 +867,7 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
*typeRecursionDetected = true;
} else {
QQmlType returnType = fetchOrCreateTypeForUrl(
- qmlUrl, type, registrationType == QQmlType::CompositeSingletonType, nullptr);
+ qmlUrl, type, registrationType == QQmlType::CompositeSingletonType, errors);
if (type_return)
*type_return = returnType;
return returnType.isValid();
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index 2b21591017..cb6a467c6c 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -81,19 +81,26 @@ QQmlValueTypeFactoryImpl::~QQmlValueTypeFactoryImpl()
bool QQmlValueTypeFactoryImpl::isValueType(int idx)
{
- if (idx >= (int)QVariant::UserType) {
- return (valueType(idx) != nullptr);
- } else if (idx >= 0
- && idx != QVariant::StringList
- && idx != QMetaType::QObjectStar
- && idx != QMetaType::VoidStar
- && idx != QMetaType::Nullptr
- && idx != QMetaType::QVariant
- && idx != QMetaType::QLocale) {
+ if (idx >= QMetaType::User)
+ return valueType(idx) != nullptr;
+
+ if (idx < 0)
+ return false;
+
+ // Qt internal types
+ switch (idx) {
+ case QMetaType::QStringList:
+ case QMetaType::QObjectStar:
+ case QMetaType::VoidStar:
+ case QMetaType::Nullptr:
+ case QMetaType::QVariant:
+ case QMetaType::QLocale:
+ case QMetaType::QImage: // scarce type, keep as QVariant
+ case QMetaType::QPixmap: // scarce type, keep as QVariant
+ return false;
+ default:
return true;
}
-
- return false;
}
const QMetaObject *QQmlValueTypeFactoryImpl::metaObjectForMetaType(int t)
diff --git a/src/qml/types/qqmlmodelsmodule.cpp b/src/qml/types/qqmlmodelsmodule.cpp
index 30915d96fd..bb72771cd9 100644
--- a/src/qml/types/qqmlmodelsmodule.cpp
+++ b/src/qml/types/qqmlmodelsmodule.cpp
@@ -72,9 +72,11 @@ void QQmlModelsModule::defineLabsModule()
{
const char uri[] = "Qt.labs.qmlmodels";
+#if QT_CONFIG(qml_delegate_model)
qmlRegisterUncreatableType<QQmlAbstractDelegateComponent>(uri, 1, 0, "AbstractDelegateComponent", QQmlAbstractDelegateComponent::tr("Cannot create instance of abstract class AbstractDelegateComponent."));
qmlRegisterType<QQmlDelegateChooser>(uri, 1, 0, "DelegateChooser");
qmlRegisterType<QQmlDelegateChoice>(uri, 1, 0, "DelegateChoice");
+#endif
}
QT_END_NAMESPACE
diff --git a/src/qmltest/doc/src/qtquicktest-index.qdoc b/src/qmltest/doc/src/qtquicktest-index.qdoc
index bee160f6e8..4fad21e080 100644
--- a/src/qmltest/doc/src/qtquicktest-index.qdoc
+++ b/src/qmltest/doc/src/qtquicktest-index.qdoc
@@ -165,6 +165,10 @@
and \l {QQmlFileSelector::setExtraSelectors}{extra file selectors}
will have been set on the engine by this point.
+ This function is called once for each QML test file,
+ so any arguments are unique to that test. For example, this
+ means that each QML test file will have its own QML engine.
+
This function can be used to \l {Choosing the Correct Integration
Method Between C++ and QML}{register QML types} and
\l {QQmlEngine::addImportPath()}{add import paths},
@@ -177,10 +181,6 @@
\li Qt 5.12
\endtable
- Each function will be called once for each \c tst_*.qml file, so any
- arguments are unique to that test. For example, this means that each QML
- test file will have its own QML engine.
-
The following example demonstrates how the macro can be used to set context
properties on the QML engine:
diff --git a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
index 4c94259139..9383c78a42 100644
--- a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
+++ b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
@@ -269,7 +269,7 @@ animations, process events, etc.
\endlist
The threaded renderer is currently used by default on Windows with
-opengl32.dll, Linux with non-Mesa based drivers, \macos, mobile
+opengl32.dll, Linux with non-Mesa based drivers, mobile
platforms, and Embedded Linux with EGLFS but this is subject to
change. It is possible to force use of the threaded renderer by
setting \c {QSG_RENDER_LOOP=threaded} in the environment.
@@ -277,13 +277,19 @@ setting \c {QSG_RENDER_LOOP=threaded} in the environment.
\section2 Non-threaded Render Loops ("basic" and "windows")
The non-threaded render loop is currently used by default on Windows
-with ANGLE or a non-default opengl32 implementation and Linux with
+with ANGLE or a non-default opengl32 implementation, \macos, and Linux with
Mesa drivers. For the latter this is mostly a precautionary measure,
as not all combinations of OpenGL drivers and windowing systems have
been tested. At the same time implementations like ANGLE or Mesa
llvmpipe are not able to function properly with threaded rendering at
all so not using threaded rendering is essential for these.
+On macOS, the threaded render loop is not supported when building
+with XCode 10 (10.14 SDK) or later, since this opts in to layer-backed
+views on macOS 10.14. You can build with Xcode 9 (10.13 SDK) to opt
+out of layer-backing, in which case the threaded render loop is
+available and used by default.
+
By default \c windows is used for non-threaded rendering on Windows
with ANGLE, while \c basic is used for all other platforms when
non-threaded rendering is needed.
diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp
index 48f0599284..e5531369cf 100644
--- a/src/quick/handlers/qquickdraghandler.cpp
+++ b/src/quick/handlers/qquickdraghandler.cpp
@@ -112,14 +112,13 @@ QPointF QQuickDragHandler::targetCentroidPosition()
void QQuickDragHandler::onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabTransition transition, QQuickEventPoint *point)
{
QQuickMultiPointHandler::onGrabChanged(grabber, transition, point);
- if (grabber == this && transition == QQuickEventPoint::GrabExclusive) {
+ if (grabber == this && transition == QQuickEventPoint::GrabExclusive && target()) {
// In case the grab got handed over from another grabber, we might not get the Press.
if (!m_pressedInsideTarget) {
- if (target())
+ if (target() != parentItem())
m_pressTargetPos = QPointF(target()->width(), target()->height()) / 2;
} else if (m_pressTargetPos.isNull()) {
- if (target())
- m_pressTargetPos = targetCentroidPosition();
+ m_pressTargetPos = targetCentroidPosition();
}
}
}
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index fa9aa88faa..f705f132fc 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -2017,8 +2017,8 @@ bool QQuickWindowPrivate::deliverTouchCancelEvent(QTouchEvent *event)
qCDebug(DBG_TOUCH) << event;
Q_Q(QQuickWindow);
- if (q->mouseGrabberItem())
- q->mouseGrabberItem()->ungrabMouse();
+ if (QQuickItem *grabber = q->mouseGrabberItem())
+ sendUngrabEvent(grabber, true);
cancelTouchMouseSynthesis();
// A TouchCancel event will typically not contain any points.
@@ -2543,7 +2543,7 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event,
if (point->grabberPointerHandler())
cancelTouchMouseSynthesis();
} else {
- qCWarning(DBG_TOUCH_TARGET) << "during delivery of touch press, synth-mouse ID" << touchMouseId << "is missing from" << event;
+ qCWarning(DBG_TOUCH_TARGET) << "during delivery of touch press, synth-mouse ID" << hex << touchMouseId << "is missing from" << event;
}
}
for (int i = 0; i < pointCount; ++i) {
@@ -4828,10 +4828,18 @@ void QQuickWindow::scheduleRenderJob(QRunnable *job, RenderStage stage)
} else if (stage == AfterSwapStage) {
d->afterSwapJobs << job;
} else if (stage == NoStage) {
- if (isExposed())
+ if (d->renderControl && openglContext()
+#if QT_CONFIG(opengl)
+ && openglContext()->thread() == QThread::currentThread()
+#endif
+ ) {
+ job->run();
+ delete job;
+ } else if (isExposed()) {
d->windowManager->postJob(this, job);
- else
+ } else {
delete job;
+ }
}
d->renderJobMutex.unlock();
}
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index 79e8a11aa8..53fe0a4c4b 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -241,6 +241,7 @@ private:
friend class QQuickWidget;
friend class QQuickRenderControl;
friend class QQuickAnimatorController;
+ friend class QQuickWidgetPrivate;
Q_DISABLE_COPY(QQuickWindow)
};
diff --git a/src/quick/scenegraph/qsgdefaultcontext.cpp b/src/quick/scenegraph/qsgdefaultcontext.cpp
index 1124bf1727..5813844cd2 100644
--- a/src/quick/scenegraph/qsgdefaultcontext.cpp
+++ b/src/quick/scenegraph/qsgdefaultcontext.cpp
@@ -62,6 +62,8 @@
#include <private/qqmlglobal_p.h>
+#include <algorithm>
+
QT_BEGIN_NAMESPACE
namespace QSGMultisampleAntialiasing {
@@ -158,11 +160,9 @@ void QSGDefaultContext::renderContextInitialized(QSGRenderContext *renderContext
qCDebug(QSG_LOG_INFO, "GL_RENDERER: %s",
(const char*)funcs->glGetString(GL_RENDERER));
qCDebug(QSG_LOG_INFO, "GL_VERSION: %s", (const char*)funcs->glGetString(GL_VERSION));
- QSet<QByteArray> exts = openglRenderContext->openglContext()->extensions();
- QByteArray all;
- for (const QByteArray &e : qAsConst(exts))
- all += ' ' + e;
- qCDebug(QSG_LOG_INFO, "GL_EXTENSIONS: %s", all.constData());
+ QByteArrayList exts = openglRenderContext->openglContext()->extensions().toList();
+ std::sort(exts.begin(), exts.end());
+ qCDebug(QSG_LOG_INFO, "GL_EXTENSIONS: %s", exts.join(' ').constData());
qCDebug(QSG_LOG_INFO, "Max Texture Size: %d", openglRenderContext->maxTextureSize());
qCDebug(QSG_LOG_INFO, "Debug context: %s",
format.testOption(QSurfaceFormat::DebugContext) ? "true" : "false");
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index a098c94670..f1a0f0c863 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -76,6 +76,18 @@
QT_BEGIN_NAMESPACE
+// override setVisble to prevent accidental offscreen window being created
+// by base class.
+class QQuickOffcreenWindowPrivate: public QQuickWindowPrivate {
+public:
+ void setVisible(bool visible) override {
+ Q_Q(QWindow);
+ // this stays always invisible
+ visibility = visible ? QWindow::Windowed : QWindow::Hidden;
+ q->visibilityChanged(visibility); // workaround for QTBUG-49054
+ }
+};
+
class QQuickWidgetRenderControl : public QQuickRenderControl
{
public:
@@ -94,7 +106,7 @@ void QQuickWidgetPrivate::init(QQmlEngine* e)
Q_Q(QQuickWidget);
renderControl = new QQuickWidgetRenderControl(q);
- offscreenWindow = new QQuickWindow(renderControl);
+ offscreenWindow = new QQuickWindow(*new QQuickOffcreenWindowPrivate(),renderControl);
offscreenWindow->setTitle(QString::fromLatin1("Offscreen"));
// Do not call create() on offscreenWindow.
@@ -1321,12 +1333,9 @@ void QQuickWidget::showEvent(QShowEvent *)
triggerUpdate();
}
}
- QWindowPrivate *offscreenPrivate = QWindowPrivate::get(d->offscreenWindow);
- if (!offscreenPrivate->visible) {
- offscreenPrivate->visible = true;
- emit d->offscreenWindow->visibleChanged(true);
- offscreenPrivate->updateVisibility();
- }
+
+ // note offscreenWindow is "QQuickOffScreenWindow" instance
+ d->offscreenWindow->setVisible(true);
if (QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>())
service->setParentWindow(d->offscreenWindow, window()->windowHandle());
}
@@ -1337,12 +1346,8 @@ void QQuickWidget::hideEvent(QHideEvent *)
Q_D(QQuickWidget);
if (!d->offscreenWindow->isPersistentSceneGraph())
d->invalidateRenderControl();
- QWindowPrivate *offscreenPrivate = QWindowPrivate::get(d->offscreenWindow);
- if (offscreenPrivate->visible) {
- offscreenPrivate->visible = false;
- emit d->offscreenWindow->visibleChanged(false);
- offscreenPrivate->updateVisibility();
- }
+ // note offscreenWindow is "QQuickOffScreenWindow" instance
+ d->offscreenWindow->setVisible(false);
if (QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>())
service->setParentWindow(d->offscreenWindow, d->offscreenWindow);
}
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index 0b1f1e0bca..dbb758ae42 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -4427,6 +4427,34 @@ void tst_QJSEngine::stringReplace()
val = engine.evaluate("'x'.replace(/()()()()()()()()()(x)/, '$10')");
QVERIFY(val.isString());
QCOMPARE(val.toString(), QString("x"));
+
+ val = engine.evaluate("'123'.replace(/\\.0*$|(\\.\\d*[1-9])(0+)$/, '$1')");
+ QVERIFY(val.isString());
+ QCOMPARE(val.toString(), QString("123"));
+
+ val = engine.evaluate("'123.00'.replace(/\\.0*$|(\\.\\d*[1-9])(0+)$/, '$1')");
+ QVERIFY(val.isString());
+ QCOMPARE(val.toString(), QString("123"));
+
+ val = engine.evaluate("'123.0'.replace(/\\.0*$|(\\.\\d*[1-9])(0+)$/, '$1')");
+ QVERIFY(val.isString());
+ QCOMPARE(val.toString(), QString("123"));
+
+ val = engine.evaluate("'123.'.replace(/\\.0*$|(\\.\\d*[1-9])(0+)$/, '$1')");
+ QVERIFY(val.isString());
+ QCOMPARE(val.toString(), QString("123"));
+
+ val = engine.evaluate("'123.50'.replace(/\\.0*$|(\\.\\d*[1-9])(0+)$/, '$1')");
+ QVERIFY(val.isString());
+ QCOMPARE(val.toString(), QString("123.5"));
+
+ val = engine.evaluate("'123.05'.replace(/\\.0*$|(\\.\\d*[1-9])(0+)$/, '$1')");
+ QVERIFY(val.isString());
+ QCOMPARE(val.toString(), QString("123.05"));
+
+ val = engine.evaluate("'0.050'.replace(/\\.0*$|(\\.\\d*[1-9])(0+)$/, '$1')");
+ QVERIFY(val.isString());
+ QCOMPARE(val.toString(), QString("0.05"));
}
void tst_QJSEngine::protoChanges_QTBUG68369()
diff --git a/tests/auto/qml/qmlmin/tst_qmlmin.cpp b/tests/auto/qml/qmlmin/tst_qmlmin.cpp
index c393149f59..d1e74aecef 100644
--- a/tests/auto/qml/qmlmin/tst_qmlmin.cpp
+++ b/tests/auto/qml/qmlmin/tst_qmlmin.cpp
@@ -128,6 +128,7 @@ void tst_qmlmin::initTestCase()
invalidFiles << "tests/auto/qml/parserstress/tests/ecma_3/FunExpr/fe-001.js";
invalidFiles << "tests/auto/qml/qjsengine/script/com/trolltech/syntaxerror/__init__.js";
invalidFiles << "tests/auto/qml/debugger/qqmlpreview/data/broken.qml";
+ invalidFiles << "tests/auto/qml/qqmllanguage/data/fuzzed.2.qml";
}
QStringList tst_qmlmin::findFiles(const QDir &d)
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index d8784f4855..0e8844d23f 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -366,6 +366,7 @@ private slots:
void tailCallWithArguments();
void deleteSparseInIteration();
void saveAccumulatorBeforeToInt32();
+ void intMinDividedByMinusOne();
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -8941,6 +8942,22 @@ void tst_qqmlecmascript::saveAccumulatorBeforeToInt32()
QCOMPARE(value.toString(), QLatin1String("RangeError: Maximum call stack size exceeded."));
}
+void tst_qqmlecmascript::intMinDividedByMinusOne()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData(QByteArray("import QtQml 2.2\n"
+ "QtObject {\n"
+ " property int intMin: -2147483648\n"
+ " property int minusOne: -1\n"
+ " property double doesNotFitInInt: intMin / minusOne\n"
+ "}"), QUrl());
+ QVERIFY(component.isReady());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("doesNotFitInInt").toUInt(), 2147483648u);
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"
diff --git a/tests/auto/qml/qqmllanguage/data/cyclicAlias.errors.txt b/tests/auto/qml/qqmllanguage/data/cyclicAlias.errors.txt
new file mode 100644
index 0000000000..46951ef69f
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/cyclicAlias.errors.txt
@@ -0,0 +1 @@
+4:5:Cyclic alias
diff --git a/tests/auto/qml/qqmllanguage/data/cyclicAlias.qml b/tests/auto/qml/qqmllanguage/data/cyclicAlias.qml
new file mode 100644
index 0000000000..23129e210d
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/cyclicAlias.qml
@@ -0,0 +1,5 @@
+import QtQml 2.2
+QtObject {
+ id: o
+ property alias t: o.t
+}
diff --git a/tests/auto/qml/qqmllanguage/data/fuzzed.1.errors.txt b/tests/auto/qml/qqmllanguage/data/fuzzed.1.errors.txt
new file mode 100644
index 0000000000..e399799fe9
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/fuzzed.1.errors.txt
@@ -0,0 +1,2 @@
+2:8:Cannot assign to non-existent property "_G"
+
diff --git a/tests/auto/qml/qqmllanguage/data/fuzzed.1.qml b/tests/auto/qml/qqmllanguage/data/fuzzed.1.qml
new file mode 100644
index 0000000000..f80b9c3a2d
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/fuzzed.1.qml
@@ -0,0 +1,2 @@
+import QtQuick 2.4
+Item { _G.G.G:G }
diff --git a/tests/auto/qml/qqmllanguage/data/fuzzed.2.errors.txt b/tests/auto/qml/qqmllanguage/data/fuzzed.2.errors.txt
new file mode 100644
index 0000000000..92ce4c649f
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/fuzzed.2.errors.txt
@@ -0,0 +1,2 @@
+5:1:TetZ$ is not a type
+-1:-1:Invalid QML type name "TetZ$"
diff --git a/tests/auto/qml/qqmllanguage/data/fuzzed.2.qml b/tests/auto/qml/qqmllanguage/data/fuzzed.2.qml
new file mode 100644
index 0000000000..e726f6783c
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/fuzzed.2.qml
Binary files differ
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index dea7c6c7ee..85dddbcb54 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -361,7 +361,7 @@ private:
} \
file.close(); \
} else { \
- QCOMPARE(expected, actual); \
+ QCOMPARE(actual, expected); \
} \
}
@@ -612,6 +612,10 @@ void tst_qqmllanguage::errors_data()
QTest::newRow("badCompositeRegistration.1") << "badCompositeRegistration.1.qml" << "badCompositeRegistration.1.errors.txt" << false;
QTest::newRow("badCompositeRegistration.2") << "badCompositeRegistration.2.qml" << "badCompositeRegistration.2.errors.txt" << false;
+ QTest::newRow("cyclicAlias") << "cyclicAlias.qml" << "cyclicAlias.errors.txt" << false;
+
+ QTest::newRow("fuzzed.1") << "fuzzed.1.qml" << "fuzzed.1.errors.txt" << false;
+ QTest::newRow("fuzzed.2") << "fuzzed.2.qml" << "fuzzed.2.errors.txt" << false;
}
@@ -622,6 +626,7 @@ void tst_qqmllanguage::errors()
QFETCH(bool, create);
QQmlComponent component(&engine, testFileUrl(file));
+ QTRY_VERIFY(!component.isLoading());
QScopedPointer<QObject> object;
diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
index 1ee4510e30..41fa87d848 100644
--- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
+++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
@@ -33,6 +33,8 @@
#include <QJSValueIterator>
#include <private/qquickvaluetypes_p.h>
#include <private/qqmlglobal_p.h>
+#include <private/qv4engine_p.h>
+#include <private/qv4variantobject_p.h>
#include "../../shared/util.h"
#include "testtypes.h"
@@ -93,6 +95,7 @@ private slots:
void toStringConversion();
void enumerableProperties();
void enumProperties();
+ void scarceTypes();
private:
QQmlEngine engine;
@@ -1766,6 +1769,26 @@ void tst_qqmlvaluetypes::enumProperties()
QCOMPARE(enumValue.toInt(), int(g.enumProperty()));
}
+void tst_qqmlvaluetypes::scarceTypes()
+{
+ // These should not be treated as value types because we want the scarce resource
+ // mechanism to clear them when going out of scope. The scarce resource mechanism
+ // only works on QV4::VariantObject as that has an additional level of redirection.
+ QVERIFY(!QQmlValueTypeFactory::isValueType(qMetaTypeId<QImage>()));
+ QVERIFY(!QQmlValueTypeFactory::isValueType(qMetaTypeId<QPixmap>()));
+
+ QV4::ExecutionEngine engine;
+ QV4::Scope scope(&engine);
+
+ QImage img(20, 20, QImage::Format_ARGB32);
+ QV4::ScopedObject imgValue(scope, engine.fromVariant(QVariant::fromValue(img)));
+ QCOMPARE(QByteArray(imgValue->vtable()->className), QByteArray("VariantObject"));
+
+ QPixmap pixmap;
+ QV4::ScopedObject pixmapValue(scope, engine.fromVariant(QVariant::fromValue(img)));
+ QCOMPARE(QByteArray(pixmapValue->vtable()->className), QByteArray("VariantObject"));
+}
+
QTEST_MAIN(tst_qqmlvaluetypes)
diff --git a/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp b/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp
index 9bd1afa256..afc00ec72c 100644
--- a/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp
+++ b/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp
@@ -29,6 +29,7 @@
#include <QtTest/QtTest>
#include <QtCore/qprocess.h>
#include <QtCore/qtemporaryfile.h>
+#include <private/qv4global_p.h>
class tst_QV4Assembler : public QObject
{
@@ -36,6 +37,7 @@ class tst_QV4Assembler : public QObject
private slots:
void perfMapFile();
+ void jitEnabled();
};
void tst_QV4Assembler::perfMapFile()
@@ -85,6 +87,26 @@ void tst_QV4Assembler::perfMapFile()
#endif
}
+#ifdef V4_ENABLE_JIT
+#define JIT_ENABLED 1
+#else
+#define JIT_ENABLED 0
+#endif
+
+void tst_QV4Assembler::jitEnabled()
+{
+#if defined(Q_OS_IOS) || defined(Q_OS_TVOS)
+ /* JIT should be disabled on iOS and tvOS. */
+ QCOMPARE(JIT_ENABLED, 0);
+#elif defined(Q_OS_WIN) && defined(Q_PROCESSOR_ARM)
+ /* JIT should be disabled Windows on ARM/ARM64 for now. */
+ QCOMPARE(JIT_ENABLED, 0);
+#else
+ /* JIT should be enabled on all other architectures/OSes tested in CI. */
+ QCOMPARE(JIT_ENABLED, 1);
+#endif
+}
+
QTEST_MAIN(tst_QV4Assembler)
#include "tst_qv4assembler.moc"
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/dragMargin.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/dragMargin.qml
new file mode 100644
index 0000000000..e5ca681bd5
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/dragMargin.qml
@@ -0,0 +1,36 @@
+import QtQuick 2.12
+
+Rectangle {
+ color: "#333"
+ width: 480; height: 480
+
+ Rectangle {
+ color: "#112"
+ width: 100
+ height: 100
+ x: 50; y: 50
+
+ DragHandler {
+ id: dragHandler
+ margin: 20
+ }
+
+ Rectangle {
+ id: rect
+ anchors.fill: parent
+ anchors.margins: -dragHandler.margin
+ color: "transparent"
+ border.color: "cyan"
+ border.width: 2
+ radius: 10
+ antialiasing: true
+
+ Text {
+ color: "cyan"
+ text: "drag this margin area"
+ font.pixelSize: 10
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
index eb210c2112..cc8c567e5c 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
@@ -55,6 +55,7 @@ private slots:
void defaultPropertyValues();
void touchDrag();
void mouseDrag();
+ void dragFromMargin();
void touchDragMulti();
void touchDragMultiSliders_data();
void touchDragMultiSliders();
@@ -251,6 +252,38 @@ void tst_DragHandler::mouseDrag()
QCOMPARE(centroidChangedSpy.count(), 5);
}
+void tst_DragHandler::dragFromMargin() // QTBUG-74966
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "dragMargin.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *draggableItem = window->rootObject()->childItems().first();
+ QVERIFY(draggableItem);
+ QQuickDragHandler *dragHandler = draggableItem->findChild<QQuickDragHandler*>();
+ QVERIFY(dragHandler);
+
+ QPointF originalPos = draggableItem->position();
+ QPointF scenePressPos = originalPos - QPointF(10, 0);
+ QPoint p1 = scenePressPos.toPoint();
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QVERIFY(!dragHandler->active());
+ QCOMPARE(dragHandler->centroid().scenePosition(), scenePressPos);
+ QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
+ p1 += QPoint(dragThreshold * 2, 0);
+ QTest::mouseMove(window, p1);
+ QTRY_VERIFY(dragHandler->active());
+ QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
+ QCOMPARE(dragHandler->centroid().sceneGrabPosition(), p1);
+ QCOMPARE(dragHandler->translation().x(), 0.0); // hmm that's odd
+ QCOMPARE(dragHandler->translation().y(), 0.0);
+ QCOMPARE(draggableItem->position(), originalPos + QPointF(dragThreshold * 2, 0));
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTRY_VERIFY(!dragHandler->active());
+ QCOMPARE(dragHandler->centroid().pressedButtons(), Qt::NoButton);
+}
+
void tst_DragHandler::touchDragMulti()
{
const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
diff --git a/tests/auto/quick/qquicklistview/BLACKLIST b/tests/auto/quick/qquicklistview/BLACKLIST
index ecdf8f558e..893f95dcea 100644
--- a/tests/auto/quick/qquicklistview/BLACKLIST
+++ b/tests/auto/quick/qquicklistview/BLACKLIST
@@ -6,3 +6,6 @@ opensuse-leap
[populateTransitions]
opensuse-42.1
#QTBUG-65964
+
+[contentHeightWithDelayRemove]
+osx-10.12
diff --git a/tests/auto/quick/qquicklistview/data/delegateWithMouseArea.qml b/tests/auto/quick/qquicklistview/data/delegateWithMouseArea.qml
new file mode 100644
index 0000000000..e0b8222bfb
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/delegateWithMouseArea.qml
@@ -0,0 +1,29 @@
+import QtQuick 2.12
+
+ListView {
+ id: root
+ objectName: "view"
+ width: 600
+ height: 600
+ model: 3
+ snapMode: ListView.SnapOneItem
+ boundsBehavior: Flickable.StopAtBounds
+ highlightRangeMode: ListView.StrictlyEnforceRange
+ preferredHighlightBegin: 0
+ preferredHighlightEnd: 0
+ highlightMoveDuration: 100
+ delegate: Rectangle {
+ id: delegateRect
+ width: 500
+ height: 500
+ color: Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
+ Text {
+ text: index
+ font.pixelSize: 128
+ anchors.centerIn: parent
+ }
+ MouseArea {
+ anchors.fill: parent
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index ff796a5bd8..fddba77f35 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -37,6 +37,7 @@
#include <QtQml/qqmlincubator.h>
#include <QtQuick/private/qquickitemview_p_p.h>
#include <QtQuick/private/qquicklistview_p.h>
+#include <QtQuick/private/qquickmousearea_p.h>
#include <QtQuick/private/qquicktext_p.h>
#include <QtQml/private/qqmlobjectmodel_p.h>
#include <QtQml/private/qqmllistmodel_p.h>
@@ -273,6 +274,7 @@ private slots:
void addOnCompleted();
void setPositionOnLayout();
+ void touchCancel();
private:
template <class T> void items(const QUrl &source);
@@ -328,6 +330,7 @@ private:
QQuickView *m_view;
QString testForView;
+ QTouchDevice *touchDevice = QTest::createTouchDevice();
};
class TestObject : public QObject
@@ -8944,6 +8947,37 @@ void tst_QQuickListView::useDelegateChooserWithoutDefault()
window->show();
};
+void tst_QQuickListView::touchCancel() // QTBUG-74679
+{
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("delegateWithMouseArea.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickListView *listview = qobject_cast<QQuickListView *>(window->rootObject());
+ QVERIFY(listview);
+ QQuickMouseArea *mouseArea = listview->currentItem()->findChild<QQuickMouseArea *>();
+ QVERIFY(mouseArea);
+
+ QPoint p1(300, 300);
+ QTest::touchEvent(window.data(), touchDevice).press(0, p1, window.data());
+ QQuickTouchUtils::flush(window.data());
+ QTRY_VERIFY(mouseArea->pressed());
+ // and because Flickable filtered it, QQuickFlickablePrivate::pressed
+ // should be true, but it's not easily tested here
+
+ QTouchEvent cancelEvent(QEvent::TouchCancel);
+ cancelEvent.setDevice(touchDevice);
+ QCoreApplication::sendEvent(window.data(), &cancelEvent);
+ // now QQuickWindowPrivate::sendUngrabEvent() will be called, Flickable will filter it,
+ // QQuickFlickablePrivate::pressed will be set to false, and that will allow setCurrentIndex() to make it move
+ QQuickTouchUtils::flush(window.data());
+
+ listview->setCurrentIndex(1);
+ // ensure that it actually moves (animates) to the second delegate
+ QTRY_COMPARE(listview->contentY(), 500.0);
+}
+
QTEST_MAIN(tst_QQuickListView)
#include "tst_qquicklistview.moc"
diff --git a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
index de939b5273..6af00ab76f 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
+++ b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
@@ -3,8 +3,10 @@ ubuntu-16.04
ubuntu-18.04
opensuse-42.3
opensuse-leap
+sles
[nested]
ubuntu-16.04
ubuntu-18.04
opensuse-42.3
opensuse-leap
+sles
diff --git a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
index aaf37b32cd..fd5c3653ad 100644
--- a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
+++ b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
@@ -161,7 +161,7 @@ void tst_qquickwidget::showHide()
window.show();
QVERIFY(QTest::qWaitForWindowExposed(&window));
- QVERIFY(childView->quickWindow()->isVisible());
+ QVERIFY(!childView->quickWindow()->isVisible()); // this window is always not visible see QTBUG-65761
QVERIFY(childView->quickWindow()->visibility() != QWindow::Hidden);
window.hide();
@@ -612,7 +612,7 @@ void tst_qquickwidget::synthMouseFromTouch()
childView->resize(300, 300);
window.show();
QVERIFY(QTest::qWaitForWindowActive(&window));
- QVERIFY(childView->quickWindow()->isVisible());
+ QVERIFY(!childView->quickWindow()->isVisible()); // this window is always not visible see QTBUG-65761
QVERIFY(item->isVisible());
QPoint p1 = QPoint(20, 20);
diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp
index 7dfae2b53d..8918de57d4 100644
--- a/tools/qml/main.cpp
+++ b/tools/qml/main.cpp
@@ -77,6 +77,7 @@ static QQmlApplicationEngine *qae = nullptr;
static int exitTimerId = -1;
#endif
bool verboseMode = false;
+static const QString iconResourcePath(QStringLiteral(":/qt-project.org/QmlRuntime/resources/qml-64.png"));
static void loadConf(const QString &override, bool quiet) // Terminates app on failure
{
@@ -134,7 +135,10 @@ void noFilesGiven();
class LoaderApplication : public QGuiApplication
{
public:
- LoaderApplication(int& argc, char **argv) : QGuiApplication(argc, argv) {}
+ LoaderApplication(int& argc, char **argv) : QGuiApplication(argc, argv)
+ {
+ setWindowIcon(QIcon(iconResourcePath));
+ }
bool event(QEvent *ev) override
{
@@ -450,6 +454,7 @@ int main(int argc, char *argv[])
#ifdef QT_WIDGETS_LIB
case QmlApplicationTypeWidget:
app = new QApplication(argc, argv);
+ static_cast<QApplication *>(app)->setWindowIcon(QIcon(iconResourcePath));
break;
#endif // QT_WIDGETS_LIB
#endif // QT_GUI_LIB
diff --git a/tools/qml/qml.icns b/tools/qml/qml.icns
deleted file mode 100644
index c76051626a..0000000000
--- a/tools/qml/qml.icns
+++ /dev/null
Binary files differ
diff --git a/tools/qml/qml.pro b/tools/qml/qml.pro
index 3f41707275..f086b7bff9 100644
--- a/tools/qml/qml.pro
+++ b/tools/qml/qml.pro
@@ -8,10 +8,14 @@ RESOURCES += qml.qrc
QMAKE_TARGET_DESCRIPTION = QML Runtime
+ICON = resources/qml64.png
+win32 {
+ RC_ICONS = resources/qml.ico
+}
mac {
- OTHER_FILES += Info.plist
- QMAKE_INFO_PLIST = Info.plist
- ICON = qml.icns
+ OTHER_FILES += resources/Info.plist
+ QMAKE_INFO_PLIST = resources/Info.plist
+ ICON = resources/qml.icns
}
qtConfig(qml-debug): DEFINES += QT_QML_DEBUG_NO_WARNING
diff --git a/tools/qml/qml.qrc b/tools/qml/qml.qrc
index 1f0ffdace2..e4be1793d4 100644
--- a/tools/qml/qml.qrc
+++ b/tools/qml/qml.qrc
@@ -2,5 +2,6 @@
<qresource prefix="qt-project.org/QmlRuntime">
<file>conf/configuration.qml</file>
<file>conf/qtquick.qml</file>
+ <file>resources/qml-64.png</file>
</qresource>
</RCC>
diff --git a/tools/qml/Info.plist b/tools/qml/resources/Info.plist
index 567c5bf8fd..567c5bf8fd 100644
--- a/tools/qml/Info.plist
+++ b/tools/qml/resources/Info.plist
diff --git a/tools/qml/resources/qml-64.png b/tools/qml/resources/qml-64.png
new file mode 100644
index 0000000000..83dbeab9af
--- /dev/null
+++ b/tools/qml/resources/qml-64.png
Binary files differ
diff --git a/tools/qml/resources/qml.icns b/tools/qml/resources/qml.icns
new file mode 100644
index 0000000000..b092ffd943
--- /dev/null
+++ b/tools/qml/resources/qml.icns
Binary files differ
diff --git a/tools/qml/resources/qml.ico b/tools/qml/resources/qml.ico
new file mode 100644
index 0000000000..09ec5ccece
--- /dev/null
+++ b/tools/qml/resources/qml.ico
Binary files differ
diff --git a/tools/qmlscene/main.cpp b/tools/qmlscene/main.cpp
index 58a45781a2..5c282d1d1d 100644
--- a/tools/qmlscene/main.cpp
+++ b/tools/qmlscene/main.cpp
@@ -42,6 +42,7 @@
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlfileselector.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/qquickview.h>
@@ -361,6 +362,7 @@ static void usage()
#endif
puts(" --textrendertype [qt|native].......Select the default render type for text-like elements.");
puts(" -I <path> ........................ Add <path> to the list of import paths");
+ puts(" -S <selector> .....................Add <selector> to the list of QQmlFileSelector selectors");
puts(" -P <path> ........................ Add <path> to the list of plugin paths");
puts(" -translation <translationfile> ... Set the language to run in");
@@ -457,6 +459,7 @@ int main(int argc, char ** argv)
Options options;
QStringList imports;
+ QStringList customSelectors;
QStringList pluginPaths;
// Parse arguments for application attributes to be applied before Q[Gui]Application creation.
@@ -531,6 +534,8 @@ int main(int argc, char ** argv)
options.verbose = true;
else if (lowerArgument == QLatin1String("-i") && i + 1 < size)
imports.append(arguments.at(++i));
+ else if (lowerArgument == QLatin1String("-s") && i + 1 < size)
+ customSelectors.append(arguments.at(++i));
else if (lowerArgument == QLatin1String("-p") && i + 1 < size)
pluginPaths.append(arguments.at(++i));
else if (lowerArgument == QLatin1String("--apptype"))
@@ -586,6 +591,8 @@ int main(int argc, char ** argv)
// TODO: as soon as the engine construction completes, the debug service is
// listening for connections. But actually we aren't ready to debug anything.
QQmlEngine engine;
+ QQmlFileSelector* selector = new QQmlFileSelector(&engine, &engine);
+ selector->setExtraSelectors(customSelectors);
QPointer<QQmlComponent> component = new QQmlComponent(&engine);
for (int i = 0; i < imports.size(); ++i)
engine.addImportPath(imports.at(i));