[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kwin] effects/cube: [effects/cubeslide] Fix visual glitches with Blur / BackgroundContrast effect
From:       Igor Poboiko <null () kde ! org>
Date:       2018-09-14 9:39:15
Message-ID: E1g0kZH-0007fl-15 () code ! kde ! org
[Download RAW message or body]

Git commit ca1b5ea1070ccd23dd742f35d449e4a531ff7951 by Igor Poboiko.
Committed on 14/09/2018 at 09:36.
Pushed by poboiko into branch 'master'.

[effects/cubeslide] Fix visual glitches with Blur / BackgroundContrast effect

Summary:
Bugs occurred because KWin was not very happy when windows were painted during \
CubeSlideEffect::paintScreen(). Another issue is that blur, although it was supposed \
to, did not work at all (haven't found appropriate bug on bugzilla). As well as \
background contrast effect.

This patch does the following thing:

 - Adopted WindowForceBlur / WindowForceBackgroundContrast logic from SlideEffect, \
                instead of panels/stickyWindows QSets (those become useless anyway)
 - Added shouldAnimate code, which determines whether a window should be animated \
with the cube (i.e. ordinary windows) or should stick (i.e. panels or pinned windows, \
                if corresponding options are checked in the settings)
 - It paints an additional non-transformed screen, on which it paints only "sticky" \
windows. This is done because otherwise KWin would apply blur not behind the OSD, but \
                on the same place on moving cube face.
 - (in addition) switched to new Qt5 connect syntax.

Reviewers: #kwin, zzag

Differential Revision: https://phabricator.kde.org/D15175

BUG: 361516
BUG: 362360
FIXED-IN: 5.15.0

M  +87   -54   effects/cube/cubeslide.cpp
M  +10   -3    effects/cube/cubeslide.h

https://commits.kde.org/kwin/ca1b5ea1070ccd23dd742f35d449e4a531ff7951

diff --git a/effects/cube/cubeslide.cpp b/effects/cube/cubeslide.cpp
index 3d4db3151..176bd2805 100644
--- a/effects/cube/cubeslide.cpp
+++ b/effects/cube/cubeslide.cpp
@@ -33,14 +33,22 @@ namespace KWin
 {
 
 CubeSlideEffect::CubeSlideEffect()
-    : windowMoving(false)
+    : stickyPainting(false)
+    , windowMoving(false)
     , desktopChangedWhileMoving(false)
     , progressRestriction(0.0f)
 {
     initConfig<CubeSlideConfig>();
-    connect(effects, SIGNAL(desktopChanged(int,int)), this, \
                SLOT(slotDesktopChanged(int,int)));
-    connect(effects, SIGNAL(windowStepUserMovedResized(KWin::EffectWindow*,QRect)), \
                this, SLOT(slotWindowStepUserMovedResized(KWin::EffectWindow*)));
-    connect(effects, SIGNAL(windowFinishUserMovedResized(KWin::EffectWindow*)), \
this, SLOT(slotWindowFinishUserMovedResized(KWin::EffectWindow*))); +    \
connect(effects, &EffectsHandler::windowAdded, +            this, \
&CubeSlideEffect::slotWindowAdded); +    connect(effects, \
&EffectsHandler::windowDeleted, +            this, \
&CubeSlideEffect::slotWindowDeleted); +    connect(effects, \
QOverload<int,int,EffectWindow *>::of(&EffectsHandler::desktopChanged), +            \
this, &CubeSlideEffect::slotDesktopChanged); +    connect(effects, \
&EffectsHandler::windowStepUserMovedResized, +            this, \
&CubeSlideEffect::slotWindowStepUserMovedResized); +    connect(effects, \
&EffectsHandler::windowFinishUserMovedResized, +            this, \
&CubeSlideEffect::slotWindowFinishUserMovedResized);  reconfigure(ReconfigureAll);
 }
 
@@ -68,37 +76,29 @@ void CubeSlideEffect::reconfigure(ReconfigureFlags)
 
 void CubeSlideEffect::prePaintScreen(ScreenPrePaintData& data, int time)
 {
-    if (!slideRotations.empty()) {
-        data.mask |= PAINT_SCREEN_TRANSFORMED | \
Effect::PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS | PAINT_SCREEN_BACKGROUND_FIRST; +    \
if (isActive()) { +        data.mask |= PAINT_SCREEN_TRANSFORMED | \
PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS | PAINT_SCREEN_BACKGROUND_FIRST;  \
                timeLine.setCurrentTime(timeLine.currentTime() + time);
         if (windowMoving && timeLine.currentTime() > progressRestriction * \
                (qreal)timeLine.duration())
             timeLine.setCurrentTime(progressRestriction * \
                (qreal)timeLine.duration());
-        if (dontSlidePanels)
-            panels.clear();
-        stickyWindows.clear();
     }
     effects->prePaintScreen(data, time);
 }
 
 void CubeSlideEffect::paintScreen(int mask, QRegion region, ScreenPaintData& data)
 {
-    if (!slideRotations.empty()) {
+    if (isActive()) {
         glEnable(GL_CULL_FACE);
         glCullFace(GL_FRONT);
         paintSlideCube(mask, region, data);
         glCullFace(GL_BACK);
         paintSlideCube(mask, region, data);
         glDisable(GL_CULL_FACE);
-
-        if (dontSlidePanels) {
-            foreach (EffectWindow * w, panels) {
-                WindowPaintData wData(w);
-                effects->paintWindow(w, 0, infiniteRegion(), wData);
-            }
-        }
-        foreach (EffectWindow * w, stickyWindows) {
-            WindowPaintData wData(w);
-            effects->paintWindow(w, 0, infiniteRegion(), wData);
+        // Paint an extra screen with 'sticky' windows.
+        if (!staticWindows.isEmpty()) {
+            stickyPainting = true;
+            effects->paintScreen(mask, region, data);
+            stickyPainting = false;
         }
     } else
         effects->paintScreen(mask, region, data);
@@ -181,20 +181,19 @@ void CubeSlideEffect::paintSlideCube(int mask, QRegion region, \
ScreenPaintData&  
 void CubeSlideEffect::prePaintWindow(EffectWindow* w,  WindowPrePaintData& data, int \
time)  {
-    if (!slideRotations.empty() && cube_painting) {
-        QRect rect = effects->clientArea(FullArea, effects->activeScreen(), \
                painting_desktop);
-        if (dontSlidePanels && w->isDock()) {
-            w->setData(WindowForceBlurRole, QVariant(true));
-            panels.insert(w);
+    if (stickyPainting) {
+        if (staticWindows.contains(w)) {
+            w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP);
+        } else {
+            w->disablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP);
         }
-        if (!w->isManaged()) {
-            w->setData(WindowForceBlurRole, QVariant(true));
-            stickyWindows.insert(w);
-        } else if (dontSlideStickyWindows && !w->isDock() &&
-                  !w->isDesktop() && w->isOnAllDesktops()) {
-            w->setData(WindowForceBlurRole, QVariant(true));
-            stickyWindows.insert(w);
+    } else if (isActive() && cube_painting) {
+        if (staticWindows.contains(w)) {
+            w->disablePainting(EffectWindow::PAINT_DISABLED_BY_DESKTOP);
+            effects->prePaintWindow(w, data, time);
+            return;
         }
+        QRect rect = effects->clientArea(FullArea, effects->activeScreen(), \
painting_desktop);  if (w->isOnDesktop(painting_desktop)) {
             if (w->x() < rect.x()) {
                 data.quads = data.quads.splitAtX(-w->x());
@@ -246,12 +245,7 @@ void CubeSlideEffect::prePaintWindow(EffectWindow* w,  \
WindowPrePaintData& data,  
 void CubeSlideEffect::paintWindow(EffectWindow* w, int mask, QRegion region, \
WindowPaintData& data)  {
-    if (!slideRotations.empty() && cube_painting) {
-        if (dontSlidePanels && w->isDock())
-            return;
-        if (stickyWindows.contains(w))
-            return;
-
+    if (isActive() && cube_painting && !staticWindows.contains(w)) {
         // filter out quads overlapping the edges
         QRect rect = effects->clientArea(FullArea, effects->activeScreen(), \
painting_desktop);  if (w->isOnDesktop(painting_desktop)) {
@@ -351,7 +345,7 @@ void CubeSlideEffect::paintWindow(EffectWindow* w, int mask, \
QRegion region, Win  void CubeSlideEffect::postPaintScreen()
 {
     effects->postPaintScreen();
-    if (!slideRotations.empty()) {
+    if (isActive()) {
         if (timeLine.currentValue() == 1.0) {
             RotationDirection direction = slideRotations.dequeue();
             switch(direction) {
@@ -386,12 +380,11 @@ void CubeSlideEffect::postPaintScreen()
             else
                 timeLine.setCurveShape(QTimeLine::LinearCurve);
             if (slideRotations.empty()) {
-                foreach (EffectWindow * w, panels)
-                w->setData(WindowForceBlurRole, QVariant(false));
-                foreach (EffectWindow * w, stickyWindows)
-                w->setData(WindowForceBlurRole, QVariant(false));
-                stickyWindows.clear();
-                panels.clear();
+                for (EffectWindow* w : staticWindows) {
+                    w->setData(WindowForceBlurRole, QVariant());
+                    w->setData(WindowForceBackgroundContrastRole, QVariant());
+                }
+                staticWindows.clear();
                 effects->setActiveFullScreenEffect(0);
             }
         }
@@ -399,8 +392,9 @@ void CubeSlideEffect::postPaintScreen()
     }
 }
 
-void CubeSlideEffect::slotDesktopChanged(int old, int current)
+void CubeSlideEffect::slotDesktopChanged(int old, int current, EffectWindow* w)
 {
+    Q_UNUSED(w)
     if (effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != \
this)  return;
     if (old > effects->numberOfDesktops()) {
@@ -499,17 +493,57 @@ void CubeSlideEffect::slotDesktopChanged(int old, int current)
     }
     timeLine.setDuration((float)rotationDuration / (float)slideRotations.count());
     if (activate) {
-        if (slideRotations.count() == 1)
-            timeLine.setCurveShape(QTimeLine::EaseInOutCurve);
-        else
-            timeLine.setCurveShape(QTimeLine::EaseInCurve);
-        effects->setActiveFullScreenEffect(this);
-        timeLine.setCurrentTime(0);
+        startAnimation();
         front_desktop = old;
         effects->addRepaintFull();
     }
 }
 
+void CubeSlideEffect::startAnimation() {
+    const EffectWindowList windows = effects->stackingOrder();
+    for (EffectWindow* w : windows) {
+        if (!shouldAnimate(w)) {
+            w->setData(WindowForceBlurRole, QVariant(true));
+            w->setData(WindowForceBackgroundContrastRole, QVariant(true));
+            staticWindows.insert(w);
+        }
+    }
+    if (slideRotations.count() == 1) {
+        timeLine.setCurveShape(QTimeLine::EaseInOutCurve);
+    } else {
+        timeLine.setCurveShape(QTimeLine::EaseInCurve);
+    }
+    effects->setActiveFullScreenEffect(this);
+    timeLine.setCurrentTime(0);
+}
+
+void CubeSlideEffect::slotWindowAdded(EffectWindow* w) {
+    if (!isActive() || shouldAnimate(w)) {
+        return;
+    }
+    staticWindows.insert(w);
+    w->setData(WindowForceBlurRole, QVariant(true));
+    w->setData(WindowForceBackgroundContrastRole, QVariant(true));
+}
+
+void CubeSlideEffect::slotWindowDeleted(EffectWindow* w) {
+    staticWindows.remove(w);
+}
+
+bool CubeSlideEffect::shouldAnimate(const EffectWindow* w) const
+{
+    if (w->isDock()) {
+        return !dontSlidePanels;
+    }
+    if (w->isOnAllDesktops()) {
+        if (!w->isManaged()) {
+            return false;
+        }
+        return !dontSlideStickyWindows;
+    }
+    return true;
+}
+
 void CubeSlideEffect::slotWindowStepUserMovedResized(EffectWindow* w)
 {
     if (!useWindowMoving)
@@ -594,9 +628,8 @@ void CubeSlideEffect::windowMovingChanged(float progress, \
RotationDirection dire  front_desktop = effects->currentDesktop();
     if (slideRotations.isEmpty()) {
         slideRotations.enqueue(direction);
-        timeLine.setCurveShape(QTimeLine::EaseInOutCurve);
         windowMoving = true;
-        effects->setActiveFullScreenEffect(this);
+        startAnimation();
     }
     effects->addRepaintFull();
 }
diff --git a/effects/cube/cubeslide.h b/effects/cube/cubeslide.h
index 92369f18a..9fac0dad7 100644
--- a/effects/cube/cubeslide.h
+++ b/effects/cube/cubeslide.h
@@ -72,7 +72,10 @@ public:
         return useWindowMoving;
     }
 private Q_SLOTS:
-    void slotDesktopChanged(int old, int current);
+    void slotWindowAdded(EffectWindow* w);
+    void slotWindowDeleted(EffectWindow* w);
+
+    void slotDesktopChanged(int old, int current, EffectWindow* w);
     void slotWindowStepUserMovedResized(KWin::EffectWindow *w);
     void slotWindowFinishUserMovedResized(KWin::EffectWindow *w);
 
@@ -85,15 +88,19 @@ private:
     };
     void paintSlideCube(int mask, QRegion region, ScreenPaintData& data);
     void windowMovingChanged(float progress, RotationDirection direction);
+
+    bool shouldAnimate(const EffectWindow* w) const;
+    void startAnimation();
+
     bool cube_painting;
     int front_desktop;
     int painting_desktop;
     int other_desktop;
     bool firstDesktop;
+    bool stickyPainting;
+    QSet<EffectWindow*> staticWindows;
     QTimeLine timeLine;
     QQueue<RotationDirection> slideRotations;
-    QSet<EffectWindow*> panels;
-    QSet<EffectWindow*> stickyWindows;
     bool dontSlidePanels;
     bool dontSlideStickyWindows;
     bool usePagerLayout;


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic