aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Arve Saether <jan-arve.saether@qt.io>2017-11-06 14:20:59 +0100
committerShawn Rutledge <shawn.rutledge@qt.io>2017-11-07 05:03:01 +0000
commit75cc5fdc219c42ae26ec8497647eda5440c324f2 (patch)
tree8a4cb5a57afabe36ddb6fff23792ce3951ddcd21
parent37d25a5112cdf13620715c03d6bdbd1bc3cde515 (diff)
Never create pointer events from mouseGrabberItem()
Normally, this was not a problem, but it is problematic during QQuickWindow destruction: The list of pointer event instances are destroyed, but later the grabber is removed (through call to removeGrabber()). This queries the mouseGrabberItem(), which would create a new pointer event instance. It also has the benefit that d->pointerEventInstances are now only populated due to actual incoming events. Task-number: QTBUG-61434 Change-Id: I4e7b6f5643f3b971138a1f7c7237ee734d29783c Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
-rw-r--r--src/quick/items/qquickwindow.cpp38
-rw-r--r--src/quick/items/qquickwindow_p.h1
2 files changed, 24 insertions, 15 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index b58caa061a..112a338920 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -823,12 +823,13 @@ void QQuickWindowPrivate::removeGrabber(QQuickItem *grabber, bool mouse, bool to
if (Q_LIKELY(touch)) {
const auto touchDevices = QQuickPointerDevice::touchDevices();
for (auto device : touchDevices) {
- auto pointerEvent = pointerEventInstance(device);
- for (int i = 0; i < pointerEvent->pointCount(); ++i) {
- if (pointerEvent->point(i)->grabber() == grabber) {
- pointerEvent->point(i)->setGrabber(nullptr);
- // FIXME send ungrab event only once
- grabber->touchUngrabEvent();
+ if (auto pointerEvent = queryPointerEventInstance(device)) {
+ for (int i = 0; i < pointerEvent->pointCount(); ++i) {
+ if (pointerEvent->point(i)->grabber() == grabber) {
+ pointerEvent->point(i)->setGrabber(nullptr);
+ // FIXME send ungrab event only once
+ grabber->touchUngrabEvent();
+ }
}
}
}
@@ -1492,14 +1493,15 @@ QQuickItem *QQuickWindow::mouseGrabberItem() const
Q_D(const QQuickWindow);
if (d->touchMouseId != -1 && d->touchMouseDevice) {
- QQuickPointerEvent *event = d->pointerEventInstance(d->touchMouseDevice);
- auto point = event->pointById(d->touchMouseId);
- return point ? point->grabber() : nullptr;
+ if (QQuickPointerEvent *event = d->queryPointerEventInstance(d->touchMouseDevice)) {
+ auto point = event->pointById(d->touchMouseId);
+ return point ? point->grabber() : nullptr;
+ }
+ } else if (QQuickPointerEvent *event = d->queryPointerEventInstance(QQuickPointerDevice::genericMouseDevice())) {
+ Q_ASSERT(event->pointCount());
+ return event->point(0)->grabber();
}
-
- QQuickPointerEvent *event = d->pointerEventInstance(QQuickPointerDevice::genericMouseDevice());
- Q_ASSERT(event->pointCount());
- return event->point(0)->grabber();
+ return nullptr;
}
@@ -2111,15 +2113,21 @@ void QQuickWindowPrivate::flushFrameSynchronousEvents()
}
}
-QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QQuickPointerDevice *device) const
+QQuickPointerEvent *QQuickWindowPrivate::queryPointerEventInstance(QQuickPointerDevice *device) const
{
// the list of devices should be very small so a linear search should be ok
for (QQuickPointerEvent *e: pointerEventInstances) {
if (e->device() == device)
return e;
}
+ return nullptr;
+}
- QQuickPointerEvent *ev = nullptr;
+QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QQuickPointerDevice *device) const
+{
+ QQuickPointerEvent *ev = queryPointerEventInstance(device);
+ if (ev)
+ return ev;
QQuickWindow *q = const_cast<QQuickWindow*>(q_func());
switch (device->type()) {
case QQuickPointerDevice::Mouse:
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index b3ff5a2b35..e47dde6464 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -164,6 +164,7 @@ public:
// the device-specific event instances which are reused during event delivery
mutable QVector<QQuickPointerEvent *> pointerEventInstances;
+ QQuickPointerEvent *queryPointerEventInstance(QQuickPointerDevice *device) const;
QQuickPointerEvent *pointerEventInstance(QQuickPointerDevice *device) const;
// delivery of pointer events: