summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel/qapplication.cpp
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2021-08-29 23:00:48 +0200
committerShawn Rutledge <shawn.rutledge@qt.io>2021-09-06 19:41:22 +0000
commitdad1e1494128ff963b2a38870c44081f493f1e54 (patch)
tree754b0b226395ff46ae042fd5a670d63c58f29647 /src/widgets/kernel/qapplication.cpp
parent78dee15da43597126d0a8579cf5db3ec4f019ca8 (diff)
Forward touchEvents to children inside QGraphicsProxyWidget
This reapplies the fix from 1ecf2212fae176b78c9951a37df9e33eb24d4f2d, using QApplication::translateRawTouchEvent to dispatch the touch event received by the QGraphicsProxyWidget to the relevant child widgets under each touch point. In addition, limit the implicit grabbing of each touch point before sending the event to those cases where we have to: touch pads, and if the target widget comes from a closest-widget matching. And don't call the QTouchEvent override of QEvent::setAccepted() on QTouchEvent instances in QGraphicsView classes, as this will override each event point's acceptance state. This way, we can identify which touch points have been accepted after event delivery, any only implicitly grab those points that were. Otherwise, touch points not accepted by a proxied widget hierarchy will still be part of an accepted event, and be grabbed by the viewport of the QGraphicsView. This would then lead to infinite recursion when the QGraphicsProxyWidget passes the TouchUpdate event on to each touch point's grabber. Re-activate the test case, and extend it with more combinations. Refactor touch-event recording to make it easier to test multi-touch scenarios. Task-number: QTBUG-45737 Fixes: QTBUG-67819 Pick-to: 6.2 Change-Id: Id5611f4feecb43b9367d9c2c71ad863b117efbcb Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'src/widgets/kernel/qapplication.cpp')
-rw-r--r--src/widgets/kernel/qapplication.cpp24
1 files changed, 19 insertions, 5 deletions
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 4c704f3946..de450923ff 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -3911,8 +3911,13 @@ void QApplicationPrivate::activateImplicitTouchGrab(QWidget *widget, QTouchEvent
if (touchEvent->type() != QEvent::TouchBegin)
return;
- for (int i = 0; i < touchEvent->pointCount(); ++i)
- QMutableEventPoint::from(touchEvent->point(i)).setTarget(widget);
+ // If the widget dispatched the event further (see QGraphicsProxyWidget), then
+ // there might already be an implicit grabber. Don't override that.
+ for (int i = 0; i < touchEvent->pointCount(); ++i) {
+ auto &mep = QMutableEventPoint::from(touchEvent->point(i));
+ if (!mep.target() && mep.isAccepted())
+ mep.setTarget(widget);
+ }
// TODO setExclusiveGrabber() to be consistent with Qt Quick?
}
@@ -3946,16 +3951,21 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, const QTouchEv
target = window;
}
+ bool usingClosestWidget = false;
if (device->type() == QInputDevice::DeviceType::TouchScreen) {
QWidget *closestWidget = d->findClosestTouchPointTarget(device, touchPoint);
QWidget *widget = static_cast<QWidget *>(target.data());
if (closestWidget
&& (widget->isAncestorOf(closestWidget) || closestWidget->isAncestorOf(widget))) {
target = closestWidget;
+ usingClosestWidget = true;
}
}
- QMutableEventPoint::from(touchPoint).setTarget(target);
+ // on touch pads, implicitly grab all touch points
+ // on touch screens, grab touch points that are redirected to the closest widget
+ if (device->type() == QInputDevice::DeviceType::TouchPad || usingClosestWidget)
+ QMutableEventPoint::from(touchPoint).setTarget(target);
} else {
target = QMutableEventPoint::from(touchPoint).target();
if (!target)
@@ -4020,7 +4030,9 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, const QTouchEv
{
// if the TouchBegin handler recurses, we assume that means the event
// has been implicitly accepted and continue to send touch events
- if (QApplication::sendSpontaneousEvent(widget, &touchEvent) && touchEvent.isAccepted()) {
+ bool res = te->spontaneous() ? QApplication::sendSpontaneousEvent(widget, &touchEvent)
+ : QApplication::sendEvent(widget, &touchEvent);
+ if (res && touchEvent.isAccepted()) {
accepted = true;
if (!widget.isNull())
widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent);
@@ -4033,7 +4045,9 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, const QTouchEv
|| QGestureManager::gesturePending(widget)
#endif
) {
- if (QApplication::sendSpontaneousEvent(widget, &touchEvent) && touchEvent.isAccepted())
+ bool res = te->spontaneous() ? QApplication::sendSpontaneousEvent(widget, &touchEvent)
+ : QApplication::sendEvent(widget, &touchEvent);
+ if (res && touchEvent.isAccepted())
accepted = true;
// widget can be deleted on TouchEnd
if (touchEvent.type() == QEvent::TouchEnd && !widget.isNull())