From a43ffb81822d14ea8a26108b92e30620dc8be7cb Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Fri, 2 Jun 2023 14:56:19 +0300 Subject: [PATCH] Advance window animations in prePaintWindow() This will ensure that the window animation is advanced only if the window is painted. I'd like to rely on this to allow effects schedule animations as soon as Workspace::windowAdded signal is emitted. As is, the issue with delaying EffectsHandler::windowAdded is that we don't filter out all "not ready" windows, which breaks some effects because EffectWindows are leaked in some properties but no EffectsHandler::windowRemoved signal is emitted so those effects can perform cleanup. Fixing that by the means of ensuring that only renderable EffectWindows are exposed is hard too, and it would also mean that effects need to use their own api, which I would like to avoid and port the effects to kwin core apis instead. --- src/libkwineffects/kwinanimationeffect.cpp | 31 +++++----------------- src/libkwineffects/kwinanimationeffect.h | 1 - src/plugins/glide/glide.cpp | 10 +++---- src/plugins/magiclamp/magiclamp.cpp | 11 +++----- src/plugins/sheet/sheet.cpp | 10 +++---- 5 files changed, 16 insertions(+), 47 deletions(-) diff --git a/src/libkwineffects/kwinanimationeffect.cpp b/src/libkwineffects/kwinanimationeffect.cpp index ae042897a1..658bc08006 100644 --- a/src/libkwineffects/kwinanimationeffect.cpp +++ b/src/libkwineffects/kwinanimationeffect.cpp @@ -441,27 +441,6 @@ void AnimationEffect::genericAnimation(EffectWindow *w, WindowPaintData &data, f { } -void AnimationEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) -{ - Q_D(AnimationEffect); - if (d->m_animations.isEmpty()) { - effects->prePaintScreen(data, presentTime); - return; - } - - for (auto entry = d->m_animations.begin(); entry != d->m_animations.end(); ++entry) { - for (auto anim = entry->first.begin(); anim != entry->first.end(); ++anim) { - if (anim->startTime <= clock()) { - if (anim->frozenTime < 0) { - anim->timeLine.advance(presentTime); - } - } - } - } - - effects->prePaintScreen(data, presentTime); -} - static qreal xCoord(const QRectF &r, int flag) { if (flag & AnimationEffect::Left) { @@ -514,13 +493,17 @@ void AnimationEffect::disconnectGeometryChanges() void AnimationEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) { Q_D(AnimationEffect); - AniMap::const_iterator entry = d->m_animations.constFind(w); - if (entry != d->m_animations.constEnd()) { - for (QList::const_iterator anim = entry->first.constBegin(); anim != entry->first.constEnd(); ++anim) { + auto entry = d->m_animations.find(w); + if (entry != d->m_animations.end()) { + for (auto anim = entry->first.begin(); anim != entry->first.end(); ++anim) { if (anim->startTime > clock() && !anim->waitAtSource) { continue; } + if (anim->frozenTime < 0) { + anim->timeLine.advance(presentTime); + } + if (anim->attribute == Opacity || anim->attribute == CrossFadePrevious) { data.setTranslucent(); } else if (!(anim->attribute == Brightness || anim->attribute == Saturation)) { diff --git a/src/libkwineffects/kwinanimationeffect.h b/src/libkwineffects/kwinanimationeffect.h index b4280c1069..e982a65e74 100644 --- a/src/libkwineffects/kwinanimationeffect.h +++ b/src/libkwineffects/kwinanimationeffect.h @@ -322,7 +322,6 @@ public: // Reimplemented from KWin::Effect. QString debug(const QString ¶meter) const override; - void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override; void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) override; void paintWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, QRegion region, WindowPaintData &data) override; void postPaintScreen() override; diff --git a/src/plugins/glide/glide.cpp b/src/plugins/glide/glide.cpp index e4aab50214..29e936e744 100644 --- a/src/plugins/glide/glide.cpp +++ b/src/plugins/glide/glide.cpp @@ -102,12 +102,6 @@ void GlideEffect::reconfigure(ReconfigureFlags flags) void GlideEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) { - auto animationIt = m_animations.begin(); - while (animationIt != m_animations.end()) { - (*animationIt).timeLine.advance(presentTime); - ++animationIt; - } - data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; effects->prePaintScreen(data, presentTime); @@ -115,7 +109,9 @@ void GlideEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::millisec void GlideEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) { - if (m_animations.contains(w)) { + auto animationIt = m_animations.find(w); + if (animationIt != m_animations.end()) { + (*animationIt).timeLine.advance(presentTime); data.setTransformed(); } diff --git a/src/plugins/magiclamp/magiclamp.cpp b/src/plugins/magiclamp/magiclamp.cpp index 8924d07a95..4c16c31a94 100644 --- a/src/plugins/magiclamp/magiclamp.cpp +++ b/src/plugins/magiclamp/magiclamp.cpp @@ -46,12 +46,6 @@ void MagicLampEffect::reconfigure(ReconfigureFlags) void MagicLampEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) { - auto animationIt = m_animations.begin(); - while (animationIt != m_animations.end()) { - (*animationIt).timeLine.advance(presentTime); - ++animationIt; - } - // We need to mark the screen windows as transformed. Otherwise the // whole screen won't be repainted, resulting in artefacts. data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; @@ -63,8 +57,9 @@ void MagicLampEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, { // Schedule window for transformation if the animation is still in // progress - if (m_animations.contains(w)) { - // We'll transform this window + auto animationIt = m_animations.find(w); + if (animationIt != m_animations.end()) { + (*animationIt).timeLine.advance(presentTime); data.setTransformed(); } diff --git a/src/plugins/sheet/sheet.cpp b/src/plugins/sheet/sheet.cpp index 7a30d36a8f..7ca77645b2 100644 --- a/src/plugins/sheet/sheet.cpp +++ b/src/plugins/sheet/sheet.cpp @@ -74,12 +74,6 @@ void SheetEffect::reconfigure(ReconfigureFlags flags) void SheetEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) { - auto animationIt = m_animations.begin(); - while (animationIt != m_animations.end()) { - (*animationIt).timeLine.advance(presentTime); - ++animationIt; - } - data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; effects->prePaintScreen(data, presentTime); @@ -87,7 +81,9 @@ void SheetEffect::prePaintScreen(ScreenPrePaintData &data, std::chrono::millisec void SheetEffect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) { - if (m_animations.contains(w)) { + auto animationIt = m_animations.find(w); + if (animationIt != m_animations.end()) { + (*animationIt).timeLine.advance(presentTime); data.setTransformed(); }