[libkwineffects] Gracefully release previous window pixmap

Summary:
If the cross fade animation is cancelled, we are not gracefully
unreference the previous window pixmap.

This change addresses that issue by using RAII approach to
reference/unreference the previous window pixmap.

Test Plan: Manually. The Maximize and the Morphing Popups effect still work.

Reviewers: #kwin, davidedmundson

Reviewed By: #kwin, davidedmundson

Subscribers: davidedmundson, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D16391
This commit is contained in:
Vlad Zagorodniy 2018-10-23 20:21:27 +03:00
parent 93abb9a273
commit 688d946ffb
3 changed files with 56 additions and 10 deletions

View file

@ -52,6 +52,21 @@ KeepAliveLock::~KeepAliveLock()
m_window->unrefWindow(); 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() AniData::AniData()
: attribute(AnimationEffect::Opacity) : attribute(AnimationEffect::Opacity)
, customCurve(0) // Linear , customCurve(0) // Linear
@ -67,7 +82,8 @@ AniData::AniData()
AniData::AniData(AnimationEffect::Attribute a, int meta_, int ms, const FPx2 &to_, AniData::AniData(AnimationEffect::Attribute a, int meta_, int ms, const FPx2 &to_,
QEasingCurve curve_, int delay, const FPx2 &from_, bool waitAtSource_, bool keepAtTarget_, QEasingCurve curve_, int delay, const FPx2 &from_, bool waitAtSource_, bool keepAtTarget_,
FullScreenEffectLockPtr fullScreenEffectLock_, bool keepAlive) FullScreenEffectLockPtr fullScreenEffectLock_, bool keepAlive,
PreviousWindowPixmapLockPtr previousWindowPixmapLock_)
: attribute(a) : attribute(a)
, curve(curve_) , curve(curve_)
, from(from_) , from(from_)
@ -80,6 +96,7 @@ AniData::AniData(AnimationEffect::Attribute a, int meta_, int ms, const FPx2 &to
, waitAtSource(waitAtSource_) , waitAtSource(waitAtSource_)
, keepAtTarget(keepAtTarget_) , keepAtTarget(keepAtTarget_)
, keepAlive(keepAlive) , keepAlive(keepAlive)
, previousWindowPixmapLock(previousWindowPixmapLock_)
{ {
} }

View file

@ -56,13 +56,28 @@ private:
}; };
typedef QSharedPointer<KeepAliveLock> KeepAliveLockPtr; typedef QSharedPointer<KeepAliveLock> 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<PreviousWindowPixmapLock> PreviousWindowPixmapLockPtr;
class KWINEFFECTS_EXPORT AniData { class KWINEFFECTS_EXPORT AniData {
public: public:
AniData(); AniData();
AniData(AnimationEffect::Attribute a, int meta, int ms, const FPx2 &to, AniData(AnimationEffect::Attribute a, int meta, int ms, const FPx2 &to,
QEasingCurve curve, int delay, const FPx2 &from, bool waitAtSource, QEasingCurve curve, int delay, const FPx2 &from, bool waitAtSource,
bool keepAtTarget = false, FullScreenEffectLockPtr=FullScreenEffectLockPtr(), bool keepAtTarget = false, FullScreenEffectLockPtr=FullScreenEffectLockPtr(),
bool keepAlive = true); bool keepAlive = true, PreviousWindowPixmapLockPtr previousWindowPixmapLock = {});
inline void addTime(int t) { time += t; } inline void addTime(int t) { time += t; }
inline bool isOneDimensional() const { inline bool isOneDimensional() const {
return from[0] == from[1] && to[0] == to[1]; return from[0] == from[1] && to[0] == to[1];
@ -81,6 +96,7 @@ public:
bool waitAtSource, keepAtTarget; bool waitAtSource, keepAtTarget;
bool keepAlive; bool keepAlive;
KeepAliveLockPtr keepAliveLock; KeepAliveLockPtr keepAliveLock;
PreviousWindowPixmapLockPtr previousWindowPixmapLock;
}; };
} // namespace } // namespace

View file

@ -220,8 +220,6 @@ quint64 AnimationEffect::p_animate( EffectWindow *w, Attribute a, uint meta, int
{ {
const bool waitAtSource = from.isValid(); const bool waitAtSource = from.isValid();
validate(a, meta, &from, &to, w); validate(a, meta, &from, &to, w);
if (a == CrossFadePrevious)
w->referencePreviousWindowPixmap();
Q_D(AnimationEffect); Q_D(AnimationEffect);
if (!d->m_isInitialized) if (!d->m_isInitialized)
@ -247,7 +245,27 @@ quint64 AnimationEffect::p_animate( EffectWindow *w, Attribute a, uint meta, int
fullscreen = d->m_fullScreenEffectLock.toStrongRef(); 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; quint64 ret_id = ++d->m_animCounter;
it->first.last().id = ret_id; it->first.last().id = ret_id;
it->second = QRect(); it->second = QRect();
@ -344,11 +362,6 @@ void AnimationEffect::prePaintScreen( ScreenPrePaintData& data, int time )
++animCounter; ++animCounter;
} else { } else {
EffectWindow *oldW = entry.key(); EffectWindow *oldW = entry.key();
AniData *aData = &(*anim);
if (aData->attribute == KWin::AnimationEffect::CrossFadePrevious) {
oldW->unreferencePreviousWindowPixmap();
effects->addRepaint(oldW->expandedGeometry());
}
d->m_justEndedAnimation = anim->id; d->m_justEndedAnimation = anim->id;
animationEnded(oldW, anim->attribute, anim->meta); animationEnded(oldW, anim->attribute, anim->meta);
d->m_justEndedAnimation = 0; d->m_justEndedAnimation = 0;