summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBradley T. Hughes <bradley.hughes@nokia.com>2009-05-13 14:16:11 (GMT)
committerBradley T. Hughes <bradley.hughes@nokia.com>2009-05-13 14:16:11 (GMT)
commitfdd2ad0813a856a00cac83ccff9bdd210b398c9c (patch)
treeeb0595f41b627217ba2339809b791327b37cc7f5
parent3134a71a6b2a1b31ca02c445adc7d9c66e082b25 (diff)
downloadQt-fdd2ad0813a856a00cac83ccff9bdd210b398c9c.zip
Qt-fdd2ad0813a856a00cac83ccff9bdd210b398c9c.tar.gz
Qt-fdd2ad0813a856a00cac83ccff9bdd210b398c9c.tar.bz2
Implement QEvent::GraphicsSceneTouchBegin propagation
This event will be propagated to all items under the first touch point, otherwise it's the same as QEvent::TouchBegin propagation: the first item to accept the event gets the remaining touch events. If none of the GraphicsSceneTouchEvents sent to the items are sent, then the GraphicsSceneTouchEvent that was sent to the seen will be ignored, causing the QTouchEvent sent to the QGraphicsView to also be ignored, meaning widget TouchBegin event propagation resumes.
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp74
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h1
2 files changed, 69 insertions, 6 deletions
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 8140fea..3d4bb5c 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -3798,6 +3798,9 @@ bool QGraphicsScene::event(QEvent *event)
case QEvent::GraphicsSceneHoverEnter:
case QEvent::GraphicsSceneHoverLeave:
case QEvent::GraphicsSceneHoverMove:
+ case QEvent::GraphicsSceneTouchBegin:
+ case QEvent::GraphicsSceneTouchUpdate:
+ case QEvent::GraphicsSceneTouchEnd:
// Reset the under-mouse list to ensure that this event gets fresh
// item-under-mouse data. Be careful about this list; if people delete
// items from inside event handlers, this list can quickly end up
@@ -5722,8 +5725,6 @@ QEvent::Type QGraphicsScenePrivate::removeTouchPoint(QGraphicsSceneTouchEvent::T
void QGraphicsScenePrivate::touchEventHandler(QGraphicsSceneTouchEvent *sceneTouchEvent)
{
- Q_Q(QGraphicsScene);
-
QList<QGraphicsSceneTouchEvent::TouchPoint *> sceneActiveTouchPoints = sceneCurrentTouchPoints;
QHash<QGraphicsItem *, QGraphicsSceneTouchEvent *> itemsNeedingEvents;
@@ -5735,8 +5736,11 @@ void QGraphicsScenePrivate::touchEventHandler(QGraphicsSceneTouchEvent *sceneTou
QEvent::Type eventType = QEvent::None;
QList<QGraphicsSceneTouchEvent::TouchPoint *> activeTouchPoints;
if (touchPoint->state() == Qt::TouchPointPressed) {
- // determine which widget this event will go to
- item = q->itemAt(touchPoint->scenePos());
+ // determine which item this event will go to
+ cachedItemsUnderMouse = itemsAtPosition(touchPoint->screenPos().toPoint(),
+ touchPoint->scenePos(),
+ sceneTouchEvent->widget());
+ item = cachedItemsUnderMouse.isEmpty() ? 0 : cachedItemsUnderMouse.first();
QGraphicsSceneTouchEvent::TouchPoint *closestTouchPoint = findClosestTouchPoint(sceneActiveTouchPoints, touchPoint->scenePos());
if (closestTouchPoint) {
QGraphicsItem *closestItem = itemForTouchPointId.value(closestTouchPoint->id());
@@ -5781,6 +5785,7 @@ void QGraphicsScenePrivate::touchEventHandler(QGraphicsSceneTouchEvent *sceneTou
QGraphicsSceneTouchEvent *&touchEvent = itemsNeedingEvents[item];
if (!touchEvent) {
touchEvent = new QGraphicsSceneTouchEvent(eventType);
+ touchEvent->setWidget(sceneTouchEvent->widget());
touchEvent->setModifiers(sceneTouchEvent->modifiers());
}
Q_ASSERT(touchEvent->type() == eventType);
@@ -5800,7 +5805,6 @@ void QGraphicsScenePrivate::touchEventHandler(QGraphicsSceneTouchEvent *sceneTou
QGraphicsItem *item = it.key();
QGraphicsSceneTouchEvent *touchEvent = it.value();
- updateTouchPointsForItem(item, touchEvent);
switch (touchEvent->type()) {
case QEvent::GraphicsSceneTouchBegin:
@@ -5808,7 +5812,7 @@ void QGraphicsScenePrivate::touchEventHandler(QGraphicsSceneTouchEvent *sceneTou
// if the TouchBegin handler recurses, we assume that means the event
// has been implicitly accepted and continue to send touch events
item->d_ptr->acceptedTouchBeginEvent = true;
- bool res = sendEvent(item, touchEvent)
+ bool res = sendTouchBeginEvent(item, touchEvent)
&& touchEvent->isAccepted();
acceptSceneTouchEvent = acceptSceneTouchEvent || res;
break;
@@ -5823,6 +5827,7 @@ void QGraphicsScenePrivate::touchEventHandler(QGraphicsSceneTouchEvent *sceneTou
}
default:
if (item->d_ptr->acceptedTouchBeginEvent) {
+ updateTouchPointsForItem(item, touchEvent);
(void) sendEvent(item, touchEvent);
acceptSceneTouchEvent = true;
}
@@ -5834,6 +5839,63 @@ void QGraphicsScenePrivate::touchEventHandler(QGraphicsSceneTouchEvent *sceneTou
sceneTouchEvent->setAccepted(acceptSceneTouchEvent);
}
+bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QGraphicsSceneTouchEvent *touchEvent)
+{
+ Q_Q(QGraphicsScene);
+
+ if (cachedItemsUnderMouse.isEmpty() || cachedItemsUnderMouse.first() != origin) {
+ QGraphicsSceneTouchEvent::TouchPoint *firstTouchPoint = touchEvent->touchPoints().first();
+ cachedItemsUnderMouse = itemsAtPosition(firstTouchPoint->screenPos().toPoint(),
+ firstTouchPoint->scenePos(),
+ touchEvent->widget());
+ }
+ Q_ASSERT(cachedItemsUnderMouse.first() == origin);
+
+ // Set focus on the topmost enabled item that can take focus.
+ bool setFocus = false;
+ foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
+ if (item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) {
+ if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
+ setFocus = true;
+ if (item != q->focusItem())
+ q->setFocusItem(item, Qt::MouseFocusReason);
+ break;
+ }
+ }
+ }
+
+ // If nobody could take focus, clear it.
+ if (!stickyFocus && !setFocus)
+ q->setFocusItem(0, Qt::MouseFocusReason);
+
+ bool res = false;
+ bool eventAccepted = touchEvent->isAccepted();
+ foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
+ // first, try to deliver the touch event
+ updateTouchPointsForItem(item, touchEvent);
+ touchEvent->ignore();
+ res = item->acceptTouchEvents()
+ && sendEvent(item, touchEvent);
+ eventAccepted = touchEvent->isAccepted();
+ item->d_ptr->acceptedTouchBeginEvent = (res && eventAccepted);
+ touchEvent->spont = false;
+ if (res && eventAccepted) {
+ // the first item to accept the TouchBegin gets an implicit grab.
+ for (int i = 0; i < touchEvent->touchPoints().count(); ++i) {
+ QGraphicsSceneTouchEvent::TouchPoint *touchPoint = touchEvent->touchPoints().at(i);
+ itemForTouchPointId[touchPoint->id()] = item;
+ }
+ if (origin != item)
+ itemCurrentTouchPoints.remove(origin);
+ itemCurrentTouchPoints[item] = touchEvent->touchPoints();
+ break;
+ }
+ }
+
+ touchEvent->setAccepted(eventAccepted);
+ return res;
+}
+
QT_END_NAMESPACE
#include "moc_qgraphicsscene.cpp"
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index 589ab75..7928a45 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -287,6 +287,7 @@ public:
QEvent::Type removeTouchPoint(QGraphicsSceneTouchEvent::TouchPoint *touchPoint,
QList<QGraphicsSceneTouchEvent::TouchPoint *> *currentTouchPoints);
void touchEventHandler(QGraphicsSceneTouchEvent *touchEvent);
+ bool sendTouchBeginEvent(QGraphicsItem *item, QGraphicsSceneTouchEvent *touchEvent);
};
QT_END_NAMESPACE