aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickmultipointtoucharea.cpp
diff options
context:
space:
mode:
authorKent Hansen <kent.hansen@nokia.com>2011-11-23 15:14:07 +0100
committerQt by Nokia <qt-info@nokia.com>2011-12-02 14:18:20 +0100
commit6c8378eaf1edbbefe6aaa3672b0127816a004fd7 (patch)
tree8ee08fb447e052f7a7a685fbeaaa04f04ea60126 /src/quick/items/qquickmultipointtoucharea.cpp
parente01219b77b1e889e70437635905d7ff820568e23 (diff)
Say hello to QtQuick module
This change moves the QtQuick 2 types and C++ API (including SceneGraph) to a new module (AKA library), QtQuick. 99% of this change is moving files from src/declarative to src/quick, and from tests/auto/declarative to tests/auto/qtquick2. The loading of QtQuick 2 ("import QtQuick 2.0") is now delegated to a plugin, src/imports/qtquick2, just like it's done for QtQuick 1. All tools, examples, and tests that use QtQuick C++ API have gotten "QT += quick" or "QT += quick-private" added to their .pro file. A few additional internal QtDeclarative classes had to be exported (via Q_DECLARATIVE_PRIVATE_EXPORT) since they're needed by the QtQuick 2 implementation. The old header locations (e.g. QtDeclarative/qquickitem.h) will still be supported for some time, but will produce compile-time warnings. (To avoid the QtQuick implementation using the compatibility headers (since QtDeclarative's includepath comes first), a few include statements were modified, e.g. from "#include <qsgnode.h>" to "#include <QtQuick/qsgnode.h>".) There's a change in qtbase that automatically adds QtQuick to the module list if QtDeclarative is used. Together with the compatibility headers, this should help reduce the migration pain for existing projects. In theory, simply getting an existing QtDeclarative-based project to compile and link shouldn't require any changes for now -- but porting to the new scheme is of course recommended, and will eventually become mandatory. Task-number: QTBUG-22889 Reviewed-by: Lars Knoll <lars.knoll@nokia.com> Change-Id: Ia52be9373172ba2f37e7623231ecb060316c96a7 Reviewed-by: Kent Hansen <kent.hansen@nokia.com> Reviewed-by: Sergio Ahumada <sergio.ahumada@nokia.com>
Diffstat (limited to 'src/quick/items/qquickmultipointtoucharea.cpp')
-rw-r--r--src/quick/items/qquickmultipointtoucharea.cpp729
1 files changed, 729 insertions, 0 deletions
diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp
new file mode 100644
index 0000000000..c94abc6c9d
--- /dev/null
+++ b/src/quick/items/qquickmultipointtoucharea.cpp
@@ -0,0 +1,729 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickmultipointtoucharea_p.h"
+#include <QtQuick/qquickcanvas.h>
+#include <QEvent>
+#include <QMouseEvent>
+#include <math.h>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlclass TouchPoint QQuickTouchPoint
+ \inqmlmodule QtQuick 2
+ \ingroup qml-event-elements
+ \brief The TouchPoint element describes a touch point in a MultiPointTouchArea.
+
+ The TouchPoint element contains information about a touch point, such as the current
+ position, pressure, and area.
+*/
+
+/*!
+ \qmlproperty int QtQuick2::TouchPoint::pointId
+
+ This property holds the point id of the touch point.
+
+ Each touch point within a MultiPointTouchArea will have a unique id.
+*/
+void QQuickTouchPoint::setPointId(int id)
+{
+ if (_id == id)
+ return;
+ _id = id;
+ emit pointIdChanged();
+}
+
+/*!
+ \qmlproperty real QtQuick2::TouchPoint::x
+ \qmlproperty real QtQuick2::TouchPoint::y
+
+ These properties hold the current position of the touch point.
+*/
+
+void QQuickTouchPoint::setX(qreal x)
+{
+ if (_x == x)
+ return;
+ _x = x;
+ emit xChanged();
+}
+
+void QQuickTouchPoint::setY(qreal y)
+{
+ if (_y == y)
+ return;
+ _y = y;
+ emit yChanged();
+}
+
+/*!
+ \qmlproperty real QtQuick2::TouchPoint::pressure
+ \qmlproperty rectangle QtQuick2::TouchPoint::area
+
+ These properties hold additional information about the current state of the touch point.
+
+ \list
+ \i \c pressure is a value in the range of 0.0 to 1.0.
+ \i \c area is a rectangle covering the area of the touch point, centered on the current position of the touch point.
+ \endlist
+*/
+void QQuickTouchPoint::setPressure(qreal pressure)
+{
+ if (_pressure == pressure)
+ return;
+ _pressure = pressure;
+ emit pressureChanged();
+}
+
+void QQuickTouchPoint::setArea(const QRectF &area)
+{
+ if (_area == area)
+ return;
+ _area = area;
+ emit areaChanged();
+}
+
+/*!
+ \qmlproperty bool QtQuick2::TouchPoint::valid
+
+ This property holds whether the touch point is valid.
+
+ An invalid touch point is one that has not yet been pressed,
+ or has already been released.
+*/
+void QQuickTouchPoint::setValid(bool valid)
+{
+ if (_valid == valid)
+ return;
+ _valid = valid;
+ emit validityChanged();
+}
+
+/*!
+ \qmlproperty real QtQuick2::TouchPoint::startX
+ \qmlproperty real QtQuick2::TouchPoint::startY
+
+ These properties hold the starting position of the touch point.
+*/
+
+void QQuickTouchPoint::setStartX(qreal startX)
+{
+ if (_startX == startX)
+ return;
+ _startX = startX;
+ emit startXChanged();
+}
+
+void QQuickTouchPoint::setStartY(qreal startY)
+{
+ if (_startY == startY)
+ return;
+ _startY = startY;
+ emit startYChanged();
+}
+
+/*!
+ \qmlproperty real QtQuick2::TouchPoint::previousX
+ \qmlproperty real QtQuick2::TouchPoint::previousY
+
+ These properties hold the previous position of the touch point.
+*/
+void QQuickTouchPoint::setPreviousX(qreal previousX)
+{
+ if (_previousX == previousX)
+ return;
+ _previousX = previousX;
+ emit previousXChanged();
+}
+
+void QQuickTouchPoint::setPreviousY(qreal previousY)
+{
+ if (_previousY == previousY)
+ return;
+ _previousY = previousY;
+ emit previousYChanged();
+}
+
+/*!
+ \qmlproperty real QtQuick2::TouchPoint::sceneX
+ \qmlproperty real QtQuick2::TouchPoint::sceneY
+
+ These properties hold the current position of the touch point in scene coordinates.
+*/
+
+void QQuickTouchPoint::setSceneX(qreal sceneX)
+{
+ if (_sceneX == sceneX)
+ return;
+ _sceneX = sceneX;
+ emit sceneXChanged();
+}
+
+void QQuickTouchPoint::setSceneY(qreal sceneY)
+{
+ if (_sceneY == sceneY)
+ return;
+ _sceneY = sceneY;
+ emit sceneYChanged();
+}
+
+/*!
+ \qmlclass MultiPointTouchArea QQuickMultiPointTouchArea
+ \inqmlmodule QtQuick 2
+ \brief The MultiPointTouchArea item enables handling of multiple touch points.
+ \inherits Item
+
+ A MultiPointTouchArea is an invisible item that is used to track multiple touch points.
+
+ The \l enabled property is used to enable and disable touch handling. When disabled,
+ the touch area becomes transparent to mouse/touch events.
+
+ MultiPointTouchArea can be used in two ways:
+
+ \list
+ \o setting \c touchPoints to provide touch point objects with properties that can be bound to
+ \o using the onTouchUpdated or onTouchPointsPressed, onTouchPointsUpdated and onTouchPointsReleased handlers
+ \endlist
+
+ While a MultiPointTouchArea \i can take exclusive ownership of certain touch points, it is also possible to have
+ multiple MultiPointTouchAreas active at the same time, each operating on a different set of touch points.
+
+ \sa TouchPoint
+*/
+
+/*!
+ \qmlsignal QtQuick2::MultiPointTouchArea::touchPointsPressed(list<TouchPoint> touchPoints)
+
+ This handler is called when new touch points are added. \a touchPoints is a list of these new points.
+
+ If minimumTouchPoints is set to a value greater than one, this handler will not be called until the minimum number
+ of required touch points has been reached. At that point, touchPointsPressed will be called with all the current touch points.
+*/
+
+/*!
+ \qmlsignal QtQuick2::MultiPointTouchArea::touchPointsUpdated(list<TouchPoint> touchPoints)
+
+ This handler is called when existing touch points are updated. \a touchPoints is a list of these updated points.
+*/
+
+/*!
+ \qmlsignal QtQuick2::MultiPointTouchArea::touchPointsReleased(list<TouchPoint> touchPoints)
+
+ This handler is called when existing touch points are removed. \a touchPoints is a list of these removed points.
+*/
+
+/*!
+ \qmlsignal QtQuick2::MultiPointTouchArea::touchPointsCanceled(list<TouchPoint> touchPoints)
+
+ This handler is called when new touch events have been canceled because another element stole the touch event handling.
+
+ This signal is for advanced use: it is useful when there is more than one MultiPointTouchArea
+ that is handling input, or when there is a MultiPointTouchArea inside a \l Flickable. In the latter
+ case, if you execute some logic on the touchPointsPressed signal and then start dragging, the
+ \l Flickable may steal the touch handling from the MultiPointTouchArea. In these cases, to reset
+ the logic when the MultiPointTouchArea has lost the touch handling to the \l Flickable,
+ \c onTouchPointsCanceled should be used in addition to onTouchPointsReleased.
+
+ \a touchPoints is the list of canceled points.
+*/
+
+/*!
+ \qmlsignal QtQuick2::MultiPointTouchArea::gestureStarted(GestureEvent gesture)
+
+ This handler is called when the global drag threshold has been reached.
+
+ This function is typically used when a MultiPointTouchAreas has been nested in a Flickable or another MultiPointTouchArea.
+ Wnen the threshold has been reached, and the handler called, you can determine whether or not the touch
+ area should grab the current touch points. By default they will not be grabbed; to grab them call \c gesture.grab(). If the
+ gesture is not grabbed, the nesting Flickable, for example, would also have an opportunity to grab.
+
+ The gesture object also includes information on the current set of \c touchPoints and the \c dragThreshold.
+*/
+
+/*!
+ \qmlsignal QtQuick2::MultiPointTouchArea::touchUpdated(list<TouchPoint> touchPoints)
+
+ This handler is called when the touch points handled by the MultiPointTouchArea change. This includes adding new touch points,
+ removing previous touch points, as well as updating current touch point data. \a touchPoints is the list of all current touch
+ points.
+*/
+
+/*!
+ \qmlproperty list<TouchPoint> QtQuick2::MultiPointTouchArea::touchPoints
+
+ This property holds a set of user-defined touch point objects that can be bound to.
+
+ In the following example, we have two small rectangles that follow our touch points.
+
+ \snippet doc/src/snippets/declarative/multipointtoucharea/multipointtoucharea.qml 0
+
+ By default this property holds an empty list.
+
+ \sa TouchPoint
+*/
+
+QQuickMultiPointTouchArea::QQuickMultiPointTouchArea(QQuickItem *parent)
+ : QQuickItem(parent),
+ _minimumTouchPoints(0),
+ _maximumTouchPoints(INT_MAX),
+ _stealMouse(false)
+{
+ setAcceptedMouseButtons(Qt::LeftButton);
+ setFiltersChildMouseEvents(true);
+}
+
+QQuickMultiPointTouchArea::~QQuickMultiPointTouchArea()
+{
+ clearTouchLists();
+ foreach (QObject *obj, _touchPoints) {
+ QQuickTouchPoint *dtp = static_cast<QQuickTouchPoint*>(obj);
+ if (!dtp->isQmlDefined())
+ delete dtp;
+ }
+}
+
+/*!
+ \qmlproperty int QtQuick2::MultiPointTouchArea::minimumTouchPoints
+ \qmlproperty int QtQuick2::MultiPointTouchArea::maximumTouchPoints
+
+ These properties hold the range of touch points to be handled by the touch area.
+
+ These are convenience that allow you to, for example, have nested MultiPointTouchAreas,
+ one handling two finger touches, and another handling three finger touches.
+
+ By default, all touch points within the touch area are handled.
+*/
+
+int QQuickMultiPointTouchArea::minimumTouchPoints() const
+{
+ return _minimumTouchPoints;
+}
+
+void QQuickMultiPointTouchArea::setMinimumTouchPoints(int num)
+{
+ if (_minimumTouchPoints == num)
+ return;
+ _minimumTouchPoints = num;
+ emit minimumTouchPointsChanged();
+}
+
+int QQuickMultiPointTouchArea::maximumTouchPoints() const
+{
+ return _maximumTouchPoints;
+}
+
+void QQuickMultiPointTouchArea::setMaximumTouchPoints(int num)
+{
+ if (_maximumTouchPoints == num)
+ return;
+ _maximumTouchPoints = num;
+ emit maximumTouchPointsChanged();
+}
+
+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
+ QQuickCanvas *c = canvas();
+ 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) {
+ //TODO: move to canvas
+ _stealMouse = false;
+ setKeepMouseGrab(false);
+ QQuickCanvas *c = canvas();
+ if (c && c->mouseGrabberItem() == this)
+ ungrabMouse();
+ setKeepTouchGrab(false);
+ ungrabTouchPoints();
+ }
+ break;
+ }
+ default:
+ QQuickItem::touchEvent(event);
+ break;
+ }
+}
+
+void QQuickMultiPointTouchArea::grabGesture()
+{
+ _stealMouse = true;
+
+ grabMouse();
+ setKeepMouseGrab(true);
+
+ grabTouchPoints(_touchPoints.keys());
+ setKeepTouchGrab(true);
+}
+
+void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
+{
+ bool ended = false;
+ bool moved = false;
+ bool started = false;
+
+ clearTouchLists();
+ QTouchEvent *e = static_cast<QTouchEvent*>(event);
+ QList<QTouchEvent::TouchPoint> touchPoints = e->touchPoints();
+ int numTouchPoints = touchPoints.count();
+ //always remove released touches, and make sure we handle all releases before adds.
+ foreach (QTouchEvent::TouchPoint p, touchPoints) {
+ Qt::TouchPointState touchPointState = p.state();
+ int id = p.id();
+ if (touchPointState & Qt::TouchPointReleased) {
+ QQuickTouchPoint* dtp = static_cast<QQuickTouchPoint*>(_touchPoints.value(id));
+ if (!dtp)
+ continue;
+ _releasedTouchPoints.append(dtp);
+ _touchPoints.remove(id);
+ ended = true;
+ }
+ }
+ if (numTouchPoints >= _minimumTouchPoints && numTouchPoints <= _maximumTouchPoints) {
+ foreach (QTouchEvent::TouchPoint p, touchPoints) {
+ Qt::TouchPointState touchPointState = p.state();
+ int id = p.id();
+ if (touchPointState & Qt::TouchPointReleased) {
+ //handled above
+ } else if (!_touchPoints.contains(id)) { //could be pressed, moved, or stationary
+ addTouchPoint(&p);
+ started = true;
+ } else if (touchPointState & Qt::TouchPointMoved) {
+ QQuickTouchPoint* dtp = static_cast<QQuickTouchPoint*>(_touchPoints[id]);
+ Q_ASSERT(dtp);
+ _movedTouchPoints.append(dtp);
+ updateTouchPoint(dtp,&p);
+ moved = true;
+ } else {
+ QQuickTouchPoint* dtp = static_cast<QQuickTouchPoint*>(_touchPoints[id]);
+ Q_ASSERT(dtp);
+ updateTouchPoint(dtp,&p);
+ }
+ }
+
+ //see if we should be grabbing the gesture
+ if (!_stealMouse /* !ignoring gesture*/) {
+ bool offerGrab = false;
+ const int dragThreshold = qApp->styleHints()->startDragDistance();
+ foreach (const QTouchEvent::TouchPoint &p, touchPoints) {
+ if (p.state() == Qt::TouchPointReleased)
+ continue;
+ const QPointF &currentPos = p.scenePos();
+ const QPointF &startPos = p.startScenePos();
+ if (qAbs(currentPos.x() - startPos.x()) > dragThreshold)
+ offerGrab = true;
+ else if (qAbs(currentPos.y() - startPos.y()) > dragThreshold)
+ offerGrab = true;
+ if (offerGrab)
+ break;
+ }
+
+ if (offerGrab) {
+ QQuickGrabGestureEvent event;
+ event._touchPoints = _touchPoints.values();
+ emit gestureStarted(&event);
+ if (event.wantsGrab())
+ grabGesture();
+ }
+ }
+
+ if (ended) emit(touchPointsReleased(_releasedTouchPoints));
+ if (moved) emit(touchPointsUpdated(_movedTouchPoints));
+ if (started) emit(touchPointsPressed(_pressedTouchPoints));
+ if (!_touchPoints.isEmpty()) emit touchUpdated(_touchPoints.values());
+ }
+}
+
+void QQuickMultiPointTouchArea::clearTouchLists()
+{
+ foreach (QObject *obj, _releasedTouchPoints) {
+ QQuickTouchPoint *dtp = static_cast<QQuickTouchPoint*>(obj);
+ if (!dtp->isQmlDefined())
+ delete dtp;
+ else
+ dtp->setValid(false);
+ }
+ _releasedTouchPoints.clear();
+ _pressedTouchPoints.clear();
+ _movedTouchPoints.clear();
+}
+
+void QQuickMultiPointTouchArea::addTouchPoint(const QTouchEvent::TouchPoint *p)
+{
+ QQuickTouchPoint *dtp = 0;
+ foreach (QQuickTouchPoint* tp, _touchPrototypes) {
+ if (!tp->isValid()) {
+ tp->setValid(true);
+ dtp = tp;
+ break;
+ }
+ }
+
+ if (dtp == 0)
+ dtp = new QQuickTouchPoint(false);
+ dtp->setPointId(p->id());
+ updateTouchPoint(dtp,p);
+ _touchPoints.insert(p->id(),dtp);
+ //we may have just obtained enough points to start tracking them -- in that case moved or stationary count as newly pressed
+ if (p->state() & Qt::TouchPointPressed || p->state() & Qt::TouchPointMoved || p->state() & Qt::TouchPointStationary)
+ _pressedTouchPoints.append(dtp);
+}
+
+void QQuickMultiPointTouchArea::addTouchPrototype(QQuickTouchPoint *prototype)
+{
+ int id = _touchPrototypes.count();
+ prototype->setPointId(id);
+ _touchPrototypes.insert(id, prototype);
+}
+
+void QQuickMultiPointTouchArea::updateTouchPoint(QQuickTouchPoint *dtp, const QTouchEvent::TouchPoint *p)
+{
+ //TODO: if !qmlDefined, could bypass setters.
+ // also, should only emit signals after all values have been set
+ dtp->setX(p->pos().x());
+ dtp->setY(p->pos().y());
+ dtp->setPressure(p->pressure());
+ dtp->setArea(p->rect());
+ dtp->setStartX(p->startPos().x());
+ dtp->setStartY(p->startPos().y());
+ dtp->setPreviousX(p->lastPos().x());
+ dtp->setPreviousY(p->lastPos().y());
+ dtp->setSceneX(p->scenePos().x());
+ dtp->setSceneY(p->scenePos().y());
+}
+
+void QQuickMultiPointTouchArea::mousePressEvent(QMouseEvent *event)
+{
+ if (!isEnabled()) {
+ QQuickItem::mousePressEvent(event);
+ return;
+ }
+
+ _stealMouse = false;
+ setKeepMouseGrab(false);
+ event->setAccepted(true);
+}
+
+void QQuickMultiPointTouchArea::mouseMoveEvent(QMouseEvent *event)
+{
+ if (!isEnabled()) {
+ QQuickItem::mouseMoveEvent(event);
+ return;
+ }
+
+ //do nothing
+}
+
+void QQuickMultiPointTouchArea::mouseReleaseEvent(QMouseEvent *event)
+{
+ _stealMouse = false;
+ if (!isEnabled()) {
+ QQuickItem::mouseReleaseEvent(event);
+ return;
+ }
+ QQuickCanvas *c = canvas();
+ if (c && c->mouseGrabberItem() == this)
+ ungrabMouse();
+ setKeepMouseGrab(false);
+}
+
+void QQuickMultiPointTouchArea::ungrab()
+{
+ if (_touchPoints.count()) {
+ QQuickCanvas *c = canvas();
+ if (c && c->mouseGrabberItem() == this) {
+ _stealMouse = false;
+ setKeepMouseGrab(false);
+ }
+ setKeepTouchGrab(false);
+ emit touchPointsCanceled(_touchPoints.values());
+ clearTouchLists();
+ foreach (QObject *obj, _touchPoints) {
+ QQuickTouchPoint *dtp = static_cast<QQuickTouchPoint*>(obj);
+ if (!dtp->isQmlDefined())
+ delete dtp;
+ else
+ dtp->setValid(false);
+ }
+ _touchPoints.clear();
+ }
+}
+
+void QQuickMultiPointTouchArea::mouseUngrabEvent()
+{
+ ungrab();
+}
+
+void QQuickMultiPointTouchArea::touchUngrabEvent()
+{
+ ungrab();
+}
+
+bool QQuickMultiPointTouchArea::sendMouseEvent(QMouseEvent *event)
+{
+ QRectF myRect = mapRectToScene(QRectF(0, 0, width(), height()));
+
+ QQuickCanvas *c = canvas();
+ QQuickItem *grabber = c ? c->mouseGrabberItem() : 0;
+ bool stealThisEvent = _stealMouse;
+ if ((stealThisEvent || myRect.contains(event->windowPos())) && (!grabber || !grabber->keepMouseGrab())) {
+ QMouseEvent mouseEvent(event->type(), mapFromScene(event->windowPos()), event->windowPos(), event->screenPos(),
+ event->button(), event->buttons(), event->modifiers());
+ mouseEvent.setAccepted(false);
+
+ switch (mouseEvent.type()) {
+ case QEvent::MouseMove:
+ mouseMoveEvent(&mouseEvent);
+ break;
+ case QEvent::MouseButtonPress:
+ mousePressEvent(&mouseEvent);
+ break;
+ case QEvent::MouseButtonRelease:
+ mouseReleaseEvent(&mouseEvent);
+ break;
+ default:
+ break;
+ }
+ grabber = c->mouseGrabberItem();
+ if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this)
+ grabMouse();
+
+ return stealThisEvent;
+ }
+ if (event->type() == QEvent::MouseButtonRelease) {
+ _stealMouse = false;
+ if (c && c->mouseGrabberItem() == this)
+ ungrabMouse();
+ setKeepMouseGrab(false);
+ }
+ return false;
+}
+
+bool QQuickMultiPointTouchArea::childMouseEventFilter(QQuickItem *i, QEvent *event)
+{
+ if (!isEnabled() || !isVisible())
+ return QQuickItem::childMouseEventFilter(i, event);
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ return sendMouseEvent(static_cast<QMouseEvent *>(event));
+ break;
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ if (!shouldFilter(event))
+ return false;
+ updateTouchData(event);
+ return _stealMouse;
+ case QEvent::TouchEnd: {
+ if (!shouldFilter(event))
+ return false;
+ updateTouchData(event);
+ //TODO: verify this behavior
+ _stealMouse = false;
+ setKeepMouseGrab(false);
+ QQuickCanvas *c = canvas();
+ if (c && c->mouseGrabberItem() == this)
+ ungrabMouse();
+ setKeepTouchGrab(false);
+ ungrabTouchPoints();
+ }
+ break;
+ default:
+ break;
+ }
+ return QQuickItem::childMouseEventFilter(i, event);
+}
+
+bool QQuickMultiPointTouchArea::shouldFilter(QEvent *event)
+{
+ QQuickCanvas *c = canvas();
+ QQuickItem *grabber = c ? c->mouseGrabberItem() : 0;
+ bool disabledItem = grabber && !grabber->isEnabled();
+ bool stealThisEvent = _stealMouse;
+ bool contains = false;
+ if (!stealThisEvent) {
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease: {
+ QMouseEvent *me = static_cast<QMouseEvent*>(event);
+ QRectF myRect = mapRectToScene(QRectF(0, 0, width(), height()));
+ contains = myRect.contains(me->windowPos());
+ }
+ break;
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd: {
+ QTouchEvent *te = static_cast<QTouchEvent*>(event);
+ QRectF myRect = mapRectToScene(QRectF(0, 0, width(), height()));
+ foreach (const QTouchEvent::TouchPoint &point, te->touchPoints()) {
+ if (myRect.contains(point.scenePos())) {
+ contains = true;
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if ((stealThisEvent || contains) && (!grabber || !grabber->keepMouseGrab() || disabledItem)) {
+ return true;
+ }
+ ungrab();
+ return false;
+}
+
+QT_END_NAMESPACE