From 1b7cad95c775fc4d05d68f3001bf501ffb887984 Mon Sep 17 00:00:00 2001 From: Vlad Zagorodniy Date: Wed, 31 Oct 2018 14:16:46 +0200 Subject: [PATCH] [libkwineffects] Don't enable painting for windows that are not kept alive Summary: 862bf0f153255d4e3c36d862e718f3328d683d3e introduced a regression(sorry for that): if you close a confirmation dialog(with the Scale effect and the Dialog Parent effect being enabled), the main window(s) will flicker. That flickering happens because the C++ version of the Scale effect and AnimationEffect unref deleted windows in different places. AnimationEffect unrefs deleted windows in prePaintScreen, which btw is not the best place to do that. The C++ version unrefed windows in postPaintScreen. So, when the Scale effect has finished animating the main windows, it will unref them, but windowDeleted signal won't be emitted immediately. Which means that the Dialog Parent won't be able to delete corresponding animations on its side and main windows will be painted for a single frame. This change addresses flickering by adjusting prePaintWindow in AnimationEffect so deleted windows won't be painted if none of animations keeps them alive. Test Plan: (make sure that both the scale and the dialog parent effect are enabled) * Go to System Settings > Application Style > Window Decorations; * Select a decoration that is different from the current; * Close the system settings window (don't click "Apply" button); * When a dialog is shown, click "Discard" or "Apply" button. Reviewers: #kwin, davidedmundson Reviewed By: #kwin, davidedmundson Subscribers: kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D16542 --- libkwineffects/kwinanimationeffect.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libkwineffects/kwinanimationeffect.cpp b/libkwineffects/kwinanimationeffect.cpp index 144996f227..ba5c191715 100644 --- a/libkwineffects/kwinanimationeffect.cpp +++ b/libkwineffects/kwinanimationeffect.cpp @@ -491,6 +491,7 @@ void AnimationEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, AniMap::const_iterator entry = d->m_animations.constFind( w ); if ( entry != d->m_animations.constEnd() ) { bool isUsed = false; + bool paintDeleted = false; for (QList::const_iterator anim = entry->first.constBegin(); anim != entry->first.constEnd(); ++anim) { if (anim->startTime > clock() && !anim->waitAtSource) continue; @@ -504,11 +505,13 @@ void AnimationEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, if (anim->attribute == Clip) clipWindow(w, *anim, data.quads); } + + paintDeleted |= anim->keepAlive; } if ( isUsed ) { if ( w->isMinimized() ) w->enablePainting( EffectWindow::PAINT_DISABLED_BY_MINIMIZE ); - else if ( w->isDeleted() ) + else if ( w->isDeleted() && paintDeleted ) w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DELETE ); else if ( !w->isOnCurrentDesktop() ) w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP );