aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--src/quick/items/qquickpincharea.cpp99
-rw-r--r--src/quick/items/qquickpincharea_p.h10
-rw-r--r--src/quick/items/qquickpincharea_p_p.h29
3 files changed, 69 insertions, 69 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());
diff --git a/src/quick/items/qquickpincharea_p.h b/src/quick/items/qquickpincharea_p.h
index b488f436df..124f0fe5d3 100644
--- a/src/quick/items/qquickpincharea_p.h
+++ b/src/quick/items/qquickpincharea_p.h
@@ -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.
@@ -300,12 +300,10 @@ protected:
bool event(QEvent *) override;
private:
- void clearPinch();
- void cancelPinch();
- void updatePinch();
+ void clearPinch(QTouchEvent *event);
+ void cancelPinch(QTouchEvent *event);
+ void updatePinch(QTouchEvent *event, bool filtering);
void updatePinchTarget();
- void handlePress();
- void handleRelease();
private:
Q_DISABLE_COPY(QQuickPinchArea)
diff --git a/src/quick/items/qquickpincharea_p_p.h b/src/quick/items/qquickpincharea_p_p.h
index 986aa53900..fdba06f070 100644
--- a/src/quick/items/qquickpincharea_p_p.h
+++ b/src/quick/items/qquickpincharea_p_p.h
@@ -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.
@@ -64,11 +64,7 @@ class QQuickPinchAreaPrivate : public QQuickItemPrivate
Q_DECLARE_PUBLIC(QQuickPinchArea)
public:
QQuickPinchAreaPrivate()
- : enabled(true), stealMouse(false), inPinch(false)
- , pinchRejected(false), pinchActivated(false), initPinch(false)
- , pinch(0), pinchStartDist(0), pinchStartScale(1.0)
- , pinchLastScale(1.0), pinchStartRotation(0.0), pinchStartAngle(0.0)
- , pinchLastAngle(0.0), pinchRotation(0.0)
+ : enabled(true), inPinch(false), pinchRejected(false), pinchActivated(false), initPinch(false)
{
}
@@ -77,34 +73,33 @@ public:
void init()
{
Q_Q(QQuickPinchArea);
- q->setAcceptedMouseButtons(Qt::LeftButton);
+ q->setAcceptTouchEvents(true);
q->setFiltersChildMouseEvents(true);
}
bool enabled : 1;
- bool stealMouse : 1;
bool inPinch : 1;
bool pinchRejected : 1;
bool pinchActivated : 1;
bool initPinch : 1;
- QQuickPinch *pinch;
+ int id1 = -1;
+ QQuickPinch *pinch = nullptr;
QPointF sceneStartPoint1;
QPointF sceneStartPoint2;
QPointF lastPoint1;
QPointF lastPoint2;
- qreal pinchStartDist;
- qreal pinchStartScale;
- qreal pinchLastScale;
- qreal pinchStartRotation;
- qreal pinchStartAngle;
- qreal pinchLastAngle;
- qreal pinchRotation;
+ qreal pinchStartDist = 0;
+ qreal pinchStartScale = 1;
+ qreal pinchLastScale = 1;
+ qreal pinchStartRotation = 0;
+ qreal pinchStartAngle = 0;
+ qreal pinchLastAngle = 0;
+ qreal pinchRotation = 0;
QPointF sceneStartCenter;
QPointF pinchStartCenter;
QPointF sceneLastCenter;
QPointF pinchStartPos;
QList<QEventPoint> touchPoints;
- int id1;
};
QT_END_NAMESPACE