From ed3ed0b9db97a8fab0c03add23228b6b0a96f171 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 12 Feb 2018 16:26:38 +0100 Subject: Fix touch point positions of non-transformable QGraphicsItems TouchEvent::TouchPoint::pos was not updated in QGraphicsScenePrivate::updateTouchPointsForItem(). To prevent the transformation being calculated repeatedly for each touch point member, extract a function genericMapFromSceneTransform() from genericMapFromScene() returning the transformation and use that whereever multiple points are transformed. Add a test, extracting helper functionality from tst_QGraphicsItem::touchEventPropagation(). In addition, fold tst_QGraphicsScene::checkTouchPointsEllipseDiameters() from c48f4bde0044bd5b23af231f3639d0779ecbdb03 into this test, so that it is testing all transformations. Task-number: QTBUG-66192 Change-Id: If71886d2c14c4e216f7781ea2f22f1adc444e6cf Reviewed-by: Andy Shaw Reviewed-by: Richard Moe Gustavsen --- src/widgets/graphicsview/qgraphicsitem.cpp | 25 ++++++++++++++++--------- src/widgets/graphicsview/qgraphicsitem_p.h | 1 + src/widgets/graphicsview/qgraphicsscene.cpp | 26 ++++++++++++++++++-------- 3 files changed, 35 insertions(+), 17 deletions(-) (limited to 'src/widgets/graphicsview') diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp index 0bc3af2f77..cef1d1b6da 100644 --- a/src/widgets/graphicsview/qgraphicsitem.cpp +++ b/src/widgets/graphicsview/qgraphicsitem.cpp @@ -1134,19 +1134,26 @@ void QGraphicsItemPrivate::remapItemPos(QEvent *event, QGraphicsItem *item) is untransformable, this function will correctly map \a pos from the scene using the view's transformation. */ -QPointF QGraphicsItemPrivate::genericMapFromScene(const QPointF &pos, - const QWidget *viewport) const + +QTransform QGraphicsItemPrivate::genericMapFromSceneTransform(const QWidget *viewport) const { Q_Q(const QGraphicsItem); if (!itemIsUntransformable()) - return q->mapFromScene(pos); - QGraphicsView *view = 0; - if (viewport) - view = qobject_cast(viewport->parentWidget()); - if (!view) - return q->mapFromScene(pos); + return sceneTransform.inverted(); + const QGraphicsView *view = viewport + ? qobject_cast(viewport->parentWidget()) + : nullptr; + if (view == nullptr) + return sceneTransform.inverted(); // ### More ping pong than needed. - return q->deviceTransform(view->viewportTransform()).inverted().map(view->mapFromScene(pos)); + const QTransform viewportTransform = view->viewportTransform(); + return viewportTransform * q->deviceTransform(viewportTransform).inverted(); +} + +QPointF QGraphicsItemPrivate::genericMapFromScene(const QPointF &pos, + const QWidget *viewport) const +{ + return genericMapFromSceneTransform(viewport).map(pos); } /*! diff --git a/src/widgets/graphicsview/qgraphicsitem_p.h b/src/widgets/graphicsview/qgraphicsitem_p.h index bae38473f9..9fc6c0794a 100644 --- a/src/widgets/graphicsview/qgraphicsitem_p.h +++ b/src/widgets/graphicsview/qgraphicsitem_p.h @@ -190,6 +190,7 @@ public: void updateAncestorFlags(); void setIsMemberOfGroup(bool enabled); void remapItemPos(QEvent *event, QGraphicsItem *item); + QTransform genericMapFromSceneTransform(const QWidget *viewport = nullptr) const; QPointF genericMapFromScene(const QPointF &pos, const QWidget *viewport) const; inline bool itemIsUntransformable() const { diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp index 25b77aa02f..37c631483a 100644 --- a/src/widgets/graphicsview/qgraphicsscene.cpp +++ b/src/widgets/graphicsview/qgraphicsscene.cpp @@ -1286,10 +1286,11 @@ void QGraphicsScenePrivate::sendHoverEvent(QEvent::Type type, QGraphicsItem *ite { QGraphicsSceneHoverEvent event(type); event.setWidget(hoverEvent->widget()); - event.setPos(item->d_ptr->genericMapFromScene(hoverEvent->scenePos(), hoverEvent->widget())); + const QTransform mapFromScene = item->d_ptr->genericMapFromSceneTransform(hoverEvent->widget()); + event.setPos(mapFromScene.map(hoverEvent->scenePos())); event.setScenePos(hoverEvent->scenePos()); event.setScreenPos(hoverEvent->screenPos()); - event.setLastPos(item->d_ptr->genericMapFromScene(hoverEvent->lastScenePos(), hoverEvent->widget())); + event.setLastPos(mapFromScene.map(hoverEvent->lastScenePos())); event.setLastScenePos(hoverEvent->lastScenePos()); event.setLastScreenPos(hoverEvent->lastScreenPos()); event.setModifiers(hoverEvent->modifiers()); @@ -1312,14 +1313,16 @@ void QGraphicsScenePrivate::sendMouseEvent(QGraphicsSceneMouseEvent *mouseEvent) if (item->isBlockedByModalPanel()) return; + const QTransform mapFromScene = item->d_ptr->genericMapFromSceneTransform(mouseEvent->widget()); + const QPointF itemPos = mapFromScene.map(mouseEvent->scenePos()); for (int i = 0x1; i <= 0x10; i <<= 1) { Qt::MouseButton button = Qt::MouseButton(i); - mouseEvent->setButtonDownPos(button, mouseGrabberButtonDownPos.value(button, item->d_ptr->genericMapFromScene(mouseEvent->scenePos(), mouseEvent->widget()))); + mouseEvent->setButtonDownPos(button, mouseGrabberButtonDownPos.value(button, itemPos)); mouseEvent->setButtonDownScenePos(button, mouseGrabberButtonDownScenePos.value(button, mouseEvent->scenePos())); mouseEvent->setButtonDownScreenPos(button, mouseGrabberButtonDownScreenPos.value(button, mouseEvent->screenPos())); } - mouseEvent->setPos(item->d_ptr->genericMapFromScene(mouseEvent->scenePos(), mouseEvent->widget())); - mouseEvent->setLastPos(item->d_ptr->genericMapFromScene(mouseEvent->lastScenePos(), mouseEvent->widget())); + mouseEvent->setPos(itemPos); + mouseEvent->setLastPos(mapFromScene.map(mouseEvent->lastScenePos())); sendEvent(item, mouseEvent); } @@ -5858,10 +5861,17 @@ void QGraphicsScenePrivate::removeView(QGraphicsView *view) void QGraphicsScenePrivate::updateTouchPointsForItem(QGraphicsItem *item, QTouchEvent *touchEvent) { + const QTransform mapFromScene = + item->d_ptr->genericMapFromSceneTransform(static_cast(touchEvent->target())); + for (auto &touchPoint : touchEvent->_touchPoints) { - touchPoint.setRect(item->mapFromScene(touchPoint.sceneRect()).boundingRect()); - touchPoint.setStartPos(item->d_ptr->genericMapFromScene(touchPoint.startScenePos(), static_cast(touchEvent->target()))); - touchPoint.setLastPos(item->d_ptr->genericMapFromScene(touchPoint.lastScenePos(), static_cast(touchEvent->target()))); + // Deprecated TouchPoint::setRect clobbers ellipseDiameters, restore + const QSizeF ellipseDiameters = touchPoint.ellipseDiameters(); + touchPoint.setRect(mapFromScene.map(touchPoint.sceneRect()).boundingRect()); + touchPoint.setEllipseDiameters(ellipseDiameters); + touchPoint.setPos(mapFromScene.map(touchPoint.scenePos())); + touchPoint.setStartPos(mapFromScene.map(touchPoint.startScenePos())); + touchPoint.setLastPos(mapFromScene.map(touchPoint.lastScenePos())); } } -- cgit v1.2.3