diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2018-12-12 01:00:38 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2018-12-12 13:08:25 +0100 |
commit | 39643ef86e8bc48b8b6cf83ac0ebae7411029030 (patch) | |
tree | 79277e468160ebc04a65a85c9668dabefbf3ce33 | |
parent | 489d6c28dda51c187c85017e30c1e018420e26ac (diff) | |
parent | e3446c8225acbaa6a613d6c62e8e2fc58e2b70b0 (diff) |
Merge remote-tracking branch 'origin/5.12' into dev
Conflicts:
tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
Change-Id: Ic1dace832ad4b29023d24808b8617b5dcc915eb5
41 files changed, 582 insertions, 63 deletions
diff --git a/dist/changes-5.11.3 b/dist/changes-5.11.3 new file mode 100644 index 0000000000..8701cdeed4 --- /dev/null +++ b/dist/changes-5.11.3 @@ -0,0 +1,58 @@ +Qt 5.11.3 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.11.0 through 5.11.2. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +http://doc.qt.io/qt-5/index.html + +The Qt version 5.11 series is binary compatible with the 5.10.x series. +Applications compiled for 5.10 will continue to run with 5.11. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + +https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Qt 5.11.3 Changes * +**************************************************************************** + +**************************************************************************** +* QtQml * +**************************************************************************** + + - [QTBUG-69973] Fixed QML comma operator property lookup failure. + - [QTBUG-70350] Fixed allocation of multi-page executable memory for + INTEGRITY. + - [QTBUG-69996] Fixed undefined behavior in MASM on 64bit architectures. + - [QTBUG-70460] Fixed deadlock in qmlplugindump. + +**************************************************************************** +* QtQuick * +**************************************************************************** + + - Accessibility: The StaticText role for Text items is now only used if + there is no explicit role set. + - Scene Graph: Fixed Leaking of resources in the OpenVG backend. + - [QTBUG-69290] Fixed leaking of textures and animation resources in + software backend. + - [QTBUG-58924] Added a warning message for the case of too many tiles in + a BorderImage. + - [QTBUG-70898] Fixed a crash on nested delivery of mouse or touch presses. + - [QTBUG-64402] Fixed a crash in QQuickAnimatorProxyJob. + - [QTBUG-69059][QTBUG-61144] Fixed confusion about mouse grabbing when + delivering pointer events to a QQuickWindow. + - [QTBUG-59620] Prevented PathView's parent from stealing mouse grabs + during double-flick. + +**************************************************************************** +* Building * +**************************************************************************** + + - [QTBUG-70414] Disabled building of XmlListModel if the "qml-network" + feature is unavailable. + - Enabled building without the "filesystemwatcher" feature. diff --git a/src/3rdparty/masm/stubs/wtf/Optional.h b/src/3rdparty/masm/stubs/wtf/Optional.h index fdb7de51ce..602dbc1b43 100644 --- a/src/3rdparty/masm/stubs/wtf/Optional.h +++ b/src/3rdparty/masm/stubs/wtf/Optional.h @@ -84,7 +84,8 @@ private: #endif -#if __cplusplus < 201402L && !QT_CONFIG(cxx14_make_unique) +#if __cplusplus < 201402L && !QT_CONFIG(cxx14_make_unique)\ +&& !defined(__cpp_lib_make_unique) namespace std { template<typename T, class ...Args> diff --git a/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.cpp b/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.cpp index e45b79706b..b5f6b39c60 100644 --- a/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.cpp +++ b/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.cpp @@ -174,7 +174,7 @@ void QSGOpenVGRectangleNode::render() } -QSGOpenVGImageNode::QSGOpenVGImageNode() +QSGOpenVGImageNode::QSGOpenVGImageNode() : m_texture(nullptr), m_owns(false) { // Set Dummy material and geometry to avoid asserts setMaterial((QSGMaterial*)1); @@ -184,9 +184,8 @@ QSGOpenVGImageNode::QSGOpenVGImageNode() QSGOpenVGImageNode::~QSGOpenVGImageNode() { - if (m_owns) { - m_texture->deleteLater(); - } + if (m_owns) + delete m_texture; } void QSGOpenVGImageNode::setRect(const QRectF &rect) @@ -212,6 +211,8 @@ QRectF QSGOpenVGImageNode::sourceRect() const void QSGOpenVGImageNode::setTexture(QSGTexture *texture) { + if (m_owns) + delete m_texture; m_texture = texture; markDirty(DirtyMaterial); } @@ -321,7 +322,7 @@ void QSGOpenVGImageNode::render() } -QSGOpenVGNinePatchNode::QSGOpenVGNinePatchNode() +QSGOpenVGNinePatchNode::QSGOpenVGNinePatchNode() : m_texture(nullptr) { // Set Dummy material and geometry to avoid asserts setMaterial((QSGMaterial*)1); @@ -329,8 +330,14 @@ QSGOpenVGNinePatchNode::QSGOpenVGNinePatchNode() } +QSGOpenVGNinePatchNode::~QSGOpenVGNinePatchNode() +{ + delete m_texture; +} + void QSGOpenVGNinePatchNode::setTexture(QSGTexture *texture) { + delete m_texture; m_texture = texture; markDirty(DirtyMaterial); } diff --git a/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.h b/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.h index 8e12c27824..e1cd3063a1 100644 --- a/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.h +++ b/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.h @@ -118,6 +118,7 @@ class QSGOpenVGNinePatchNode : public QSGNinePatchNode, public QSGOpenVGRenderab { public: QSGOpenVGNinePatchNode(); + ~QSGOpenVGNinePatchNode(); void setTexture(QSGTexture *texture) override; void setBounds(const QRectF &bounds) override; diff --git a/src/plugins/scenegraph/openvg/qsgopenvgrenderloop.cpp b/src/plugins/scenegraph/openvg/qsgopenvgrenderloop.cpp index 9493920100..c41dfd7400 100644 --- a/src/plugins/scenegraph/openvg/qsgopenvgrenderloop.cpp +++ b/src/plugins/scenegraph/openvg/qsgopenvgrenderloop.cpp @@ -43,6 +43,7 @@ #include <QtCore/QCoreApplication> #include <QtCore/QElapsedTimer> +#include <private/qquickanimatorcontroller_p.h> #include <private/qquickwindow_p.h> #include <private/qquickprofiler_p.h> @@ -94,6 +95,8 @@ void QSGOpenVGRenderLoop::windowDestroyed(QQuickWindow *window) } else if (vg && window == vg->window()) { vg->doneCurrent(); } + + delete d->animationController; } void QSGOpenVGRenderLoop::exposureChanged(QQuickWindow *window) diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 9ff38db911..84fd66b114 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1835,8 +1835,9 @@ JSCodeGen::JSCodeGen(const QString &sourceCode, QV4::Compiler::JSUnitGenerator * , _scopeObject(nullptr) , _qmlContextSlot(-1) , _importedScriptsSlot(-1) - , m_globalNames(globalNames) { + m_globalNames = globalNames; + _module = jsModule; _fileNameIsUrl = true; } @@ -2306,15 +2307,10 @@ QV4::Compiler::Codegen::Reference JSCodeGen::fallbackNameLookup(const QString &n return Reference::fromQmlContextObject(base, data->coreIndex(), data->notifyIndex(), capturePolicy); } } - - Reference r = Reference::fromName(this, name); - if (m_globalNames.contains(name)) - r.global = true; - return r; #else Q_UNUSED(name) - return Reference(); #endif // V4_BOOTSTRAP + return Reference(); } #ifndef V4_BOOTSTRAP diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index d1e2b17bb7..3dde929cc4 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -640,7 +640,6 @@ private: QQmlPropertyCache *_scopeObject; int _qmlContextSlot; int _importedScriptsSlot; - QSet<QString> m_globalNames; }; struct Q_QML_PRIVATE_EXPORT IRLoader { diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 63cdb78d27..cdba21604d 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -102,6 +102,62 @@ Codegen::Codegen(QV4::Compiler::JSUnitGenerator *jsUnitGenerator, bool strict) jsUnitGenerator->codeGeneratorName = QStringLiteral("moth"); } +const char *globalNames[] = { + "isNaN", + "parseFloat", + "String", + "EvalError", + "URIError", + "Math", + "encodeURIComponent", + "RangeError", + "eval", + "isFinite", + "ReferenceError", + "Infinity", + "Function", + "RegExp", + "Number", + "parseInt", + "Object", + "decodeURI", + "TypeError", + "Boolean", + "encodeURI", + "NaN", + "Error", + "decodeURIComponent", + "Date", + "Array", + "Symbol", + "escape", + "unescape", + "SyntaxError", + "undefined", + "JSON", + "ArrayBuffer", + "SharedArrayBuffer", + "DataView", + "Int8Array", + "Uint8Array", + "Uint8ClampedArray", + "Int16Array", + "Uint16Array", + "Int32Array", + "Uint32Array", + "Float32Array", + "Float64Array", + "WeakSet", + "Set", + "WeakMap", + "Map", + "Reflect", + "Proxy", + "Atomics", + "Promise", + nullptr +}; + void Codegen::generateFromProgram(const QString &fileName, const QString &finalUrl, const QString &sourceCode, @@ -118,6 +174,18 @@ void Codegen::generateFromProgram(const QString &fileName, _module->fileName = fileName; _module->finalUrl = finalUrl; + if (contextType == ContextType::ScriptImportedByQML) { + // the global object is frozen, so we know that members of it are + // pointing to the global object. This is important so that references + // to Math etc. do not go through the expensive path in the context wrapper + // that tries to see whether we have a matching type + // + // Since this can be called from the loader thread we can't get the list + // directly from the engine, so let's hardcode the most important ones here + for (const char **g = globalNames; *g != nullptr; ++g) + m_globalNames << QString::fromLatin1(*g); + } + ScanFunctions scan(this, sourceCode, contextType); scan(node); @@ -2336,6 +2404,8 @@ Codegen::Reference Codegen::referenceForName(const QString &name, bool isLhs, co Reference r = Reference::fromName(this, name); r.global = useFastLookups && (resolved.type == Context::ResolvedName::Global); + if (!r.global && m_globalNames.contains(name)) + r.global = true; return r; } diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index 289728f505..3f96afc7c2 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -708,6 +708,11 @@ public: return *_returnLabel; } + void setGlobalNames(const QSet<QString>& globalNames) { + m_globalNames = globalNames; + } + + protected: friend class ScanFunctions; friend struct ControlFlow; @@ -730,6 +735,7 @@ protected: bool inFormalParameterList = false; bool functionEndsWithReturn = false; bool _tailCallsAreAllowed = true; + QSet<QString> m_globalNames; ControlFlow *controlFlow = nullptr; diff --git a/src/qml/jsruntime/qv4alloca_p.h b/src/qml/jsruntime/qv4alloca_p.h index 1e9f83a90e..65c3e4d65a 100644 --- a/src/qml/jsruntime/qv4alloca_p.h +++ b/src/qml/jsruntime/qv4alloca_p.h @@ -89,7 +89,7 @@ public: Qt_AllocaWrapper() { m_data = 0; } ~Qt_AllocaWrapper() { free(m_data); } void *data() { return m_data; } - void allocate(int size) { m_data = malloc(size); } + void allocate(int size) { m_data = malloc(size); memset(m_data, 0, size); } private: void *m_data; }; diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index f80db86be5..7bbef3335e 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -241,6 +241,7 @@ Script *Script::createFromFileOrCache(ExecutionEngine *engine, QmlContext *qmlCo QmlIR::Document::removeScriptPragmas(sourceCode); auto result = new QV4::Script(engine, qmlContext, /*parseAsBinding*/false, sourceCode, originalUrl.toString()); + result->contextType = QV4::Compiler::ContextType::ScriptImportedByQML; result->parse(); return result; } diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 5208894934..937a535b83 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -550,6 +550,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, MOTH_END_INSTR(LoadName) MOTH_BEGIN_INSTR(LoadGlobalLookup) + STORE_IP(); QV4::Lookup *l = function->compilationUnit->runtimeLookups + index; acc = l->globalGetter(l, engine); CHECK_EXCEPTION; diff --git a/src/qml/parser/qqmljslexer.cpp b/src/qml/parser/qqmljslexer.cpp index e5b8894fb1..c53b13f64d 100644 --- a/src/qml/parser/qqmljslexer.cpp +++ b/src/qml/parser/qqmljslexer.cpp @@ -884,7 +884,7 @@ int Lexer::scanString(ScanStringMode mode) scanChar(); while (_codePtr <= _endPtr) { - if (_char == mode) { + if (_char == quote) { scanChar(); if (_engine) { diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index f288646ec7..c400e9239b 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -755,6 +755,9 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o) d->context = nullptr; } + if (d->outerContext && d->outerContext->contextObject == o) + d->outerContext->contextObject = nullptr; + // Mark this object as in the process of deletion to // prevent it resolving in bindings QQmlData::markAsDeleted(o); diff --git a/src/qmltest/doc/src/qtquicktest-index.qdoc b/src/qmltest/doc/src/qtquicktest-index.qdoc index 15ea33d06a..48b41d4f0a 100644 --- a/src/qmltest/doc/src/qtquicktest-index.qdoc +++ b/src/qmltest/doc/src/qtquicktest-index.qdoc @@ -151,17 +151,18 @@ \li Name \li Purpose \row - \row \li void applicationAvailable() \li Called right after the QApplication object was instantiated. Use this function to setup everything that is not related to QML directly. + \row \li void qmlEngineAvailable(QQmlEngine*) \li Called when the QML engine is available. Any \l {QQmlEngine::addImportPath}{import paths}, \l {QQmlEngine::addPluginPath}{plugin paths}, and \l {QQmlFileSelector::setExtraSelectors}{extra file selectors} will have been set on the engine by this point. + \row \li void cleanupTestCase() \li Called right after the test execution has finished. Use this function to clean up before everything will start to be destructed. diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp index e97722d6b7..d480d3b491 100644 --- a/src/quick/handlers/qquicktaphandler.cpp +++ b/src/quick/handlers/qquicktaphandler.cpp @@ -107,6 +107,10 @@ static bool dragOverThreshold(const QQuickEventPoint *point) bool QQuickTapHandler::wantsEventPoint(QQuickEventPoint *point) { + if (!point->pointerEvent()->asPointerMouseEvent() && + !point->pointerEvent()->asPointerTouchEvent() && + !point->pointerEvent()->asPointerTabletEvent() ) + return false; // If the user has not violated any constraint, it could be a tap. // Otherwise we want to give up the grab so that a competing handler // (e.g. DragHandler) gets a chance to take over. diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h index d1a8bbd901..e614b1bd6d 100644 --- a/src/quick/items/qquickevents_p_p.h +++ b/src/quick/items/qquickevents_p_p.h @@ -723,5 +723,6 @@ QML_DECLARE_TYPE(QQuickCloseEvent) QML_DECLARE_TYPE(QQuickPointerDevice) QML_DECLARE_TYPE(QPointingDeviceUniqueId) QML_DECLARE_TYPE(QQuickPointerEvent) +Q_DECLARE_METATYPE(QQuickEventPoint::GrabTransition) #endif // QQUICKEVENTS_P_P_H diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index f58e08038f..0cd4c446d9 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -89,6 +89,7 @@ QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(DBG_MOUSE_TARGET) Q_DECLARE_LOGGING_CATEGORY(DBG_HOVER_TRACE) Q_DECLARE_LOGGING_CATEGORY(lcTransient) +Q_LOGGING_CATEGORY(lcHandlerParent, "qt.quick.handler.parent") void debugFocusTree(QQuickItem *item, QQuickItem *scope = nullptr, int depth = 1) { @@ -3280,12 +3281,11 @@ void QQuickItemPrivate::data_append(QQmlListProperty<QObject> *prop, QObject *o) if (o->inherits("QGraphicsItem")) qWarning("Cannot add a QtQuick 1.0 item (%s) into a QtQuick 2.0 scene!", o->metaObject()->className()); else if (QQuickPointerHandler *pointerHandler = qmlobject_cast<QQuickPointerHandler *>(o)) { - Q_ASSERT(pointerHandler->parentItem() == that); - // Accept all buttons, and leave filtering to pointerEvent() and/or user JS, - // because there can be multiple handlers... - that->setAcceptedMouseButtons(Qt::AllButtons); - QQuickItemPrivate *p = QQuickItemPrivate::get(that); - p->extra.value().pointerHandlers.prepend(pointerHandler); + if (pointerHandler->parent() != that) { + qCDebug(lcHandlerParent) << "reparenting handler" << pointerHandler << ":" << pointerHandler->parent() << "->" << that; + pointerHandler->setParent(that); + } + QQuickItemPrivate::get(that)->addPointerHandler(pointerHandler); } else { QQuickWindow *thisWindow = qmlobject_cast<QQuickWindow *>(o); QQuickItem *item = that; @@ -8209,6 +8209,17 @@ bool QQuickItemPrivate::hasHoverHandlers() const return false; } +void QQuickItemPrivate::addPointerHandler(QQuickPointerHandler *h) +{ + Q_Q(QQuickItem); + // Accept all buttons, and leave filtering to pointerEvent() and/or user JS, + // because there can be multiple handlers... + q->setAcceptedMouseButtons(Qt::AllButtons); + auto &handlers = extra.value().pointerHandlers; + if (!handlers.contains(h)) + handlers.prepend(h); +} + #if QT_CONFIG(quick_shadereffect) QQuickItemLayer::QQuickItemLayer(QQuickItem *item) : m_item(item) diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 11b47114cf..4ca3a01d02 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -281,6 +281,7 @@ public: bool hasPointerHandlers() const; bool hasHoverHandlers() const; + void addPointerHandler(QQuickPointerHandler *h); // data property static void data_append(QQmlListProperty<QObject> *, QObject *); diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index a20150e3b9..b2fcfb4307 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -145,6 +145,7 @@ static QQmlPrivate::AutoParentResult qquickitem_autoParent(QObject *obj, QObject return QQmlPrivate::Parented; } } else if (QQuickPointerHandler *handler = qmlobject_cast<QQuickPointerHandler *>(obj)) { + QQuickItemPrivate::get(parentItem)->addPointerHandler(handler); handler->setParent(parent); return QQmlPrivate::Parented; } @@ -156,13 +157,14 @@ static QQmlPrivate::AutoParentResult qquickitem_autoParent(QObject *obj, QObject qCDebug(lcTransient) << win << "is transient for" << parentWindow; win->setTransientParent(parentWindow); return QQmlPrivate::Parented; - } else { - QQuickItem *item = qmlobject_cast<QQuickItem *>(obj); - if (item) { - // The parent of an Item inside a Window is actually the implicit content Item - item->setParentItem(parentWindow->contentItem()); - return QQmlPrivate::Parented; - } + } else if (QQuickItem *item = qmlobject_cast<QQuickItem *>(obj)) { + // The parent of an Item inside a Window is actually the implicit content Item + item->setParentItem(parentWindow->contentItem()); + return QQmlPrivate::Parented; + } else if (QQuickPointerHandler *handler = qmlobject_cast<QQuickPointerHandler *>(obj)) { + QQuickItemPrivate::get(parentWindow->contentItem())->addPointerHandler(handler); + handler->setParent(parentWindow->contentItem()); + return QQmlPrivate::Parented; } return QQmlPrivate::IncompatibleObject; } else if (qmlobject_cast<QQuickItem *>(obj)) { diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index 4d4540bc36..dd7fbccff5 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -2082,6 +2082,8 @@ void QQuickText::resetMaximumLineCount() \code <b></b> - bold + <del></del> - strike out (removed content) + <s></s> - strike out (no longer accurate or no longer relevant content) <strong></strong> - bold <i></i> - italic <br> - new line diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index a09aa830fb..b5a68a2283 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -2246,13 +2246,14 @@ QQuickPointerEvent *QQuickWindowPrivate::queryPointerEventInstance(QQuickPointer { // Search for a matching reusable event object. for (QQuickPointerEvent *e : pointerEventInstances) { - // If device can generate native gestures (e.g. a trackpad), there might be two QQuickPointerEvents: - // QQuickPointerNativeGestureEvent and QQuickPointerTouchEvent. Use eventType to disambiguate. + // If device can generate native gestures (e.g. a trackpad), there might be multiple QQuickPointerEvents: + // QQuickPointerNativeGestureEvent, QQuickPointerScrollEvent, and QQuickPointerTouchEvent. + // Use eventType to disambiguate. #if QT_CONFIG(gestures) - if (eventType == QEvent::NativeGesture && !qobject_cast<QQuickPointerNativeGestureEvent*>(e)) + if ((eventType == QEvent::NativeGesture) != bool(e->asPointerNativeGestureEvent())) continue; #endif - if (eventType == QEvent::Wheel && !qobject_cast<QQuickPointerScrollEvent*>(e)) + if ((eventType == QEvent::Wheel) != bool(e->asPointerScrollEvent())) continue; // Otherwise we assume there's only one event type per device. // More disambiguation tests might need to be added above if that changes later. diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes.cpp index bd0698be6c..20286a03d5 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes.cpp @@ -156,10 +156,11 @@ void QSGSoftwareNinePatchNode::setTexture(QSGTexture *texture) QSGSoftwarePixmapTexture *pt = qobject_cast<QSGSoftwarePixmapTexture*>(texture); if (!pt) { qWarning() << "Image used with invalid texture format."; - return; + } else { + m_pixmap = pt->pixmap(); + markDirty(DirtyMaterial); } - m_pixmap = pt->pixmap(); - markDirty(DirtyMaterial); + delete texture; } void QSGSoftwareNinePatchNode::setBounds(const QRectF &bounds) diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp index b400473128..f5a41410ee 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp @@ -45,6 +45,7 @@ #include <private/qquickwindow_p.h> #include <QElapsedTimer> +#include <private/qquickanimatorcontroller_p.h> #include <private/qquickprofiler_p.h> #include <private/qsgsoftwarerenderer_p.h> #include <qpa/qplatformbackingstore.h> @@ -98,6 +99,8 @@ void QSGSoftwareRenderLoop::windowDestroyed(QQuickWindow *window) if (m_windows.size() == 0) { rc->invalidate(); } + + delete d->animationController; } void QSGSoftwareRenderLoop::renderWindow(QQuickWindow *window, bool isNewExpose) diff --git a/src/quick/util/qquickstyledtext.cpp b/src/quick/util/qquickstyledtext.cpp index 762d49f2d2..5e1aaf121e 100644 --- a/src/quick/util/qquickstyledtext.cpp +++ b/src/quick/util/qquickstyledtext.cpp @@ -50,6 +50,8 @@ QQuickStyledText supports few tags: <b></b> - bold + <del></del> - strike out (removed content) + <s></s> - strike out (no longer accurate or no longer relevant content) <strong></strong> - bold <i></i> - italic <br> - new line @@ -379,8 +381,16 @@ bool QQuickStyledTextPrivate::parseTag(const QChar *&ch, const QString &textIn, format.setFontWeight(QFont::Bold); return true; } - } else if (tag == QLatin1String("strong")) { - format.setFontWeight(QFont::Bold); + } else if (char0 == QLatin1Char('s')) { + if (tagLength == 1) { + format.setFontStrikeOut(true); + return true; + } else if (tag == QLatin1String("strong")) { + format.setFontWeight(QFont::Bold); + return true; + } + } else if (tag == QLatin1String("del")) { + format.setFontStrikeOut(true); return true; } else if (tag == QLatin1String("ol")) { List listItem; @@ -511,7 +521,13 @@ bool QQuickStyledTextPrivate::parseCloseTag(const QChar *&ch, const QString &tex return true; } else if (tag == QLatin1String("font")) { return true; - } else if (tag == QLatin1String("strong")) { + } else if (char0 == QLatin1Char('s')) { + if (tagLength == 1) { + return true; + } else if (tag == QLatin1String("strong")) { + return true; + } + } else if (tag == QLatin1String("del")) { return true; } else if (tag == QLatin1String("ol")) { if (!listStack.isEmpty()) { diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp index f8fa6e6716..1ac28c473b 100644 --- a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp +++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp @@ -527,7 +527,7 @@ void tst_QQmlDebugJS::changeBreakpoint() QCOMPARE(init(qmlscene, CHANGEBREAKPOINT_QMLFILE), ConnectSuccess); bool isStopped = false; - QObject::connect(m_client, &QV4DebugClient::stopped, this, [&]() { isStopped = true; }); + QObject::connect(m_client.data(), &QV4DebugClient::stopped, this, [&]() { isStopped = true; }); auto continueDebugging = [&]() { m_client->continueDebugging(QV4DebugClient::Continue); @@ -549,7 +549,7 @@ void tst_QQmlDebugJS::changeBreakpoint() auto setBreakPoint = [&](int sourceLine, bool enabled) { int id = -1; - auto connection = QObject::connect(m_client, &QV4DebugClient::result, [&]() { + auto connection = QObject::connect(m_client.data(), &QV4DebugClient::result, [&]() { id = extractBody().value("breakpoint").toInt(); }); @@ -888,7 +888,7 @@ void tst_QQmlDebugJS::encodeQmlScope() bool isStopped = false; bool scopesFailed = false; - QObject::connect(m_client, &QV4DebugClient::failure, this, [&]() { + QObject::connect(m_client.data(), &QV4DebugClient::failure, this, [&]() { qWarning() << "received failure" << m_client->response().body; scopesFailed = true; m_process->stop(); @@ -896,12 +896,12 @@ void tst_QQmlDebugJS::encodeQmlScope() isStopped = false; }); - QObject::connect(m_client, &QV4DebugClient::stopped, this, [&]() { + QObject::connect(m_client.data(), &QV4DebugClient::stopped, this, [&]() { m_client->frame(); isStopped = true; }); - QObject::connect(m_client, &QV4DebugClient::result, this, [&]() { + QObject::connect(m_client.data(), &QV4DebugClient::result, this, [&]() { const QV4DebugClient::Response value = m_client->response(); if (value.command == QString("scope")) { @@ -944,20 +944,20 @@ void tst_QQmlDebugJS::breakOnAnchor() int breaks = 0; bool stopped = false; - QObject::connect(m_client, &QV4DebugClient::stopped, this, [&]() { + QObject::connect(m_client.data(), &QV4DebugClient::stopped, this, [&]() { stopped = true; ++breaks; m_client->evaluate("this", 0, -1); }); - QObject::connect(m_client, &QV4DebugClient::result, this, [&]() { + QObject::connect(m_client.data(), &QV4DebugClient::result, this, [&]() { if (stopped) { m_client->continueDebugging(QV4DebugClient::Continue); stopped = false; } }); - QObject::connect(m_client, &QV4DebugClient::failure, this, [&]() { + QObject::connect(m_client.data(), &QV4DebugClient::failure, this, [&]() { qWarning() << "received failure" << m_client->response().body; }); diff --git a/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp b/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp index b4f8f389cf..4c4c514832 100644 --- a/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp +++ b/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp @@ -101,11 +101,11 @@ QList<QQmlDebugClient *> tst_QQmlPreview::createClients() { m_client = new QQmlPreviewClient(m_connection); - QObject::connect(m_client, &QQmlPreviewClient::request, this, &tst_QQmlPreview::serveRequest); - QObject::connect(m_client, &QQmlPreviewClient::error, this, [this](const QString &error) { + QObject::connect(m_client.data(), &QQmlPreviewClient::request, this, &tst_QQmlPreview::serveRequest); + QObject::connect(m_client.data(), &QQmlPreviewClient::error, this, [this](const QString &error) { m_serviceErrors.append(error); }); - QObject::connect(m_client, &QQmlPreviewClient::fps, + QObject::connect(m_client.data(), &QQmlPreviewClient::fps, this, [this](const QQmlPreviewClient::FpsInfo &info) { m_frameStats = info; }); diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp index 3337e6d3fd..085eb7b87a 100644 --- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp +++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp @@ -468,7 +468,7 @@ QList<QQmlDebugClient *> tst_QQmlProfilerService::createClients() m_client.reset(new QQmlProfilerTestClient(m_connection)); m_client->client->setRecording(m_recordFromStart); m_client->client->setFlushInterval(m_flushInterval); - QObject::connect(m_client->client, &QQmlProfilerClient::complete, + QObject::connect(m_client->client.data(), &QQmlProfilerClient::complete, this, [this](){ m_isComplete = true; }); return QList<QQmlDebugClient *>({m_client->client}); } diff --git a/tests/auto/qml/qqmlcontext/data/MyItem.qml b/tests/auto/qml/qqmlcontext/data/MyItem.qml new file mode 100644 index 0000000000..2ffd984dfa --- /dev/null +++ b/tests/auto/qml/qqmlcontext/data/MyItem.qml @@ -0,0 +1,5 @@ +import QtQuick 2.0 + +QtObject { + Component.onCompleted: 5 + 5 +} diff --git a/tests/auto/qml/qqmlcontext/data/outerContextObject.qml b/tests/auto/qml/qqmlcontext/data/outerContextObject.qml new file mode 100644 index 0000000000..992b760915 --- /dev/null +++ b/tests/auto/qml/qqmlcontext/data/outerContextObject.qml @@ -0,0 +1,18 @@ +import QtQml 2.2 + +QtObject { + id: window + + property Component itemComponent: Qt.createComponent("MyItem.qml") + property MyItem item + + property Timer timer: Timer { + running: true + interval: 10 + repeat: true + onTriggered: { + item = itemComponent.createObject(null, {}); + gc(); + } + } +} diff --git a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp index 990e364c76..5838193a6b 100644 --- a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp +++ b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp @@ -28,6 +28,7 @@ #include <qtest.h> #include <QDebug> +#include <QTimer> #include <QQmlEngine> #include <QQmlContext> #include <QQmlComponent> @@ -68,6 +69,8 @@ private slots: void contextViaClosureAfterDestruction(); void contextLeak(); + void outerContextObject(); + private: QQmlEngine engine; }; @@ -815,6 +818,61 @@ void tst_qqmlcontext::contextLeak() QVERIFY(scriptContext.isNull()); } + +static bool buildObjectList(QQmlContext *ctxt) +{ + static QHash<QObject *, QString> deletedObjects; + QQmlContextData *p = QQmlContextData::get(ctxt); + QObject *object = p->contextObject; + if (object) { + // If the object was actually deleted this is likely to crash in one way or another. + // Either the memory is still intact, then we will probably find the objectName, or it is + // not, then the connect() below is likely to fail. + if (deletedObjects.contains(object) && deletedObjects[object] == object->objectName()) + return false; + QObject::connect(object, &QObject::destroyed, [object]() { + object->setObjectName(QString::number(deletedObjects.size())); + deletedObjects.insert(object, object->objectName()); + }); + } + + QQmlContextData *child = p->childContexts; + while (child) { + if (!buildObjectList(child->asQQmlContext())) + return false; + child = child->nextChild; + } + + return true; +} + +void tst_qqmlcontext::outerContextObject() +{ + QQmlEngine engine; + + QQmlComponent component(&engine, testFileUrl("outerContextObject.qml")); + QVERIFY(component.isReady()); + + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); + + int iterations = 0; + QTimer timer; + timer.setInterval(1); + QObject::connect(&timer, &QTimer::timeout, &engine, [&]() { + if (!buildObjectList(engine.rootContext())) { + iterations = 100; + timer.stop(); + QFAIL("Deleted object found as context object"); + } else { + ++iterations; + } + }); + timer.start(); + + QTRY_VERIFY(iterations >= 100); +} + QTEST_MAIN(tst_qqmlcontext) #include "tst_qqmlcontext.moc" diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 71c4e03812..254a6bc878 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -360,6 +360,7 @@ private slots: void importLexicalVariables_data(); void importLexicalVariables(); void hugeObject(); + void templateStringTerminator(); private: // static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter); @@ -8858,6 +8859,14 @@ void tst_qqmlecmascript::hugeObject() QVERIFY(!v.isError()); } +void tst_qqmlecmascript::templateStringTerminator() +{ + QJSEngine engine; + const QJSValue value = engine.evaluate("let a = 123; let b = `x${a}\ny^`; b;"); + QVERIFY(!value.isError()); + QCOMPARE(value.toString(), QLatin1String("x123\ny^")); +} + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc" diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/dynamicallyCreated.qml b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/dynamicallyCreated.qml new file mode 100644 index 0000000000..8f774a7ec3 --- /dev/null +++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/dynamicallyCreated.qml @@ -0,0 +1,34 @@ +import QtQuick 2.12 +import Qt.test 1.0 + +Item { + id: root + objectName: "root Item" + width: 320 + height: 480 + + Rectangle { + objectName: "eventItem's bounds" + anchors.fill: eventItem + color: "lightsteelblue" + } + + EventItem { + id: eventItem + objectName: "eventItem1" + x: 5 + y: 5 + height: 30 + width: 30 + + Component.onCompleted: handlerComponent.createObject(eventItem) + + Component { + id: handlerComponent + + EventHandler { + objectName: "eventHandler" + } + } + } +} diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/dynamicallyCreatedInWindow.qml b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/dynamicallyCreatedInWindow.qml new file mode 100644 index 0000000000..058726b267 --- /dev/null +++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/dynamicallyCreatedInWindow.qml @@ -0,0 +1,20 @@ +import QtQuick 2.12 +import QtQuick.Window 2.12 +import Qt.test 1.0 + +Window { + id: root + objectName: "root Window" + width: 320 + height: 480 + + Component.onCompleted: handlerComponent.createObject(root) + + Component { + id: handlerComponent + + EventHandler { + objectName: "eventHandler" + } + } +} diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/handlerInWindow.qml b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/handlerInWindow.qml new file mode 100644 index 0000000000..49ec9be4a7 --- /dev/null +++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/handlerInWindow.qml @@ -0,0 +1,14 @@ +import QtQuick 2.12 +import QtQuick.Window 2.12 +import Qt.test 1.0 + +Window { + id: root + objectName: "root Window" + width: 320 + height: 480 + + EventHandler { + objectName: "eventHandler" + } +} diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp index e8b076052a..feb356a7d5 100644 --- a/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp @@ -182,12 +182,18 @@ public: class EventHandler : public QQuickPointerHandler { +public: void handlePointerEventImpl(QQuickPointerEvent *event) override { QQuickPointerHandler::handlePointerEventImpl(event); if (!enabled()) return; - EventItem *item = static_cast<EventItem *>(target()); + ++eventCount; + EventItem *item = qmlobject_cast<EventItem *>(target()); + if (!item) { + event->point(0)->setGrabberPointerHandler(this); + return; + } qCDebug(lcPointerTests) << item->objectName() << event; int c = event->pointCount(); for (int i = 0; i < c; ++i) { @@ -206,10 +212,13 @@ class EventHandler : public QQuickPointerHandler void onGrabChanged(QQuickPointerHandler *, QQuickEventPoint::GrabTransition stateChange, QQuickEventPoint *point) override { - EventItem *item = static_cast<EventItem *>(target()); - item->eventList.append(Event(Event::HandlerDestination, QEvent::None, - static_cast<Qt::TouchPointState>(point->state()), stateChange, eventPos(point), point->scenePosition())); + EventItem *item = qmlobject_cast<EventItem *>(target()); + if (item) + item->eventList.append(Event(Event::HandlerDestination, QEvent::None, + static_cast<Qt::TouchPointState>(point->state()), stateChange, eventPos(point), point->scenePosition())); } + + int eventCount = 0; }; class tst_PointerHandlers : public QQmlDataTest @@ -228,6 +237,9 @@ private slots: void mouseEventDelivery(); void touchReleaseOutside_data(); void touchReleaseOutside(); + void dynamicCreation(); + void handlerInWindow(); + void dynamicCreationInWindow(); protected: bool eventFilter(QObject *, QEvent *event) @@ -593,6 +605,76 @@ void tst_PointerHandlers::touchReleaseOutside() QCOMPARE_EVENT(endIndexToTest, endDestination, endType, endState, endGrabState); } +void tst_PointerHandlers::dynamicCreation() +{ + QScopedPointer<QQuickView> windowPtr; + createView(windowPtr, "dynamicallyCreated.qml"); + QQuickView * window = windowPtr.data(); + + EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1"); + QVERIFY(eventItem1); + EventHandler *handler = window->rootObject()->findChild<EventHandler*>("eventHandler"); + QVERIFY(handler); + + QCOMPARE(handler->parentItem(), eventItem1); + QCOMPARE(handler->target(), eventItem1); + + QPoint p1(20, 20); + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1); + QTRY_COMPARE(eventItem1->eventList.size(), 2); + QCOMPARE_EVENT(0, Event::HandlerDestination, QEvent::Pointer, Qt::TouchPointPressed, NoGrab); + QCOMPARE_EVENT(1, Event::MouseDestination, QEvent::MouseButtonPress, Qt::TouchPointPressed, NoGrab); + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1); +} + +void tst_PointerHandlers::handlerInWindow() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(testFileUrl("handlerInWindow.qml")); + QQuickWindow *window = qobject_cast<QQuickWindow*>(component.create()); + QScopedPointer<QQuickWindow> cleanup(window); + QVERIFY(window); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + EventHandler *handler = window->contentItem()->findChild<EventHandler*>("eventHandler"); + QVERIFY(handler); + + QCOMPARE(handler->parentItem(), window->contentItem()); + QCOMPARE(handler->target(), window->contentItem()); + + QPoint p1(20, 20); + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1); + QTRY_COMPARE(handler->eventCount, 1); + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1); + QTRY_COMPARE(handler->eventCount, 2); +} + +void tst_PointerHandlers::dynamicCreationInWindow() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(testFileUrl("dynamicallyCreatedInWindow.qml")); + QQuickWindow *window = qobject_cast<QQuickWindow*>(component.create()); + QScopedPointer<QQuickWindow> cleanup(window); + QVERIFY(window); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + EventHandler *handler = window->contentItem()->findChild<EventHandler*>("eventHandler"); + QVERIFY(handler); + + QCOMPARE(handler->parentItem(), window->contentItem()); + QCOMPARE(handler->target(), window->contentItem()); + + QPoint p1(20, 20); + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1); + QTRY_COMPARE(handler->eventCount, 1); + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1); + QTRY_COMPARE(handler->eventCount, 2); +} + QTEST_MAIN(tst_PointerHandlers) #include "tst_qquickpointerhandler.moc" diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml new file mode 100644 index 0000000000..aea01c154c --- /dev/null +++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/rightTapHandler.qml @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.12 + +Rectangle { + width: 320 + height: 240 + color: rightTap.pressed ? "tomato" : "beige" + TapHandler { + id: rightTap + objectName: "right button TapHandler" + longPressThreshold: 0.5 + acceptedButtons: Qt.RightButton + } +} diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp index 467c964001..ab6fa0dbe4 100644 --- a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp @@ -69,6 +69,7 @@ private slots: void mouseLongPress(); void buttonsMultiTouch(); void componentUserBehavioralOverride(); + void rightLongPressIgnoreWheel(); private: void createView(QScopedPointer<QQuickView> &window, const char *fileName); @@ -622,6 +623,44 @@ void tst_TapHandler::componentUserBehavioralOverride() QCOMPARE(userGrabChangedSpy.count(), 2); } +void tst_TapHandler::rightLongPressIgnoreWheel() +{ + QScopedPointer<QQuickView> windowPtr; + createView(windowPtr, "rightTapHandler.qml"); + QQuickView * window = windowPtr.data(); + + QQuickTapHandler *tap = window->rootObject()->findChild<QQuickTapHandler*>(); + QVERIFY(tap); + QSignalSpy tappedSpy(tap, SIGNAL(tapped(QQuickEventPoint *))); + QSignalSpy longPressedSpy(tap, SIGNAL(longPressed())); + QPoint p1(100, 100); + + // Mouse wheel with ScrollBegin phase (because as soon as two fingers are touching + // the trackpad, it will send such an event: QTBUG-71955) + { + QWheelEvent wheelEvent(p1, p1, QPoint(0, 0), QPoint(0, 0), + Qt::NoButton, Qt::NoModifier, Qt::ScrollBegin, false, Qt::MouseEventNotSynthesized); + QGuiApplication::sendEvent(window, &wheelEvent); + } + + // Press + QTest::mousePress(window, Qt::RightButton, Qt::NoModifier, p1); + QTRY_COMPARE(tap->isPressed(), true); + + // Mouse wheel ScrollEnd phase + QWheelEvent wheelEvent(p1, p1, QPoint(0, 0), QPoint(0, 0), + Qt::NoButton, Qt::NoModifier, Qt::ScrollEnd, false, Qt::MouseEventNotSynthesized); + QGuiApplication::sendEvent(window, &wheelEvent); + QTRY_COMPARE(longPressedSpy.count(), 1); + QCOMPARE(tap->isPressed(), true); + QCOMPARE(tappedSpy.count(), 0); + + // Release + QTest::mouseRelease(window, Qt::RightButton, Qt::NoModifier, p1, 500); + QTRY_COMPARE(tap->isPressed(), false); + QCOMPARE(tappedSpy.count(), 0); +} + QTEST_MAIN(tst_TapHandler) #include "tst_qquicktaphandler.moc" diff --git a/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp b/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp index 6ca5ad2653..88b0e95e0a 100644 --- a/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp +++ b/tests/auto/quick/qquickstyledtext/tst_qquickstyledtext.cpp @@ -44,7 +44,8 @@ public: Bold = 0x01, Underline = 0x02, Italic = 0x04, - Anchor = 0x08 + Anchor = 0x08, + StrikeOut = 0x10 }; Format(int t, int s, int l) : type(t), start(s), length(l) {} @@ -92,6 +93,10 @@ void tst_qquickstyledtext::textOutput_data() QTest::newRow("underline") << "<u>underline</u>" << "underline" << (FormatList() << Format(Format::Underline, 0, 9)) << false; QTest::newRow("strong") << "<strong>strong</strong>" << "strong" << (FormatList() << Format(Format::Bold, 0, 6)) << false; QTest::newRow("underline") << "<u>underline</u>" << "underline" << (FormatList() << Format(Format::Underline, 0, 9)) << false; + QTest::newRow("strike out s") << "<s>strike out</s>" << "strike out" << (FormatList() << Format(Format::StrikeOut, 0, 10)) << false; + QTest::newRow("strike out del") << "<del>strike out</del>" << "strike out" << (FormatList() << Format(Format::StrikeOut, 0, 10)) << false; + QTest::newRow("strike out not s") << "this is <s>not</s> a test" << "this is not a test" << (FormatList() << Format(Format::StrikeOut, 8, 3)) << false; + QTest::newRow("strike out not del") << "this is <del>not</del> a test" << "this is not a test" << (FormatList() << Format(Format::StrikeOut, 8, 3)) << false; QTest::newRow("missing >") << "<b>text</b" << "text" << (FormatList() << Format(Format::Bold, 0, 4)) << false; QTest::newRow("missing b>") << "<b>text</" << "text" << (FormatList() << Format(Format::Bold, 0, 4)) << false; QTest::newRow("missing /b>") << "<b>text<" << "text" << (FormatList() << Format(Format::Bold, 0, 4)) << false; @@ -178,6 +183,7 @@ void tst_qquickstyledtext::textOutput() QCOMPARE(layoutFormats.at(i).format.fontWeight(), int(QFont::Normal)); QVERIFY(layoutFormats.at(i).format.fontItalic() == bool(formats.at(i).type & Format::Italic)); QVERIFY(layoutFormats.at(i).format.fontUnderline() == bool(formats.at(i).type & Format::Underline)); + QVERIFY(layoutFormats.at(i).format.fontStrikeOut() == bool(formats.at(i).type & Format::StrikeOut)); } QCOMPARE(fontSizeModified, modifiesFontSize); } diff --git a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp index e523274d0a..24e55e3b3a 100644 --- a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp +++ b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp @@ -35,6 +35,7 @@ #include <QtQuick/qquickitem.h> #include "../../shared/util.h" #include <QtGui/QWindow> +#include <QtGui/QScreen> #include <QtGui/QImage> #include <QtCore/QDebug> #include <QtQml/qqmlengine.h> @@ -144,6 +145,7 @@ private slots: private: QTouchDevice *device = QTest::createTouchDevice(); + const QRect m_availableGeometry = QGuiApplication::primaryScreen()->availableGeometry(); }; tst_qquickwidget::tst_qquickwidget() @@ -199,7 +201,7 @@ void tst_qquickwidget::changeGeometry() void tst_qquickwidget::resizemodeitem() { QWidget window; - window.setGeometry(0, 0, 400, 400); + window.setGeometry(m_availableGeometry.left(), m_availableGeometry.top(), 400, 400); QScopedPointer<QQuickWidget> view(new QQuickWidget); view->setParent(&window); @@ -533,18 +535,20 @@ void tst_qquickwidget::enterLeave() view.setSource(testFileUrl("enterleave.qml")); // Ensure it is not inside the window first - QCursor::setPos(QPoint(50, 50)); - QTRY_VERIFY(QCursor::pos() == QPoint(50, 50)); + const auto outside = m_availableGeometry.topLeft() + QPoint(50, 50); + QCursor::setPos(outside); + QTRY_VERIFY(QCursor::pos() == outside); - view.move(100, 100); + view.move(m_availableGeometry.topLeft() + QPoint(100, 100)); view.show(); QVERIFY(QTest::qWaitForWindowExposed(&view, 5000)); QQuickItem *rootItem = view.rootObject(); QVERIFY(rootItem); + const QPoint frameOffset = view.geometry().topLeft() - view.frameGeometry().topLeft(); QTRY_VERIFY(!rootItem->property("hasMouse").toBool()); // Check the enter - QCursor::setPos(view.pos() + QPoint(50, 50)); + QCursor::setPos(view.pos() + QPoint(50, 50) + frameOffset); QTRY_VERIFY(rootItem->property("hasMouse").toBool()); // Now check the leave QCursor::setPos(view.pos() - QPoint(50, 50)); diff --git a/tools/tools.pro b/tools/tools.pro index ef4872d1a1..2e2eb831a9 100644 --- a/tools/tools.pro +++ b/tools/tools.pro @@ -3,6 +3,7 @@ QT_FOR_CONFIG += qml-private qtConfig(qml-devtools) { SUBDIRS += \ + qmllint \ qmlmin \ qmlimportscanner @@ -13,7 +14,6 @@ qtConfig(thread):!android|android_app { SUBDIRS += \ qml - qtConfig(qml-devtools): SUBDIRS += qmllint qtConfig(qml-profiler): SUBDIRS += qmlprofiler qtConfig(qml-preview): SUBDIRS += qmlpreview |