aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp4
-rw-r--r--src/qml/qml/qqmlengine.cpp4
-rw-r--r--src/quick/handlers/qquickmultipointhandler_p.h1
-rw-r--r--src/quick/handlers/qquickwheelhandler.cpp9
-rw-r--r--src/quick/items/qquickevents.cpp133
-rw-r--r--src/quick/items/qquickitemsmodule.cpp2
-rw-r--r--src/quick/items/qquickitemview.cpp28
-rw-r--r--tests/auto/qml/qqmlengine/data/evilSingletonInstantiation.qml6
-rw-r--r--tests/auto/qml/qqmlengine/tst_qqmlengine.cpp31
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST1
10 files changed, 199 insertions, 20 deletions
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index 5055e13223..5a1b27fda6 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -310,8 +310,10 @@ public:
return false;
}
- if (d()->isReadOnly)
+ if (d()->isReadOnly) {
+ engine()->throwTypeError(QLatin1String("Cannot insert into a readonly container"));
return false;
+ }
if (d()->isReference) {
if (!d()->object)
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 6bdf7475f2..d7001dbbe3 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -1014,8 +1014,6 @@ QQmlEngine::~QQmlEngine()
Q_D(QQmlEngine);
QJSEnginePrivate::removeFromDebugServer(this);
- d->typeLoader.invalidate();
-
// Emit onDestruction signals for the root context before
// we destroy the contexts, engine, Singleton Types etc. that
// may be required to handle the destruction signal.
@@ -1031,6 +1029,8 @@ QQmlEngine::~QQmlEngine()
delete d->rootContext;
d->rootContext = nullptr;
+
+ d->typeLoader.invalidate();
}
/*! \fn void QQmlEngine::quit()
diff --git a/src/quick/handlers/qquickmultipointhandler_p.h b/src/quick/handlers/qquickmultipointhandler_p.h
index 480f69035b..c0751aa5c5 100644
--- a/src/quick/handlers/qquickmultipointhandler_p.h
+++ b/src/quick/handlers/qquickmultipointhandler_p.h
@@ -81,7 +81,6 @@ public:
signals:
void minimumPointCountChanged();
void maximumPointCountChanged();
- void marginChanged();
void centroidChanged();
protected:
diff --git a/src/quick/handlers/qquickwheelhandler.cpp b/src/quick/handlers/qquickwheelhandler.cpp
index aef2e8ebfb..16f38af962 100644
--- a/src/quick/handlers/qquickwheelhandler.cpp
+++ b/src/quick/handlers/qquickwheelhandler.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
@@ -500,6 +500,13 @@ void QQuickWheelHandler::timerEvent(QTimerEvent *event)
}
}
+/*!
+ \qmlsignal QtQuick::WheelHandler::wheel(PointerScrollEvent event)
+
+ This signal is emitted every time this handler receives a \l QWheelEvent:
+ that is, every time the wheel is moved or the scrolling gesture is updated.
+*/
+
QQuickWheelHandlerPrivate::QQuickWheelHandlerPrivate()
: QQuickSinglePointHandlerPrivate()
{
diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp
index b241a34337..87708e1483 100644
--- a/src/quick/items/qquickevents.cpp
+++ b/src/quick/items/qquickevents.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
@@ -448,7 +448,7 @@ Item {
*/
/*!
- \qmlproperty int QtQuick::WheelEvent::inverted
+ \qmlproperty bool QtQuick::WheelEvent::inverted
Returns whether the delta values delivered with the event are inverted.
@@ -1431,6 +1431,135 @@ QQuickEventPoint *QQuickSinglePointEvent::point(int i) const
return nullptr;
}
+
+/*!
+ \qmltype PointerScrollEvent
+ \instantiates QQuickPointerScrollEvent
+ \inqmlmodule QtQuick
+ \ingroup qtquick-input-events
+ \brief Provides information about a scrolling event, such as from a mouse wheel.
+
+ \sa WheelHandler
+*/
+
+/*!
+ \internal
+ \class QQuickPointerScrollEvent
+*/
+
+/*!
+ \readonly
+ \qmlproperty PointerDevice QtQuick::PointerScrollEvent::device
+
+ This property holds the device that generated the event.
+*/
+
+/*!
+ \qmlproperty int QtQuick::PointerScrollEvent::buttons
+
+ This property holds the mouse buttons pressed when the wheel event was generated.
+
+ It contains a bitwise combination of:
+ \list
+ \li \l {Qt::LeftButton} {Qt.LeftButton}
+ \li \l {Qt::RightButton} {Qt.RightButton}
+ \li \l {Qt::MiddleButton} {Qt.MiddleButton}
+ \endlist
+*/
+
+/*!
+ \readonly
+ \qmlproperty int QtQuick::PointerScrollEvent::modifiers
+
+ This property holds the \l {Qt::KeyboardModifier}{keyboard modifier} keys
+ that were pressed immediately before the event occurred.
+
+ It contains a bitwise combination of the following flags:
+ \value Qt.NoModifier
+ No modifier key is pressed.
+ \value Qt.ShiftModifier
+ A Shift key on the keyboard is pressed.
+ \value Qt.ControlModifier
+ A Ctrl key on the keyboard is pressed.
+ \value Qt.AltModifier
+ An Alt key on the keyboard is pressed.
+ \value Qt.MetaModifier
+ A Meta key on the keyboard is pressed.
+ \value Qt.KeypadModifier
+ A keypad button is pressed.
+
+ For example, to react to a Shift key + Left mouse button click:
+ \qml
+ Item {
+ TapHandler {
+ onTapped: {
+ if ((event.button == Qt.LeftButton) && (event.modifiers & Qt.ShiftModifier))
+ doSomething();
+ }
+ }
+ }
+ \endqml
+*/
+
+/*!
+ \qmlproperty point QtQuick::PointerScrollEvent::angleDelta
+
+ This property holds the distance that the wheel is rotated in wheel degrees.
+ The x and y cordinate of this property holds the delta in horizontal and
+ vertical orientation.
+
+ A positive value indicates that the wheel was rotated up/right;
+ a negative value indicates that the wheel was rotated down/left.
+
+ Most mouse types work in steps of 15 degrees, in which case the delta value is a
+ multiple of 120; i.e., 120 units * 1/8 = 15 degrees.
+*/
+
+/*!
+ \qmlproperty point QtQuick::PointerScrollEvent::pixelDelta
+
+ This property holds the delta in screen pixels and is available in platforms that
+ have high-resolution trackpads, such as \macos.
+ The x and y coordinates of this property hold the delta in horizontal and
+ vertical orientation. The value should be used directly to scroll content on screen.
+
+ For platforms without high-resolution touchpad support, pixelDelta will
+ always be (0,0), and angleDelta should be used instead.
+*/
+
+/*!
+ \qmlproperty bool QtQuick::PointerScrollEvent::hasAngleDelta
+
+ Returns whether the \l angleDelta property has a non-null value.
+*/
+
+/*!
+ \qmlproperty bool QtQuick::PointerScrollEvent::hasPixelDelta
+
+ Returns whether the \l pixelDelta property has a non-null value.
+*/
+
+/*!
+ \qmlproperty bool QtQuick::PointerScrollEvent::inverted
+
+ Returns whether the delta values delivered with the event are inverted.
+
+ Normally, a vertical wheel will produce a PointerScrollEvent with positive delta
+ values if the top of the wheel is rotating away from the hand operating it.
+ Similarly, a horizontal wheel movement will produce a PointerScrollEvent with
+ positive delta values if the top of the wheel is moved to the left.
+
+ However, on some platforms this is configurable, so that the same
+ operations described above will produce negative delta values (but with the
+ same magnitude). In a QML component (such as a tumbler or a slider) where
+ it is appropriate to synchronize the movement or rotation of an item with
+ the direction of the wheel, regardless of the system settings, the wheel
+ event handler can use the inverted property to decide whether to negate the
+ \l angleDelta or \l pixelDelta values.
+
+ \note Many platforms provide no such information. On such platforms,
+ \c inverted always returns false.
+*/
QQuickPointerEvent *QQuickPointerScrollEvent::reset(QEvent *event)
{
m_event = static_cast<QInputEvent*>(event);
diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp
index 162f772250..2bd3d2a9cb 100644
--- a/src/quick/items/qquickitemsmodule.cpp
+++ b/src/quick/items/qquickitemsmodule.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick module of the Qt Toolkit.
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index 2ac5e60912..031ac6337a 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -1934,21 +1934,25 @@ void QQuickItemViewPrivate::layout()
prepareVisibleItemTransitions();
- for (auto it = releasePendingTransition.begin(); it != releasePendingTransition.end(); ) {
- auto old_count = releasePendingTransition.count();
- auto success = prepareNonVisibleItemTransition(*it, viewBounds);
- // prepareNonVisibleItemTransition() may invalidate iterators while in fast flicking
- // invisible animating items are kicked in or out the viewPort
- // use old_count to test if the abrupt erasure occurs
- if (old_count > releasePendingTransition.count()) {
+ // We cannot use iterators here as erasing from a container invalidates them.
+ for (int i = 0, count = releasePendingTransition.count(); i < count;) {
+ auto success = prepareNonVisibleItemTransition(releasePendingTransition[i], viewBounds);
+ // prepareNonVisibleItemTransition() may remove items while in fast flicking.
+ // Invisible animating items are kicked in or out the viewPort.
+ // Recheck count to test if the item got removed. In that case the same index points
+ // to a different item now.
+ const int old_count = count;
+ count = releasePendingTransition.count();
+ if (old_count > count)
continue;
- }
+
if (!success) {
- releaseItem(*it, reusableFlag);
- it = releasePendingTransition.erase(it);
- continue;
+ releaseItem(releasePendingTransition[i], reusableFlag);
+ releasePendingTransition.remove(i);
+ --count;
+ } else {
+ ++i;
}
- ++it;
}
for (int i=0; i<visibleItems.count(); i++)
diff --git a/tests/auto/qml/qqmlengine/data/evilSingletonInstantiation.qml b/tests/auto/qml/qqmlengine/data/evilSingletonInstantiation.qml
new file mode 100644
index 0000000000..757b0c90bb
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/evilSingletonInstantiation.qml
@@ -0,0 +1,6 @@
+import QtQml 2.12
+import foo.foo 1.0
+
+QtObject {
+ objectName: Singleton.objectName
+}
diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
index 2a3b945509..d782df3e7f 100644
--- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
+++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
@@ -83,6 +83,7 @@ private slots:
void singletonInstance();
void aggressiveGc();
void cachedGetterLookup_qtbug_75335();
+ void createComponentOnSingletonDestruction();
public slots:
QObject *createAQObjectForOwnershipTest ()
@@ -1144,6 +1145,36 @@ void tst_qqmlengine::cachedGetterLookup_qtbug_75335()
QVERIFY(object != nullptr);
}
+class EvilSingleton : public QObject
+{
+ Q_OBJECT
+public:
+ QPointer<QQmlEngine> m_engine;
+ EvilSingleton(QQmlEngine *engine) : m_engine(engine) {
+ connect(this, &QObject::destroyed, this, [this]() {
+ QQmlComponent component(m_engine);
+ component.setData("import QtQml 2.0\nQtObject {}", QUrl("file://Stuff.qml"));
+ QVERIFY(component.isReady());
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(obj);
+ });
+ }
+};
+
+void tst_qqmlengine::createComponentOnSingletonDestruction()
+{
+ qmlRegisterSingletonType<EvilSingleton>("foo.foo", 1, 0, "Singleton",
+ [](QQmlEngine *engine, QJSEngine *) {
+ return new EvilSingleton(engine);
+ });
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("evilSingletonInstantiation.qml"));
+ QVERIFY(component.isReady());
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(obj);
+}
+
QTEST_MAIN(tst_qqmlengine)
#include "tst_qqmlengine.moc"
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST b/tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST
index 20f989fc50..92903955ac 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/BLACKLIST
@@ -1,5 +1,6 @@
[touchAndDragHandlerOnFlickable]
windows gcc
+opensuse-leap
[touchDragFlickableBehindSlider]
windows gcc
[touchDragFlickableBehindButton]