aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2017-09-12 09:55:25 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2017-09-12 09:56:04 +0200
commit29316abe1ad363179cfc2eefe31d085131d1dfd7 (patch)
tree4f1248046acb0a87de7f8762ec98de3fbc9f47f1 /src
parentbde8c3cd9583ed9f3bdfc36a8699f56db20a6928 (diff)
parent47b3b1b10246cad6709c0cd99f02208dbaf6b7c0 (diff)
Merge remote-tracking branch 'origin/5.10' into wip/new-backend
Diffstat (limited to 'src')
-rw-r--r--src/imports/shapes/qquickshapegenericrenderer.cpp34
-rw-r--r--src/imports/shapes/qquickshapegenericrenderer_p.h7
-rw-r--r--src/qml/doc/src/cppintegration/data.qdoc5
-rw-r--r--src/qml/jsruntime/qv4engine.cpp5
-rw-r--r--src/qml/qml/qqmlmetatype.cpp2
-rw-r--r--src/qmltest/quicktest.cpp68
-rw-r--r--src/quick/handlers/qquickdraghandler.cpp6
-rw-r--r--src/quick/handlers/qquickmultipointhandler.cpp10
-rw-r--r--src/quick/handlers/qquickpinchhandler.cpp2
-rw-r--r--src/quick/handlers/qquickpointerhandler.cpp4
-rw-r--r--src/quick/handlers/qquicksinglepointhandler.cpp14
-rw-r--r--src/quick/handlers/qquicktaphandler.cpp6
-rw-r--r--src/quick/items/qquickevents.cpp12
-rw-r--r--src/quick/items/qquickevents_p_p.h18
-rw-r--r--src/quick/items/qquickpathview_p_p.h1
-rw-r--r--src/quick/items/qquickwindow.cpp284
-rw-r--r--src/quick/items/qquickwindow_p.h11
17 files changed, 228 insertions, 261 deletions
diff --git a/src/imports/shapes/qquickshapegenericrenderer.cpp b/src/imports/shapes/qquickshapegenericrenderer.cpp
index 98ba89dc3d..8131f02f1a 100644
--- a/src/imports/shapes/qquickshapegenericrenderer.cpp
+++ b/src/imports/shapes/qquickshapegenericrenderer.cpp
@@ -75,38 +75,32 @@ static inline QQuickShapeGenericRenderer::Color4ub colorToColor4ub(const QColor
}
QQuickShapeGenericStrokeFillNode::QQuickShapeGenericStrokeFillNode(QQuickWindow *window)
- : m_geometry(new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), 0, 0)),
- m_window(window),
- m_material(nullptr)
+ : m_material(nullptr)
{
- setGeometry(m_geometry);
- activateMaterial(MatSolidColor);
+ setFlag(QSGNode::OwnsGeometry, true);
+ setGeometry(new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), 0, 0));
+ activateMaterial(window, MatSolidColor);
#ifdef QSG_RUNTIME_DESCRIPTION
qsgnode_set_description(this, QLatin1String("stroke-fill"));
#endif
}
-QQuickShapeGenericStrokeFillNode::~QQuickShapeGenericStrokeFillNode()
-{
- delete m_geometry;
-}
-
-void QQuickShapeGenericStrokeFillNode::activateMaterial(Material m)
+void QQuickShapeGenericStrokeFillNode::activateMaterial(QQuickWindow *window, Material m)
{
switch (m) {
case MatSolidColor:
// Use vertexcolor material. Items with different colors remain batchable
// this way, at the expense of having to provide per-vertex color values.
- m_material.reset(QQuickShapeGenericMaterialFactory::createVertexColor(m_window));
+ m_material.reset(QQuickShapeGenericMaterialFactory::createVertexColor(window));
break;
case MatLinearGradient:
- m_material.reset(QQuickShapeGenericMaterialFactory::createLinearGradient(m_window, this));
+ m_material.reset(QQuickShapeGenericMaterialFactory::createLinearGradient(window, this));
break;
case MatRadialGradient:
- m_material.reset(QQuickShapeGenericMaterialFactory::createRadialGradient(m_window, this));
+ m_material.reset(QQuickShapeGenericMaterialFactory::createRadialGradient(window, this));
break;
case MatConicalGradient:
- m_material.reset(QQuickShapeGenericMaterialFactory::createConicalGradient(m_window, this));
+ m_material.reset(QQuickShapeGenericMaterialFactory::createConicalGradient(window, this));
break;
default:
qWarning("Unknown material %d", m);
@@ -583,7 +577,7 @@ void QQuickShapeGenericRenderer::updateFillNode(ShapePathData *d, QQuickShapeGen
QQuickShapeGenericStrokeFillNode *n = node->m_fillNode;
updateShadowDataInNode(d, n);
- QSGGeometry *g = n->m_geometry;
+ QSGGeometry *g = n->geometry();
if (d->fillVertices.isEmpty()) {
if (g->vertexCount() || g->indexCount()) {
g->allocate(0, 0);
@@ -607,7 +601,7 @@ void QQuickShapeGenericRenderer::updateFillNode(ShapePathData *d, QQuickShapeGen
default:
Q_UNREACHABLE();
}
- n->activateMaterial(gradMat);
+ n->activateMaterial(m_item->window(), gradMat);
if (d->effectiveDirty & DirtyFillGradient) {
// Gradients are implemented via a texture-based material.
n->markDirty(QSGNode::DirtyMaterial);
@@ -616,7 +610,7 @@ void QQuickShapeGenericRenderer::updateFillNode(ShapePathData *d, QQuickShapeGen
return;
}
} else {
- n->activateMaterial(QQuickShapeGenericStrokeFillNode::MatSolidColor);
+ n->activateMaterial(m_item->window(), QQuickShapeGenericStrokeFillNode::MatSolidColor);
// fast path for updating only color values when no change in vertex positions
if ((d->effectiveDirty & DirtyColor) && !(d->effectiveDirty & DirtyFillGeom)) {
ColoredVertex *vdst = reinterpret_cast<ColoredVertex *>(g->vertexData());
@@ -633,8 +627,6 @@ void QQuickShapeGenericRenderer::updateFillNode(ShapePathData *d, QQuickShapeGen
g = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(),
d->fillVertices.count(), indexCount, d->indexType);
n->setGeometry(g);
- delete n->m_geometry;
- n->m_geometry = g;
} else {
g->allocate(d->fillVertices.count(), indexCount);
}
@@ -653,7 +645,7 @@ void QQuickShapeGenericRenderer::updateStrokeNode(ShapePathData *d, QQuickShapeG
return;
QQuickShapeGenericStrokeFillNode *n = node->m_strokeNode;
- QSGGeometry *g = n->m_geometry;
+ QSGGeometry *g = n->geometry();
if (d->strokeVertices.isEmpty()) {
if (g->vertexCount() || g->indexCount()) {
g->allocate(0, 0);
diff --git a/src/imports/shapes/qquickshapegenericrenderer_p.h b/src/imports/shapes/qquickshapegenericrenderer_p.h
index 32cec798ec..11070ae7dc 100644
--- a/src/imports/shapes/qquickshapegenericrenderer_p.h
+++ b/src/imports/shapes/qquickshapegenericrenderer_p.h
@@ -205,7 +205,6 @@ class QQuickShapeGenericStrokeFillNode : public QSGGeometryNode
{
public:
QQuickShapeGenericStrokeFillNode(QQuickWindow *window);
- ~QQuickShapeGenericStrokeFillNode();
enum Material {
MatSolidColor,
@@ -214,16 +213,12 @@ public:
MatConicalGradient
};
- void activateMaterial(Material m);
-
- QQuickWindow *window() const { return m_window; }
+ void activateMaterial(QQuickWindow *window, Material m);
// shadow data for custom materials
QQuickAbstractPathRenderer::GradientDesc m_fillGradient;
private:
- QSGGeometry *m_geometry;
- QQuickWindow *m_window;
QScopedPointer<QSGMaterial> m_material;
friend class QQuickShapeGenericRenderer;
diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc
index 65559f640a..c748161ee8 100644
--- a/src/qml/doc/src/cppintegration/data.qdoc
+++ b/src/qml/doc/src/cppintegration/data.qdoc
@@ -347,6 +347,11 @@ them with default constructed values, do not use the indexed delete operator
("delete sequence[i]") but instead use the \c {splice} function
("sequence.splice(startIndex, deleteCount)").
+\section2 QByteArray to JavaScript ArrayBuffer
+
+The QML engine provides automatic type conversion between QByteArray values and
+JavaScript \c ArrayBuffer objects.
+
\section2 Value Types
Some value types in Qt such as QPoint are represented in JavaScript as objects
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 531bfa3737..d10fd78973 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -930,10 +930,13 @@ void ExecutionEngine::markObjects(MarkStack *markStack)
}
classPool->markObjects(markStack);
+ markStack->drain();
for (QSet<CompiledData::CompilationUnit*>::ConstIterator it = compilationUnits.constBegin(), end = compilationUnits.constEnd();
- it != end; ++it)
+ it != end; ++it) {
(*it)->markObjects(markStack);
+ markStack->drain();
+ }
}
ReturnedValue ExecutionEngine::throwError(const Value &value)
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 3dfdbf572a..a9464c9759 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -812,10 +812,10 @@ void QQmlTypePrivate::insertEnumsFromPropertyCache(const QQmlPropertyCache *cach
const QMetaObject *cppMetaObject = cache->firstCppMetaObject();
while (cache && cache->metaObject() != cppMetaObject) {
- QStringHash<int> *scoped = new QStringHash<int>();
int count = cache->qmlEnumCount();
for (int ii = 0; ii < count; ++ii) {
+ QStringHash<int> *scoped = new QStringHash<int>();
QQmlEnumData *enumData = cache->qmlEnum(ii);
for (int jj = 0; jj < enumData->values.count(); ++jj) {
diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp
index 8cf0d2918e..993a411013 100644
--- a/src/qmltest/quicktest.cpp
+++ b/src/qmltest/quicktest.cpp
@@ -87,7 +87,7 @@ public:
static QTestRootObject *instance() {
static QPointer<QTestRootObject> object = new QTestRootObject;
if (!object) {
- qWarning("A new test root object has been created, the behavior may be compromised");
+ // QTestRootObject was deleted when previous test ended, create a new one
object = new QTestRootObject;
}
return object;
@@ -331,43 +331,45 @@ int quick_test_main(int argc, char **argv, const char *name, const char *sourceD
// Register the test object
qmlRegisterSingletonType<QTestRootObject>("Qt.test.qtestroot", 1, 0, "QTestRootObject", testRootObject);
+
// Scan through all of the "tst_*.qml" files and run each of them
- // in turn with a QQuickView.
- QQuickView *view = new QQuickView;
- view->setFlags(Qt::Window | Qt::WindowSystemMenuHint
- | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint
- | Qt::WindowCloseButtonHint);
- QEventLoop eventLoop;
- QObject::connect(view->engine(), SIGNAL(quit()),
- QTestRootObject::instance(), SLOT(quit()));
- QObject::connect(view->engine(), SIGNAL(quit()),
- &eventLoop, SLOT(quit()));
- view->rootContext()->setContextProperty
- (QLatin1String("qtest"), QTestRootObject::instance()); // Deprecated. Use QTestRootObject from Qt.test.qtestroot instead
- for (const QString &path : qAsConst(imports))
- view->engine()->addImportPath(path);
- for (const QString &path : qAsConst(pluginPaths))
- view->engine()->addPluginPath(path);
+ // in turn with a separate QQuickView (for test isolation).
for (const QString &file : qAsConst(files)) {
const QFileInfo fi(file);
if (!fi.exists())
continue;
- view->setObjectName(fi.baseName());
- view->setTitle(view->objectName());
+ QQuickView view ;
+ view.setFlags(Qt::Window | Qt::WindowSystemMenuHint
+ | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint
+ | Qt::WindowCloseButtonHint);
+ QEventLoop eventLoop;
+ QObject::connect(view.engine(), SIGNAL(quit()),
+ QTestRootObject::instance(), SLOT(quit()));
+ QObject::connect(view.engine(), SIGNAL(quit()),
+ &eventLoop, SLOT(quit()));
+ view.rootContext()->setContextProperty
+ (QLatin1String("qtest"), QTestRootObject::instance()); // Deprecated. Use QTestRootObject from Qt.test.qtestroot instead
+ for (const QString &path : qAsConst(imports))
+ view.engine()->addImportPath(path);
+ for (const QString &path : qAsConst(pluginPaths))
+ view.engine()->addPluginPath(path);
+
+ view.setObjectName(fi.baseName());
+ view.setTitle(view.objectName());
QTestRootObject::instance()->init();
QString path = fi.absoluteFilePath();
if (path.startsWith(QLatin1String(":/")))
- view->setSource(QUrl(QLatin1String("qrc:") + path.midRef(2)));
+ view.setSource(QUrl(QLatin1String("qrc:") + path.midRef(2)));
else
- view->setSource(QUrl::fromLocalFile(path));
+ view.setSource(QUrl::fromLocalFile(path));
if (QTest::printAvailableFunctions)
continue;
- while (view->status() == QQuickView::Loading)
+ while (view.status() == QQuickView::Loading)
QTest::qWait(10);
- if (view->status() == QQuickView::Error) {
- handleCompileErrors(fi, view);
+ if (view.status() == QQuickView::Error) {
+ handleCompileErrors(fi, &view);
continue;
}
if (!QTestRootObject::instance()->hasQuit) {
@@ -376,21 +378,21 @@ int quick_test_main(int argc, char **argv, const char *name, const char *sourceD
// an asynchronous test and we need to show the window
// and wait for the first frame to be rendered
// and then wait for quit indication.
- view->setFramePosition(QPoint(50, 50));
- if (view->size().isEmpty()) { // Avoid hangs with empty windows.
- view->resize(200, 200);
+ view.setFramePosition(QPoint(50, 50));
+ if (view.size().isEmpty()) { // Avoid hangs with empty windows.
+ view.resize(200, 200);
}
- view->show();
- if (!QTest::qWaitForWindowExposed(view)) {
+ view.show();
+ if (!QTest::qWaitForWindowExposed(&view)) {
qWarning().nospace()
<< "Test '" << QDir::toNativeSeparators(path) << "' window not exposed after show().";
}
- view->requestActivate();
- if (!QTest::qWaitForWindowActive(view)) {
+ view.requestActivate();
+ if (!QTest::qWaitForWindowActive(&view)) {
qWarning().nospace()
<< "Test '" << QDir::toNativeSeparators(path) << "' window not active after requestActivate().";
}
- if (view->isExposed()) {
+ if (view.isExposed()) {
QTestRootObject::instance()->setWindowShown(true);
} else {
qWarning().nospace()
@@ -399,13 +401,11 @@ int quick_test_main(int argc, char **argv, const char *name, const char *sourceD
}
if (!QTestRootObject::instance()->hasQuit && QTestRootObject::instance()->hasTestCase())
eventLoop.exec();
- // view->hide(); Causes a crash in Qt 3D due to deletion of the GL context, see QTBUG-27696
}
}
// Flush the current logging stream.
QuickTestResult::setProgramName(0);
- delete view;
delete app;
// Return the number of failures as the exit code.
diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp
index 49b391c7d5..840459ba3e 100644
--- a/src/quick/handlers/qquickdraghandler.cpp
+++ b/src/quick/handlers/qquickdraghandler.cpp
@@ -97,7 +97,7 @@ void QQuickDragHandler::handleEventPoint(QQuickEventPoint *point)
setPassiveGrab(point);
break;
case QQuickEventPoint::Updated: {
- QPointF delta = point->scenePos() - point->scenePressPos();
+ QPointF delta = point->scenePosition() - point->scenePressPosition();
if (!m_xAxis.enabled())
delta.setX(0);
if (!m_yAxis.enabled())
@@ -151,10 +151,10 @@ void QQuickDragHandler::initializeTargetStartPos(QQuickEventPoint *point)
{
if (target() && target()->parentItem() && m_targetStartPos.isNull()) { // prefer the m_targetStartPos we got when it got Pressed.
m_targetStartPos = target()->parentItem()->mapToScene(target()->position());
- if (!target()->contains(point->pos())) {
+ if (!target()->contains(point->position())) {
// If pressed outside of target item, move the target item so that the touchpoint is in its center,
// while still respecting the axis constraints.
- const QPointF center = target()->parentItem()->mapFromScene(point->scenePos());
+ const QPointF center = target()->parentItem()->mapFromScene(point->scenePosition());
const QPointF pointCenteredInItemPos = target()->parentItem()->mapToScene(center - QPointF(target()->width(), target()->height())/2);
if (m_xAxis.enabled())
m_targetStartPos.setX(pointCenteredInItemPos.x());
diff --git a/src/quick/handlers/qquickmultipointhandler.cpp b/src/quick/handlers/qquickmultipointhandler.cpp
index 66b6fdb4a6..6cc7747e3a 100644
--- a/src/quick/handlers/qquickmultipointhandler.cpp
+++ b/src/quick/handlers/qquickmultipointhandler.cpp
@@ -93,7 +93,7 @@ QVector<QQuickEventPoint *> QQuickMultiPointHandler::eligiblePoints(QQuickPointe
if (exclusiveGrabber && exclusiveGrabber != this)
continue;
}
- if (p->state() != QQuickEventPoint::Released && targetBounds.contains(p->scenePos()))
+ if (p->state() != QQuickEventPoint::Released && targetBounds.contains(p->scenePosition()))
ret << p;
}
return ret;
@@ -146,7 +146,7 @@ QPointF QQuickMultiPointHandler::touchPointCentroid()
if (Q_UNLIKELY(m_currentPoints.size() == 0))
return ret;
for (QQuickEventPoint *point : qAsConst(m_currentPoints))
- ret += point->scenePos();
+ ret += point->scenePosition();
return ret / m_currentPoints.size();
}
@@ -166,7 +166,7 @@ qreal QQuickMultiPointHandler::averageTouchPointDistance(const QPointF &ref)
if (Q_UNLIKELY(m_currentPoints.size() == 0))
return ret;
for (QQuickEventPoint *point : qAsConst(m_currentPoints))
- ret += QVector2D(point->scenePos() - ref).length();
+ ret += QVector2D(point->scenePosition() - ref).length();
return ret / m_currentPoints.size();
}
@@ -177,7 +177,7 @@ qreal QQuickMultiPointHandler::averageStartingDistance(const QPointF &ref)
if (Q_UNLIKELY(m_currentPoints.size() == 0))
return ret;
for (QQuickEventPoint *point : qAsConst(m_currentPoints))
- ret += QVector2D(point->sceneGrabPos() - ref).length();
+ ret += QVector2D(point->sceneGrabPosition() - ref).length();
return ret / m_currentPoints.size();
}
@@ -186,7 +186,7 @@ QVector<QQuickMultiPointHandler::PointData> QQuickMultiPointHandler::angles(cons
QVector<PointData> angles;
angles.reserve(m_currentPoints.count());
for (QQuickEventPoint *point : qAsConst(m_currentPoints)) {
- qreal angle = QLineF(ref, point->scenePos()).angle();
+ qreal angle = QLineF(ref, point->scenePosition()).angle();
angles.append(PointData(point->pointId(), -angle)); // convert to clockwise, to be consistent with QQuickItem::rotation
}
return angles;
diff --git a/src/quick/handlers/qquickpinchhandler.cpp b/src/quick/handlers/qquickpinchhandler.cpp
index 4dd51e744d..92bcc643f3 100644
--- a/src/quick/handlers/qquickpinchhandler.cpp
+++ b/src/quick/handlers/qquickpinchhandler.cpp
@@ -225,7 +225,7 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event)
Q_UNUSED(event)
if (Q_UNLIKELY(lcPinchHandler().isDebugEnabled())) {
for (QQuickEventPoint *point : qAsConst(m_currentPoints))
- qCDebug(lcPinchHandler) << point->state() << point->sceneGrabPos() << "->" << point->scenePos();
+ qCDebug(lcPinchHandler) << point->state() << point->sceneGrabPosition() << "->" << point->scenePosition();
}
bool containsReleasedPoints = event->isReleaseEvent();
diff --git a/src/quick/handlers/qquickpointerhandler.cpp b/src/quick/handlers/qquickpointerhandler.cpp
index bcccfac318..14ce8fea03 100644
--- a/src/quick/handlers/qquickpointerhandler.cpp
+++ b/src/quick/handlers/qquickpointerhandler.cpp
@@ -152,14 +152,14 @@ void QQuickPointerHandler::cancelAllGrabs(QQuickEventPoint *point)
QPointF QQuickPointerHandler::eventPos(const QQuickEventPoint *point) const
{
- return (target() ? target()->mapFromScene(point->scenePos()) : point->scenePos());
+ return (target() ? target()->mapFromScene(point->scenePosition()) : point->scenePosition());
}
bool QQuickPointerHandler::parentContains(const QQuickEventPoint *point) const
{
if (point) {
if (QQuickItem *par = parentItem())
- return par->contains(par->mapFromScene(point->scenePos()));
+ return par->contains(par->mapFromScene(point->scenePosition()));
}
return false;
}
diff --git a/src/quick/handlers/qquicksinglepointhandler.cpp b/src/quick/handlers/qquicksinglepointhandler.cpp
index 8747f5023d..2588c4c180 100644
--- a/src/quick/handlers/qquicksinglepointhandler.cpp
+++ b/src/quick/handlers/qquicksinglepointhandler.cpp
@@ -135,15 +135,15 @@ void QQuickSinglePointHandler::handlePointerEventImpl(QQuickPointerEvent *event)
m_pointInfo.m_pressure = event->buttons() ? 1 : 0;
m_pointInfo.m_ellipseDiameters = QSizeF();
}
- m_pointInfo.m_position = currentPoint->pos();
- m_pointInfo.m_scenePosition = currentPoint->scenePos();
+ m_pointInfo.m_position = currentPoint->position();
+ m_pointInfo.m_scenePosition = currentPoint->scenePosition();
if (currentPoint->state() == QQuickEventPoint::Updated)
m_pointInfo.m_velocity = currentPoint->velocity();
handleEventPoint(currentPoint);
switch (currentPoint->state()) {
case QQuickEventPoint::Pressed:
- m_pointInfo.m_pressPosition = currentPoint->pos();
- m_pointInfo.m_scenePressPosition = currentPoint->scenePos();
+ m_pointInfo.m_pressPosition = currentPoint->position();
+ m_pointInfo.m_scenePressPosition = currentPoint->scenePosition();
m_pointInfo.m_pressedButtons = event->buttons();
break;
case QQuickEventPoint::Released:
@@ -169,12 +169,12 @@ void QQuickSinglePointHandler::onGrabChanged(QQuickPointerHandler *grabber, QQui
return;
switch (stateChange) {
case QQuickEventPoint::GrabExclusive:
- m_pointInfo.m_sceneGrabPosition = point->sceneGrabPos();
+ m_pointInfo.m_sceneGrabPosition = point->sceneGrabPosition();
setActive(true);
QQuickPointerHandler::onGrabChanged(grabber, stateChange, point);
break;
case QQuickEventPoint::GrabPassive:
- m_pointInfo.m_sceneGrabPosition = point->sceneGrabPos();
+ m_pointInfo.m_sceneGrabPosition = point->sceneGrabPosition();
QQuickPointerHandler::onGrabChanged(grabber, stateChange, point);
break;
case QQuickEventPoint::OverrideGrabPassive:
@@ -199,7 +199,7 @@ void QQuickSinglePointHandler::setIgnoreAdditionalPoints(bool v)
void QQuickSinglePointHandler::moveTarget(QPointF pos, QQuickEventPoint *point)
{
target()->setPosition(pos);
- m_pointInfo.m_scenePosition = point->scenePos();
+ m_pointInfo.m_scenePosition = point->scenePosition();
m_pointInfo.m_position = target()->mapFromScene(m_pointInfo.m_scenePosition);
}
diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp
index b8d9754cde..f99f84bdb0 100644
--- a/src/quick/handlers/qquicktaphandler.cpp
+++ b/src/quick/handlers/qquicktaphandler.cpp
@@ -102,7 +102,7 @@ QQuickTapHandler::~QQuickTapHandler()
static bool dragOverThreshold(QQuickEventPoint *point)
{
- QPointF delta = point->scenePos() - point->scenePressPos();
+ QPointF delta = point->scenePosition() - point->scenePressPosition();
return (QQuickWindowPrivate::dragOverThreshold(delta.x(), Qt::XAxis, point) ||
QQuickWindowPrivate::dragOverThreshold(delta.y(), Qt::YAxis, point));
}
@@ -280,7 +280,7 @@ void QQuickTapHandler::setPressed(bool press, bool cancel, QQuickEventPoint *poi
// Assuming here that pointerEvent()->timestamp() is in ms.
qreal ts = point->pointerEvent()->timestamp() / 1000.0;
if (ts - m_lastTapTimestamp < m_multiTapInterval &&
- QVector2D(point->scenePos() - m_lastTapPos).lengthSquared() <
+ QVector2D(point->scenePosition() - m_lastTapPos).lengthSquared() <
(point->pointerEvent()->device()->type() == QQuickPointerDevice::Mouse ?
m_mouseMultiClickDistanceSquared : m_touchMultiTapDistanceSquared))
++m_tapCount;
@@ -290,7 +290,7 @@ void QQuickTapHandler::setPressed(bool press, bool cancel, QQuickEventPoint *poi
emit tapped();
emit tapCountChanged();
m_lastTapTimestamp = ts;
- m_lastTapPos = point->scenePos();
+ m_lastTapPos = point->scenePosition();
} else {
qCDebug(lcTapHandler) << objectName() << "tap threshold" << longPressThreshold() << "exceeded:" << point->timeHeld();
}
diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp
index d133729625..90e72ebde6 100644
--- a/src/quick/items/qquickevents.cpp
+++ b/src/quick/items/qquickevents.cpp
@@ -548,7 +548,7 @@ void QQuickEventPoint::reset(Qt::TouchPointState state, const QPointF &scenePos,
void QQuickEventPoint::localizePosition(QQuickItem *target)
{
if (target)
- m_pos = target->mapFromScene(scenePos());
+ m_pos = target->mapFromScene(scenePosition());
else
m_pos = QPointF();
}
@@ -938,8 +938,8 @@ QQuickPointerEvent *QQuickPointerTouchEvent::reset(QEvent *event)
if (auto point = pointById(pid)) {
preserves[i].pointId = pid;
preserves[i].pressTimestamp = point->m_pressTimestamp;
- preserves[i].scenePressPos = point->scenePressPos();
- preserves[i].sceneGrabPos = point->sceneGrabPos();
+ preserves[i].scenePressPos = point->scenePressPosition();
+ preserves[i].sceneGrabPos = point->sceneGrabPosition();
preserves[i].grabber = point->exclusiveGrabber();
preserves[i].passiveGrabbers = point->passiveGrabbers();
}
@@ -1155,7 +1155,7 @@ QVector<QPointF> QQuickPointerEvent::unacceptedPressedPointScenePositions() cons
QVector<QPointF> points;
for (int i = 0; i < pointCount(); ++i) {
if (!point(i)->isAccepted() && point(i)->state() == QQuickEventPoint::Pressed)
- points << point(i)->scenePos();
+ points << point(i)->scenePosition();
}
return points;
}
@@ -1277,7 +1277,7 @@ QTouchEvent *QQuickPointerTouchEvent::touchEventForItem(QQuickItem *item, bool i
if (isGrabber)
anyGrabber = true;
// include points inside the bounds if no other item is the grabber or if the item is filtering
- bool isInside = item->contains(item->mapFromScene(p->scenePos()));
+ bool isInside = item->contains(item->mapFromScene(p->scenePosition()));
bool hasAnotherGrabber = p->exclusiveGrabber() && p->exclusiveGrabber() != item;
// filtering: (childMouseEventFilter) include points that are grabbed by children of the target item
@@ -1395,7 +1395,7 @@ Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickEventPoint *eve
dbg << "QQuickEventPoint(accepted:" << event->isAccepted()
<< " state:";
QtDebugUtils::formatQEnum(dbg, event->state());
- dbg << " scenePos:" << event->scenePos() << " id:" << hex << event->pointId() << dec
+ dbg << " scenePos:" << event->scenePosition() << " id:" << hex << event->pointId() << dec
<< " timeHeld:" << event->timeHeld() << ')';
return dbg;
}
diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h
index 48c29f00de..2954695b1b 100644
--- a/src/quick/items/qquickevents_p_p.h
+++ b/src/quick/items/qquickevents_p_p.h
@@ -253,10 +253,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickEventPoint : public QObject
{
Q_OBJECT
Q_PROPERTY(QQuickPointerEvent *event READ pointerEvent)
- Q_PROPERTY(QPointF pos READ pos)
- Q_PROPERTY(QPointF scenePos READ scenePos)
- Q_PROPERTY(QPointF scenePressPos READ scenePressPos)
- Q_PROPERTY(QPointF sceneGrabPos READ sceneGrabPos)
+ Q_PROPERTY(QPointF position READ position)
+ Q_PROPERTY(QPointF scenePosition READ scenePosition)
+ Q_PROPERTY(QPointF scenePressPosition READ scenePressPosition)
+ Q_PROPERTY(QPointF sceneGrabPosition READ sceneGrabPosition)
Q_PROPERTY(State state READ state)
Q_PROPERTY(int pointId READ pointId)
Q_PROPERTY(qreal timeHeld READ timeHeld)
@@ -288,14 +288,14 @@ public:
QQuickEventPoint(QQuickPointerEvent *parent);
- void reset(Qt::TouchPointState state, const QPointF &scenePos, int pointId, ulong timestamp, const QVector2D &velocity = QVector2D());
+ void reset(Qt::TouchPointState state, const QPointF &scenePosition, int pointId, ulong timestamp, const QVector2D &velocity = QVector2D());
void localizePosition(QQuickItem *target);
QQuickPointerEvent *pointerEvent() const;
- QPointF pos() const { return m_pos; }
- QPointF scenePos() const { return m_scenePos; }
- QPointF scenePressPos() const { return m_scenePressPos; }
- QPointF sceneGrabPos() const { return m_sceneGrabPos; }
+ QPointF position() const { return m_pos; }
+ QPointF scenePosition() const { return m_scenePos; }
+ QPointF scenePressPosition() const { return m_scenePressPos; }
+ QPointF sceneGrabPosition() const { return m_sceneGrabPos; }
QVector2D velocity() const { return m_velocity; }
State state() const { return m_state; }
int pointId() const { return m_pointId; }
diff --git a/src/quick/items/qquickpathview_p_p.h b/src/quick/items/qquickpathview_p_p.h
index d58c986d1a..274086ea7c 100644
--- a/src/quick/items/qquickpathview_p_p.h
+++ b/src/quick/items/qquickpathview_p_p.h
@@ -153,7 +153,6 @@ public:
bool moving : 1;
bool flicking : 1;
bool dragging : 1;
- bool requestedOnPath : 1;
bool inRequest : 1;
bool delegateValidated : 1;
bool inRefill : 1;
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 2d129f0823..bd1a5076fd 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -780,8 +780,8 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber)
if (oldGrabber) {
QEvent e(QEvent::UngrabMouse);
- QSet<QQuickItem *> hasFiltered;
- if (!sendFilteredMouseEvent(oldGrabber->parentItem(), oldGrabber, &e, &hasFiltered))
+ hasFiltered.clear();
+ if (!sendFilteredMouseEvent(&e, oldGrabber, oldGrabber->parentItem()))
oldGrabber->mouseUngrabEvent();
}
}
@@ -1667,7 +1667,7 @@ QMouseEvent *QQuickWindowPrivate::cloneMouseEvent(QMouseEvent *event, QPointF *t
void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEvent)
{
auto point = pointerEvent->point(0);
- lastMousePosition = point->scenePos();
+ lastMousePosition = point->scenePosition();
const bool mouseIsReleased = (point->state() == QQuickEventPoint::Released && pointerEvent->buttons() == Qt::NoButton);
if (point->exclusiveGrabber()) {
@@ -1722,7 +1722,7 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven
}
// If some points weren't grabbed, deliver to non-grabber PointerHandlers in reverse paint order
if (!pointerEvent->allPointsGrabbed() && pointerEvent->buttons()) {
- QVector<QQuickItem *> targetItems = pointerTargets(contentItem, point->scenePos(), false, false);
+ QVector<QQuickItem *> targetItems = pointerTargets(contentItem, point->scenePosition(), false, false);
for (QQuickItem *item : targetItems) {
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
pointerEvent->localize(item);
@@ -1757,10 +1757,9 @@ bool QQuickWindowPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item,
hoverEvent.setTimestamp(timestamp);
hoverEvent.setAccepted(accepted);
- QSet<QQuickItem *> hasFiltered;
- if (sendFilteredMouseEvent(item->parentItem(), item, &hoverEvent, &hasFiltered)) {
+ hasFiltered.clear();
+ if (sendFilteredMouseEvent(&hoverEvent, item, item->parentItem()))
return true;
- }
QCoreApplication::sendEvent(item, &hoverEvent);
@@ -2233,6 +2232,7 @@ void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event)
// the usecase a bit evil, but we at least don't want to lose events.
++pointerEventRecursionGuard;
+ skipDelivery.clear();
if (event->asPointerMouseEvent()) {
deliverMouseEvent(event->asPointerMouseEvent());
} else if (event->asPointerTouchEvent()) {
@@ -2387,7 +2387,7 @@ void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *eve
QQuickEventPoint *point = event->point(i);
if (point->state() == QQuickEventPoint::Pressed)
continue; // presses were delivered earlier; not the responsibility of deliverUpdatedTouchPoints
- QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point->scenePos(), false, false);
+ QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point->scenePosition(), false, false);
if (targetItems.count()) {
targetItems = mergePointerTargets(targetItems, targetItemsForPoint);
} else {
@@ -2419,7 +2419,7 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event,
point->setAccepted(false); // because otherwise touchEventForItem will ignore it
if (point->grabberPointerHandler() && point->state() == QQuickEventPoint::Released)
point->setGrabberPointerHandler(nullptr, true);
- QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point->scenePos(), !isTouchEvent, isTouchEvent);
+ QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point->scenePosition(), !isTouchEvent, isTouchEvent);
if (targetItems.count()) {
targetItems = mergePointerTargets(targetItems, targetItemsForPoint);
} else {
@@ -2427,24 +2427,19 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event,
}
}
- if (allowChildEventFiltering && !handlersOnly)
- updateFilteringParentItems(targetItems);
-
- QVarLengthArray<QQuickItem *> filteredItems;
for (QQuickItem *item : targetItems) {
- if (sendFilteredPointerEvent(event, item)) {
+ if (!handlersOnly && sendFilteredPointerEvent(event, item)) {
if (event->isAccepted()) {
for (int i = 0; i < event->pointCount(); ++i)
event->point(i)->setAccepted();
return true;
}
- while (!filteringParentItems.isEmpty() && filteringParentItems.first().first == item)
- filteringParentItems.removeFirst();
- filteredItems << item;
+ skipDelivery.append(item);
}
- // Do not deliverMatchingPointsTo any item for which the parent-filter already intercepted the event
- if (filteredItems.contains(item))
+ // Do not deliverMatchingPointsTo any item for which the filtering parent already intercepted the event,
+ // nor to any item which already had a chance to filter.
+ if (skipDelivery.contains(item))
continue;
deliverMatchingPointsToItem(item, event, handlersOnly);
if (event->allPointsAccepted())
@@ -2486,7 +2481,7 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo
// The only reason to already have a mouse grabber here is
// synthetic events - flickable sends one when setPressDelay is used.
auto oldMouseGrabber = q->mouseGrabberItem();
- QPointF localPos = item->mapFromScene(point->scenePos());
+ QPointF localPos = item->mapFromScene(point->scenePosition());
Q_ASSERT(item->contains(localPos)); // transform is checked already
QMouseEvent *me = event->asMouseEvent(localPos);
me->accept();
@@ -2515,8 +2510,6 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo
bool eventAccepted = false;
// If any parent filters the event, we're done.
- // updateFilteringParentItems was called when the press occurred,
- // and we assume that the filtering relationships don't change between press and release.
if (sendFilteredPointerEvent(pointerEvent, item))
return;
@@ -2728,167 +2721,146 @@ QQuickItem *QQuickWindowPrivate::findCursorItem(QQuickItem *item, const QPointF
}
#endif
-void QQuickWindowPrivate::updateFilteringParentItems(const QVector<QQuickItem *> &targetItems)
+bool QQuickWindowPrivate::sendFilteredPointerEvent(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent)
{
- filteringParentItems.clear();
- for (QQuickItem *item : targetItems) {
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
- bool acceptsTouchEvents = item->acceptTouchEvents();
-#else
- // In versions prior to Qt 6, we can't trust item->acceptTouchEvents() here, because it defaults to true.
- bool acceptsTouchEvents = false;
-#endif
- QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
- // If the item neither handles events nor has handlers which do, then it will never be a receiver, so filtering is irrelevant.
- if (!item->acceptedMouseButtons() && !acceptsTouchEvents &&
- !(itemPriv->extra.isAllocated() && !itemPriv->extra->pointerHandlers.isEmpty()))
- continue;
- QQuickItem *parent = item->parentItem();
- while (parent) {
- if (parent->filtersChildMouseEvents()) {
- bool foundParent = false;
- for (const QPair<QQuickItem*,QQuickItem*> existingItemAndParent : filteringParentItems)
- if (existingItemAndParent.second == parent)
- foundParent = true;
- if (!foundParent)
- filteringParentItems.append(QPair<QQuickItem*,QQuickItem*>(item, parent));
- }
- parent = parent->parentItem();
- }
- }
- if (Q_UNLIKELY(DBG_MOUSE_TARGET().isDebugEnabled())) {
- QStringList l;
- for (QPair<QQuickItem *,QQuickItem *> pair : filteringParentItems)
- l << (QLatin1String(pair.first->metaObject()->className()) + QLatin1Char(' ') + pair.first->objectName() +
- QLatin1String(" <- ") + pair.second->metaObject()->className()) + QLatin1Char(' ') + pair.second->objectName();
- qCDebug(DBG_MOUSE_TARGET) << "potential filtering parents:" << l;
- }
+ hasFiltered.clear();
+ return sendFilteredPointerEventImpl(event, receiver, filteringParent ? filteringParent : receiver->parentItem());
}
-bool QQuickWindowPrivate::sendFilteredPointerEvent(QQuickPointerEvent *event, QQuickItem *receiver)
+bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent)
{
if (!allowChildEventFiltering)
return false;
- bool ret = false;
- QVarLengthArray<QQuickItem *> filteringParentsToSkip;
- if (QQuickPointerMouseEvent *pme = event->asPointerMouseEvent()) {
- for (QPair<QQuickItem *,QQuickItem *> itemAndParent : filteringParentItems) {
- QQuickItem *item = receiver ? receiver : itemAndParent.first;
- QQuickItem *filteringParent = itemAndParent.second;
- if (item == filteringParent)
- continue; // a filtering item never needs to filter for itself
- if (filteringParentsToSkip.contains(filteringParent))
- continue;
- QPointF localPos = item->mapFromScene(pme->point(0)->scenePos());
- QMouseEvent *me = pme->asMouseEvent(localPos);
- if (filteringParent->childMouseEventFilter(item, me))
- ret = true;
- filteringParentsToSkip.append(filteringParent);
- }
- } else if (QQuickPointerTouchEvent *pte = event->asPointerTouchEvent()) {
- QVarLengthArray<QPair<QQuickPointerHandler *, QQuickEventPoint *>, 32> passiveGrabsToCancel;
- for (QPair<QQuickItem *,QQuickItem *> itemAndParent : filteringParentItems) {
- QQuickItem *item = receiver ? receiver : itemAndParent.first;
- if (item != itemAndParent.first)
- continue;
- if (!item->acceptTouchEvents() && !item->acceptedMouseButtons())
- continue; // if this item won't accept, parents don't need to filter the touch for it
- QQuickItem *filteringParent = itemAndParent.second;
- if (item == filteringParent)
- continue; // a filtering item never needs to filter for itself
- // get a touch event customized for delivery to filteringParent
- QScopedPointer<QTouchEvent> filteringParentTouchEvent(pte->touchEventForItem(filteringParent, true));
- if (!filteringParentTouchEvent)
- continue; // all points are stationary, or no touchpoints inside that parent
- if (filteringParent->childMouseEventFilter(item, filteringParentTouchEvent.data())) {
- qCDebug(DBG_TOUCH) << "touch event intercepted by childMouseEventFilter of " << filteringParent;
- for (auto point: qAsConst(filteringParentTouchEvent->touchPoints()))
- event->pointById(point.id())->setAccepted();
- ret = true;
- break;
- }
- // filteringParent didn't filter the touch event. Give it a chance to filter a synthetic mouse event.
- for (int i = 0; i < filteringParentTouchEvent->touchPoints().size(); ++i) {
- const QTouchEvent::TouchPoint &tp = filteringParentTouchEvent->touchPoints().at(i);
-
- QEvent::Type t;
- switch (tp.state()) {
- case Qt::TouchPointPressed:
- t = QEvent::MouseButtonPress;
- break;
- case Qt::TouchPointReleased:
- t = QEvent::MouseButtonRelease;
- break;
- case Qt::TouchPointStationary:
- continue;
- default:
- t = QEvent::MouseMove;
- break;
+ if (!filteringParent)
+ return false;
+ bool filtered = false;
+ if (filteringParent->filtersChildMouseEvents() && !hasFiltered.contains(filteringParent)) {
+ hasFiltered.append(filteringParent);
+ if (QQuickPointerMouseEvent *pme = event->asPointerMouseEvent()) {
+ if (receiver->acceptedMouseButtons()) {
+ QPointF localPos = receiver->mapFromScene(pme->point(0)->scenePosition());
+ QMouseEvent *me = pme->asMouseEvent(localPos);
+ if (filteringParent->childMouseEventFilter(receiver, me)) {
+ qCDebug(DBG_MOUSE) << "mouse event intercepted by childMouseEventFilter of " << filteringParent;
+ skipDelivery.append(filteringParent);
+ filtered = true;
}
-
- bool touchMouseUnset = (touchMouseId == -1);
- // Only deliver mouse event if it is the touchMouseId or it could become the touchMouseId
- if (touchMouseUnset || touchMouseId == tp.id()) {
- // convert filteringParentTouchEvent (which is already transformed wrt local position, velocity, etc.)
- // into a synthetic mouse event, and let childMouseEventFilter() have another chance with that
- QScopedPointer<QMouseEvent> mouseEvent(touchToMouseEvent(t, tp, filteringParentTouchEvent.data(), item, false));
- // If a filtering item calls QQuickWindow::mouseGrabberItem(), it should
- // report the touchpoint's grabber. Whenever we send a synthetic mouse event,
- // touchMouseId and touchMouseDevice must be set, even if it's only temporarily and isn't grabbed.
- touchMouseId = tp.id();
- touchMouseDevice = event->device();
- if (filteringParent->childMouseEventFilter(item, mouseEvent.data())) {
- qCDebug(DBG_TOUCH) << "touch event intercepted as synth mouse event by childMouseEventFilter of " << filteringParent;
- if (t != QEvent::MouseButtonRelease) {
- qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << hex << tp.id() << "->" << filteringParent;
- pointerEventInstance(touchMouseDevice)->pointById(tp.id())->setGrabberItem(filteringParent);
- touchMouseUnset = false; // We want to leave touchMouseId and touchMouseDevice set
- filteringParent->grabMouse();
- auto pointerEventPoint = pte->pointById(tp.id());
+ }
+ } else if (QQuickPointerTouchEvent *pte = event->asPointerTouchEvent()) {
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ bool acceptsTouchEvents = receiver->acceptTouchEvents();
+#else
+ // In versions prior to Qt 6, we can't trust item->acceptTouchEvents() here, because it defaults to true.
+ bool acceptsTouchEvents = false;
+#endif
+ if (acceptsTouchEvents || receiver->acceptedMouseButtons()) {
+ // get a touch event customized for delivery to filteringParent
+ QScopedPointer<QTouchEvent> filteringParentTouchEvent(pte->touchEventForItem(filteringParent, true));
+ if (filteringParentTouchEvent) {
+ QVarLengthArray<QPair<QQuickPointerHandler *, QQuickEventPoint *>, 32> passiveGrabsToCancel;
+ if (filteringParent->childMouseEventFilter(receiver, filteringParentTouchEvent.data())) {
+ qCDebug(DBG_TOUCH) << "touch event intercepted by childMouseEventFilter of " << filteringParent;
+ skipDelivery.append(filteringParent);
+ filteringParent->grabMouse();
+ for (auto point: qAsConst(filteringParentTouchEvent->touchPoints())) {
+ auto pointerEventPoint = pte->pointById(point.id());
for (auto handler : pointerEventPoint->passiveGrabbers()) {
QPair<QQuickPointerHandler *, QQuickEventPoint *> grab(handler, pointerEventPoint);
if (!passiveGrabsToCancel.contains(grab))
passiveGrabsToCancel.append(grab);
}
+ event->pointById(point.id())->setAccepted();
+ }
+ return true;
+ } else {
+ // filteringParent didn't filter the touch event. Give it a chance to filter a synthetic mouse event.
+ for (int i = 0; i < filteringParentTouchEvent->touchPoints().size(); ++i) {
+ const QTouchEvent::TouchPoint &tp = filteringParentTouchEvent->touchPoints().at(i);
+
+ QEvent::Type t;
+ switch (tp.state()) {
+ case Qt::TouchPointPressed:
+ t = QEvent::MouseButtonPress;
+ break;
+ case Qt::TouchPointReleased:
+ t = QEvent::MouseButtonRelease;
+ break;
+ case Qt::TouchPointStationary:
+ continue;
+ default:
+ t = QEvent::MouseMove;
+ break;
+ }
+
+ bool touchMouseUnset = (touchMouseId == -1);
+ // Only deliver mouse event if it is the touchMouseId or it could become the touchMouseId
+ if (touchMouseUnset || touchMouseId == tp.id()) {
+ // convert filteringParentTouchEvent (which is already transformed wrt local position, velocity, etc.)
+ // into a synthetic mouse event, and let childMouseEventFilter() have another chance with that
+ QScopedPointer<QMouseEvent> mouseEvent(touchToMouseEvent(t, tp, filteringParentTouchEvent.data(), receiver, false));
+ // If a filtering item calls QQuickWindow::mouseGrabberItem(), it should
+ // report the touchpoint's grabber. Whenever we send a synthetic mouse event,
+ // touchMouseId and touchMouseDevice must be set, even if it's only temporarily and isn't grabbed.
+ touchMouseId = tp.id();
+ touchMouseDevice = event->device();
+ if (filteringParent->childMouseEventFilter(receiver, mouseEvent.data())) {
+ qCDebug(DBG_TOUCH) << "touch event intercepted as synth mouse event by childMouseEventFilter of " << filteringParent;
+ skipDelivery.append(filteringParent);
+ if (t != QEvent::MouseButtonRelease) {
+ qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << hex << tp.id() << "->" << filteringParent;
+ pointerEventInstance(touchMouseDevice)->pointById(tp.id())->setGrabberItem(filteringParent);
+ touchMouseUnset = false; // We want to leave touchMouseId and touchMouseDevice set
+ filteringParent->grabMouse();
+ auto pointerEventPoint = pte->pointById(tp.id());
+ for (auto handler : pointerEventPoint->passiveGrabbers()) {
+ QPair<QQuickPointerHandler *, QQuickEventPoint *> grab(handler, pointerEventPoint);
+ if (!passiveGrabsToCancel.contains(grab))
+ passiveGrabsToCancel.append(grab);
+ }
+ }
+ filtered = true;
+ }
+ if (touchMouseUnset) {
+ // Now that we're done sending a synth mouse event, and it wasn't grabbed,
+ // the touchpoint is no longer acting as a synthetic mouse. Restore previous state.
+ touchMouseId = -1;
+ touchMouseDevice = nullptr;
+ }
+ // Only one touchpoint can be treated as a synthetic mouse, so after childMouseEventFilter
+ // has been called once, we're done with this loop over the touchpoints.
+ break;
+ }
}
- ret = true;
- }
- if (touchMouseUnset) {
- // Now that we're done sending a synth mouse event, and it wasn't grabbed,
- // the touchpoint is no longer acting as a synthetic mouse. Restore previous state.
- touchMouseId = -1;
- touchMouseDevice = nullptr;
}
- // Only one touchpoint can be treated as a synthetic mouse, so after childMouseEventFilter
- // has been called once, we're done with this loop over the touchpoints.
- break;
+ for (auto grab : passiveGrabsToCancel)
+ grab.second->cancelPassiveGrab(grab.first);
}
}
}
- for (auto grab : passiveGrabsToCancel)
- grab.second->cancelPassiveGrab(grab.first);
}
- return ret;
+ return sendFilteredPointerEventImpl(event, receiver, filteringParent->parentItem()) || filtered;
}
-bool QQuickWindowPrivate::sendFilteredMouseEvent(QQuickItem *target, QQuickItem *item, QEvent *event, QSet<QQuickItem *> *hasFiltered)
+bool QQuickWindowPrivate::sendFilteredMouseEvent(QEvent *event, QQuickItem *receiver, QQuickItem *filteringParent)
{
- if (!target)
+ if (!filteringParent)
return false;
- QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(target);
- if (targetPrivate->replayingPressEvent)
+ QQuickItemPrivate *filteringParentPrivate = QQuickItemPrivate::get(filteringParent);
+ if (filteringParentPrivate->replayingPressEvent)
return false;
bool filtered = false;
- if (targetPrivate->filtersChildMouseEvents && !hasFiltered->contains(target)) {
- hasFiltered->insert(target);
- if (target->childMouseEventFilter(item, event))
+ if (filteringParentPrivate->filtersChildMouseEvents && !hasFiltered.contains(filteringParent)) {
+ hasFiltered.append(filteringParent);
+ if (filteringParent->childMouseEventFilter(receiver, event)) {
filtered = true;
- qCDebug(DBG_MOUSE_TARGET) << "for" << item << target << "childMouseEventFilter ->" << filtered;
+ skipDelivery.append(filteringParent);
+ }
+ qCDebug(DBG_MOUSE_TARGET) << "for" << receiver << filteringParent << "childMouseEventFilter ->" << filtered;
}
- return sendFilteredMouseEvent(target->parentItem(), item, event, hasFiltered) || filtered;
+ return sendFilteredMouseEvent(event, receiver, filteringParent->parentItem()) || filtered;
}
bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent *event, int startDragThreshold)
@@ -3038,8 +3010,8 @@ bool QQuickWindow::sendEvent(QQuickItem *item, QEvent *e)
case QEvent::MouseButtonDblClick:
case QEvent::MouseMove: {
// XXX todo - should sendEvent be doing this? how does it relate to forwarded events?
- QSet<QQuickItem *> hasFiltered;
- if (!d->sendFilteredMouseEvent(item->parentItem(), item, e, &hasFiltered)) {
+ d->hasFiltered.clear();
+ if (!d->sendFilteredMouseEvent(e, item, item->parentItem())) {
// accept because qml items by default accept and have to explicitly opt out of accepting
e->accept();
QCoreApplication::sendEvent(item, e);
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 36b2c57e5c..0399b26f62 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -147,8 +147,9 @@ public:
void removeGrabber(QQuickItem *grabber, bool mouse = true, bool touch = true);
static QMouseEvent *cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos = 0);
void deliverMouseEvent(QQuickPointerMouseEvent *pointerEvent);
- bool sendFilteredMouseEvent(QQuickItem *, QQuickItem *, QEvent *, QSet<QQuickItem *> *);
- bool sendFilteredPointerEvent(QQuickPointerEvent *event, QQuickItem *receiver);
+ bool sendFilteredMouseEvent(QEvent *event, QQuickItem *receiver, QQuickItem *filteringParent);
+ bool sendFilteredPointerEvent(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent = nullptr);
+ bool sendFilteredPointerEventImpl(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent);
#if QT_CONFIG(wheelevent)
bool deliverWheelEvent(QQuickItem *, QWheelEvent *);
#endif
@@ -178,7 +179,6 @@ public:
QVector<QQuickItem *> pointerTargets(QQuickItem *, const QPointF &, bool checkMouseButtons, bool checkAcceptsTouch) const;
QVector<QQuickItem *> mergePointerTargets(const QVector<QQuickItem *> &list1, const QVector<QQuickItem *> &list2) const;
- void updateFilteringParentItems(const QVector<QQuickItem *> &targetItems);
// hover delivery
bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, ulong timestamp, bool &accepted);
@@ -227,7 +227,8 @@ public:
QList<QSGNode *> cleanupNodeList;
QVector<QQuickItem *> itemsToPolish;
- QVector<QPair<QQuickItem *,QQuickItem *> > filteringParentItems; // item:parent pairs
+ QVector<QQuickItem *> hasFiltered; // during event delivery to a single receiver, the filtering parents for which childMouseEventFilter was already called
+ QVector<QQuickItem *> skipDelivery; // during delivery of one event to all receivers, Items to which we know delivery is no longer necessary
qreal devicePixelRatio;
QMetaObject::Connection physicalDpiChangedConnection;
@@ -298,7 +299,7 @@ public:
static bool dragOverThreshold(const QQuickEventPoint *point)
{
- QPointF delta = point->scenePos() - point->scenePressPos();
+ QPointF delta = point->scenePosition() - point->scenePressPosition();
return (QQuickWindowPrivate::dragOverThreshold(delta.x(), Qt::XAxis, point) ||
QQuickWindowPrivate::dragOverThreshold(delta.y(), Qt::YAxis, point));
}