diff --git a/libkwineffects/anidata.cpp b/libkwineffects/anidata.cpp --- a/libkwineffects/anidata.cpp +++ b/libkwineffects/anidata.cpp @@ -52,6 +52,21 @@ m_window->unrefWindow(); } +PreviousWindowPixmapLock::PreviousWindowPixmapLock(EffectWindow *w) + : m_window(w) +{ + m_window->referencePreviousWindowPixmap(); +} + +PreviousWindowPixmapLock::~PreviousWindowPixmapLock() +{ + m_window->unreferencePreviousWindowPixmap(); + + // Add synthetic repaint to prevent glitches after cross-fading + // translucent windows. + effects->addRepaint(m_window->expandedGeometry()); +} + AniData::AniData() : attribute(AnimationEffect::Opacity) , customCurve(0) // Linear @@ -67,7 +82,8 @@ AniData::AniData(AnimationEffect::Attribute a, int meta_, int ms, const FPx2 &to_, QEasingCurve curve_, int delay, const FPx2 &from_, bool waitAtSource_, bool keepAtTarget_, - FullScreenEffectLockPtr fullScreenEffectLock_, bool keepAlive) + FullScreenEffectLockPtr fullScreenEffectLock_, bool keepAlive, + PreviousWindowPixmapLockPtr previousWindowPixmapLock_) : attribute(a) , curve(curve_) , from(from_) @@ -80,6 +96,7 @@ , waitAtSource(waitAtSource_) , keepAtTarget(keepAtTarget_) , keepAlive(keepAlive) + , previousWindowPixmapLock(previousWindowPixmapLock_) { } diff --git a/libkwineffects/anidata_p.h b/libkwineffects/anidata_p.h --- a/libkwineffects/anidata_p.h +++ b/libkwineffects/anidata_p.h @@ -56,13 +56,28 @@ }; typedef QSharedPointer KeepAliveLockPtr; +/** + * References the previous window pixmap to prevent discarding. + **/ +class PreviousWindowPixmapLock +{ +public: + PreviousWindowPixmapLock(EffectWindow *w); + ~PreviousWindowPixmapLock(); + +private: + EffectWindow *m_window; + Q_DISABLE_COPY(PreviousWindowPixmapLock) +}; +typedef QSharedPointer PreviousWindowPixmapLockPtr; + class KWINEFFECTS_EXPORT AniData { public: AniData(); AniData(AnimationEffect::Attribute a, int meta, int ms, const FPx2 &to, QEasingCurve curve, int delay, const FPx2 &from, bool waitAtSource, bool keepAtTarget = false, FullScreenEffectLockPtr=FullScreenEffectLockPtr(), - bool keepAlive = true); + bool keepAlive = true, PreviousWindowPixmapLockPtr previousWindowPixmapLock = {}); inline void addTime(int t) { time += t; } inline bool isOneDimensional() const { return from[0] == from[1] && to[0] == to[1]; @@ -81,6 +96,7 @@ bool waitAtSource, keepAtTarget; bool keepAlive; KeepAliveLockPtr keepAliveLock; + PreviousWindowPixmapLockPtr previousWindowPixmapLock; }; } // namespace diff --git a/libkwineffects/kwinanimationeffect.cpp b/libkwineffects/kwinanimationeffect.cpp --- a/libkwineffects/kwinanimationeffect.cpp +++ b/libkwineffects/kwinanimationeffect.cpp @@ -220,8 +220,6 @@ { const bool waitAtSource = from.isValid(); validate(a, meta, &from, &to, w); - if (a == CrossFadePrevious) - w->referencePreviousWindowPixmap(); Q_D(AnimationEffect); if (!d->m_isInitialized) @@ -247,7 +245,27 @@ fullscreen = d->m_fullScreenEffectLock.toStrongRef(); } } - it->first.append(AniData(a, meta, ms, to, curve, delay, from, waitAtSource, keepAtTarget, fullscreen, keepAlive)); + + PreviousWindowPixmapLockPtr previousPixmap; + if (a == CrossFadePrevious) { + previousPixmap = PreviousWindowPixmapLockPtr::create(w); + } + + it->first.append(AniData( + a, // Attribute + meta, // Metadata + ms, // Duration + to, // Target + curve, // Easing curve + delay, // Delay + from, // Source + waitAtSource, // Whether the animation should be kept at source + keepAtTarget, // Whether the animation is persistent + fullscreen, // Full screen effect lock + keepAlive, // Keep alive flag + previousPixmap // Previous window pixmap lock + )); + quint64 ret_id = ++d->m_animCounter; it->first.last().id = ret_id; it->second = QRect(); @@ -344,11 +362,6 @@ ++animCounter; } else { EffectWindow *oldW = entry.key(); - AniData *aData = &(*anim); - if (aData->attribute == KWin::AnimationEffect::CrossFadePrevious) { - oldW->unreferencePreviousWindowPixmap(); - effects->addRepaint(oldW->expandedGeometry()); - } d->m_justEndedAnimation = anim->id; animationEnded(oldW, anim->attribute, anim->meta); d->m_justEndedAnimation = 0;