summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/qquickwindow.cpp3
-rw-r--r--src/quick/util/qquickanimatorcontroller.cpp44
-rw-r--r--src/quick/util/qquickanimatorcontroller_p.h21
-rw-r--r--src/quick/util/qquickanimatorjob.cpp11
-rw-r--r--src/quick/util/qquickanimatorjob_p.h2
5 files changed, 63 insertions, 18 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 7b300c9ab6..4ec901ceb4 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -458,8 +458,7 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control)
q->setSurfaceType(windowManager ? windowManager->windowSurfaceType() : QSurface::OpenGLSurface);
q->setFormat(sg->defaultSurfaceFormat());
- animationController = new QQuickAnimatorController();
- animationController->m_window = q;
+ animationController = new QQuickAnimatorController(q);
delayedTouch = 0;
diff --git a/src/quick/util/qquickanimatorcontroller.cpp b/src/quick/util/qquickanimatorcontroller.cpp
index e009de205c..cfaa439072 100644
--- a/src/quick/util/qquickanimatorcontroller.cpp
+++ b/src/quick/util/qquickanimatorcontroller.cpp
@@ -44,10 +44,19 @@
QT_BEGIN_NAMESPACE
-QQuickAnimatorController::QQuickAnimatorController()
- : m_window(0)
+QQuickAnimatorController::QQuickAnimatorController(QQuickWindow *window)
+ : m_window(window)
, m_nodesAreInvalid(false)
{
+ m_guiEntity = new QQuickAnimatorControllerGuiThreadEntity();
+ m_guiEntity->controller = this;
+ connect(window, SIGNAL(frameSwapped()), m_guiEntity, SLOT(frameSwapped()));
+}
+
+void QQuickAnimatorControllerGuiThreadEntity::frameSwapped()
+{
+ if (!controller.isNull())
+ controller->stopProxyJobs();
}
QQuickAnimatorController::~QQuickAnimatorController()
@@ -71,6 +80,8 @@ QQuickAnimatorController::~QQuickAnimatorController()
if (!m_animatorRoots.contains(job))
delete job;
}
+
+ delete m_guiEntity;
}
static void qquickanimator_invalidate_node(QAbstractAnimationJob *job)
@@ -211,6 +222,27 @@ void QQuickAnimatorController::afterNodeSync()
}
}
+void QQuickAnimatorController::proxyWasDestroyed(QQuickAnimatorProxyJob *proxy)
+{
+ lock();
+ m_proxiesToStop.remove(proxy);
+ unlock();
+}
+
+void QQuickAnimatorController::stopProxyJobs()
+{
+ // Need to make a copy under lock and then stop while unlocked.
+ // Stopping triggers writeBack which in turn may lock, so it needs
+ // to be outside the lock. It is also safe because deletion of
+ // proxies happens on the GUI thread, where this code is also executing.
+ lock();
+ QSet<QQuickAnimatorProxyJob *> jobs = m_proxiesToStop;
+ m_proxiesToStop.clear();
+ unlock();
+ foreach (QQuickAnimatorProxyJob *p, jobs)
+ p->stop();
+}
+
void QQuickAnimatorController::animationFinished(QAbstractAnimationJob *job)
{
/* We are currently on the render thread and m_deleting is primarily
@@ -221,8 +253,10 @@ void QQuickAnimatorController::animationFinished(QAbstractAnimationJob *job)
*/
if (!m_deleting.contains(job)) {
QQuickAnimatorProxyJob *proxy = m_animatorRoots[job];
- if (proxy)
- QCoreApplication::postEvent(proxy, new QEvent(QEvent::User));
+ if (proxy) {
+ m_window->update();
+ m_proxiesToStop << proxy;
+ }
// else already gone...
}
}
@@ -254,12 +288,14 @@ void QQuickAnimatorController::startJob(QQuickAnimatorProxyJob *proxy, QAbstract
{
proxy->markJobManagedByController();
m_starting[job] = proxy;
+ m_stopping.remove(job);
requestSync();
}
void QQuickAnimatorController::stopJob(QQuickAnimatorProxyJob *proxy, QAbstractAnimationJob *job)
{
m_stopping[job] = proxy;
+ m_starting.remove(job);
requestSync();
}
diff --git a/src/quick/util/qquickanimatorcontroller_p.h b/src/quick/util/qquickanimatorcontroller_p.h
index bd44adf928..b13c174606 100644
--- a/src/quick/util/qquickanimatorcontroller_p.h
+++ b/src/quick/util/qquickanimatorcontroller_p.h
@@ -43,12 +43,14 @@
QT_BEGIN_NAMESPACE
+class QQuickAnimatorControllerGuiThreadEntity;
+
class QQuickAnimatorController : public QObject, public QAnimationJobChangeListener
{
Q_OBJECT
public:
- QQuickAnimatorController();
+ QQuickAnimatorController(QQuickWindow *window);
~QQuickAnimatorController();
void advance();
@@ -68,6 +70,9 @@ public:
void lock() { m_mutex.lock(); }
void unlock() { m_mutex.unlock(); }
+
+ void proxyWasDestroyed(QQuickAnimatorProxyJob *proxy);
+ void stopProxyJobs();
void windowNodesDestroyed();
public Q_SLOTS:
@@ -85,11 +90,25 @@ public:
QHash<QQuickItem *, QQuickTransformAnimatorJob::Helper *> m_transforms;
QSet<QQuickItem *> m_deletedSinceLastFrame;
QQuickWindow *m_window;
+ QQuickAnimatorControllerGuiThreadEntity *m_guiEntity;
+ QSet<QQuickAnimatorProxyJob *> m_proxiesToStop;
QMutex m_mutex;
bool m_nodesAreInvalid;
};
+class QQuickAnimatorControllerGuiThreadEntity : public QObject
+{
+ Q_OBJECT
+public:
+ QPointer<QQuickAnimatorController> controller;
+
+public Q_SLOTS:
+ void frameSwapped();
+};
+
+
+
QT_END_NAMESPACE
#endif // QQUICKANIMATORCONTROLLER_P_H
diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp
index fdbffd4709..f29ec49b9f 100644
--- a/src/quick/util/qquickanimatorjob.cpp
+++ b/src/quick/util/qquickanimatorjob.cpp
@@ -85,6 +85,8 @@ QQuickAnimatorProxyJob::QQuickAnimatorProxyJob(QAbstractAnimationJob *job, QObje
QQuickAnimatorProxyJob::~QQuickAnimatorProxyJob()
{
deleteJob();
+ if (m_controller)
+ m_controller->proxyWasDestroyed(this);
}
void QQuickAnimatorProxyJob::deleteJob()
@@ -179,15 +181,6 @@ void QQuickAnimatorProxyJob::startedByController()
m_internalState = State_Running;
}
-bool QQuickAnimatorProxyJob::event(QEvent *e)
-{
- if (e->type() == QEvent::User) {
- stop();
- return true;
- }
- return QObject::event(e);
-}
-
static void qquick_syncback_helper(QAbstractAnimationJob *job)
{
if (job->isRenderThreadJob()) {
diff --git a/src/quick/util/qquickanimatorjob_p.h b/src/quick/util/qquickanimatorjob_p.h
index 4bdcd6917d..d87c9072a2 100644
--- a/src/quick/util/qquickanimatorjob_p.h
+++ b/src/quick/util/qquickanimatorjob_p.h
@@ -72,8 +72,6 @@ public:
void markJobManagedByController() { m_jobManagedByController = true; }
protected:
- bool event(QEvent *);
-
void updateCurrentTime(int);
void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState);