• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KWinLibraries

kwineffects.cpp

Go to the documentation of this file.
00001 /********************************************************************
00002  KWin - the KDE window manager
00003  This file is part of the KDE project.
00004 
00005 Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org>
00006 
00007 This program is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2 of the License, or
00010 (at your option) any later version.
00011 
00012 This program is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with this program.  If not, see <http://www.gnu.org/licenses/>.
00019 *********************************************************************/
00020 
00021 #include "kwineffects.h"
00022 
00023 #include "kwinglutils.h"
00024 #include "kwinxrenderutils.h"
00025 
00026 #include <QtDBus/QtDBus>
00027 #include <QVariant>
00028 #include <QList>
00029 #include <QtCore/QTimeLine>
00030 #include <QtGui/QFontMetrics>
00031 #include <QtGui/QPainter>
00032 #include <QtGui/QPixmap>
00033 
00034 #include <kdebug.h>
00035 #include <ksharedconfig.h>
00036 #include <kconfiggroup.h>
00037 
00038 #include <assert.h>
00039 
00040 #ifdef KWIN_HAVE_XRENDER_COMPOSITING
00041 #include <X11/extensions/Xrender.h>
00042 #include <X11/extensions/Xfixes.h>
00043 #endif
00044 
00045 namespace KWin
00046 {
00047 
00048 void WindowPrePaintData::setTranslucent()
00049     {
00050     mask |= Effect::PAINT_WINDOW_TRANSLUCENT;
00051     mask &= ~Effect::PAINT_WINDOW_OPAQUE;
00052     clip = QRegion(); // cannot clip, will be transparent
00053     }
00054 
00055 void WindowPrePaintData::setTransformed()
00056     {
00057     mask |= Effect::PAINT_WINDOW_TRANSFORMED;
00058     }
00059 
00060 
00061 WindowPaintData::WindowPaintData( EffectWindow* w )
00062     : opacity( w->opacity())
00063     , contents_opacity( 1.0 )
00064     , decoration_opacity( 1.0 )
00065     , xScale( 1 )
00066     , yScale( 1 )
00067     , xTranslate( 0 )
00068     , yTranslate( 0 )
00069     , saturation( 1 )
00070     , brightness( 1 )
00071     , shader( NULL )
00072     {
00073     quads = w->buildQuads();
00074     }
00075 
00076 ScreenPaintData::ScreenPaintData()
00077     : xScale( 1 )
00078     , yScale( 1 )
00079     , xTranslate( 0 )
00080     , yTranslate( 0 )
00081     {
00082     }
00083 
00084 //****************************************
00085 // Effect
00086 //****************************************
00087 
00088 Effect::Effect()
00089     {
00090     }
00091 
00092 Effect::~Effect()
00093     {
00094     }
00095 
00096 void Effect::windowUserMovedResized( EffectWindow* , bool, bool )
00097     {
00098     }
00099 
00100 void Effect::windowOpacityChanged( EffectWindow*, double )
00101     {
00102     }
00103 
00104 void Effect::windowAdded( EffectWindow* )
00105     {
00106     }
00107 
00108 void Effect::windowClosed( EffectWindow* )
00109     {
00110     }
00111 
00112 void Effect::windowDeleted( EffectWindow* )
00113     {
00114     }
00115 
00116 void Effect::windowActivated( EffectWindow* )
00117     {
00118     }
00119 
00120 void Effect::windowMinimized( EffectWindow* )
00121     {
00122     }
00123 
00124 void Effect::windowUnminimized( EffectWindow* )
00125     {
00126     }
00127 
00128 void Effect::windowInputMouseEvent( Window, QEvent* )
00129     {
00130     }
00131 
00132 void Effect::grabbedKeyboardEvent( QKeyEvent* )
00133     {
00134     }
00135 
00136 void Effect::propertyNotify( EffectWindow* , long )
00137     {
00138     }
00139 
00140 void Effect::desktopChanged( int )
00141     {
00142     }
00143 
00144 void Effect::windowDamaged( EffectWindow*, const QRect& )
00145     {
00146     }
00147 
00148 void Effect::windowGeometryShapeChanged( EffectWindow*, const QRect& )
00149     {
00150     }
00151 
00152 void Effect::tabBoxAdded( int )
00153     {
00154     }
00155 
00156 void Effect::tabBoxClosed()
00157     {
00158     }
00159 
00160 void Effect::tabBoxUpdated()
00161     {
00162     }
00163 bool Effect::borderActivated( ElectricBorder )
00164     {
00165     return false;
00166     }
00167 
00168 void Effect::mouseChanged( const QPoint&, const QPoint&, Qt::MouseButtons,
00169     Qt::MouseButtons, Qt::KeyboardModifiers, Qt::KeyboardModifiers )
00170     {
00171     }
00172 
00173 void Effect::prePaintScreen( ScreenPrePaintData& data, int time )
00174     {
00175     effects->prePaintScreen( data, time );
00176     }
00177 
00178 void Effect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
00179     {
00180     effects->paintScreen( mask, region, data );
00181     }
00182     
00183 void Effect::postPaintScreen()
00184     {
00185     effects->postPaintScreen();
00186     }
00187 
00188 void Effect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
00189     {
00190     effects->prePaintWindow( w, data, time );
00191     }
00192 
00193 void Effect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
00194     {
00195     effects->paintWindow( w, mask, region, data );
00196     }
00197 
00198 void Effect::postPaintWindow( EffectWindow* w )
00199     {
00200     effects->postPaintWindow( w );
00201     }
00202 
00203 void Effect::drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
00204     {
00205     effects->drawWindow( w, mask, region, data );
00206     }
00207 
00208 QRect Effect::transformWindowDamage( EffectWindow* w, const QRect& r )
00209     {
00210     return effects->transformWindowDamage( w, r );
00211     }
00212 
00213 void Effect::setPositionTransformations( WindowPaintData& data, QRect& region, EffectWindow* w,
00214     const QRect& r, Qt::AspectRatioMode aspect )
00215     {
00216     QSize size = w->size();
00217     size.scale( r.size(), aspect );
00218     data.xScale = size.width() / double( w->width());
00219     data.yScale = size.height() / double( w->height());
00220     int width = int( w->width() * data.xScale );
00221     int height = int( w->height() * data.yScale );
00222     int x = r.x() + ( r.width() - width ) / 2;
00223     int y = r.y() + ( r.height() - height ) / 2;
00224     region = QRect( x, y, width, height );
00225     data.xTranslate = x - w->x();
00226     data.yTranslate = y - w->y();
00227     }
00228 
00229 int Effect::displayWidth()
00230     {
00231     return KWin::displayWidth();
00232     }
00233 
00234 int Effect::displayHeight()
00235     {
00236     return KWin::displayHeight();
00237     }
00238 
00239 QPoint Effect::cursorPos()
00240     {
00241     return effects->cursorPos();
00242     }
00243 
00244 //****************************************
00245 // EffectsHandler
00246 //****************************************
00247 
00248 EffectsHandler::EffectsHandler(CompositingType type)
00249     : current_paint_screen( 0 )
00250     , current_paint_window( 0 )
00251     , current_draw_window( 0 )
00252     , current_transform( 0 )
00253     , compositing_type( type )
00254     {
00255     if( compositing_type == NoCompositing )
00256         return;
00257     KWin::effects = this;
00258     }
00259 
00260 EffectsHandler::~EffectsHandler()
00261     {
00262     // All effects should already be unloaded by Impl dtor
00263     assert( loaded_effects.count() == 0 );
00264     }
00265 
00266 QRect EffectsHandler::transformWindowDamage( EffectWindow* w, const QRect& r )
00267     {
00268     if( current_transform < loaded_effects.size())
00269         {
00270         QRect rr = loaded_effects[current_transform++].second->transformWindowDamage( w, r );
00271         --current_transform;
00272         return rr;
00273         }
00274     else
00275         return r;
00276     }
00277 
00278 Window EffectsHandler::createInputWindow( Effect* e, const QRect& r, const QCursor& cursor )
00279     {
00280     return createInputWindow( e, r.x(), r.y(), r.width(), r.height(), cursor );
00281     }
00282 
00283 Window EffectsHandler::createFullScreenInputWindow( Effect* e, const QCursor& cursor )
00284     {
00285     return createInputWindow( e, 0, 0, displayWidth(), displayHeight(), cursor );
00286     }
00287 
00288 CompositingType EffectsHandler::compositingType() const
00289     {
00290     return compositing_type;
00291     }
00292 
00293 bool EffectsHandler::saturationSupported() const
00294     {
00295     switch( compositing_type )
00296         {
00297 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00298         case OpenGLCompositing:
00299             return GLTexture::saturationSupported();
00300 #endif
00301         case XRenderCompositing:
00302             return false; // never
00303         default:
00304             abort();
00305         }
00306     }
00307 
00308 void EffectsHandler::sendReloadMessage( const QString& effectname )
00309     {
00310     QDBusMessage message = QDBusMessage::createMethodCall("org.kde.kwin", "/KWin", "org.kde.KWin", "reloadEffect");
00311     message << QString("kwin4_effect_" + effectname);
00312     QDBusConnection::sessionBus().send(message);
00313     }
00314 
00315 KConfigGroup EffectsHandler::effectConfig( const QString& effectname )
00316     {
00317     KSharedConfig::Ptr kwinconfig = KSharedConfig::openConfig( "kwinrc", KConfig::NoGlobals );
00318     return kwinconfig->group( "Effect-" + effectname );
00319     }
00320 
00321 bool EffectsHandler::paintText( const QString& text, const QPoint& center, int maxwidth,
00322         const QColor& color, const QFont& font )
00323 {
00324     QPainter p;
00325     // Calculate size of the text
00326     QFontMetrics fm( font );
00327     QString painttext = fm.elidedText( text, Qt::ElideRight, maxwidth );
00328     QRect textrect = fm.boundingRect( painttext );
00329 
00330     // Create temporary QPixmap where the text will be drawn onto
00331     QPixmap textPixmap( textrect.width(), textrect.height());
00332     textPixmap.fill( Qt::transparent );
00333 
00334     // Draw the text
00335     p.begin( &textPixmap );
00336     p.setFont( font );
00337     p.setRenderHint( QPainter::TextAntialiasing );
00338     p.setPen( color );
00339     p.drawText( -textrect.topLeft(), painttext );
00340     p.end();
00341 
00342     // Area covered by text
00343     QRect area( center.x() - textrect.width() / 2, center.y() - textrect.height() / 2,
00344                  textrect.width(), textrect.height() );
00345 
00346 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00347     if( effects->compositingType() == OpenGLCompositing )
00348         {
00349         GLTexture textTexture( textPixmap, GL_TEXTURE_RECTANGLE_ARB );
00350         glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT );
00351         glEnable( GL_BLEND );
00352         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00353         textTexture.bind();
00354         const float verts[ 4 * 2 ] =
00355             {
00356             area.x(), area.y(),
00357             area.x(), area.y() + area.height(),
00358             area.x() + area.width(), area.y() + area.height(),
00359             area.x() + area.width(), area.y()
00360             };
00361         const float texcoords[ 4 * 2 ] =
00362             {
00363             0, textPixmap.height(),
00364             0, 0,
00365             textPixmap.width(), 0,
00366             textPixmap.width(), textPixmap.height()
00367             };
00368         renderGLGeometry( 4, verts, texcoords );
00369         textTexture.unbind();
00370         glPopAttrib();
00371         return true;
00372         }
00373 #endif
00374 #ifdef KWIN_HAVE_XRENDER_COMPOSITING
00375     if( effects->compositingType() == XRenderCompositing )
00376         {
00377         XRenderPicture textPicture( textPixmap );
00378         XRenderComposite( display(), textPixmap.depth() == 32 ? PictOpOver : PictOpSrc,
00379             textPicture, None, effects->xrenderBufferPicture(),
00380             0, 0, 0, 0, area.x(), area.y(), area.width(), area.height());
00381         return true;
00382         }
00383 #endif
00384     return false;
00385 }
00386 
00387 bool EffectsHandler::paintTextWithBackground( const QString& text, const QPoint& center, int maxwidth,
00388         const QColor& color, const QColor& bgcolor, const QFont& font )
00389 {
00390     // Calculate size of the text
00391     QFontMetrics fm( font );
00392     QString painttext = fm.elidedText( text, Qt::ElideRight, maxwidth );
00393     QRect textrect = fm.boundingRect( painttext );
00394 
00395     // Area covered by text
00396     QRect area( center.x() - textrect.width() / 2, center.y() - textrect.height() / 2,
00397                 textrect.width(), textrect.height() );
00398 
00399 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00400     if( effects->compositingType() == OpenGLCompositing )
00401     {
00402         glColor4f( bgcolor.redF(), bgcolor.greenF(), bgcolor.blueF(), bgcolor.alphaF() );
00403         renderRoundBox( area.adjusted( -8, -3, 8, 3 ), 5 );
00404 
00405         return paintText( text, center, maxwidth, color, font );
00406     }
00407 #endif
00408 #ifdef KWIN_HAVE_XRENDER_COMPOSITING
00409     if( effects->compositingType() == XRenderCompositing )
00410     {
00411         xRenderRoundBox( effects->xrenderBufferPicture(), area.adjusted( -8, -3, 8, 3 ), 5, bgcolor );
00412         return paintText( text, center, maxwidth, color, font );
00413     }
00414 #endif
00415     return false;
00416 }
00417 
00418 
00419 EffectsHandler* effects = 0;
00420 
00421 
00422 //****************************************
00423 // EffectWindow
00424 //****************************************
00425 
00426 EffectWindow::EffectWindow()
00427     {
00428     }
00429 
00430 EffectWindow::~EffectWindow()
00431     {
00432     }
00433 
00434 bool EffectWindow::isOnCurrentDesktop() const
00435     {
00436     return isOnDesktop( effects->currentDesktop());
00437     }
00438 
00439 bool EffectWindow::isOnDesktop( int d ) const
00440     {
00441     return desktop() == d || isOnAllDesktops();
00442     }
00443 
00444 bool EffectWindow::hasDecoration() const
00445     {
00446     return contentsRect() != QRect( 0, 0, width(), height());
00447     }
00448 
00449 
00450 //****************************************
00451 // EffectWindowGroup
00452 //****************************************
00453 
00454 EffectWindowGroup::~EffectWindowGroup()
00455     {
00456     }
00457 
00458 //****************************************
00459 // GlobalShortcutsEditor
00460 //****************************************
00461 
00462 GlobalShortcutsEditor::GlobalShortcutsEditor( QWidget *parent ) :
00463         KShortcutsEditor( parent, GlobalAction )
00464     {
00465     }
00466 
00467 /***************************************************************
00468  WindowQuad
00469 ***************************************************************/
00470 
00471 WindowQuad WindowQuad::makeSubQuad( double x1, double y1, double x2, double y2 ) const
00472     {
00473     assert( x1 < x2 && y1 < y2 && x1 >= left() && x2 <= right() && y1 >= top() && y2 <= bottom());
00474 #ifndef NDEBUG
00475     if( isTransformed())
00476         kFatal( 1212 ) << "Splitting quads is allowed only in pre-paint calls!" ;
00477 #endif
00478     WindowQuad ret( *this );
00479     // vertices are clockwise starting from topleft
00480     ret.verts[ 0 ].px = x1;
00481     ret.verts[ 3 ].px = x1;
00482     ret.verts[ 1 ].px = x2;
00483     ret.verts[ 2 ].px = x2;
00484     ret.verts[ 0 ].py = y1;
00485     ret.verts[ 1 ].py = y1;
00486     ret.verts[ 2 ].py = y2;
00487     ret.verts[ 3 ].py = y2;
00488     // original x/y are supposed to be the same, no transforming is done here
00489     ret.verts[ 0 ].ox = x1;
00490     ret.verts[ 3 ].ox = x1;
00491     ret.verts[ 1 ].ox = x2;
00492     ret.verts[ 2 ].ox = x2;
00493     ret.verts[ 0 ].oy = y1;
00494     ret.verts[ 1 ].oy = y1;
00495     ret.verts[ 2 ].oy = y2;
00496     ret.verts[ 3 ].oy = y2;
00497     double my_tleft = verts[ 0 ].tx;
00498     double my_tright = verts[ 2 ].tx;
00499     double my_ttop = verts[ 0 ].ty;
00500     double my_tbottom = verts[ 2 ].ty;
00501     double tleft = ( x1 - left()) / ( right() - left()) * ( my_tright - my_tleft ) + my_tleft;
00502     double tright = ( x2 - left()) / ( right() - left()) * ( my_tright - my_tleft ) + my_tleft;
00503     double ttop = ( y1 - top()) / ( bottom() - top()) * ( my_tbottom - my_ttop ) + my_ttop;
00504     double tbottom = ( y2 - top()) / ( bottom() - top()) * ( my_tbottom - my_ttop ) + my_ttop;
00505     ret.verts[ 0 ].tx = tleft;
00506     ret.verts[ 3 ].tx = tleft;
00507     ret.verts[ 1 ].tx = tright;
00508     ret.verts[ 2 ].tx = tright;
00509     ret.verts[ 0 ].ty = ttop;
00510     ret.verts[ 1 ].ty = ttop;
00511     ret.verts[ 2 ].ty = tbottom;
00512     ret.verts[ 3 ].ty = tbottom;
00513     return ret;
00514     }
00515 
00516 bool WindowQuad::smoothNeeded() const
00517     {
00518     // smoothing is needed if the width or height of the quad does not match the original size
00519     double width = verts[ 1 ].ox - verts[ 0 ].ox;
00520     double height = verts[ 2 ].oy - verts[ 1 ].oy;
00521     return( verts[ 1 ].px - verts[ 0 ].px != width || verts[ 2 ].px - verts[ 3 ].px != width
00522         || verts[ 2 ].py - verts[ 1 ].py != height || verts[ 3 ].py - verts[ 0 ].py != height );
00523     }
00524 
00525 /***************************************************************
00526  WindowQuadList
00527 ***************************************************************/
00528 
00529 WindowQuadList WindowQuadList::splitAtX( double x ) const
00530     {
00531     WindowQuadList ret;
00532     foreach( WindowQuad quad, *this )
00533         {
00534 #ifndef NDEBUG
00535         if( quad.isTransformed())
00536             kFatal( 1212 ) << "Splitting quads is allowed only in pre-paint calls!" ;
00537 #endif
00538         bool wholeleft = true;
00539         bool wholeright = true;
00540         for( int i = 0;
00541              i < 4;
00542              ++i )
00543             {
00544             if( quad[ i ].x() < x )
00545                 wholeright = false;
00546             if( quad[ i ].x() >= x )
00547                 wholeleft = false;
00548             }
00549         if( wholeleft || wholeright ) // is whole in one split part
00550             {
00551             ret.append( quad );
00552             continue;
00553             }
00554         ret.append( quad.makeSubQuad( quad.left(), quad.top(), x, quad.bottom()));
00555         ret.append( quad.makeSubQuad( x, quad.top(), quad.right(), quad.bottom()));
00556         }
00557     return ret;
00558     }
00559 
00560 WindowQuadList WindowQuadList::splitAtY( double y ) const
00561     {
00562     WindowQuadList ret;
00563     foreach( WindowQuad quad, *this )
00564         {
00565 #ifndef NDEBUG
00566         if( quad.isTransformed())
00567             kFatal( 1212 ) << "Splitting quads is allowed only in pre-paint calls!" ;
00568 #endif
00569         bool wholetop = true;
00570         bool wholebottom = true;
00571         for( int i = 0;
00572              i < 4;
00573              ++i )
00574             {
00575             if( quad[ i ].y() < y )
00576                 wholebottom = false;
00577             if( quad[ i ].y() >= y )
00578                 wholetop = false;
00579             }
00580         if( wholetop || wholebottom ) // is whole in one split part
00581             {
00582             ret.append( quad );
00583             continue;
00584             }
00585         ret.append( quad.makeSubQuad( quad.left(), quad.top(), quad.right(), y ));
00586         ret.append( quad.makeSubQuad( quad.left(), y, quad.right(), quad.bottom()));
00587         }
00588     return ret;
00589     }
00590 
00591 WindowQuadList WindowQuadList::makeGrid( int maxquadsize ) const
00592     {
00593     if( empty())
00594         return *this;
00595     // find the bounding rectangle
00596     double left = first().left();
00597     double right = first().right();
00598     double top = first().top();
00599     double bottom = first().bottom();
00600     foreach( WindowQuad quad, *this )
00601         {
00602 #ifndef NDEBUG
00603         if( quad.isTransformed())
00604             kFatal( 1212 ) << "Splitting quads is allowed only in pre-paint calls!" ;
00605 #endif
00606         left = qMin( left, quad.left());
00607         right = qMax( right, quad.right());
00608         top = qMin( top, quad.top());
00609         bottom = qMax( bottom, quad.bottom());
00610         }
00611     WindowQuadList ret;
00612     for( double x = left;
00613          x < right;
00614          x += maxquadsize )
00615         {
00616         for( double y = top;
00617              y < bottom;
00618              y += maxquadsize )
00619             {
00620             foreach( WindowQuad quad, *this )
00621                 {
00622                 if( QRectF( QPointF( quad.left(), quad.top()), QPointF( quad.right(), quad.bottom()))
00623                     .intersects( QRectF( x, y, maxquadsize, maxquadsize )))
00624                     {
00625                     ret.append( quad.makeSubQuad( qMax( x, quad.left()), qMax( y, quad.top()),
00626                         qMin( quad.right(), x + maxquadsize ), qMin( quad.bottom(), y + maxquadsize )));
00627                     }
00628                 }
00629             }
00630         }
00631     return ret;
00632     }
00633 
00634 WindowQuadList WindowQuadList::makeRegularGrid( int xSubdivisions, int ySubdivisions ) const
00635     {
00636     if( empty())
00637         return *this;
00638     // find the bounding rectangle
00639     double left = first().left();
00640     double right = first().right();
00641     double top = first().top();
00642     double bottom = first().bottom();
00643     foreach( WindowQuad quad, *this )
00644         {
00645 #ifndef NDEBUG
00646         if( quad.isTransformed())
00647             kFatal( 1212 ) << "Splitting quads is allowed only in pre-paint calls!" ;
00648 #endif
00649         left = qMin( left, quad.left());
00650         right = qMax( right, quad.right());
00651         top = qMin( top, quad.top());
00652         bottom = qMax( bottom, quad.bottom());
00653         }
00654 
00655     double xincrement = (right - left) / xSubdivisions;
00656     double yincrement = (bottom - top) / ySubdivisions;
00657     WindowQuadList ret;
00658     for( double y = top;
00659          y < bottom;
00660          y += yincrement )
00661         {
00662         for( double x = left;
00663              x < right;
00664              x +=  xincrement)
00665             {
00666             foreach( WindowQuad quad, *this )
00667                 {
00668                 if( QRectF( QPointF( quad.left(), quad.top()), QPointF( quad.right(), quad.bottom()))
00669                     .intersects( QRectF( x, y, xincrement, yincrement )))
00670                     {
00671                     ret.append( quad.makeSubQuad( qMax( x, quad.left()), qMax( y, quad.top()),
00672                         qMin( quad.right(), x + xincrement ), qMin( quad.bottom(), y + yincrement )));
00673                     }
00674                 }
00675             }
00676         }
00677     return ret;
00678     }
00679 
00680 void WindowQuadList::makeArrays( float** vertices, float** texcoords ) const
00681     {
00682     *vertices = new float[ count() * 4 * 2 ];
00683     *texcoords = new float[ count() * 4 * 2 ];
00684     float* vpos = *vertices;
00685     float* tpos = *texcoords;
00686     for( int i = 0;
00687          i < count();
00688          ++i )
00689         for( int j = 0;
00690              j < 4;
00691              ++j )
00692             {
00693             *vpos++ = at( i )[ j ].x();
00694             *vpos++ = at( i )[ j ].y();
00695             *tpos++ = at( i )[ j ].tx;
00696             *tpos++ = at( i )[ j ].ty;
00697             }
00698     }
00699 
00700 WindowQuadList WindowQuadList::select( WindowQuadType type ) const
00701     {
00702     foreach( WindowQuad q, *this )
00703         {
00704         if( q.type != type ) // something else than ones to select, make a copy and filter
00705             {
00706             WindowQuadList ret;
00707             foreach( WindowQuad q, *this )
00708                 {
00709                 if( q.type == type )
00710                     ret.append( q );
00711                 }
00712             return ret;
00713             }
00714         }
00715     return *this; // nothing to filter out
00716     }
00717 
00718 WindowQuadList WindowQuadList::filterOut( WindowQuadType type ) const
00719     {
00720     foreach( WindowQuad q, *this )
00721         {
00722         if( q.type == type ) // something to filter out, make a copy and filter
00723             {
00724             WindowQuadList ret;
00725             foreach( WindowQuad q, *this )
00726                 {
00727                 if( q.type != type )
00728                     ret.append( q );
00729                 }
00730             return ret;
00731             }
00732         }
00733     return *this; // nothing to filter out
00734     }
00735 
00736 bool WindowQuadList::smoothNeeded() const
00737     {
00738     foreach( WindowQuad q, *this )
00739         if( q.smoothNeeded())
00740             return true;
00741     return false;
00742     }
00743 
00744 /***************************************************************
00745  PaintClipper
00746 ***************************************************************/
00747 
00748 QStack< QRegion >* PaintClipper::areas = NULL;
00749 
00750 PaintClipper::PaintClipper( const QRegion& allowed_area )
00751     : area( allowed_area )
00752     {
00753     push( area );
00754     }
00755 
00756 PaintClipper::~PaintClipper()
00757     {
00758     pop( area );
00759     }
00760 
00761 void PaintClipper::push( const QRegion& allowed_area )
00762     {
00763     if( allowed_area == infiniteRegion()) // don't push these
00764         return;
00765     if( areas == NULL )
00766         areas = new QStack< QRegion >;
00767     areas->push( allowed_area );
00768     }
00769 
00770 void PaintClipper::pop( const QRegion& allowed_area )
00771     {
00772     if( allowed_area == infiniteRegion())
00773         return;
00774     Q_ASSERT( areas != NULL );
00775     Q_ASSERT( areas->top() == allowed_area );
00776     areas->pop();
00777     if( areas->isEmpty())
00778         {
00779         delete areas;
00780         areas = NULL;
00781         }
00782     }
00783 
00784 bool PaintClipper::clip()
00785     {
00786     return areas != NULL;
00787     }
00788 
00789 QRegion PaintClipper::paintArea()
00790     {
00791     assert( areas != NULL ); // can be called only with clip() == true
00792     QRegion ret = QRegion( 0, 0, displayWidth(), displayHeight());
00793     foreach( QRegion r, *areas )
00794         ret &= r;
00795     return ret;
00796     }
00797 
00798 struct PaintClipper::Iterator::Data
00799     {
00800     Data() : index( 0 ) {}
00801     int index;
00802 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00803     QVector< QRect > rects;
00804 #endif
00805     };
00806 
00807 PaintClipper::Iterator::Iterator()
00808     : data( new Data )
00809     {
00810 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00811     if( clip() && effects->compositingType() == OpenGLCompositing )
00812         {
00813         glPushAttrib( GL_SCISSOR_BIT );
00814         glEnable( GL_SCISSOR_TEST );
00815         data->rects = paintArea().rects();
00816         data->index = -1;
00817         next(); // move to the first one
00818         }
00819 #endif
00820 #ifdef KWIN_HAVE_XRENDER_COMPOSITING
00821     if( clip() && effects->compositingType() == XRenderCompositing )
00822         {
00823         XserverRegion region = toXserverRegion( paintArea());
00824         XFixesSetPictureClipRegion( display(), effects->xrenderBufferPicture(), 0, 0, region );
00825         XFixesDestroyRegion( display(), region ); // it's ref-counted
00826         }
00827 #endif
00828     }
00829 
00830 PaintClipper::Iterator::~Iterator()
00831     {
00832 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00833     if( clip() && effects->compositingType() == OpenGLCompositing )
00834         glPopAttrib();
00835 #endif
00836 #ifdef KWIN_HAVE_XRENDER_COMPOSITING
00837     if( clip() && effects->compositingType() == XRenderCompositing )
00838         XFixesSetPictureClipRegion( display(), effects->xrenderBufferPicture(), 0, 0, None );
00839 #endif
00840     delete data;
00841     }
00842 
00843 bool PaintClipper::Iterator::isDone()
00844     {
00845     if( !clip())
00846         return data->index == 1; // run once
00847 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00848     if( effects->compositingType() == OpenGLCompositing )
00849         return data->index >= data->rects.count(); // run once per each area
00850 #endif
00851 #ifdef KWIN_HAVE_XRENDER_COMPOSITING
00852     if( effects->compositingType() == XRenderCompositing )
00853         return data->index == 1; // run once
00854 #endif
00855     abort();
00856     }
00857 
00858 void PaintClipper::Iterator::next()
00859     {
00860     data->index++;
00861 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00862     if( clip() && effects->compositingType() == OpenGLCompositing && data->index < data->rects.count())
00863         {
00864         const QRect& r = data->rects[ data->index ];
00865         // Scissor rect has to be given in OpenGL coords
00866         glScissor( r.x(), displayHeight() - r.y() - r.height(), r.width(), r.height());
00867         }
00868 #endif
00869     }
00870 
00871 QRect PaintClipper::Iterator::boundingRect() const
00872     {
00873     if( !clip())
00874         return infiniteRegion();
00875 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00876     if( effects->compositingType() == OpenGLCompositing )
00877         return data->rects[ data->index ];
00878 #endif
00879 #ifdef KWIN_HAVE_XRENDER_COMPOSITING
00880     if( effects->compositingType() == XRenderCompositing )
00881         return paintArea().boundingRect();
00882 #endif
00883     abort();
00884     return infiniteRegion();
00885     }
00886 
00887 
00888 /***************************************************************
00889  TimeLine
00890 ***************************************************************/
00891 
00892 TimeLine::TimeLine(const int duration)
00893     {
00894     m_Time = 0;
00895     m_CurveShape = TimeLine::EaseInCurve;
00896     m_Duration = duration;
00897     m_TimeLine = new QTimeLine(m_Duration);
00898     m_TimeLine->setFrameRange(0, m_Duration);
00899     m_TimeLine->setCurveShape(QTimeLine::EaseInCurve);
00900     }
00901 
00902 TimeLine::TimeLine(const TimeLine &other)
00903     {
00904     m_Time = other.m_Time;
00905     m_CurveShape = other.m_CurveShape;
00906     m_Duration = other.m_Duration;
00907     m_TimeLine = new QTimeLine(m_Duration);
00908     m_TimeLine->setFrameRange(0, m_Duration);
00909     setProgress(m_Progress);
00910     setCurveShape(m_CurveShape);
00911     }
00912 
00913 TimeLine::~TimeLine()
00914     {
00915     delete m_TimeLine;
00916     }
00917 
00918 int TimeLine::duration() const
00919     {
00920     return m_Duration;
00921     }
00922 
00923 void TimeLine::setDuration(const int msec)
00924     {
00925     m_Duration = msec;
00926     m_TimeLine->setDuration(msec);
00927     }
00928 
00929 double TimeLine::value() const
00930     {
00931     return valueForTime(m_Time);
00932     }
00933 
00934 double TimeLine::valueForTime(const int msec) const
00935     {
00936     // Catch non QTimeLine CurveShapes here, (but there are none right now)
00937 
00938 
00939     // else use QTimeLine ...
00940     return m_TimeLine->valueForTime(msec);
00941     }
00942 
00943 void TimeLine::addTime(const int msec)
00944     {
00945     m_Time = qMin(m_Duration, m_Time + msec);
00946     m_Progress = (double)m_Time / m_Duration;
00947     }
00948 
00949 void TimeLine::removeTime(const int msec)
00950     {
00951     m_Time = qMax(0, m_Time - msec);
00952     m_Progress = (double)m_Time / m_Duration;
00953     }
00954 
00955 void TimeLine::setProgress(const double progress)
00956     {
00957     m_Progress = progress;
00958     m_Time = qRound(m_Duration * progress);
00959     }
00960 
00961 double TimeLine::progress() const
00962     {
00963     return m_Progress;
00964     }
00965 
00966 int TimeLine::time() const
00967     {
00968     return m_Time;
00969     }
00970 
00971 void TimeLine::addProgress(const double progress)
00972     {
00973     m_Progress += progress;
00974     m_Time = (int)(m_Duration * m_Progress);
00975     }
00976 
00977 void TimeLine::setCurveShape(CurveShape curveShape)
00978     {
00979     switch (curveShape)
00980         {
00981         case EaseInCurve:
00982             m_TimeLine->setCurveShape(QTimeLine::EaseInCurve);
00983             break;
00984         case EaseOutCurve:
00985             m_TimeLine->setCurveShape(QTimeLine::EaseOutCurve);
00986             break;
00987         case EaseInOutCurve:
00988             m_TimeLine->setCurveShape(QTimeLine::EaseInOutCurve);
00989             break;
00990         case LinearCurve:
00991             m_TimeLine->setCurveShape(QTimeLine::LinearCurve);
00992             break;
00993         case SineCurve:
00994             m_TimeLine->setCurveShape(QTimeLine::SineCurve);
00995             break;
00996         }
00997         m_CurveShape = curveShape;
00998     }
00999 
01000 } // namespace

KWinLibraries

Skip menu "KWinLibraries"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libplasma
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal