Stop copying mouse events when delivering them

Reduce allocations of events, just refill the local pos.

Change-Id: I2948faf0e302bff315e482f2c1432fe0def19bc5
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
Frederik Gladhorn 2016-07-29 14:09:00 +02:00 committed by Shawn Rutledge
parent 388b2c5b46
commit e611c00d8c
5 changed files with 34 additions and 23 deletions

View File

@ -619,9 +619,11 @@ bool QQuickPointerMouseEvent::allPointsAccepted() const {
return m_mousePoint->isAccepted();
}
QMouseEvent *QQuickPointerMouseEvent::asMouseEvent() const
QMouseEvent *QQuickPointerMouseEvent::asMouseEvent(const QPointF &localPos) const
{
return static_cast<QMouseEvent *>(m_event);
auto event = static_cast<QMouseEvent *>(m_event);
event->setLocalPos(localPos);
return event;
}
QVector<QQuickItem *> QQuickPointerMouseEvent::grabbers() const

View File

@ -401,7 +401,7 @@ public:
QVector<QQuickItem *> grabbers() const override;
void clearGrabbers() const override;
QMouseEvent *asMouseEvent() const;
QMouseEvent *asMouseEvent(const QPointF& localPos) const;
private:
QQuickEventPoint *m_mousePoint;

View File

@ -1622,56 +1622,57 @@ QMouseEvent *QQuickWindowPrivate::cloneMouseEvent(QMouseEvent *event, QPointF *t
return me;
}
bool QQuickWindowPrivate::deliverInitialMousePressEvent(QMouseEvent *event)
void QQuickWindowPrivate::deliverInitialMousePressEvent(QQuickPointerMouseEvent *event)
{
Q_Q(QQuickWindow);
QPointF scenePos = event->point(0)->scenePos();
QVector<QQuickItem *> targets = pointerTargets(contentItem, event->windowPos(), true);
QVector<QQuickItem *> targets = pointerTargets(contentItem, scenePos, true);
for (QQuickItem *item: qAsConst(targets)) {
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
if (itemPrivate->acceptedMouseButtons() & event->button()) {
QPointF localPos = item->mapFromScene(event->windowPos());
QPointF localPos = item->mapFromScene(scenePos);
if (item->contains(localPos)) {
QScopedPointer<QMouseEvent> me(cloneMouseEvent(event, &localPos));
QMouseEvent *me = event->asMouseEvent(localPos);
me->accept();
q->sendEvent(item, me.data());
event->setAccepted(me->isAccepted());
q->sendEvent(item, me);
if (me->isAccepted()) {
if (!q->mouseGrabberItem())
item->grabMouse();
return true;
return;
}
}
}
}
return false;
// no item accepted the event, make sure we don't accept the original mouse event
event->asMouseEvent(QPointF())->setAccepted(false);
}
void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEvent)
{
Q_Q(QQuickWindow);
auto event = pointerEvent->asMouseEvent();
lastMousePosition = pointerEvent->point(0)->scenePos();
QQuickItem *mouseGrabberItem = q->mouseGrabberItem();
if (mouseGrabberItem) {
// send update
QPointF localPos = mouseGrabberItem->mapFromScene(event->windowPos());
QScopedPointer<QMouseEvent> me(cloneMouseEvent(event, &localPos));
QPointF localPos = mouseGrabberItem->mapFromScene(lastMousePosition);
auto me = pointerEvent->asMouseEvent(localPos);
me->accept();
q->sendEvent(mouseGrabberItem, me.data());
event->setAccepted(me->isAccepted());
q->sendEvent(mouseGrabberItem, me);
pointerEvent->point(0)->setAccepted(me->isAccepted());
// release event, make sure to ungrab if there still is a grabber
if (event->type() == QEvent::MouseButtonRelease && !event->buttons() && q->mouseGrabberItem())
if (me->type() == QEvent::MouseButtonRelease && !me->buttons() && q->mouseGrabberItem())
q->mouseGrabberItem()->ungrabMouse();
} else {
// send initial press
event->setAccepted(false);
if (pointerEvent->isPressEvent()) {
bool delivered = deliverInitialMousePressEvent(event);
event->setAccepted(delivered);
deliverInitialMousePressEvent(pointerEvent);
} else {
// make sure not to accept unhandled events
pointerEvent->asMouseEvent(QPointF())->setAccepted(false);
}
}
}

View File

@ -145,7 +145,7 @@ public:
void removeGrabber(QQuickItem *grabber, bool mouse = true, bool touch = true);
static void transformTouchPoints(QList<QTouchEvent::TouchPoint> &touchPoints, const QTransform &transform);
static QMouseEvent *cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos = 0);
bool deliverInitialMousePressEvent(QMouseEvent *);
void deliverInitialMousePressEvent(QQuickPointerMouseEvent *);
void deliverMouseEvent(QQuickPointerMouseEvent *pointerEvent);
bool sendFilteredMouseEvent(QQuickItem *, QQuickItem *, QEvent *, QSet<QQuickItem *> *);
#ifndef QT_NO_WHEELEVENT

View File

@ -2400,19 +2400,27 @@ void tst_qquickwindow::testHoverChildMouseEventFilter()
void tst_qquickwindow::pointerEventTypeAndPointCount()
{
QMouseEvent me(QEvent::MouseButtonPress, QPointF(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QPointF localPosition(33, 66);
QPointF scenePosition(133, 166);
QPointF screenPosition(333, 366);
QMouseEvent me(QEvent::MouseButtonPress, localPosition, scenePosition, screenPosition,
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QTouchEvent te(QEvent::TouchBegin, touchDevice, Qt::NoModifier, Qt::TouchPointPressed,
QList<QTouchEvent::TouchPoint>() << QTouchEvent::TouchPoint(1));
QQuickPointerMouseEvent pme;
pme.reset(&me);
QVERIFY(pme.isValid());
QCOMPARE(pme.asMouseEvent(), &me);
QCOMPARE(pme.asMouseEvent(localPosition), &me);
QVERIFY(pme.asPointerMouseEvent());
QVERIFY(!pme.asPointerTouchEvent());
QVERIFY(!pme.asPointerTabletEvent());
// QVERIFY(!pe->asTabletEvent()); // TODO
QCOMPARE(pme.pointCount(), 1);
QCOMPARE(pme.point(0)->scenePos(), scenePosition);
QCOMPARE(pme.asMouseEvent(localPosition)->localPos(), localPosition);
QCOMPARE(pme.asMouseEvent(localPosition)->screenPos(), screenPosition);
QQuickPointerTouchEvent pte;
pte.reset(&te);