From c1ead32a84db96fd1b48e47d81511adf64cfe410 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Mon, 23 Apr 2018 11:39:56 +0200 Subject: Fix crash in QMacPanGestureRecognizer The reason it crashed was this: 1. Button was pressed => _panTimer started with the graphics view as destination. 2. Button was released => the graphicsview is destroyed 3. 300 ms later: Qt tries to deliver TimerEvent from _panTimer to the graphics view. Unfortunately, the graphics view is deleted, but Qt doesn't know that... (*crash*) We therefore chose to start the timer with a destination we are controlling the lifetime of: the QMacPanGestureRecognizer. Inside the timerEvent of that we can check if the actual target is already destroyed. Task-number: QTBUG-60404 Change-Id: Iff8f5b7217de42c4c5cf551ca507f0cff1c99a78 Reviewed-by: Frederik Gladhorn --- src/widgets/kernel/qmacgesturerecognizer.cpp | 15 +++++++++++++-- src/widgets/kernel/qmacgesturerecognizer_p.h | 4 ++++ 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'src/widgets/kernel') diff --git a/src/widgets/kernel/qmacgesturerecognizer.cpp b/src/widgets/kernel/qmacgesturerecognizer.cpp index 6dedd3c2d0..d39b93e320 100644 --- a/src/widgets/kernel/qmacgesturerecognizer.cpp +++ b/src/widgets/kernel/qmacgesturerecognizer.cpp @@ -43,6 +43,7 @@ #include "qevent.h" #include "qwidget.h" #include "qdebug.h" +#include #ifndef QT_NO_GESTURES @@ -181,6 +182,16 @@ QGesture *QMacPanGestureRecognizer::create(QObject *target) return 0; } +void QMacPanGestureRecognizer::timerEvent(QTimerEvent *ev) +{ + if (ev->timerId() == _panTimer.timerId()) { + if (_panTimer.isActive()) + _panTimer.stop(); + if (_target) + QCoreApplication::sendEvent(_target, ev); + } +} + QGestureRecognizer::Result QMacPanGestureRecognizer::recognize(QGesture *gesture, QObject *target, QEvent *event) { @@ -195,7 +206,8 @@ QMacPanGestureRecognizer::recognize(QGesture *gesture, QObject *target, QEvent * if (ev->touchPoints().size() == 1) { reset(gesture); _startPos = QCursor::pos(); - _panTimer.start(panBeginDelay, target); + _target = target; + _panTimer.start(panBeginDelay, this); _panCanceled = false; return QGestureRecognizer::MayBeGesture; } @@ -242,7 +254,6 @@ QMacPanGestureRecognizer::recognize(QGesture *gesture, QObject *target, QEvent * case QEvent::Timer: { QTimerEvent *ev = static_cast(event); if (ev->timerId() == _panTimer.timerId()) { - _panTimer.stop(); if (_panCanceled) break; // Begin new pan session! diff --git a/src/widgets/kernel/qmacgesturerecognizer_p.h b/src/widgets/kernel/qmacgesturerecognizer_p.h index be3f3266ac..e381a6cc2f 100644 --- a/src/widgets/kernel/qmacgesturerecognizer_p.h +++ b/src/widgets/kernel/qmacgesturerecognizer_p.h @@ -55,6 +55,7 @@ #include "qtimer.h" #include "qpoint.h" #include "qgesturerecognizer.h" +#include #ifndef QT_NO_GESTURES @@ -88,10 +89,13 @@ public: QGesture *create(QObject *target); QGestureRecognizer::Result recognize(QGesture *gesture, QObject *watched, QEvent *event); void reset(QGesture *gesture); +protected: + void timerEvent(QTimerEvent *ev) override; private: QPointF _startPos; QBasicTimer _panTimer; bool _panCanceled; + QPointer _target; }; QT_END_NAMESPACE -- cgit v1.2.3