/***************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2007 Lubos Lunak You can Freely distribute this program under the GNU General Public License. See the file "COPYING" for the exact licensing terms. ******************************************************************/ #include "shadow.h" #include #include #include namespace KWin { KWIN_EFFECT( shadow, ShadowEffect ) ShadowEffect::ShadowEffect() { KConfigGroup conf = effects->effectConfig("Shadow"); shadowXOffset = conf.readEntry( "XOffset", 10 ); shadowYOffset = conf.readEntry( "YOffset", 10 ); shadowOpacity = (float)conf.readEntry( "Opacity", 0.2 ); shadowFuzzyness = conf.readEntry( "Fuzzyness", 10 ); QString shadowtexture = KGlobal::dirs()->findResource("data", "kwin/shadow-texture.png"); mShadowTexture = new GLTexture(shadowtexture); } QRect ShadowEffect::shadowRectangle(const QRect& windowRectangle) const { return windowRectangle.adjusted( shadowXOffset - shadowFuzzyness - 20, shadowYOffset - shadowFuzzyness - 20, shadowXOffset + shadowFuzzyness + 20, shadowYOffset + shadowFuzzyness + 20); } void ShadowEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time ) { *mask |= PAINT_WINDOW_TRANSLUCENT; *paint |= QRegion( shadowRectangle( ( QRegion( w->geometry()) & *paint ).boundingRect() )); effects->prePaintWindow( w, mask, paint, clip, time ); } void ShadowEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) { if( !w->isDeleted() ) drawShadow( w, mask, region, data ); effects->paintWindow( w, mask, region, data ); } void ShadowEffect::postPaintWindow( EffectWindow* w ) { effects->postPaintWindow( w ); } QRect ShadowEffect::transformWindowDamage( EffectWindow* w, const QRect& r ) { QRect r2 = r | shadowRectangle( r ); return effects->transformWindowDamage( w, r2 ); } void ShadowEffect::addQuadVertices(QVector& verts, float x1, float y1, float x2, float y2) const { verts << x1 << y1; verts << x1 << y2; verts << x2 << y2; verts << x2 << y1; } void ShadowEffect::drawShadow( EffectWindow* window, int mask, QRegion region, WindowPaintData& data ) { if(( mask & PAINT_WINDOW_TRANSLUCENT ) == 0 ) return; glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glPushMatrix(); if( mask & PAINT_WINDOW_TRANSFORMED ) glTranslatef( data.xTranslate, data.yTranslate, 0 ); glTranslatef( window->x() + shadowXOffset, window->y() + shadowYOffset, 0 ); if(( mask & PAINT_WINDOW_TRANSFORMED ) && ( data.xScale != 1 || data.yScale != 1 )) glScalef( data.xScale, data.yScale, 1 ); int w = window->width(); int h = window->height(); int fuzzy = shadowFuzzyness; QVector verts, texcoords; // center addQuadVertices(verts, 0 + fuzzy, 0 + fuzzy, w - fuzzy, h - fuzzy); addQuadVertices(texcoords, 0.5, 0.5, 0.5, 0.5); // sides // left addQuadVertices(verts, 0 - fuzzy, 0 + fuzzy, 0 + fuzzy, h - fuzzy); addQuadVertices(texcoords, 0.0, 0.5, 0.5, 0.5); // top addQuadVertices(verts, 0 + fuzzy, 0 - fuzzy, w - fuzzy, 0 + fuzzy); addQuadVertices(texcoords, 0.5, 0.0, 0.5, 0.5); // right addQuadVertices(verts, w - fuzzy, 0 + fuzzy, w + fuzzy, h - fuzzy); addQuadVertices(texcoords, 0.5, 0.5, 1.0, 0.5); // bottom addQuadVertices(verts, 0 + fuzzy, h - fuzzy, w - fuzzy, h + fuzzy); addQuadVertices(texcoords, 0.5, 0.5, 0.5, 1.0); // corners // top-left addQuadVertices(verts, 0 - fuzzy, 0 - fuzzy, 0 + fuzzy, 0 + fuzzy); addQuadVertices(texcoords, 0.0, 0.0, 0.5, 0.5); // top-right addQuadVertices(verts, w - fuzzy, 0 - fuzzy, w + fuzzy, 0 + fuzzy); addQuadVertices(texcoords, 0.5, 0.0, 1.0, 0.5); // bottom-left addQuadVertices(verts, 0 - fuzzy, h - fuzzy, 0 + fuzzy, h + fuzzy); addQuadVertices(texcoords, 0.0, 0.5, 0.5, 1.0); // bottom-right addQuadVertices(verts, w - fuzzy, h - fuzzy, w + fuzzy, h + fuzzy); addQuadVertices(texcoords, 0.5, 0.5, 1.0, 1.0); mShadowTexture->bind(); glColor4f(0, 0, 0, shadowOpacity * data.opacity); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // We have two elements per vertex in the verts array int verticesCount = verts.count() / 2; renderGLGeometry( mask, region, verticesCount, verts.data(), texcoords.data() ); mShadowTexture->unbind(); glPopMatrix(); glPopAttrib(); } } // namespace