aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickpincharea.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/items/qquickpincharea.cpp')
-rw-r--r--src/quick/items/qquickpincharea.cpp138
1 files changed, 41 insertions, 97 deletions
diff --git a/src/quick/items/qquickpincharea.cpp b/src/quick/items/qquickpincharea.cpp
index 8c1c7bd096..f58990485e 100644
--- a/src/quick/items/qquickpincharea.cpp
+++ b/src/quick/items/qquickpincharea.cpp
@@ -247,6 +247,8 @@ QQuickPinchArea::QQuickPinchArea(QQuickItem *parent)
{
Q_D(QQuickPinchArea);
d->init();
+ setAcceptedMouseButtons(Qt::LeftButton);
+ setFiltersChildMouseEvents(true);
}
QQuickPinchArea::~QQuickPinchArea()
@@ -281,6 +283,20 @@ void QQuickPinchArea::touchEvent(QTouchEvent *event)
return;
}
+ // A common non-trivial starting scenario is the user puts down one finger,
+ // then that finger remains stationary while putting down a second one.
+ // However QQuickCanvas will not send TouchUpdates for TouchPoints which
+ // were not initially accepted; that would be inefficient and noisy.
+ // So even if there is only one touchpoint so far, it's important to accept it
+ // in order to get updates later on (and it's accepted by default anyway).
+ // If the user puts down one finger, we're waiting for the other finger to drop.
+ // Therefore updatePinch() must do the right thing for any combination of
+ // points and states that may occur, and there is no reason to ignore any event.
+ // One consequence though is that if PinchArea is on top of something else,
+ // it's always going to accept the touches, and that means the item underneath
+ // will not get them (unless the PA's parent is doing parent filtering,
+ // as the Flickable does, for example).
+
switch (event->type()) {
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
@@ -329,17 +345,27 @@ void QQuickPinchArea::updatePinch()
setKeepMouseGrab(false);
return;
}
+
+ if (d->touchPoints.count() == 1) {
+ setKeepMouseGrab(false);
+ }
+
QTouchEvent::TouchPoint touchPoint1 = d->touchPoints.at(0);
QTouchEvent::TouchPoint touchPoint2 = d->touchPoints.at(d->touchPoints. count() >= 2 ? 1 : 0);
+ QRectF bounds = clipRect();
+ // Pinch is not started unless there are exactly two touch points
+ // AND one or more of the points has just now been pressed (wasn't pressed already)
+ // AND both points are inside the bounds.
if (d->touchPoints.count() == 2
- && (touchPoint1.state() & Qt::TouchPointPressed || touchPoint2.state() & Qt::TouchPointPressed)) {
+ && (touchPoint1.state() & Qt::TouchPointPressed || touchPoint2.state() & Qt::TouchPointPressed) &&
+ bounds.contains(touchPoint1.pos()) && bounds.contains(touchPoint2.pos())) {
d->id1 = touchPoint1.id();
d->sceneStartPoint1 = touchPoint1.scenePos();
d->sceneStartPoint2 = touchPoint2.scenePos();
d->pinchActivated = true;
d->initPinch = true;
}
- if (d->pinchActivated && !d->pinchRejected){
+ if (d->pinchActivated && !d->pinchRejected) {
const int dragThreshold = qApp->styleHints()->startDragDistance();
QPointF p1 = touchPoint1.scenePos();
QPointF p2 = touchPoint2.scenePos();
@@ -361,10 +387,10 @@ void QQuickPinchArea::updatePinch()
angle -= 360;
if (!d->inPinch || d->initPinch) {
if (d->touchPoints.count() >= 2
- && (qAbs(p1.x()-d->sceneStartPoint1.x()) > dragThreshold
- || qAbs(p1.y()-d->sceneStartPoint1.y()) > dragThreshold
- || qAbs(p2.x()-d->sceneStartPoint2.x()) > dragThreshold
- || qAbs(p2.y()-d->sceneStartPoint2.y()) > dragThreshold)) {
+ && (qAbs(p1.x()-d->sceneStartPoint1.x()) >= dragThreshold
+ || qAbs(p1.y()-d->sceneStartPoint1.y()) >= dragThreshold
+ || qAbs(p2.x()-d->sceneStartPoint2.x()) >= dragThreshold
+ || qAbs(p2.y()-d->sceneStartPoint2.y()) >= dragThreshold)) {
d->initPinch = false;
d->sceneStartCenter = sceneCenter;
d->sceneLastCenter = sceneCenter;
@@ -461,106 +487,24 @@ void QQuickPinchArea::updatePinch()
}
}
-void QQuickPinchArea::mousePressEvent(QMouseEvent *event)
-{
- Q_D(QQuickPinchArea);
- d->stealMouse = false;
- if (!d->enabled)
- QQuickItem::mousePressEvent(event);
- else {
- setKeepMouseGrab(false);
- event->setAccepted(true);
- }
-}
-
-void QQuickPinchArea::mouseMoveEvent(QMouseEvent *event)
-{
- Q_D(QQuickPinchArea);
- if (!d->enabled) {
- QQuickItem::mouseMoveEvent(event);
- return;
- }
-}
-
-void QQuickPinchArea::mouseReleaseEvent(QMouseEvent *event)
-{
- Q_D(QQuickPinchArea);
- d->stealMouse = false;
- if (!d->enabled) {
- QQuickItem::mouseReleaseEvent(event);
- } else {
- QQuickCanvas *c = canvas();
- if (c && c->mouseGrabberItem() == this)
- ungrabMouse();
- setKeepMouseGrab(false);
- }
-}
-
-void QQuickPinchArea::mouseUngrabEvent()
-{
- setKeepMouseGrab(false);
-}
-
-bool QQuickPinchArea::sendMouseEvent(QMouseEvent *event)
-{
- Q_D(QQuickPinchArea);
- QPointF localPos = mapFromScene(event->windowPos());
-
- QQuickCanvas *c = canvas();
- QQuickItem *grabber = c ? c->mouseGrabberItem() : 0;
- bool stealThisEvent = d->stealMouse;
- if ((stealThisEvent || contains(localPos)) && (!grabber || !grabber->keepMouseGrab())) {
- QMouseEvent mouseEvent(event->type(), localPos, 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) {
- d->stealMouse = false;
- if (c && c->mouseGrabberItem() == this)
- ungrabMouse();
- setKeepMouseGrab(false);
- }
- return false;
-}
-
bool QQuickPinchArea::childMouseEventFilter(QQuickItem *i, QEvent *e)
{
Q_D(QQuickPinchArea);
if (!d->enabled || !isVisible())
return QQuickItem::childMouseEventFilter(i, e);
switch (e->type()) {
- case QEvent::MouseButtonPress:
- case QEvent::MouseMove:
- case QEvent::MouseButtonRelease:
- return sendMouseEvent(static_cast<QMouseEvent *>(e));
- break;
case QEvent::TouchBegin:
case QEvent::TouchUpdate: {
QTouchEvent *touch = static_cast<QTouchEvent*>(e);
- d->touchPoints.clear();
- for (int i = 0; i < touch->touchPoints().count(); ++i)
- if (!(touch->touchPoints().at(i).state() & Qt::TouchPointReleased))
- d->touchPoints << touch->touchPoints().at(i);
- updatePinch();
+ if (touch->touchPoints().count() > 1) {
+ touchEvent(touch);
+ } else {
+ d->touchPoints.clear();
+ for (int i = 0; i < touch->touchPoints().count(); ++i)
+ if (!(touch->touchPoints().at(i).state() & Qt::TouchPointReleased))
+ d->touchPoints << touch->touchPoints().at(i);
+ updatePinch();
+ }
}
return d->inPinch;
case QEvent::TouchEnd: