From de8b9f546fe15cf768fb7d45a66188b1da0da711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Sat, 10 Dec 2011 12:31:06 +0100 Subject: [PATCH] Fixing incorrect clipping of sliding popups Make use of new extension of protocol for magic number -1. If offset is -1 KWin has to decide the offset. This fixes all the incorrect animations and allows us to perform clipping again by filtering out the window quads which should not be visible. Additionally the effect now sanitizes the offset. That is for e.g. Yakuake setting an offset of 0, but there is a strut on the top corner causing Yakuake not to appear on 0, but with an offset of the strut. Such cases are now considered as well and the animation is fixed. REVIEW: 103367 BUG: 287602 CCBUG: 261159 CCBUG: 278760 FIXED-IN: 4.8.0 --- effects/slidingpopups/slidingpopups.cpp | 152 ++++++++++++++++++------ 1 file changed, 115 insertions(+), 37 deletions(-) diff --git a/effects/slidingpopups/slidingpopups.cpp b/effects/slidingpopups/slidingpopups.cpp index 1065bfc7c4..12730764ea 100644 --- a/effects/slidingpopups/slidingpopups.cpp +++ b/effects/slidingpopups/slidingpopups.cpp @@ -82,17 +82,86 @@ void SlidingPopupsEffect::prePaintScreen(ScreenPrePaintData& data, int time) void SlidingPopupsEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time) { + qreal progress = 1.0; + bool appearing = false; if (mAppearingWindows.contains(w)) { mAppearingWindows[ w ]->setCurrentTime(mAppearingWindows[ w ]->currentTime() + time); - if (mAppearingWindows[ w ]->currentValue() < 1) + if (mAppearingWindows[ w ]->currentValue() < 1) { data.setTransformed(); - else + progress = mAppearingWindows[ w ]->currentValue(); + appearing = true; + } else delete mAppearingWindows.take(w); } else if (mDisappearingWindows.contains(w)) { - data.setTransformed(); - w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DELETE); mDisappearingWindows[ w ]->setCurrentTime(mDisappearingWindows[ w ]->currentTime() + time); + progress = mDisappearingWindows[ w ]->currentValue(); + + if (progress != 1.0) { + data.setTransformed(); + w->enablePainting(EffectWindow::PAINT_DISABLED_BY_DELETE); + } else { + delete mDisappearingWindows.take(w); + w->unrefWindow(); + } + } + if (progress != 1.0) { + const int start = mWindowsData[ w ].start; + if (start != 0) { + const QRect screenRect = effects->clientArea(FullScreenArea, w->screen(), effects->currentDesktop()); + // filter out window quads, but only if the window does not start from the edge + switch(mWindowsData[ w ].from) { + case West: { + const double splitPoint = w->width() - (w->x() + w->width() - screenRect.x() - start) + w->width() * (appearing ? 1.0 - progress : progress); + data.quads = data.quads.splitAtX(splitPoint); + WindowQuadList filtered; + foreach (const WindowQuad &quad, data.quads) { + if (quad.left() >= splitPoint) { + filtered << quad; + } + } + data.quads = filtered; + break; + } + case North: { + const double splitPoint = w->height() - (w->y() + w->height() - screenRect.y() - start) + w->height() * (appearing ? 1.0 - progress : progress); + data.quads = data.quads.splitAtY(splitPoint); + WindowQuadList filtered; + foreach (const WindowQuad &quad, data.quads) { + if (quad.top() >= splitPoint) { + filtered << quad; + } + } + data.quads = filtered; + break; + } + case East: { + const double splitPoint = screenRect.x() + screenRect.width() - w->x() - start - w->width() * (appearing ? 1.0 - progress : progress); + data.quads = data.quads.splitAtX(splitPoint); + WindowQuadList filtered; + foreach (const WindowQuad &quad, data.quads) { + if (quad.right() <= splitPoint) { + filtered << quad; + } + } + data.quads = filtered; + break; + } + case South: + default: { + const double splitPoint = screenRect.y() + screenRect.height() - w->y() - start - w->height() * (appearing ? 1.0 - progress : progress); + data.quads = data.quads.splitAtY(splitPoint); + WindowQuadList filtered; + foreach (const WindowQuad &quad, data.quads) { + if (quad.bottom() <= splitPoint) { + filtered << quad; + } + } + data.quads = filtered; + break; + } + } + } } effects->prePaintWindow(w, data, time); } @@ -101,7 +170,6 @@ void SlidingPopupsEffect::paintWindow(EffectWindow* w, int mask, QRegion region, { bool animating = false; bool appearing = false; - QRegion clippedRegion = region; if (mAppearingWindows.contains(w)) { appearing = true; @@ -122,59 +190,33 @@ void SlidingPopupsEffect::paintWindow(EffectWindow* w, int mask, QRegion region, progress = 1.0; } const int start = mWindowsData[ w ].start; - QRect r; + const QRect screenRect = effects->clientArea(FullScreenArea, w->screen(), w->desktop()); switch(mWindowsData[ w ].from) { case West: - data.xTranslate += (start - w->width()) * progress; - r = QRect(start - w->width(), w->y(), w->width(), w->height()); + data.xTranslate -= w->width() * progress; break; case North: - data.yTranslate += (start - w->height()) * progress; - r = QRect(w->x(), start - w->height(), w->width(), w->height()); + data.yTranslate -= w->height() * progress; break; case East: - data.xTranslate += (start - w->x()) * progress; - r = QRect(w->x() + w->width(), w->y(), w->width(), w->height()); + data.xTranslate += w->width() * progress; break; case South: default: - data.yTranslate += (start - w->y()) * progress; - r = QRect(w->x(), start, w->width(), w->height()); + data.yTranslate += w->height() * progress; } - clippedRegion = clippedRegion.subtracted(r); - effects->addRepaint(r); } - effects->paintWindow(w, mask, clippedRegion, data); + effects->paintWindow(w, mask, region, data); } void SlidingPopupsEffect::postPaintWindow(EffectWindow* w) { if (mAppearingWindows.contains(w) || mDisappearingWindows.contains(w)) { w->addRepaintFull(); // trigger next animation repaint - const int start = mWindowsData[ w ].start; - switch(mWindowsData[ w ].from) { - case West: - effects->addRepaint(QRect(start, w->y(), w->x(), w->height())); - break; - case North: - effects->addRepaint(QRect(w->x(), start, w->width(), w->y())); - break; - case East: - effects->addRepaint(QRect(w->x() + w->width(), w->y(), displayWidth() - w->x() - w->width() - start, w->height())); - break; - case South: - default: - effects->addRepaint(QRect(w->x(), w->y()+w->height(), w->width(), displayHeight() - w->y() - w->height() - start)); - } } effects->postPaintWindow(w); - if (mDisappearingWindows.contains(w) && mDisappearingWindows[ w ]->currentValue() >= 1) { - delete mDisappearingWindows.take(w); - w->unrefWindow(); - effects->addRepaint(w->geometry()); - } } void SlidingPopupsEffect::slotWindowAdded(EffectWindow *w) @@ -244,6 +286,42 @@ void SlidingPopupsEffect::slotPropertyNotify(EffectWindow* w, long a) animData.fadeInDuration = animationTime(mFadeInTime); animData.fadeOutDuration = animationTime(mFadeOutTime); } + const QRect screenRect = effects->clientArea(FullScreenArea, w->screen(), effects->currentDesktop()); + if (animData.start == -1) { + switch (animData.from) { + case West: + animData.start = qMax(w->x() - screenRect.x(), 0); + break; + case North: + animData.start = qMax(w->y() - screenRect.y(), 0); + break; + case East: + animData.start = qMax(screenRect.x() + screenRect.width() - (w->x() + w->width()), 0); + break; + case South: + default: + animData.start = qMax(screenRect.y() + screenRect.height() - (w->y() + w->height()), 0); + break; + } + } + // sanitize + int difference = 0; + switch (animData.from) { + case West: + difference = w->x() - screenRect.x(); + break; + case North: + difference = w->y() - screenRect.y(); + break; + case East: + difference = w->x() + w->width() - (screenRect.x() + screenRect.width()); + break; + case South: + default: + difference = w->y() + w->height() - (screenRect.y() + screenRect.height()); + break; + } + animData.start = qMax(animData.start, difference); mWindowsData[ w ] = animData; }