[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:
parent
93abb9a273
commit
688d946ffb
3 changed files with 56 additions and 10 deletions
|
@ -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_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue