Do not emit Timer.onTriggered while executing arbitrary JS code
authorGunnar Sletta <gunnar.sletta@jollamobile.com>
Fri, 30 May 2014 13:45:27 +0000 (15:45 +0200)
committerGunnar Sletta <gunnar.sletta@jollamobile.com>
Fri, 8 Aug 2014 17:51:10 +0000 (19:51 +0200)
Task-number: QTBUG-39371
Change-Id: Ibf232560918d30961bd979e14aac3ae7d2f264eb
Reviewed-by: Robin Burchell <robin+qt@viroteck.net>
Reviewed-by: Martin Jones <martin.jones@jollamobile.com>
src/qml/types/qqmltimer.cpp
src/qml/types/qqmltimer_p.h

index b9e28b8..9d50243 100644 (file)
 
 QT_BEGIN_NAMESPACE
 
-
+namespace {
+    const QEvent::Type QEvent_MaybeTick = QEvent::Type(QEvent::User + 1);
+    const QEvent::Type QEvent_Triggered = QEvent::Type(QEvent::User + 2);
+}
 
 class QQmlTimerPrivate : public QObjectPrivate, public QAnimationJobChangeListener
 {
@@ -57,10 +60,18 @@ class QQmlTimerPrivate : public QObjectPrivate, public QAnimationJobChangeListen
 public:
     QQmlTimerPrivate()
         : interval(1000), running(false), repeating(false), triggeredOnStart(false)
-        , classBegun(false), componentComplete(false), firstTick(true) {}
+        , classBegun(false), componentComplete(false), firstTick(true), awaitingTick(false) {}
 
     virtual void animationFinished(QAbstractAnimationJob *);
-    virtual void animationCurrentLoopChanged(QAbstractAnimationJob *)  { Q_Q(QQmlTimer); q->ticked(); }
+    virtual void animationCurrentLoopChanged(QAbstractAnimationJob *)  { maybeTick(); }
+
+    void maybeTick() {
+        Q_Q(QQmlTimer);
+        if (!awaitingTick) {
+            awaitingTick = true;
+            QCoreApplication::postEvent(q, new QEvent(QEvent_MaybeTick));
+        }
+    }
 
     int interval;
     QPauseAnimationJob pause;
@@ -70,6 +81,7 @@ public:
     bool classBegun : 1;
     bool componentComplete : 1;
     bool firstTick : 1;
+    bool awaitingTick : 1;
 };
 
 /*!
@@ -281,10 +293,8 @@ void QQmlTimer::update()
         d->pause.setLoopCount(d->repeating ? -1 : 1);
         d->pause.setDuration(d->interval);
         d->pause.start();
-        if (d->triggeredOnStart && d->firstTick) {
-            QCoreApplication::removePostedEvents(this, QEvent::MetaCall);
-            QMetaObject::invokeMethod(this, "ticked", Qt::QueuedConnection);
-        }
+        if (d->triggeredOnStart && d->firstTick)
+            d->maybeTick();
     }
 }
 
@@ -316,6 +326,23 @@ void QQmlTimer::ticked()
     d->firstTick = false;
 }
 
+/*!
+    \internal
+ */
+bool QQmlTimer::event(QEvent *e)
+{
+    Q_D(QQmlTimer);
+    if (e->type() == QEvent_MaybeTick) {
+        d->awaitingTick = false;
+        ticked();
+        return true;
+    } else if (e->type() == QEvent_Triggered) {
+        emit triggered();
+        return true;
+    }
+    return QObject::event(e);
+}
+
 void QQmlTimerPrivate::animationFinished(QAbstractAnimationJob *)
 {
     Q_Q(QQmlTimer);
@@ -323,7 +350,7 @@ void QQmlTimerPrivate::animationFinished(QAbstractAnimationJob *)
         return;
     running = false;
     firstTick = false;
-    emit q->triggered();
+    QCoreApplication::postEvent(q, new QEvent(QEvent_Triggered));
     emit q->runningChanged();
 }
 
index c625522..b51bb7f 100644 (file)
@@ -81,6 +81,8 @@ protected:
     void classBegin();
     void componentComplete();
 
+    bool event(QEvent *);
+
 public Q_SLOTS:
     void start();
     void stop();