void QQuickMultiPointTouchArea::touchEvent(QTouchEvent *event) { switch (event->type()) { case QEvent::TouchBegin: case QEvent::TouchUpdate: case QEvent::TouchEnd: { //if e.g. a parent Flickable has the mouse grab, don't process the touch events QQuickWindow *c = window(); QQuickItem *grabber = c ? c->mouseGrabberItem() : 0; if (grabber && grabber != this && grabber->keepMouseGrab() && grabber->isEnabled()) { QQuickItem *item = this; while ((item = item->parentItem())) { if (item == grabber) return; } } updateTouchData(event); if (event->type() == QEvent::TouchEnd) ungrab(); break; } case QEvent::TouchCancel: ungrab(); break; default: QQuickItem::touchEvent(event); break; } }
bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *item,const QPointF &sp, PropagateType sig) { //Based off of QQuickWindow::deliverInitialMousePressEvent //But specific to MouseArea, so doesn't belong in window Q_Q(const QQuickMouseArea); QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) { QPointF p = item->mapFromScene(sp); if (!item->contains(p)) return false; } QList<QQuickItem *> children = itemPrivate->paintOrderChildItems(); for (int ii = children.count() - 1; ii >= 0; --ii) { QQuickItem *child = children.at(ii); if (!child->isVisible() || !child->isEnabled()) continue; if (propagateHelper(ev, child, sp, sig)) return true; } QQuickMouseArea* ma = qobject_cast<QQuickMouseArea*>(item); if (ma && ma != q && ma->isEnabled() && itemPrivate->acceptedMouseButtons() & ev->button()) { switch (sig) { case Click: if (!ma->d_func()->isClickConnected()) return false; break; case DoubleClick: if (!ma->d_func()->isDoubleClickConnected()) return false; break; case PressAndHold: if (!ma->d_func()->isPressAndHoldConnected()) return false; break; } QPointF p = item->mapFromScene(sp); if (item->contains(p)) { ev->setX(p.x()); ev->setY(p.y()); ev->setAccepted(true);//It is connected, they have to explicitly ignore to let it slide switch (sig) { case Click: emit ma->clicked(ev); break; case DoubleClick: emit ma->doubleClicked(ev); break; case PressAndHold: emit ma->pressAndHold(ev); break; } if (ev->isAccepted()) return true; } } return false; }
bool QQuickMultiPointTouchArea::shouldFilter(QEvent *event) { QQuickWindow *c = window(); QQuickItem *grabber = c ? c->mouseGrabberItem() : 0; bool disabledItem = grabber && !grabber->isEnabled(); bool stealThisEvent = _stealMouse; bool containsPoint = false; if (!stealThisEvent) { switch (event->type()) { case QEvent::MouseButtonPress: case QEvent::MouseMove: case QEvent::MouseButtonRelease: { QMouseEvent *me = static_cast<QMouseEvent*>(event); containsPoint = contains(mapFromScene(me->windowPos())); } break; case QEvent::TouchBegin: case QEvent::TouchUpdate: case QEvent::TouchEnd: { QTouchEvent *te = static_cast<QTouchEvent*>(event); for (const QTouchEvent::TouchPoint &point : te->touchPoints()) { if (contains(mapFromScene(point.scenePos()))) { containsPoint = true; break; } } } break; default: break; } } if ((stealThisEvent || containsPoint) && (!grabber || !grabber->keepMouseGrab() || disabledItem)) { return true; } ungrab(); return false; }
void TouchDispatcher::dispatchTouchBegin( QTouchDevice *device, Qt::KeyboardModifiers modifiers, const QList<QTouchEvent::TouchPoint> &touchPoints, QWindow *window, ulong timestamp) { Q_ASSERT(m_status == NoActiveTouch); QQuickItem *targetItem = m_targetItem.data(); if (!targetItem->isEnabled() || !targetItem->isVisible()) { ugDebug("Cannot dispatch touch event to " << targetItem << " because it's disabled or invisible."); return; } // Map touch points to targetItem coordinates QList<QTouchEvent::TouchPoint> targetTouchPoints = touchPoints; transformTouchPoints(targetTouchPoints, QQuickItemPrivate::get(targetItem)->windowToItemTransform()); QScopedPointer<QTouchEvent> touchEvent( createQTouchEvent(QEvent::TouchBegin, device, modifiers, targetTouchPoints, window, timestamp)); ugDebug("dispatching " << qPrintable(touchEventToString(touchEvent.data())) << " to " << targetItem); QCoreApplication::sendEvent(targetItem, touchEvent.data()); if (touchEvent->isAccepted()) { ugDebug("Item accepted the touch event."); setStatus(DeliveringTouchEvents); } else if (targetItem->acceptedMouseButtons() & Qt::LeftButton) { ugDebug("Item rejected the touch event. Trying a QMouseEvent"); // NB: Arbitrarily chose the first touch point to emulate the mouse pointer QScopedPointer<QMouseEvent> mouseEvent( touchToMouseEvent(QEvent::MouseButtonPress, targetTouchPoints.at(0), timestamp, modifiers, false /* transformNeeded */)); Q_ASSERT(targetTouchPoints.at(0).state() == Qt::TouchPointPressed); ugDebug("dispatching " << qPrintable(mouseEventToString(mouseEvent.data())) << " to " << m_targetItem.data()); QCoreApplication::sendEvent(targetItem, mouseEvent.data()); if (mouseEvent->isAccepted()) { ugDebug("Item accepted the QMouseEvent."); setStatus(DeliveringMouseEvents); m_touchMouseId = targetTouchPoints.at(0).id(); if (checkIfDoubleClicked(timestamp)) { QScopedPointer<QMouseEvent> doubleClickEvent( touchToMouseEvent(QEvent::MouseButtonDblClick, targetTouchPoints.at(0), timestamp, modifiers, false /* transformNeeded */)); ugDebug("dispatching " << qPrintable(mouseEventToString(doubleClickEvent.data())) << " to " << m_targetItem.data()); QCoreApplication::sendEvent(targetItem, doubleClickEvent.data()); } } else { ugDebug("Item rejected the QMouseEvent."); setStatus(TargetRejectedTouches); } } else { ugDebug("Item rejected the touch event and does not accept mouse buttons."); setStatus(TargetRejectedTouches); } }