Changeset View
Changeset View
Standalone View
Standalone View
libkwineffects/kwinanimationeffect.cpp
Show All 38 Lines | |||||
39 | class AnimationEffectPrivate { | 39 | class AnimationEffectPrivate { | ||
40 | public: | 40 | public: | ||
41 | AnimationEffectPrivate() | 41 | AnimationEffectPrivate() | ||
42 | { | 42 | { | ||
43 | m_animated = m_damageDirty = m_animationsTouched = m_isInitialized = false; | 43 | m_animated = m_damageDirty = m_animationsTouched = m_isInitialized = false; | ||
44 | m_justEndedAnimation = 0; | 44 | m_justEndedAnimation = 0; | ||
45 | } | 45 | } | ||
46 | AnimationEffect::AniMap m_animations; | 46 | AnimationEffect::AniMap m_animations; | ||
47 | EffectWindowList m_zombies; | | |||
48 | static quint64 m_animCounter; | 47 | static quint64 m_animCounter; | ||
49 | quint64 m_justEndedAnimation; // protect against cancel | 48 | quint64 m_justEndedAnimation; // protect against cancel | ||
50 | QWeakPointer<FullScreenEffectLock> m_fullScreenEffectLock; | 49 | QWeakPointer<FullScreenEffectLock> m_fullScreenEffectLock; | ||
51 | bool m_animated, m_damageDirty, m_needSceneRepaint, m_animationsTouched, m_isInitialized; | 50 | bool m_animated, m_damageDirty, m_needSceneRepaint, m_animationsTouched, m_isInitialized; | ||
52 | }; | 51 | }; | ||
53 | } | 52 | } | ||
54 | 53 | | |||
55 | using namespace KWin; | 54 | using namespace KWin; | ||
▲ Show 20 Lines • Show All 156 Lines • ▼ Show 20 Line(s) | 210 | if (from && !from->isValid()) { | |||
212 | from->set(0.0); | 211 | from->set(0.0); | ||
213 | } | 212 | } | ||
214 | if (to && !to->isValid()) { | 213 | if (to && !to->isValid()) { | ||
215 | to->set(1.0); | 214 | to->set(1.0); | ||
216 | } | 215 | } | ||
217 | } | 216 | } | ||
218 | } | 217 | } | ||
219 | 218 | | |||
220 | quint64 AnimationEffect::p_animate( EffectWindow *w, Attribute a, uint meta, int ms, FPx2 to, QEasingCurve curve, int delay, FPx2 from, bool keepAtTarget, bool fullScreenEffect) | 219 | quint64 AnimationEffect::p_animate( EffectWindow *w, Attribute a, uint meta, int ms, FPx2 to, QEasingCurve curve, int delay, FPx2 from, bool keepAtTarget, bool fullScreenEffect, bool keepAlive) | ||
221 | { | 220 | { | ||
222 | const bool waitAtSource = from.isValid(); | 221 | const bool waitAtSource = from.isValid(); | ||
223 | validate(a, meta, &from, &to, w); | 222 | validate(a, meta, &from, &to, w); | ||
224 | if (a == CrossFadePrevious) | 223 | if (a == CrossFadePrevious) | ||
225 | w->referencePreviousWindowPixmap(); | 224 | w->referencePreviousWindowPixmap(); | ||
226 | 225 | | |||
227 | Q_D(AnimationEffect); | 226 | Q_D(AnimationEffect); | ||
228 | if (!d->m_isInitialized) | 227 | if (!d->m_isInitialized) | ||
Show All 14 Lines | |||||
243 | if (fullScreenEffect) { | 242 | if (fullScreenEffect) { | ||
244 | if (d->m_fullScreenEffectLock.isNull()) { | 243 | if (d->m_fullScreenEffectLock.isNull()) { | ||
245 | fullscreen = FullScreenEffectLockPtr::create(this); | 244 | fullscreen = FullScreenEffectLockPtr::create(this); | ||
246 | d->m_fullScreenEffectLock = fullscreen.toWeakRef(); | 245 | d->m_fullScreenEffectLock = fullscreen.toWeakRef(); | ||
247 | } else { | 246 | } else { | ||
248 | fullscreen = d->m_fullScreenEffectLock.toStrongRef(); | 247 | fullscreen = d->m_fullScreenEffectLock.toStrongRef(); | ||
249 | } | 248 | } | ||
250 | } | 249 | } | ||
251 | it->first.append(AniData(a, meta, ms, to, curve, delay, from, waitAtSource, keepAtTarget, fullscreen)); | 250 | it->first.append(AniData(a, meta, ms, to, curve, delay, from, waitAtSource, keepAtTarget, fullscreen, keepAlive)); | ||
252 | quint64 ret_id = ++d->m_animCounter; | 251 | quint64 ret_id = ++d->m_animCounter; | ||
253 | it->first.last().id = ret_id; | 252 | it->first.last().id = ret_id; | ||
254 | it->second = QRect(); | 253 | it->second = QRect(); | ||
255 | 254 | | |||
256 | d->m_animationsTouched = true; | 255 | d->m_animationsTouched = true; | ||
257 | 256 | | |||
258 | if (delay > 0) { | 257 | if (delay > 0) { | ||
259 | QTimer::singleShot(delay, this, SLOT(triggerRepaint())); | 258 | QTimer::singleShot(delay, this, SLOT(triggerRepaint())); | ||
Show All 32 Lines | |||||
292 | { | 291 | { | ||
293 | Q_D(AnimationEffect); | 292 | Q_D(AnimationEffect); | ||
294 | if (animationId == d->m_justEndedAnimation) | 293 | if (animationId == d->m_justEndedAnimation) | ||
295 | return true; // this is just ending, do not try to cancel it but fake success | 294 | return true; // this is just ending, do not try to cancel it but fake success | ||
296 | for (AniMap::iterator entry = d->m_animations.begin(), mapEnd = d->m_animations.end(); entry != mapEnd; ++entry) { | 295 | for (AniMap::iterator entry = d->m_animations.begin(), mapEnd = d->m_animations.end(); entry != mapEnd; ++entry) { | ||
297 | for (QList<AniData>::iterator anim = entry->first.begin(), animEnd = entry->first.end(); anim != animEnd; ++anim) { | 296 | for (QList<AniData>::iterator anim = entry->first.begin(), animEnd = entry->first.end(); anim != animEnd; ++anim) { | ||
298 | if (anim->id == animationId) { | 297 | if (anim->id == animationId) { | ||
299 | entry->first.erase(anim); // remove the animation | 298 | entry->first.erase(anim); // remove the animation | ||
300 | if (entry->first.isEmpty()) { // no other animations on the window, release it. | 299 | if (entry->first.isEmpty()) { // no other animations on the window, release it. | ||
davidedmundson: If I have two animations active and only one is keep alive, if I cancel the keep alive one… | |||||
Yes, we should unref window. I was thinking about implementing something similar to FullScreenEffectLock, e.g. class KeepAliveLock { public: KeepAliveLock(EffectWindow *w) { w->refWindow(); } ~KeepAliveLock() { w->unrefWindow(); } ... }; zzag: Yes, we should unref window. I was thinking about implementing something similar to… | |||||
Should allow us to remove m_zombies, that'll clean things up. Lets do it. davidedmundson: Should allow us to remove m_zombies, that'll clean things up. Lets do it. | |||||
301 | const int i = d->m_zombies.indexOf(entry.key()); | | |||
302 | if ( i > -1 ) { | | |||
303 | d->m_zombies.removeAt( i ); | | |||
304 | entry.key()->unrefWindow(); | | |||
305 | } | | |||
306 | d->m_animations.erase(entry); | 300 | d->m_animations.erase(entry); | ||
307 | } | 301 | } | ||
308 | if (d->m_animations.isEmpty()) | 302 | if (d->m_animations.isEmpty()) | ||
309 | disconnectGeometryChanges(); | 303 | disconnectGeometryChanges(); | ||
310 | d->m_animationsTouched = true; // could be called from animationEnded | 304 | d->m_animationsTouched = true; // could be called from animationEnded | ||
311 | return true; | 305 | return true; | ||
312 | } | 306 | } | ||
313 | } | 307 | } | ||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Line(s) | 366 | for (int i = 0; i < animCounter; ++i) | |||
373 | ++anim; | 367 | ++anim; | ||
374 | } | 368 | } | ||
375 | anim = entry->first.erase(anim); | 369 | anim = entry->first.erase(anim); | ||
376 | invalidateLayerRect = d->m_damageDirty = true; | 370 | invalidateLayerRect = d->m_damageDirty = true; | ||
377 | animEnd = entry->first.end(); | 371 | animEnd = entry->first.end(); | ||
378 | } | 372 | } | ||
379 | } | 373 | } | ||
380 | if (entry->first.isEmpty()) { | 374 | if (entry->first.isEmpty()) { | ||
381 | const int i = d->m_zombies.indexOf(entry.key()); | | |||
382 | if ( i > -1 ) { | | |||
383 | d->m_zombies.removeAt( i ); | | |||
384 | entry.key()->unrefWindow(); | | |||
385 | } | | |||
386 | data.paint |= entry->second; | 375 | data.paint |= entry->second; | ||
387 | // d->m_damageDirty = true; // TODO likely no longer required | 376 | // d->m_damageDirty = true; // TODO likely no longer required | ||
388 | entry = d->m_animations.erase(entry); | 377 | entry = d->m_animations.erase(entry); | ||
389 | mapEnd = d->m_animations.end(); | 378 | mapEnd = d->m_animations.end(); | ||
390 | } else { | 379 | } else { | ||
391 | if (invalidateLayerRect) | 380 | if (invalidateLayerRect) | ||
392 | *const_cast<QRect*>(&(entry->second)) = QRect(); // invalidate | 381 | *const_cast<QRect*>(&(entry->second)) = QRect(); // invalidate | ||
393 | ++entry; | 382 | ++entry; | ||
394 | } | 383 | } | ||
395 | } | 384 | } | ||
396 | 385 | | |||
397 | // janitorial... | 386 | // janitorial... | ||
398 | if (d->m_animations.isEmpty()) { | 387 | if (d->m_animations.isEmpty()) { | ||
davidedmundson: and here | |||||
399 | disconnectGeometryChanges(); | 388 | disconnectGeometryChanges(); | ||
400 | if (!d->m_zombies.isEmpty()) { // this is actually not supposed to happen | | |||
401 | foreach (EffectWindow *w, d->m_zombies) | | |||
402 | w->unrefWindow(); | | |||
403 | d->m_zombies.clear(); | | |||
404 | } | | |||
405 | } | 389 | } | ||
406 | 390 | | |||
407 | effects->prePaintScreen(data, time); | 391 | effects->prePaintScreen(data, time); | ||
408 | } | 392 | } | ||
409 | 393 | | |||
410 | static int xCoord(const QRect &r, int flag) { | 394 | static int xCoord(const QRect &r, int flag) { | ||
411 | if (flag & AnimationEffect::Left) | 395 | if (flag & AnimationEffect::Left) | ||
412 | return r.x(); | 396 | return r.x(); | ||
▲ Show 20 Lines • Show All 506 Lines • ▼ Show 20 Line(s) | 900 | if (entry != d->m_animations.constEnd()) { | |||
919 | if (!entry->second.isNull()) // actually got updated, ie. is in use - ensure it get's a repaint | 903 | if (!entry->second.isNull()) // actually got updated, ie. is in use - ensure it get's a repaint | ||
920 | w->addLayerRepaint(entry->second); | 904 | w->addLayerRepaint(entry->second); | ||
921 | } | 905 | } | ||
922 | } | 906 | } | ||
923 | 907 | | |||
924 | void AnimationEffect::_windowClosed( EffectWindow* w ) | 908 | void AnimationEffect::_windowClosed( EffectWindow* w ) | ||
925 | { | 909 | { | ||
926 | Q_D(AnimationEffect); | 910 | Q_D(AnimationEffect); | ||
927 | if (d->m_animations.contains(w) && !d->m_zombies.contains(w)) { | 911 | | ||
928 | w->refWindow(); | 912 | auto it = d->m_animations.find(w); | ||
929 | d->m_zombies << w; | 913 | if (it == d->m_animations.end()) { | ||
914 | return; | ||||
915 | } | ||||
916 | | ||||
917 | KeepAliveLockPtr keepAliveLock; | ||||
918 | | ||||
919 | QList<AniData> &animations = (*it).first; | ||||
920 | for (auto animationIt = animations.begin(); | ||||
921 | animationIt != animations.end(); | ||||
922 | ++animationIt) { | ||||
923 | if (!(*animationIt).keepAlive) { | ||||
924 | continue; | ||||
925 | } | ||||
926 | | ||||
927 | if (keepAliveLock.isNull()) { | ||||
928 | keepAliveLock = KeepAliveLockPtr::create(w); | ||||
929 | } | ||||
930 | | ||||
931 | (*animationIt).keepAliveLock = keepAliveLock; | ||||
930 | } | 932 | } | ||
931 | } | 933 | } | ||
932 | 934 | | |||
933 | void AnimationEffect::_windowDeleted( EffectWindow* w ) | 935 | void AnimationEffect::_windowDeleted( EffectWindow* w ) | ||
934 | { | 936 | { | ||
935 | Q_D(AnimationEffect); | 937 | Q_D(AnimationEffect); | ||
936 | d->m_zombies.removeAll( w ); // TODO this line is a workaround for a bug in KWin 4.8.0 & 4.8.1 | | |||
937 | d->m_animations.remove( w ); | 938 | d->m_animations.remove( w ); | ||
938 | } | 939 | } | ||
939 | 940 | | |||
940 | 941 | | |||
941 | QString AnimationEffect::debug(const QString &/*parameter*/) const | 942 | QString AnimationEffect::debug(const QString &/*parameter*/) const | ||
942 | { | 943 | { | ||
943 | Q_D(const AnimationEffect); | 944 | Q_D(const AnimationEffect); | ||
944 | QString dbg; | 945 | QString dbg; | ||
Show All 24 Lines |
If I have two animations active and only one is keep alive, if I cancel the keep alive one should I unref the window?