diff --git a/composite.cpp b/composite.cpp index 1bfa66b0df..6a10d3416d 100644 --- a/composite.cpp +++ b/composite.cpp @@ -735,24 +735,48 @@ void Toplevel::resetDamage(const QRect& r) void Toplevel::addRepaint(const QRect& r) { - addRepaint(r.x(), r.y(), r.width(), r.height()); -} - -void Toplevel::addRepaint(int x, int y, int w, int h) -{ - if (!compositing()) + if (!compositing()) { return; - QRect r(x, y, w, h); - r &= rect(); + } repaints_region += r; workspace()->checkCompositeTimer(); } +void Toplevel::addRepaint(int x, int y, int w, int h) +{ + QRect r(x, y, w, h); + addRepaint(r); +} + void Toplevel::addRepaint(const QRegion& r) +{ + if (!compositing()) { + return; + } + repaints_region += r; + workspace()->checkCompositeTimer(); +} + +void Toplevel::addLayerRepaint(const QRect& r) +{ + if (!compositing()) { + return; + } + layer_repaints_region += r; + workspace()->checkCompositeTimer(); +} + +void Toplevel::addLayerRepaint(int x, int y, int w, int h) +{ + QRect r(x, y, w, h); + addLayerRepaint(r); +} + +void Toplevel::addLayerRepaint(const QRegion& r) { if (!compositing()) return; - repaints_region += r; + layer_repaints_region += r; workspace()->checkCompositeTimer(); } @@ -762,9 +786,10 @@ void Toplevel::addRepaintFull() workspace()->checkCompositeTimer(); } -void Toplevel::resetRepaints(const QRect& r) +void Toplevel::resetRepaints() { - repaints_region -= r; + repaints_region = QRegion(); + layer_repaints_region = QRegion(); } void Toplevel::addWorkspaceRepaint(int x, int y, int w, int h) diff --git a/effects/blur/blur.cpp b/effects/blur/blur.cpp index f192765bb1..92c3d5f2c1 100644 --- a/effects/blur/blur.cpp +++ b/effects/blur/blur.cpp @@ -290,7 +290,7 @@ void BlurEffect::prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int t // if a window underneath the blurred area is damaged we have to // update the cached texture QRegion damagedCache; - if (windows.contains(w) && !windows[w].dropCache) { + if (windows.contains(w) && !windows.value(w).dropCache) { damagedCache = expand(expandedBlur & m_damagedArea) & expandedBlur; } else { damagedCache = expandedBlur; @@ -504,13 +504,17 @@ void BlurEffect::doCachedBlur(EffectWindow *w, const QRegion& region, const floa bwi.blurredBackground = GLTexture(r.width(),r.height()); bwi.damagedRegion = expanded; bwi.dropCache = false; - windows[w] = bwi; - } - - if (windows[w].blurredBackground.size() != r.size()) { + bwi.windowPos = w->pos(); + windows.insert(w, bwi); + } else if (windows.value(w).blurredBackground.size() != r.size()) { windows[w].blurredBackground = GLTexture(r.width(),r.height()); windows[w].damagedRegion = expanded; windows[w].dropCache = false; + windows[w].windowPos = w->pos(); + } else if (windows.value(w).windowPos != w->pos()) { + windows[w].damagedRegion = expanded; + windows[w].dropCache = false; + windows[w].windowPos = w->pos(); } GLTexture targetTexture = windows[w].blurredBackground; @@ -530,7 +534,7 @@ void BlurEffect::doCachedBlur(EffectWindow *w, const QRegion& region, const floa #endif // We only update that part of the background texture that is visible and marked as dirty. - const QRegion updateBackground = windows[w].damagedRegion & region; + const QRegion updateBackground = windows.value(w).damagedRegion & region; if (!updateBackground.isEmpty()) { const QRect updateRect = (expand(updateBackground) & expanded).boundingRect(); diff --git a/effects/blur/blur.h b/effects/blur/blur.h index 65ba3811ca..f2579ac16d 100644 --- a/effects/blur/blur.h +++ b/effects/blur/blur.h @@ -78,6 +78,7 @@ private: struct BlurWindowInfo { GLTexture blurredBackground; // keeps the horizontally blurred background QRegion damagedRegion; + QPoint windowPos; bool dropCache; }; diff --git a/geometry.cpp b/geometry.cpp index 6d47078e95..b4478384ca 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -1913,8 +1913,8 @@ void Client::setGeometry(int x, int y, int w, int h, ForceGeometry_t force) emit geometryShapeChanged(this, geom_before_block); } const QRect deco_rect = decorationRect().translated(geom.x(), geom.y()); - addWorkspaceRepaint(deco_rect_before_block); - addWorkspaceRepaint(deco_rect); + addLayerRepaint(deco_rect_before_block); + addLayerRepaint(deco_rect); geom_before_block = geom; deco_rect_before_block = deco_rect; @@ -1980,8 +1980,8 @@ void Client::plainResize(int w, int h, ForceGeometry_t force) discardWindowPixmap(); emit geometryShapeChanged(this, geom_before_block); const QRect deco_rect = decorationRect().translated(geom.x(), geom.y()); - addWorkspaceRepaint(deco_rect_before_block); - addWorkspaceRepaint(deco_rect); + addLayerRepaint(deco_rect_before_block); + addLayerRepaint(deco_rect); geom_before_block = geom; deco_rect_before_block = deco_rect; @@ -2027,8 +2027,8 @@ void Client::move(int x, int y, ForceGeometry_t force) #endif // client itself is not damaged const QRect deco_rect = decorationRect().translated(geom.x(), geom.y()); - addWorkspaceRepaint(deco_rect_before_block); - addWorkspaceRepaint(deco_rect); // trigger repaint of window's new location + addLayerRepaint(deco_rect_before_block); + addLayerRepaint(deco_rect); // trigger repaint of window's new location geom_before_block = geom; deco_rect_before_block = deco_rect; diff --git a/libkwineffects/kwineffects.cpp b/libkwineffects/kwineffects.cpp index b04c360576..efaca5d563 100644 --- a/libkwineffects/kwineffects.cpp +++ b/libkwineffects/kwineffects.cpp @@ -418,6 +418,16 @@ void EffectWindow::addRepaintFull() QMetaObject::invokeMethod(parent(), "addRepaintFull"); } +void EffectWindow::addLayerRepaint(int x, int y, int w, int h) +{ + QMetaObject::invokeMethod(parent(), "addLayerRepaint", Q_ARG(int, x), Q_ARG(int, y), Q_ARG(int, w), Q_ARG(int, h)); +} + +void EffectWindow::addLayerRepaint(const QRect &r) +{ + QMetaObject::invokeMethod(parent(), "addLayerRepaint", Q_ARG(const QRect&, r)); +} + bool EffectWindow::isOnCurrentActivity() const { return isOnActivity(effects->currentActivity()); diff --git a/libkwineffects/kwineffects.h b/libkwineffects/kwineffects.h index 288dad825e..b4fc0ed37b 100644 --- a/libkwineffects/kwineffects.h +++ b/libkwineffects/kwineffects.h @@ -1088,6 +1088,8 @@ public: void addRepaint(const QRect& r); void addRepaint(int x, int y, int w, int h); void addRepaintFull(); + void addLayerRepaint(const QRect& r); + void addLayerRepaint(int x, int y, int w, int h); virtual void refWindow() = 0; virtual void unrefWindow() = 0; diff --git a/scene.cpp b/scene.cpp index 2f30621d85..a2dd25cf18 100644 --- a/scene.cpp +++ b/scene.cpp @@ -202,10 +202,7 @@ void Scene::paintGenericScreen(int orig_mask, ScreenPaintData) // Reset the repaint_region. // This has to be done here because many effects schedule a repaint for // the next frame within Effects::prePaintWindow. - topw->resetRepaints(topw->decorationRect()); - if (topw->hasShadow()) { - topw->resetRepaints(topw->shadow()->shadowRegion().boundingRect()); - } + topw->resetRepaints(); WindowPrePaintData data; data.mask = orig_mask | (w->isOpaque() ? PAINT_WINDOW_OPAQUE : PAINT_WINDOW_TRANSLUCENT); @@ -253,16 +250,13 @@ void Scene::paintSimpleScreen(int orig_mask, QRegion region) data.mask = orig_mask | (w->isOpaque() ? PAINT_WINDOW_OPAQUE : PAINT_WINDOW_TRANSLUCENT); w->resetPaintingEnabled(); data.paint = region; - data.paint |= topw->repaints().translated(topw->pos()); + data.paint |= topw->repaints(); data.paint |= topw->decorationPendingRegion(); // Reset the repaint_region. // This has to be done here because many effects schedule a repaint for // the next frame within Effects::prePaintWindow. - topw->resetRepaints(topw->decorationRect()); - if (topw->hasShadow()) { - topw->resetRepaints(topw->shadow()->shadowRegion().boundingRect()); - } + topw->resetRepaints(); // Clip out the decoration for opaque windows; the decoration is drawn in the second pass if (w->isOpaque()) { // the window is fully opaque @@ -299,15 +293,8 @@ void Scene::paintSimpleScreen(int orig_mask, QRegion region) QPair< Window*, Phase2Data > *entry = &phase2data[i]; Phase2Data *data = &entry->second; - Toplevel *tlw = entry->first->window(); - // In case there is a window with a higher stackposition which has translucent regions - // (e.g. decorations) that still have to be drawn, we also have to repaint the current window - // in these particular regions - if (!(data->mask & PAINT_WINDOW_TRANSFORMED)) { - data->region |= (upperTranslucentDamage & tlw->decorationRect().translated(tlw->pos())); - } else { - data->region |= upperTranslucentDamage; - } + data->region |= upperTranslucentDamage; + // subtract the parts which will possibly been drawn as part of // a higher opaque window data->region -= allclips; diff --git a/toplevel.h b/toplevel.h index ff9933563b..32581a513c 100644 --- a/toplevel.h +++ b/toplevel.h @@ -235,12 +235,15 @@ public: Q_INVOKABLE void addRepaint(const QRect& r); Q_INVOKABLE void addRepaint(const QRegion& r); Q_INVOKABLE void addRepaint(int x, int y, int w, int h); + Q_INVOKABLE void addLayerRepaint(const QRect& r); + Q_INVOKABLE void addLayerRepaint(const QRegion& r); + Q_INVOKABLE void addLayerRepaint(int x, int y, int w, int h); Q_INVOKABLE virtual void addRepaintFull(); // these call workspace->addRepaint(), but first transform the damage if needed void addWorkspaceRepaint(const QRect& r); void addWorkspaceRepaint(int x, int y, int w, int h); QRegion repaints() const; - void resetRepaints(const QRect& r); + void resetRepaints(); QRegion damage() const; void resetDamage(const QRect& r); EffectWindowImpl* effectWindow(); @@ -324,6 +327,7 @@ protected: NETWinInfo2* info; bool ready_for_painting; QRegion repaints_region; // updating, repaint just requires repaint of that area + QRegion layer_repaints_region; private: static QByteArray staticWindowRole(WId); static QByteArray staticSessionId(WId); @@ -513,7 +517,7 @@ inline QRegion Toplevel::damage() const inline QRegion Toplevel::repaints() const { - return repaints_region; + return repaints_region.translated(pos()) | layer_repaints_region; } inline bool Toplevel::shape() const