Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickanimatorcontroller.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 Gunnar Sletta <gunnar@sletta.org>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4// Qt-Security score:significant reason:default
5
7
8#include <private/qquickitem_p.h>
9#include <private/qsgrenderloop_p.h>
10
11#include <private/qanimationgroupjob_p.h>
12
13#include <QtGui/qscreen.h>
14
15#include <QtCore/qcoreapplication.h>
16
18
19QQuickAnimatorController::~QQuickAnimatorController()
20{
21}
22
23QQuickAnimatorController::QQuickAnimatorController(QQuickWindow *window)
24 : m_window(window)
25{
26}
27
28static void qquickanimator_invalidate_jobs(QAbstractAnimationJob *job)
29{
30 if (job->isRenderThreadJob()) {
31 static_cast<QQuickAnimatorJob *>(job)->invalidate();
32 } else if (job->isGroup()) {
33 for (QAbstractAnimationJob *a : *static_cast<QAnimationGroupJob *>(job)->children())
34 qquickanimator_invalidate_jobs(a);
35 }
36}
37
38void QQuickAnimatorController::windowNodesDestroyed()
39{
40 for (const QSharedPointer<QAbstractAnimationJob> &toPause : std::as_const(m_rootsPendingPause))
41 toPause->pause();
42 m_rootsPendingPause.clear();
43 for (const QSharedPointer<QAbstractAnimationJob> &toStop : std::as_const(m_rootsPendingStop)) {
44 qquickanimator_invalidate_jobs(toStop.data());
45 toStop->stop();
46 }
47 m_rootsPendingStop.clear();
48
49 // Clear animation roots and iterate over a temporary to avoid that job->stop()
50 // modifies the m_animationRoots and messes with our iteration
51 const auto roots = m_animationRoots;
52 m_animationRoots.clear();
53 for (const QSharedPointer<QAbstractAnimationJob> &job : roots) {
54 qquickanimator_invalidate_jobs(job.data());
55
56 // Stop it and add it to the list of pending start so it might get
57 // started later on.
58 job->stop();
59 m_rootsPendingStart.insert(job);
60 }
61}
62
63void QQuickAnimatorController::advance()
64{
65 bool running = false;
66 for (const QSharedPointer<QAbstractAnimationJob> &job : std::as_const(m_animationRoots)) {
67 if (job->isRunning()) {
68 running = true;
69 break;
70 }
71 }
72
73 for (QQuickAnimatorJob *job : std::as_const(m_runningAnimators))
74 job->commit();
75
76 if (running)
77 m_window->update();
78}
79
80static void qquickanimator_sync_before_start(QAbstractAnimationJob *job)
81{
82 if (job->isRenderThreadJob()) {
83 static_cast<QQuickAnimatorJob *>(job)->preSync();
84 } else if (job->isGroup()) {
85 for (QAbstractAnimationJob *a : *static_cast<QAnimationGroupJob *>(job)->children())
86 qquickanimator_sync_before_start(a);
87 }
88}
89
90void QQuickAnimatorController::beforeNodeSync()
91{
92 for (const QSharedPointer<QAbstractAnimationJob> &toPause : std::as_const(m_rootsPendingPause)) {
93 toPause->pause();
94 m_animationRoots.remove(toPause.data());
95 }
96 m_rootsPendingPause.clear();
97 for (const QSharedPointer<QAbstractAnimationJob> &toStop : std::as_const(m_rootsPendingStop)) {
98 toStop->stop();
99 m_animationRoots.remove(toStop.data());
100 }
101 m_rootsPendingStop.clear();
102
103
104 for (QQuickAnimatorJob *job : std::as_const(m_runningAnimators))
105 job->preSync();
106
107 // Start pending jobs
108 for (const QSharedPointer<QAbstractAnimationJob> &job : std::as_const(m_rootsPendingStart)) {
109 Q_ASSERT(!job->isRunning());
110
111 // We want to make sure that presync is called before
112 // updateAnimationTime is called the very first time, so before
113 // starting a tree of jobs, we go through it and call preSync on all
114 // its animators.
115 qquickanimator_sync_before_start(job.data());
116
117 // The start the job..
118 job->start();
119 m_animationRoots.insert(job.data(), job);
120 }
121 m_rootsPendingStart.clear();
122
123 // Issue an update directly on the window to force another render pass.
124 if (m_animationRoots.size())
125 m_window->update();
126}
127
128void QQuickAnimatorController::afterNodeSync()
129{
130 for (QQuickAnimatorJob *job : std::as_const(m_runningAnimators))
131 job->postSync();
132}
133
134void QQuickAnimatorController::animationFinished(QAbstractAnimationJob *job)
135{
136 m_animationRoots.remove(job);
137}
138
139void QQuickAnimatorController::animationStateChanged(QAbstractAnimationJob *job,
140 QAbstractAnimationJob::State newState,
141 QAbstractAnimationJob::State oldState)
142{
143 Q_ASSERT(job->isRenderThreadJob());
144 QQuickAnimatorJob *animator = static_cast<QQuickAnimatorJob *>(job);
145 if (newState == QAbstractAnimationJob::Running) {
146 m_runningAnimators.insert(animator);
147 } else if (oldState == QAbstractAnimationJob::Running) {
148 animator->commit();
149 m_runningAnimators.remove(animator);
150 }
151}
152
153
154void QQuickAnimatorController::requestSync()
155{
156 // Force a "sync" pass as the newly started animation needs to sync properties from GUI.
157 m_window->maybeUpdate();
158}
159
160// All this is being executed on the GUI thread while the animator controller
161// is locked.
162void QQuickAnimatorController::start_helper(QAbstractAnimationJob *job)
163{
164 if (job->isRenderThreadJob()) {
165 QQuickAnimatorJob *j = static_cast<QQuickAnimatorJob *>(job);
166 j->addAnimationChangeListener(this, QAbstractAnimationJob::StateChange);
167 j->initialize(this);
168 } else if (job->isGroup()) {
169 for (QAbstractAnimationJob *a : *static_cast<QAnimationGroupJob *>(job)->children())
170 start_helper(a);
171 }
172}
173
174// Called by the proxy when it is time to kick off an animation job
175void QQuickAnimatorController::start(const QSharedPointer<QAbstractAnimationJob> &job)
176{
177 m_rootsPendingStart.insert(job);
178 m_rootsPendingPause.remove(job);
179 m_rootsPendingStop.remove(job);
180 job->addAnimationChangeListener(this, QAbstractAnimationJob::Completion);
181 start_helper(job.data());
182 requestSync();
183}
184
185// Called by the proxy when it is time to stop an animation job.
186void QQuickAnimatorController::cancel(const QSharedPointer<QAbstractAnimationJob> &job)
187{
188 m_rootsPendingStart.remove(job);
189 m_rootsPendingPause.remove(job);
190 m_rootsPendingStop.insert(job);
191}
192
193// Called by the proxy when it is time to pause an animation job.
194void QQuickAnimatorController::pause(const QSharedPointer<QAbstractAnimationJob> &job)
195{
196 m_rootsPendingStart.remove(job);
197 m_rootsPendingStop.remove(job);
198 m_rootsPendingPause.insert(job);
199}
200
201
202QT_END_NAMESPACE
203
204#include "moc_qquickanimatorcontroller_p.cpp"
Combined button and popup list for selecting options.
static void qquickanimator_invalidate_jobs(QAbstractAnimationJob *job)
static void qquickanimator_sync_before_start(QAbstractAnimationJob *job)