summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBradley T. Hughes <bradley.hughes@nokia.com>2010-02-12 15:18:07 (GMT)
committerBradley T. Hughes <bradley.hughes@nokia.com>2010-02-16 09:54:04 (GMT)
commitf3a47f0fe6e9f63c030e6e89f1258d4faf2025cd (patch)
tree4e0316577caa4e7d91d4c9048fe3773d6751ecfb
parent435fa2dbc44868f6ac81956be82631a2040ed1cc (diff)
downloadQt-f3a47f0fe6e9f63c030e6e89f1258d4faf2025cd.zip
Qt-f3a47f0fe6e9f63c030e6e89f1258d4faf2025cd.tar.gz
Qt-f3a47f0fe6e9f63c030e6e89f1258d4faf2025cd.tar.bz2
Don't crash when QTouchEvent is accepted but not handled by a
QGraphicsItem After propagating QEvent::TouchBegin, if there is no item that has accepted and handled the event, we must remove the touch point from our data structures. In this situation, QGraphicsScene will ignore the TouchBegin, as will QGraphicsView, and QApplication will respond by not sending any more touch events to the view/scene/item. This means our logic for handling TouchPointReleased points will never be called (and the QGraphicsScene's itemForTouchPointId and sceneCurrentTouchPoints state will be incorrect). Reviewed-by: Denis Dzyubenko Reviewed-by: Marius Storm-Olsen
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp9
-rw-r--r--tests/auto/qtouchevent/tst_qtouchevent.cpp31
2 files changed, 39 insertions, 1 deletions
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 86aaa78..4472272 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -5712,8 +5712,15 @@ void QGraphicsScenePrivate::touchEventHandler(QTouchEvent *sceneTouchEvent)
item->d_ptr->acceptedTouchBeginEvent = true;
bool res = sendTouchBeginEvent(item, &touchEvent)
&& touchEvent.isAccepted();
- if (!res)
+ if (!res) {
+ // forget about these touch points, we didn't handle them
+ for (int i = 0; i < touchEvent.touchPoints().count(); ++i) {
+ const QTouchEvent::TouchPoint &touchPoint = touchEvent.touchPoints().at(i);
+ itemForTouchPointId.remove(touchPoint.id());
+ sceneCurrentTouchPoints.remove(touchPoint.id());
+ }
ignoreSceneTouchEvent = false;
+ }
break;
}
default:
diff --git a/tests/auto/qtouchevent/tst_qtouchevent.cpp b/tests/auto/qtouchevent/tst_qtouchevent.cpp
index 639f8e4..bb80fde 100644
--- a/tests/auto/qtouchevent/tst_qtouchevent.cpp
+++ b/tests/auto/qtouchevent/tst_qtouchevent.cpp
@@ -193,6 +193,7 @@ private slots:
void multiPointRawEventTranslationOnTouchPad();
void deleteInEventHandler();
void deleteInRawEventTranslation();
+ void crashInQGraphicsSceneAfterNotHandlingTouchBegin();
};
void tst_QTouchEvent::touchDisabledByDefault()
@@ -1303,6 +1304,36 @@ void tst_QTouchEvent::deleteInRawEventTranslation()
qt_translateRawTouchEvent(&touchWidget, QTouchEvent::TouchScreen, rawTouchPoints);
}
+void tst_QTouchEvent::crashInQGraphicsSceneAfterNotHandlingTouchBegin()
+{
+ QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 100, 100);
+ rect->setAcceptTouchEvents(true);
+
+ QGraphicsRectItem *mainRect = new QGraphicsRectItem(0, 0, 100, 100, rect);
+ mainRect->setBrush(Qt::lightGray);
+
+ QGraphicsRectItem *button = new QGraphicsRectItem(-20, -20, 40, 40, mainRect);
+ button->setPos(50, 50);
+ button->setBrush(Qt::darkGreen);
+
+ QGraphicsView view;
+ QGraphicsScene scene;
+ scene.addItem(rect);
+ scene.setSceneRect(0,0,100,100);
+ view.setScene(&scene);
+
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QPoint centerPos = view.mapFromScene(rect->boundingRect().center());
+ // Touch the button
+ QTest::touchEvent(view.viewport()).press(0, centerPos);
+ QTest::touchEvent(view.viewport()).release(0, centerPos);
+ // Touch outside of the button
+ QTest::touchEvent(view.viewport()).press(0, view.mapFromScene(QPoint(10, 10)));
+ QTest::touchEvent(view.viewport()).release(0, view.mapFromScene(QPoint(10, 10)));
+}
+
QTEST_MAIN(tst_QTouchEvent)
#include "tst_qtouchevent.moc"