diff --git a/effects/blur/blur.cpp b/effects/blur/blur.cpp index befe15dc52..246637442b 100644 --- a/effects/blur/blur.cpp +++ b/effects/blur/blur.cpp @@ -20,10 +20,17 @@ #include "blur.h" #include "blurshader.h" +#include + namespace KWin { +enum { + BlurRegionRole = 0x1C50A74B +}; + + KWIN_EFFECT(blur, BlurEffect) KWIN_EFFECT_SUPPORTED(blur, BlurEffect::supported()) @@ -41,15 +48,56 @@ BlurEffect::BlurEffect() tex->setWrapMode(GL_CLAMP_TO_EDGE); target = new GLRenderTarget(tex); + + net_wm_blur_region = XInternAtom(display(), "_KDE_NET_WM_BLUR_REGION", False); + effects->registerPropertyType(net_wm_blur_region, true); + + // ### Hackish way to announce support. + // Should be included in _NET_SUPPORTED instead. + XChangeProperty(display(), rootWindow(), net_wm_blur_region, net_wm_blur_region, + 32, PropModeReplace, 0, 0); } BlurEffect::~BlurEffect() { + effects->registerPropertyType(net_wm_blur_region, false); + XDeleteProperty(display(), rootWindow(), net_wm_blur_region); + delete shader; delete target; delete tex; } +void BlurEffect::updateBlurRegion(EffectWindow *w) const +{ + QRegion region; + + const QByteArray value = w->readProperty(net_wm_blur_region, XA_CARDINAL, 32); + if (value.size() > 0 && !(value.size() % (4 * sizeof(quint32)))) { + const quint32 *cardinals = reinterpret_cast(value.constData()); + for (unsigned int i = 0; i < value.size() / sizeof(quint32);) { + int x = cardinals[i++]; + int y = cardinals[i++]; + int w = cardinals[i++]; + int h = cardinals[i++]; + region += QRect(x, y, w, h); + } + } + + w->setData(BlurRegionRole, value.isNull() ? QVariant() : region); +} + +void BlurEffect::windowAdded(EffectWindow *w) +{ + updateBlurRegion(w); +} + +void BlurEffect::propertyNotify(EffectWindow *w, long atom) +{ + if (w && atom == net_wm_blur_region) + updateBlurRegion(w); +} + bool BlurEffect::supported() { return GLRenderTarget::supported() && GLTexture::NPOTTextureSupported() && @@ -74,6 +122,29 @@ QRegion BlurEffect::expand(const QRegion ®ion) const return expanded; } +QRegion BlurEffect::blurRegion(const EffectWindow *w) const +{ + QRegion region; + + const QVariant value = w->data(BlurRegionRole); + if (value.isValid()) { + const QRegion appRegion = qvariant_cast(value); + if (!appRegion.isEmpty()) { + if (w->hasDecoration()) { + region = w->shape(); + region -= w->contentsRect(); + region |= appRegion.translated(w->contentsRect().topLeft()) & + w->contentsRect(); + } else + region = appRegion & w->contentsRect(); + } else + region = w->shape(); + } else + region = w->shape(); + + return region; +} + void BlurEffect::paintScreen(int mask, QRegion region, ScreenPaintData &data) { // Force the scene to call paintGenericScreen() so the windows are painted bottom -> top @@ -85,15 +156,18 @@ void BlurEffect::paintScreen(int mask, QRegion region, ScreenPaintData &data) void BlurEffect::drawWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data) { + const QRect screen(0, 0, displayWidth(), displayHeight()); bool scaled = !qFuzzyCompare(data.xScale, 1.0) && !qFuzzyCompare(data.yScale, 1.0); bool translated = data.xTranslate || data.yTranslate; + bool transformed = scaled || translated; bool hasAlpha = w->hasAlpha() || (w->hasDecoration() && effects->decorationsHaveAlpha()); - if (!effects->activeFullScreenEffect() && hasAlpha && !w->isDesktop() && - !scaled && !translated /* && region.intersects(w->geometry())*/) + QRegion shape; + if (!effects->activeFullScreenEffect() && hasAlpha && !w->isDesktop() && !transformed) + shape = blurRegion(w).translated(w->geometry().topLeft()) & screen; + + if (!shape.isEmpty() && region.intersects(shape.boundingRect())) { - const QRect screen(0, 0, displayWidth(), displayHeight()); - const QRegion shape = w->shape().translated(w->geometry().topLeft()) & screen; const QRect r = expand(shape.boundingRect()) & screen; const QPoint offset = -shape.boundingRect().topLeft() + (shape.boundingRect().topLeft() - r.topLeft()); diff --git a/effects/blur/blur.h b/effects/blur/blur.h index dfb6df414e..0caf608c57 100644 --- a/effects/blur/blur.h +++ b/effects/blur/blur.h @@ -39,12 +39,16 @@ public: static bool supported(); + void windowAdded(EffectWindow *w); + void propertyNotify(EffectWindow *w, long atom); void paintScreen(int mask, QRegion region, ScreenPaintData &data); void drawWindow(EffectWindow *w, int mask, QRegion region, WindowPaintData &data); private: QRect expand(const QRect &rect) const; QRegion expand(const QRegion ®ion) const; + QRegion blurRegion(const EffectWindow *w) const; + void updateBlurRegion(EffectWindow *w) const; private: BlurShader *shader; @@ -52,6 +56,7 @@ private: QVector texCoords; GLRenderTarget *target; GLTexture *tex; + long net_wm_blur_region; int radius; };