QQuickCanvas renames
[profile/ivi/qtdeclarative.git] / src / quick / items / qquickmultipointtoucharea.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qquickmultipointtoucharea_p.h"
43 #include <QtQuick/qquickwindow.h>
44 #include <private/qsgadaptationlayer_p.h>
45 #include <private/qquickitem_p.h>
46 #include <QEvent>
47 #include <QMouseEvent>
48 #include <math.h>
49 #include <QDebug>
50
51 QT_BEGIN_NAMESPACE
52
53 DEFINE_BOOL_CONFIG_OPTION(qmlVisualTouchDebugging, QML_VISUAL_TOUCH_DEBUGGING)
54
55 /*!
56     \qmlclass TouchPoint QQuickTouchPoint
57     \inqmlmodule QtQuick 2
58     \ingroup qtquick-input-events
59     \brief Describes a touch point in a MultiPointTouchArea
60
61     The TouchPoint type contains information about a touch point, such as the current
62     position, pressure, and area.
63 */
64
65 /*!
66     \qmlproperty int QtQuick2::TouchPoint::pointId
67
68     This property holds the point id of the touch point.
69
70     Each touch point within a MultiPointTouchArea will have a unique id.
71 */
72 void QQuickTouchPoint::setPointId(int id)
73 {
74     if (_id == id)
75         return;
76     _id = id;
77     emit pointIdChanged();
78 }
79
80 /*!
81     \qmlproperty real QtQuick2::TouchPoint::x
82     \qmlproperty real QtQuick2::TouchPoint::y
83
84     These properties hold the current position of the touch point.
85 */
86
87 void QQuickTouchPoint::setX(qreal x)
88 {
89     if (_x == x)
90         return;
91     _x = x;
92     emit xChanged();
93 }
94
95 void QQuickTouchPoint::setY(qreal y)
96 {
97     if (_y == y)
98         return;
99     _y = y;
100     emit yChanged();
101 }
102
103 /*!
104     \qmlproperty real QtQuick2::TouchPoint::pressure
105     \qmlproperty vector2d QtQuick2::TouchPoint::velocity
106     \qmlproperty rectangle QtQuick2::TouchPoint::area
107
108     These properties hold additional information about the current state of the touch point.
109
110     \list
111     \li \c pressure is a value in the range of 0.0 to 1.0.
112     \li \c velocity is a vector with magnitude reported in pixels per second.
113     \li \c area is a rectangle covering the area of the touch point, centered on the current position of the touch point.
114     \endlist
115
116     Not all touch devices support velocity. If velocity is not supported, it will be reported
117     as 0,0.
118 */
119 void QQuickTouchPoint::setPressure(qreal pressure)
120 {
121     if (_pressure == pressure)
122         return;
123     _pressure = pressure;
124     emit pressureChanged();
125 }
126
127 void QQuickTouchPoint::setVelocity(const QVector2D &velocity)
128 {
129     if (_velocity == velocity)
130         return;
131     _velocity = velocity;
132     emit velocityChanged();
133 }
134
135 void QQuickTouchPoint::setArea(const QRectF &area)
136 {
137     if (_area == area)
138         return;
139     _area = area;
140     emit areaChanged();
141 }
142
143 /*!
144     \qmlproperty bool QtQuick2::TouchPoint::pressed
145
146     This property holds whether the touch point is currently pressed.
147 */
148 void QQuickTouchPoint::setPressed(bool pressed)
149 {
150     if (_pressed == pressed)
151         return;
152     _pressed = pressed;
153     emit pressedChanged();
154 }
155
156 /*!
157     \qmlproperty real QtQuick2::TouchPoint::startX
158     \qmlproperty real QtQuick2::TouchPoint::startY
159
160     These properties hold the starting position of the touch point.
161 */
162
163 void QQuickTouchPoint::setStartX(qreal startX)
164 {
165     if (_startX == startX)
166         return;
167     _startX = startX;
168     emit startXChanged();
169 }
170
171 void QQuickTouchPoint::setStartY(qreal startY)
172 {
173     if (_startY == startY)
174         return;
175     _startY = startY;
176     emit startYChanged();
177 }
178
179 /*!
180     \qmlproperty real QtQuick2::TouchPoint::previousX
181     \qmlproperty real QtQuick2::TouchPoint::previousY
182
183     These properties hold the previous position of the touch point.
184 */
185 void QQuickTouchPoint::setPreviousX(qreal previousX)
186 {
187     if (_previousX == previousX)
188         return;
189     _previousX = previousX;
190     emit previousXChanged();
191 }
192
193 void QQuickTouchPoint::setPreviousY(qreal previousY)
194 {
195     if (_previousY == previousY)
196         return;
197     _previousY = previousY;
198     emit previousYChanged();
199 }
200
201 /*!
202     \qmlproperty real QtQuick2::TouchPoint::sceneX
203     \qmlproperty real QtQuick2::TouchPoint::sceneY
204
205     These properties hold the current position of the touch point in scene coordinates.
206 */
207
208 void QQuickTouchPoint::setSceneX(qreal sceneX)
209 {
210     if (_sceneX == sceneX)
211         return;
212     _sceneX = sceneX;
213     emit sceneXChanged();
214 }
215
216 void QQuickTouchPoint::setSceneY(qreal sceneY)
217 {
218     if (_sceneY == sceneY)
219         return;
220     _sceneY = sceneY;
221     emit sceneYChanged();
222 }
223
224 /*!
225     \qmlclass MultiPointTouchArea QQuickMultiPointTouchArea
226     \inqmlmodule QtQuick 2
227     \inherits Item
228     \ingroup qtquick-input
229     \brief Enables handling of multiple touch points
230
231
232     A MultiPointTouchArea is an invisible item that is used to track multiple touch points.
233
234     The \l enabled property is used to enable and disable touch handling. When disabled,
235     the touch area becomes transparent to mouse/touch events.
236
237     MultiPointTouchArea can be used in two ways:
238
239     \list
240     \li setting \c touchPoints to provide touch point objects with properties that can be bound to
241     \li using the onTouchUpdated or onPressed, onUpdated and onReleased handlers
242     \endlist
243
244     While a MultiPointTouchArea \e can take exclusive ownership of certain touch points, it is also possible to have
245     multiple MultiPointTouchAreas active at the same time, each operating on a different set of touch points.
246
247     \sa TouchPoint
248 */
249
250 /*!
251     \qmlsignal QtQuick2::MultiPointTouchArea::onPressed(list<TouchPoint> touchPoints)
252
253     This handler is called when new touch points are added. \a touchPoints is a list of these new points.
254
255     If minimumTouchPoints is set to a value greater than one, this handler will not be called until the minimum number
256     of required touch points has been reached. At that point, onPressed will be called with all the current touch points.
257 */
258
259 /*!
260     \qmlsignal QtQuick2::MultiPointTouchArea::onUpdated(list<TouchPoint> touchPoints)
261
262     This handler is called when existing touch points are updated. \a touchPoints is a list of these updated points.
263 */
264
265 /*!
266     \qmlsignal QtQuick2::MultiPointTouchArea::onReleased(list<TouchPoint> touchPoints)
267
268     This handler is called when existing touch points are removed. \a touchPoints is a list of these removed points.
269 */
270
271 /*!
272     \qmlsignal QtQuick2::MultiPointTouchArea::onCanceled(list<TouchPoint> touchPoints)
273
274     This handler is called when new touch events have been canceled because another item stole the touch event handling.
275
276     This signal is for advanced use: it is useful when there is more than one MultiPointTouchArea
277     that is handling input, or when there is a MultiPointTouchArea inside a \l Flickable. In the latter
278     case, if you execute some logic on the onPressed signal and then start dragging, the
279     \l Flickable may steal the touch handling from the MultiPointTouchArea. In these cases, to reset
280     the logic when the MultiPointTouchArea has lost the touch handling to the \l Flickable,
281     \c onCanceled should be used in addition to onReleased.
282
283     \a touchPoints is the list of canceled points.
284 */
285
286 /*!
287     \qmlsignal QtQuick2::MultiPointTouchArea::onGestureStarted(GestureEvent gesture)
288
289     This handler is called when the global drag threshold has been reached.
290
291     This function is typically used when a MultiPointTouchAreas has been nested in a Flickable or another MultiPointTouchArea.
292     When the threshold has been reached, and the handler called, you can determine whether or not the touch
293     area should grab the current touch points. By default they will not be grabbed; to grab them call \c gesture.grab(). If the
294     gesture is not grabbed, the nesting Flickable, for example, would also have an opportunity to grab.
295
296     The gesture object also includes information on the current set of \c touchPoints and the \c dragThreshold.
297 */
298
299 /*!
300     \qmlsignal QtQuick2::MultiPointTouchArea::onTouchUpdated(list<TouchPoint> touchPoints)
301
302     This handler is called when the touch points handled by the MultiPointTouchArea change. This includes adding new touch points,
303     removing or canceling previous touch points, as well as updating current touch point data. \a touchPoints is the list of all current touch
304     points.
305 */
306
307 /*!
308     \qmlproperty list<TouchPoint> QtQuick2::MultiPointTouchArea::touchPoints
309
310     This property holds a set of user-defined touch point objects that can be bound to.
311
312     In the following example, we have two small rectangles that follow our touch points.
313
314     \snippet qml/multipointtoucharea/multipointtoucharea.qml 0
315
316     By default this property holds an empty list.
317
318     \sa TouchPoint
319 */
320
321 QQuickMultiPointTouchArea::QQuickMultiPointTouchArea(QQuickItem *parent)
322     : QQuickItem(parent),
323       _minimumTouchPoints(0),
324       _maximumTouchPoints(INT_MAX),
325       _stealMouse(false)
326 {
327     setAcceptedMouseButtons(Qt::LeftButton);
328     setFiltersChildMouseEvents(true);
329     if (qmlVisualTouchDebugging()) {
330         setFlag(QQuickItem::ItemHasContents);
331     }
332 }
333
334 QQuickMultiPointTouchArea::~QQuickMultiPointTouchArea()
335 {
336     clearTouchLists();
337     foreach (QObject *obj, _touchPoints) {
338         QQuickTouchPoint *dtp = static_cast<QQuickTouchPoint*>(obj);
339         if (!dtp->isQmlDefined())
340             delete dtp;
341     }
342 }
343
344 /*!
345     \qmlproperty int QtQuick2::MultiPointTouchArea::minimumTouchPoints
346     \qmlproperty int QtQuick2::MultiPointTouchArea::maximumTouchPoints
347
348     These properties hold the range of touch points to be handled by the touch area.
349
350     These are convenience that allow you to, for example, have nested MultiPointTouchAreas,
351     one handling two finger touches, and another handling three finger touches.
352
353     By default, all touch points within the touch area are handled.
354 */
355
356 int QQuickMultiPointTouchArea::minimumTouchPoints() const
357 {
358     return _minimumTouchPoints;
359 }
360
361 void QQuickMultiPointTouchArea::setMinimumTouchPoints(int num)
362 {
363     if (_minimumTouchPoints == num)
364         return;
365     _minimumTouchPoints = num;
366     emit minimumTouchPointsChanged();
367 }
368
369 int QQuickMultiPointTouchArea::maximumTouchPoints() const
370 {
371     return _maximumTouchPoints;
372 }
373
374 void QQuickMultiPointTouchArea::setMaximumTouchPoints(int num)
375 {
376     if (_maximumTouchPoints == num)
377         return;
378     _maximumTouchPoints = num;
379     emit maximumTouchPointsChanged();
380 }
381
382 void QQuickMultiPointTouchArea::touchEvent(QTouchEvent *event)
383 {
384     switch (event->type()) {
385     case QEvent::TouchBegin:
386     case QEvent::TouchUpdate:
387     case QEvent::TouchEnd: {
388         //if e.g. a parent Flickable has the mouse grab, don't process the touch events
389         QQuickWindow *c = window();
390         QQuickItem *grabber = c ? c->mouseGrabberItem() : 0;
391         if (grabber && grabber != this && grabber->keepMouseGrab() && grabber->isEnabled()) {
392             QQuickItem *item = this;
393             while ((item = item->parentItem())) {
394                 if (item == grabber)
395                     return;
396             }
397         }
398         updateTouchData(event);
399         if (event->type() == QEvent::TouchEnd) {
400             //TODO: move to window
401             _stealMouse = false;
402             setKeepMouseGrab(false);
403             setKeepTouchGrab(false);
404             ungrabTouchPoints();
405         }
406         break;
407     }
408     default:
409         QQuickItem::touchEvent(event);
410         break;
411     }
412 }
413
414 void QQuickMultiPointTouchArea::grabGesture()
415 {
416     _stealMouse = true;
417
418     grabMouse();
419     setKeepMouseGrab(true);
420
421     grabTouchPoints(_touchPoints.keys().toVector());
422     setKeepTouchGrab(true);
423 }
424
425 void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
426 {
427     bool ended = false;
428     bool moved = false;
429     bool started = false;
430
431     clearTouchLists();
432     QTouchEvent *e = static_cast<QTouchEvent*>(event);
433     QList<QTouchEvent::TouchPoint> touchPoints = e->touchPoints();
434     int numTouchPoints = touchPoints.count();
435     //always remove released touches, and make sure we handle all releases before adds.
436     foreach (const QTouchEvent::TouchPoint &p, touchPoints) {
437         Qt::TouchPointState touchPointState = p.state();
438         int id = p.id();
439         if (touchPointState & Qt::TouchPointReleased) {
440             QQuickTouchPoint* dtp = static_cast<QQuickTouchPoint*>(_touchPoints.value(id));
441             if (!dtp)
442                 continue;
443             updateTouchPoint(dtp, &p);
444             dtp->setPressed(false);
445             _releasedTouchPoints.append(dtp);
446             _touchPoints.remove(id);
447             ended = true;
448         }
449     }
450     if (numTouchPoints >= _minimumTouchPoints && numTouchPoints <= _maximumTouchPoints) {
451         foreach (const QTouchEvent::TouchPoint &p, touchPoints) {
452             Qt::TouchPointState touchPointState = p.state();
453             int id = p.id();
454             if (touchPointState & Qt::TouchPointReleased) {
455                 //handled above
456             } else if (!_touchPoints.contains(id)) { //could be pressed, moved, or stationary
457                 // (we may have just obtained enough points to start tracking them -- in that case moved or stationary count as newly pressed)
458                 addTouchPoint(&p);
459                 started = true;
460             } else if (touchPointState & Qt::TouchPointMoved) {
461                 QQuickTouchPoint* dtp = static_cast<QQuickTouchPoint*>(_touchPoints[id]);
462                 Q_ASSERT(dtp);
463                 _movedTouchPoints.append(dtp);
464                 updateTouchPoint(dtp,&p);
465                 moved = true;
466             } else {
467                 QQuickTouchPoint* dtp = static_cast<QQuickTouchPoint*>(_touchPoints[id]);
468                 Q_ASSERT(dtp);
469                 updateTouchPoint(dtp,&p);
470             }
471         }
472
473         //see if we should be grabbing the gesture
474         if (!_stealMouse /* !ignoring gesture*/) {
475             bool offerGrab = false;
476             const int dragThreshold = qApp->styleHints()->startDragDistance();
477             foreach (const QTouchEvent::TouchPoint &p, touchPoints) {
478                 if (p.state() == Qt::TouchPointReleased)
479                     continue;
480                 const QPointF &currentPos = p.scenePos();
481                 const QPointF &startPos = p.startScenePos();
482                 if (qAbs(currentPos.x() - startPos.x()) > dragThreshold)
483                     offerGrab = true;
484                 else if (qAbs(currentPos.y() - startPos.y()) > dragThreshold)
485                     offerGrab = true;
486                 if (offerGrab)
487                     break;
488             }
489
490             if (offerGrab) {
491                 QQuickGrabGestureEvent event;
492                 event._touchPoints = _touchPoints.values();
493                 emit gestureStarted(&event);
494                 if (event.wantsGrab())
495                     grabGesture();
496             }
497         }
498
499         if (ended)
500             emit released(_releasedTouchPoints);
501         if (moved)
502             emit updated(_movedTouchPoints);
503         if (started)
504             emit pressed(_pressedTouchPoints);
505         if (ended || moved || started) emit touchUpdated(_touchPoints.values());
506     }
507 }
508
509 void QQuickMultiPointTouchArea::clearTouchLists()
510 {
511     foreach (QObject *obj, _releasedTouchPoints) {
512         QQuickTouchPoint *dtp = static_cast<QQuickTouchPoint*>(obj);
513         if (!dtp->isQmlDefined())
514             delete dtp;
515         else
516             dtp->setInUse(false);
517     }
518     _releasedTouchPoints.clear();
519     _pressedTouchPoints.clear();
520     _movedTouchPoints.clear();
521 }
522
523 void QQuickMultiPointTouchArea::addTouchPoint(const QTouchEvent::TouchPoint *p)
524 {
525     QQuickTouchPoint *dtp = 0;
526     foreach (QQuickTouchPoint* tp, _touchPrototypes) {
527         if (!tp->inUse()) {
528             tp->setInUse(true);
529             dtp = tp;
530             break;
531         }
532     }
533
534     if (dtp == 0)
535         dtp = new QQuickTouchPoint(false);
536     dtp->setPointId(p->id());
537     updateTouchPoint(dtp,p);
538     dtp->setPressed(true);
539     _touchPoints.insert(p->id(),dtp);
540     _pressedTouchPoints.append(dtp);
541 }
542
543 void QQuickMultiPointTouchArea::addTouchPrototype(QQuickTouchPoint *prototype)
544 {
545     int id = _touchPrototypes.count();
546     prototype->setPointId(id);
547     _touchPrototypes.insert(id, prototype);
548 }
549
550 void QQuickMultiPointTouchArea::updateTouchPoint(QQuickTouchPoint *dtp, const QTouchEvent::TouchPoint *p)
551 {
552     //TODO: if !qmlDefined, could bypass setters.
553     //      also, should only emit signals after all values have been set
554     dtp->setX(p->pos().x());
555     dtp->setY(p->pos().y());
556     dtp->setPressure(p->pressure());
557     dtp->setVelocity(p->velocity());
558     dtp->setArea(p->rect());
559     dtp->setStartX(p->startPos().x());
560     dtp->setStartY(p->startPos().y());
561     dtp->setPreviousX(p->lastPos().x());
562     dtp->setPreviousY(p->lastPos().y());
563     dtp->setSceneX(p->scenePos().x());
564     dtp->setSceneY(p->scenePos().y());
565 }
566
567 void QQuickMultiPointTouchArea::mousePressEvent(QMouseEvent *event)
568 {
569     if (!isEnabled()) {
570         QQuickItem::mousePressEvent(event);
571         return;
572     }
573
574     _stealMouse = false;
575     setKeepMouseGrab(false);
576     event->setAccepted(true);
577 }
578
579 void QQuickMultiPointTouchArea::mouseMoveEvent(QMouseEvent *event)
580 {
581     if (!isEnabled()) {
582         QQuickItem::mouseMoveEvent(event);
583         return;
584     }
585
586     //do nothing
587 }
588
589 void QQuickMultiPointTouchArea::mouseReleaseEvent(QMouseEvent *event)
590 {
591     _stealMouse = false;
592     if (!isEnabled()) {
593         QQuickItem::mouseReleaseEvent(event);
594         return;
595     }
596     QQuickWindow *c = window();
597     if (c && c->mouseGrabberItem() == this)
598         ungrabMouse();
599     setKeepMouseGrab(false);
600 }
601
602 void QQuickMultiPointTouchArea::ungrab()
603 {
604     if (_touchPoints.count()) {
605         QQuickWindow *c = window();
606         if (c && c->mouseGrabberItem() == this) {
607             _stealMouse = false;
608             setKeepMouseGrab(false);
609         }
610         setKeepTouchGrab(false);
611         foreach (QObject *obj, _touchPoints)
612             static_cast<QQuickTouchPoint*>(obj)->setPressed(false);
613         emit canceled(_touchPoints.values());
614         clearTouchLists();
615         foreach (QObject *obj, _touchPoints) {
616             QQuickTouchPoint *dtp = static_cast<QQuickTouchPoint*>(obj);
617             if (!dtp->isQmlDefined())
618                 delete dtp;
619             else
620                 dtp->setInUse(false);
621         }
622         _touchPoints.clear();
623         emit touchUpdated(QList<QObject*>());
624     }
625 }
626
627 void QQuickMultiPointTouchArea::mouseUngrabEvent()
628 {
629     ungrab();
630 }
631
632 void QQuickMultiPointTouchArea::touchUngrabEvent()
633 {
634     ungrab();
635 }
636
637 bool QQuickMultiPointTouchArea::sendMouseEvent(QMouseEvent *event)
638 {
639     QPointF localPos = mapFromScene(event->windowPos());
640
641     QQuickWindow *c = window();
642     QQuickItem *grabber = c ? c->mouseGrabberItem() : 0;
643     bool stealThisEvent = _stealMouse;
644     if ((stealThisEvent || contains(localPos)) && (!grabber || !grabber->keepMouseGrab())) {
645         QMouseEvent mouseEvent(event->type(), localPos, event->windowPos(), event->screenPos(),
646                                event->button(), event->buttons(), event->modifiers());
647         mouseEvent.setAccepted(false);
648
649         switch (mouseEvent.type()) {
650         case QEvent::MouseMove:
651             mouseMoveEvent(&mouseEvent);
652             break;
653         case QEvent::MouseButtonPress:
654             mousePressEvent(&mouseEvent);
655             break;
656         case QEvent::MouseButtonRelease:
657             mouseReleaseEvent(&mouseEvent);
658             break;
659         default:
660             break;
661         }
662         grabber = c->mouseGrabberItem();
663         if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this)
664             grabMouse();
665
666         return stealThisEvent;
667     }
668     if (event->type() == QEvent::MouseButtonRelease) {
669         _stealMouse = false;
670         if (c && c->mouseGrabberItem() == this)
671             ungrabMouse();
672         setKeepMouseGrab(false);
673     }
674     return false;
675 }
676
677 bool QQuickMultiPointTouchArea::childMouseEventFilter(QQuickItem *i, QEvent *event)
678 {
679     if (!isEnabled() || !isVisible())
680         return QQuickItem::childMouseEventFilter(i, event);
681     switch (event->type()) {
682     case QEvent::MouseButtonPress:
683     case QEvent::MouseMove:
684     case QEvent::MouseButtonRelease:
685         return sendMouseEvent(static_cast<QMouseEvent *>(event));
686         break;
687     case QEvent::TouchBegin:
688     case QEvent::TouchUpdate:
689         if (!shouldFilter(event))
690             return false;
691         updateTouchData(event);
692         return _stealMouse;
693     case QEvent::TouchEnd: {
694             if (!shouldFilter(event))
695                 return false;
696             updateTouchData(event);
697             //TODO: verify this behavior
698             _stealMouse = false;
699             setKeepMouseGrab(false);
700             setKeepTouchGrab(false);
701             ungrabTouchPoints();
702         }
703         break;
704     default:
705         break;
706     }
707     return QQuickItem::childMouseEventFilter(i, event);
708 }
709
710 bool QQuickMultiPointTouchArea::shouldFilter(QEvent *event)
711 {
712     QQuickWindow *c = window();
713     QQuickItem *grabber = c ? c->mouseGrabberItem() : 0;
714     bool disabledItem = grabber && !grabber->isEnabled();
715     bool stealThisEvent = _stealMouse;
716     bool containsPoint = false;
717     if (!stealThisEvent) {
718         switch (event->type()) {
719         case QEvent::MouseButtonPress:
720         case QEvent::MouseMove:
721         case QEvent::MouseButtonRelease: {
722                 QMouseEvent *me = static_cast<QMouseEvent*>(event);
723                 containsPoint = contains(mapFromScene(me->windowPos()));
724             }
725             break;
726         case QEvent::TouchBegin:
727         case QEvent::TouchUpdate:
728         case QEvent::TouchEnd: {
729                 QTouchEvent *te = static_cast<QTouchEvent*>(event);
730                 foreach (const QTouchEvent::TouchPoint &point, te->touchPoints()) {
731                     if (contains(mapFromScene(point.scenePos()))) {
732                         containsPoint = true;
733                         break;
734                     }
735                 }
736             }
737             break;
738         default:
739             break;
740         }
741     }
742     if ((stealThisEvent || containsPoint) && (!grabber || !grabber->keepMouseGrab() || disabledItem)) {
743         return true;
744     }
745     ungrab();
746     return false;
747 }
748
749 QSGNode *QQuickMultiPointTouchArea::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
750 {
751     Q_UNUSED(data);
752
753     if (!qmlVisualTouchDebugging())
754         return 0;
755
756     QSGRectangleNode *rectangle = static_cast<QSGRectangleNode *>(oldNode);
757     if (!rectangle) rectangle = QQuickItemPrivate::get(this)->sceneGraphContext()->createRectangleNode();
758
759     rectangle->setRect(QRectF(0, 0, width(), height()));
760     rectangle->setColor(QColor(255, 0, 0, 50));
761     rectangle->update();
762     return rectangle;
763 }
764
765 QT_END_NAMESPACE