aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickpincharea.cpp
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2020-10-28 07:51:26 +0100
committerShawn Rutledge <shawn.rutledge@qt.io>2020-10-30 12:19:53 +0100
commit7b911a65d238d68177a69feb773b3c9d803f6ef4 (patch)
treeb16a6954d72a91782992786c5296b7528da7cf45 /src/quick/items/qquickpincharea.cpp
parent0fa6091b1076bc3cc58303ff00d43efdad32b8ad (diff)
Modernize event handling in PinchArea
Worrying about the window's touchmouse is really not a relevant concern for a touch-only item; and grabs are done by grabbing the specific points that the pincharea chooses to handle, not by grabbing the touchmouse. We simply didn't have suitable API in Qt 5. Also some drive-by fixes: better packing and initialization in QQuickPinchAreaPrivate; and the stealMouse variable has only been set, not checked, for a long time, so we can remove it. Remove unimplemented handlePress() and handleRelease(). Change-Id: Ia76dc9b9974f663b13c4bb9dac32efe8ed7815c5 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/quick/items/qquickpincharea.cpp')
-rw-r--r--src/quick/items/qquickpincharea.cpp99
1 files changed, 53 insertions, 46 deletions
diff --git a/src/quick/items/qquickpincharea.cpp b/src/quick/items/qquickpincharea.cpp
index 8de9071b21..8ed92de051 100644
--- a/src/quick/items/qquickpincharea.cpp
+++ b/src/quick/items/qquickpincharea.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtSG module of the Qt Toolkit.
@@ -337,25 +337,25 @@ void QQuickPinchArea::touchEvent(QTouchEvent *event)
d->touchPoints.clear();
for (int i = 0; i < event->pointCount(); ++i) {
auto &tp = event->point(i);
- if (!(tp.state() & QEventPoint::State::Released)) {
+ if (tp.state() != QEventPoint::State::Released) {
d->touchPoints << tp;
tp.setAccepted();
}
}
- updatePinch();
+ updatePinch(event, false);
break;
case QEvent::TouchEnd:
- clearPinch();
+ clearPinch(event);
break;
case QEvent::TouchCancel:
- cancelPinch();
+ cancelPinch(event);
break;
default:
QQuickItem::touchEvent(event);
}
}
-void QQuickPinchArea::clearPinch()
+void QQuickPinchArea::clearPinch(QTouchEvent *event)
{
Q_D(QQuickPinchArea);
@@ -380,15 +380,17 @@ void QQuickPinchArea::clearPinch()
d->pinchActivated = false;
d->initPinch = false;
d->pinchRejected = false;
- d->stealMouse = false;
d->id1 = -1;
- QQuickWindow *win = window();
- if (win && win->mouseGrabberItem() == this)
- ungrabMouse();
- setKeepMouseGrab(false);
+ if (event) {
+ for (const auto &point : event->points()) {
+ if (event->exclusiveGrabber(point) == this)
+ event->setExclusiveGrabber(point, nullptr);
+ }
+ }
+ setKeepTouchGrab(false);
}
-void QQuickPinchArea::cancelPinch()
+void QQuickPinchArea::cancelPinch(QTouchEvent *event)
{
Q_D(QQuickPinchArea);
@@ -421,25 +423,29 @@ void QQuickPinchArea::cancelPinch()
d->pinchActivated = false;
d->initPinch = false;
d->pinchRejected = false;
- d->stealMouse = false;
d->id1 = -1;
- QQuickWindow *win = window();
- if (win && win->mouseGrabberItem() == this)
- ungrabMouse();
- setKeepMouseGrab(false);
+ for (const auto &point : event->points()) {
+ if (event->exclusiveGrabber(point) == this)
+ event->setExclusiveGrabber(point, nullptr);
+ }
+ setKeepTouchGrab(false);
}
-void QQuickPinchArea::updatePinch()
+void QQuickPinchArea::updatePinch(QTouchEvent *event, bool filtering)
{
Q_D(QQuickPinchArea);
- QQuickWindow *win = window();
-
if (d->touchPoints.count() < 2) {
- setKeepMouseGrab(false);
- QQuickWindow *c = window();
- if (c && c->mouseGrabberItem() == this)
- ungrabMouse();
+ // A pinch gesture is not occurring, so stealing the grab is permitted.
+ setKeepTouchGrab(false);
+ // During filtering, there's no need to hold a grab for one point,
+ // because filtering happens for every event anyway.
+ // But if we receive the event via direct delivery, and give up the grab,
+ // not only will we not see any more updates, but any filtering parent
+ // (such as Flickable) will also not get a chance to filter them.
+ // Continuing to hold the grab in this case keeps tst_TouchMouse::pinchOnFlickable() working.
+ if (filtering && !d->touchPoints.isEmpty() && event->exclusiveGrabber(d->touchPoints.first()) == this)
+ event->setExclusiveGrabber(d->touchPoints.first(), nullptr);
}
if (d->touchPoints.count() == 0) {
@@ -463,7 +469,6 @@ void QQuickPinchArea::updatePinch()
}
d->initPinch = false;
d->pinchRejected = false;
- d->stealMouse = false;
return;
}
@@ -481,18 +486,13 @@ void QQuickPinchArea::updatePinch()
// 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() & QEventPoint::State::Pressed || touchPoint2.state() & QEventPoint::State::Pressed) &&
+ && (touchPoint1.state() == QEventPoint::State::Pressed || touchPoint2.state() == QEventPoint::State::Pressed) &&
bounds.contains(touchPoint1.position()) && bounds.contains(touchPoint2.position())) {
d->id1 = touchPoint1.id();
d->pinchActivated = true;
d->initPinch = true;
-
- int touchMouseId = QQuickWindowPrivate::get(win)->touchMouseId;
- if (touchPoint1.id() == touchMouseId || touchPoint2.id() == touchMouseId) {
- if (win && win->mouseGrabberItem() != this) {
- grabMouse();
- }
- }
+ event->setExclusiveGrabber(touchPoint1, this);
+ event->setExclusiveGrabber(touchPoint2, this);
}
if (d->pinchActivated && !d->pinchRejected) {
const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
@@ -550,13 +550,10 @@ void QQuickPinchArea::updatePinch()
emit pinchStarted(&pe);
if (pe.accepted()) {
d->inPinch = true;
- d->stealMouse = true;
- if (win && win->mouseGrabberItem() != this)
- grabMouse();
- setKeepMouseGrab(true);
- grabTouchPoints(QList<int>() << touchPoint1.id() << touchPoint2.id());
+ event->setExclusiveGrabber(touchPoint1, this);
+ event->setExclusiveGrabber(touchPoint2, this);
+ setKeepTouchGrab(true);
d->inPinch = true;
- d->stealMouse = true;
if (d->pinch && d->pinch->target()) {
d->pinchStartPos = pinch()->target()->position();
d->pinchStartScale = d->pinch->target()->scale();
@@ -631,28 +628,38 @@ void QQuickPinchArea::updatePinchTarget()
}
}
+/*! \internal
+ PinchArea needs to filter touch events going to its children: in case
+ one of them stops event propagation by accepting the touch event, filtering
+ is the only way PinchArea can see the touch event.
+
+ This method is called childMouseEventFilter instead of childPointerEventFilter
+ for historical reasons, but actually filters all pointer events (and the
+ occasional QEvent::UngrabMouse).
+*/
bool QQuickPinchArea::childMouseEventFilter(QQuickItem *i, QEvent *e)
{
Q_D(QQuickPinchArea);
if (!d->enabled || !isVisible())
return QQuickItem::childMouseEventFilter(i, e);
+ auto *te = static_cast<QTouchEvent*>(e);
switch (e->type()) {
case QEvent::TouchBegin:
- clearPinch();
+ clearPinch(te);
Q_FALLTHROUGH();
case QEvent::TouchUpdate: {
- const auto &points = static_cast<QTouchEvent*>(e)->points();
+ const auto &points = te->points();
d->touchPoints.clear();
for (auto &tp : points) {
- if (!(tp.state() & QEventPoint::State::Released))
+ if (tp.state() != QEventPoint::State::Released)
d->touchPoints << tp;
}
- updatePinch();
+ updatePinch(te, true);
}
e->setAccepted(d->inPinch);
return d->inPinch;
case QEvent::TouchEnd:
- clearPinch();
+ clearPinch(te);
break;
default:
break;
@@ -683,7 +690,7 @@ bool QQuickPinchArea::event(QEvent *event)
QNativeGestureEvent *gesture = static_cast<QNativeGestureEvent *>(event);
switch (gesture->gestureType()) {
case Qt::BeginNativeGesture:
- clearPinch(); // probably not necessary; JIC
+ clearPinch(nullptr); // probably not necessary; JIC
d->pinchStartCenter = gesture->position();
d->pinchStartAngle = 0.0;
d->pinchStartRotation = 0.0;
@@ -703,7 +710,7 @@ bool QQuickPinchArea::event(QEvent *event)
}
break;
case Qt::EndNativeGesture:
- clearPinch();
+ clearPinch(nullptr);
break;
case Qt::ZoomNativeGesture: {
qreal scale = d->pinchLastScale * (1.0 + gesture->value());