5faa397849
for use in effects (and not only). Now a list of window quads (=window areas) is created at the beginning of the paint pass, prepaint calls can modify the split itself (i.e. divide it into more parts). The actual paint calls can then modify these quads (i.e. transform their geometry). This will allow better control of how the split is done and also allow painting e.g. only the decoration differently. Still work in progress, but it works. Also pass data to prepaint functions in a struct, as there is already quite a number of them. svn path=/trunk/KDE/kdebase/workspace/; revision=684893
139 lines
5.1 KiB
C++
139 lines
5.1 KiB
C++
/*****************************************************************
|
|
KWin - the KDE window manager
|
|
This file is part of the KDE project.
|
|
|
|
Copyright (C) 2007 Lubos Lunak <l.lunak@kde.org>
|
|
|
|
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 <kwinglutils.h>
|
|
|
|
#include <kconfiggroup.h>
|
|
#include <KStandardDirs>
|
|
|
|
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, WindowPrePaintData& data, int time )
|
|
{
|
|
data.mask |= PAINT_WINDOW_TRANSLUCENT;
|
|
data.paint |= QRegion( shadowRectangle( ( QRegion( w->geometry()) & data.paint ).boundingRect() ));
|
|
effects->prePaintWindow( w, data, 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<float>& 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 );
|
|
|
|
int fuzzy = shadowFuzzyness;
|
|
// Shadow's size must be a least 2*fuzzy in both directions (or the corners will be broken)
|
|
int w = qMax(fuzzy*2, window->width());
|
|
int h = qMax(fuzzy*2, window->height());
|
|
|
|
glPushMatrix();
|
|
if( mask & PAINT_WINDOW_TRANSFORMED )
|
|
glTranslatef( data.xTranslate, data.yTranslate, 0 );
|
|
glTranslatef( window->x() + shadowXOffset - qMax(0, w - window->width()) / 2.0,
|
|
window->y() + shadowYOffset - qMax(0, h - window->height()) / 2.0, 0 );
|
|
if(( mask & PAINT_WINDOW_TRANSFORMED ) && ( data.xScale != 1 || data.yScale != 1 ))
|
|
glScalef( data.xScale, data.yScale, 1 );
|
|
|
|
QVector<float> 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();
|
|
// Take the transparency settings and window's transparency into account.
|
|
// Also make the shadow more transparent if we've made it bigger
|
|
glColor4f(0, 0, 0, shadowOpacity * data.opacity * (window->width() / (float)w) * (window->height() / (float)h));
|
|
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
|