summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlexander Volkov <a.volkov@rusbitech.ru>2014-09-18 13:13:21 +0400
committerShawn Rutledge <shawn.rutledge@theqtcompany.com>2016-03-05 21:49:59 +0000
commit559152d911ceff8af5020355b35d7a1da100398c (patch)
treeb522f0c3403dd961ffdf711675ad8335ffc12456 /src
parent00f1c4ac3a0bbaac6996a0192abc3240972a34b5 (diff)
Make an implicit grab on TouchBegin for a widget subscribed to a gesture
A receiver of TouchUpdate and TouchEnd events is determined either as a widget which has an implicit grab for the touch point or as a visible widget if there are no implicit grabs. The events are sent if the receiver has accepted TouchBegin event or if it is subscribed to a gesture. Before sending the events to the widget they are delivered to the gesture manager. Thus, in order to detect gestures for the widget, it must own an implicit grab or be a visible widget. It can happen that the parent widget is subscribed to a gesture, but doesn't accept TouchBegin event, as in the case of QScrollArea. Then it will not get an implicit grab and gesture detection will be impossible. Activate an implicit grab for such widgets. Also don't send TouchUpdate and TouchEnd to them, because it's against the documentation. Task-number: QTBUG-43277 Change-Id: Id767583991def6d76c48ad15eb39af822cad115d Reviewed-by: Shawn Rutledge <shawn.rutledge@theqtcompany.com>
Diffstat (limited to 'src')
-rw-r--r--src/widgets/kernel/qapplication.cpp52
-rw-r--r--src/widgets/kernel/qapplication_p.h1
2 files changed, 45 insertions, 8 deletions
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 50e5ccf938..f7d4139ed8 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -3548,6 +3548,10 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
QApplicationPrivate::giveFocusAccordingToFocusPolicy(widget, e, localPos);
}
+#ifndef QT_NO_GESTURES
+ QPointer<QWidget> gesturePendingWidget;
+#endif
+
while (widget) {
// first, try to deliver the touch event
acceptTouchEvents = widget->testAttribute(Qt::WA_AcceptTouchEvents);
@@ -3565,14 +3569,16 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
touchEvent->spont = false;
if (res && eventAccepted) {
// the first widget to accept the TouchBegin gets an implicit grab.
- for (int i = 0; i < touchEvent->touchPoints().count(); ++i) {
- const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().at(i);
- d->activeTouchPoints[QGuiApplicationPrivate::ActiveTouchPointsKey(touchEvent->device(), touchPoint.id())].target = widget;
- }
- break;
- } else if (p.isNull() || widget->isWindow() || widget->testAttribute(Qt::WA_NoMousePropagation)) {
+ d->activateImplicitTouchGrab(widget, touchEvent);
break;
}
+#ifndef QT_NO_GESTURES
+ if (gesturePendingWidget.isNull() && widget && QGestureManager::gesturePending(widget))
+ gesturePendingWidget = widget;
+#endif
+ if (p.isNull() || widget->isWindow() || widget->testAttribute(Qt::WA_NoMousePropagation))
+ break;
+
QPoint offset = widget->pos();
widget = widget->parentWidget();
touchEvent->setTarget(widget);
@@ -3586,9 +3592,27 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
}
}
+#ifndef QT_NO_GESTURES
+ if (!eventAccepted && !gesturePendingWidget.isNull()) {
+ // the first widget subscribed to a gesture gets an implicit grab
+ d->activateImplicitTouchGrab(gesturePendingWidget, touchEvent);
+ }
+#endif
+
touchEvent->setAccepted(eventAccepted);
break;
}
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ {
+ QWidget *widget = static_cast<QWidget *>(receiver);
+ // We may get here if the widget is subscribed to a gesture,
+ // but has not accepted TouchBegin. Propagate touch events
+ // only if TouchBegin has been accepted.
+ if (widget && widget->testAttribute(Qt::WA_WState_AcceptedTouchBeginEvent))
+ res = d->notify_helper(widget, e);
+ break;
+ }
case QEvent::RequestSoftwareInputPanel:
inputMethod()->show();
break;
@@ -4328,6 +4352,17 @@ QWidget *QApplicationPrivate::findClosestTouchPointTarget(QTouchDevice *device,
return static_cast<QWidget *>(closestTarget);
}
+void QApplicationPrivate::activateImplicitTouchGrab(QWidget *widget, QTouchEvent *touchEvent)
+{
+ if (touchEvent->type() != QEvent::TouchBegin)
+ return;
+
+ for (int i = 0, tc = touchEvent->touchPoints().count(); i < tc; ++i) {
+ const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().at(i);
+ activeTouchPoints[QGuiApplicationPrivate::ActiveTouchPointsKey(touchEvent->device(), touchPoint.id())].target = widget;
+ }
+}
+
bool QApplicationPrivate::translateRawTouchEvent(QWidget *window,
QTouchDevice *device,
const QList<QTouchEvent::TouchPoint> &touchPoints,
@@ -4458,10 +4493,11 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window,
|| QGestureManager::gesturePending(widget)
#endif
) {
- if (touchEvent.type() == QEvent::TouchEnd)
- widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, false);
if (QApplication::sendSpontaneousEvent(widget, &touchEvent) && touchEvent.isAccepted())
accepted = true;
+ // widget can be deleted on TouchEnd
+ if (touchEvent.type() == QEvent::TouchEnd && !widget.isNull())
+ widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent, false);
}
break;
}
diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h
index 4cce2d84e8..cb158011f0 100644
--- a/src/widgets/kernel/qapplication_p.h
+++ b/src/widgets/kernel/qapplication_p.h
@@ -282,6 +282,7 @@ public:
QWidget *findClosestTouchPointTarget(QTouchDevice *device, const QTouchEvent::TouchPoint &touchPoint);
void appendTouchPoint(const QTouchEvent::TouchPoint &touchPoint);
void removeTouchPoint(int touchPointId);
+ void activateImplicitTouchGrab(QWidget *widget, QTouchEvent *touchBeginEvent);
static bool translateRawTouchEvent(QWidget *widget,
QTouchDevice *device,
const QList<QTouchEvent::TouchPoint> &touchPoints,