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

KWin

effects.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 "effects.h"
00022 
00023 #include "deleted.h"
00024 #include "client.h"
00025 #include "group.h"
00026 #include "scene_xrender.h"
00027 #include "scene_opengl.h"
00028 #include "unmanaged.h"
00029 #include "workspace.h"
00030 #include "kwinglutils.h"
00031 
00032 #include <QFile>
00033 
00034 #include "kdebug.h"
00035 #include "klibloader.h"
00036 #include "kdesktopfile.h"
00037 #include "kconfiggroup.h"
00038 #include "kstandarddirs.h"
00039 #include <kservice.h>
00040 #include <kservicetypetrader.h>
00041 #include <kplugininfo.h>
00042 
00043 #include <assert.h>
00044 
00045 
00046 namespace KWin
00047 {
00048 
00049 
00050 EffectsHandlerImpl::EffectsHandlerImpl(CompositingType type)
00051     : EffectsHandler(type)
00052     , keyboard_grab_effect( NULL )
00053     , fullscreen_effect( 0 )
00054     {
00055     reconfigure();
00056     }
00057 
00058 EffectsHandlerImpl::~EffectsHandlerImpl()
00059     {
00060     if( keyboard_grab_effect != NULL )
00061         ungrabKeyboard();
00062     foreach( const EffectPair &ep, loaded_effects )
00063         unloadEffect( ep.first );
00064     foreach( const InputWindowPair &pos, input_windows )
00065         XDestroyWindow( display(), pos.second );
00066     }
00067 
00068 void EffectsHandlerImpl::reconfigure()
00069     {
00070     KSharedConfig::Ptr _config = KGlobal::config();
00071     KConfigGroup conf(_config, "Plugins");
00072 
00073     KService::List offers = KServiceTypeTrader::self()->query("KWin/Effect");
00074     QStringList effectsToBeLoaded;
00075     // First unload necessary effects
00076     foreach( const KService::Ptr &service, offers )
00077         {
00078         KPluginInfo plugininfo( service );
00079         plugininfo.load( conf );
00080 
00081         bool isloaded = isEffectLoaded( plugininfo.pluginName() );
00082         bool shouldbeloaded = plugininfo.isPluginEnabled();
00083         if( !shouldbeloaded && isloaded )
00084             unloadEffect( plugininfo.pluginName() );
00085         if( shouldbeloaded )
00086             effectsToBeLoaded.append( plugininfo.pluginName() );
00087         }
00088     // Then load those that should be loaded
00089     foreach( const QString &effectName, effectsToBeLoaded )
00090         {
00091         if( !isEffectLoaded( effectName ))
00092             {
00093             loadEffect( effectName );
00094             }
00095         }
00096     }
00097 
00098 // the idea is that effects call this function again which calls the next one
00099 void EffectsHandlerImpl::prePaintScreen( ScreenPrePaintData& data, int time )
00100     {
00101     if( current_paint_screen < loaded_effects.size())
00102         {
00103         loaded_effects[current_paint_screen++].second->prePaintScreen( data, time );
00104         --current_paint_screen;
00105         }
00106     // no special final code
00107     }
00108 
00109 void EffectsHandlerImpl::paintScreen( int mask, QRegion region, ScreenPaintData& data )
00110     {
00111     if( current_paint_screen < loaded_effects.size())
00112         {
00113         loaded_effects[current_paint_screen++].second->paintScreen( mask, region, data );
00114         --current_paint_screen;
00115         }
00116     else
00117         scene->finalPaintScreen( mask, region, data );
00118     }
00119 
00120 void EffectsHandlerImpl::postPaintScreen()
00121     {
00122     if( current_paint_screen < loaded_effects.size())
00123         {
00124         loaded_effects[current_paint_screen++].second->postPaintScreen();
00125         --current_paint_screen;
00126         }
00127     // no special final code
00128     }
00129 
00130 void EffectsHandlerImpl::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
00131     {
00132     if( current_paint_window < loaded_effects.size())
00133         {
00134         loaded_effects[current_paint_window++].second->prePaintWindow( w, data, time );
00135         --current_paint_window;
00136         }
00137     // no special final code
00138     }
00139 
00140 void EffectsHandlerImpl::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
00141     {
00142     if( current_paint_window < loaded_effects.size())
00143         {
00144         loaded_effects[current_paint_window++].second->paintWindow( w, mask, region, data );
00145         --current_paint_window;
00146         }
00147     else
00148         scene->finalPaintWindow( static_cast<EffectWindowImpl*>( w ), mask, region, data );
00149     }
00150 
00151 void EffectsHandlerImpl::postPaintWindow( EffectWindow* w )
00152     {
00153     if( current_paint_window < loaded_effects.size())
00154         {
00155         loaded_effects[current_paint_window++].second->postPaintWindow( w );
00156         --current_paint_window;
00157         }
00158     // no special final code
00159     }
00160 
00161 void EffectsHandlerImpl::drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
00162     {
00163     if( current_draw_window < loaded_effects.size())
00164         {
00165         loaded_effects[current_draw_window++].second->drawWindow( w, mask, region, data );
00166         --current_draw_window;
00167         }
00168     else
00169         scene->finalDrawWindow( static_cast<EffectWindowImpl*>( w ), mask, region, data );
00170     }
00171 
00172 // start another painting pass
00173 void EffectsHandlerImpl::startPaint()
00174     {
00175     assert( current_paint_screen == 0 );
00176     assert( current_paint_window == 0 );
00177     assert( current_draw_window == 0 );
00178     assert( current_transform == 0 );
00179     }
00180 
00181 void EffectsHandlerImpl::windowUserMovedResized( EffectWindow* c, bool first, bool last )
00182     {
00183     foreach( const EffectPair &ep, loaded_effects )
00184         ep.second->windowUserMovedResized( c, first, last );
00185     }
00186 
00187 void EffectsHandlerImpl::windowOpacityChanged( EffectWindow* c, double old_opacity )
00188     {
00189     if( static_cast<EffectWindowImpl*>(c)->window()->opacity() == old_opacity )
00190         return;
00191     foreach( const EffectPair &ep, loaded_effects )
00192         ep.second->windowOpacityChanged( c, old_opacity );
00193     }
00194 
00195 void EffectsHandlerImpl::windowAdded( EffectWindow* c )
00196     {
00197     foreach( const EffectPair &ep, loaded_effects )
00198         ep.second->windowAdded( c );
00199     }
00200 
00201 void EffectsHandlerImpl::windowDeleted( EffectWindow* c )
00202     {
00203     foreach( const EffectPair &ep, loaded_effects )
00204         ep.second->windowDeleted( c );
00205     elevated_windows.removeAll( c );
00206     }
00207 
00208 void EffectsHandlerImpl::windowClosed( EffectWindow* c )
00209     {
00210     foreach( const EffectPair &ep, loaded_effects )
00211         ep.second->windowClosed( c );
00212     }
00213 
00214 void EffectsHandlerImpl::windowActivated( EffectWindow* c )
00215     {
00216     foreach( const EffectPair &ep, loaded_effects )
00217         ep.second->windowActivated( c );
00218     }
00219 
00220 void EffectsHandlerImpl::windowMinimized( EffectWindow* c )
00221     {
00222     foreach( const EffectPair &ep, loaded_effects )
00223         ep.second->windowMinimized( c );
00224     }
00225 
00226 void EffectsHandlerImpl::windowUnminimized( EffectWindow* c )
00227     {
00228     foreach( const EffectPair &ep, loaded_effects )
00229         ep.second->windowUnminimized( c );
00230     }
00231 
00232 void EffectsHandlerImpl::desktopChanged( int old )
00233     {
00234     foreach( const EffectPair &ep, loaded_effects )
00235         ep.second->desktopChanged( old );
00236     }
00237 
00238 void EffectsHandlerImpl::windowDamaged( EffectWindow* w, const QRect& r )
00239     {
00240     if( w == NULL )
00241         return;
00242     foreach( const EffectPair &ep, loaded_effects )
00243         ep.second->windowDamaged( w, r );
00244     }
00245 
00246 void EffectsHandlerImpl::windowGeometryShapeChanged( EffectWindow* w, const QRect& old )
00247     {
00248     if( w == NULL ) // during late cleanup effectWindow() may be already NULL
00249         return;     // in some functions that may still call this
00250     foreach( const EffectPair &ep, loaded_effects )
00251         ep.second->windowGeometryShapeChanged( w, old );
00252     }
00253 
00254 void EffectsHandlerImpl::tabBoxAdded( int mode )
00255     {
00256     foreach( const EffectPair &ep, loaded_effects )
00257         ep.second->tabBoxAdded( mode );
00258     }
00259 
00260 void EffectsHandlerImpl::tabBoxClosed()
00261     {
00262     foreach( const EffectPair &ep, loaded_effects )
00263         ep.second->tabBoxClosed();
00264     }
00265 
00266 void EffectsHandlerImpl::tabBoxUpdated()
00267     {
00268     foreach( const EffectPair &ep, loaded_effects )
00269         ep.second->tabBoxUpdated();
00270     }
00271 
00272 void EffectsHandlerImpl::setActiveFullScreenEffect( Effect* e )
00273     {
00274     fullscreen_effect = e;
00275     }
00276 
00277 Effect* EffectsHandlerImpl::activeFullScreenEffect() const
00278     {
00279     return fullscreen_effect;
00280     }
00281 
00282 bool EffectsHandlerImpl::borderActivated( ElectricBorder border )
00283     {
00284     bool ret = false;
00285     foreach( const EffectPair &ep, loaded_effects )
00286         if( ep.second->borderActivated( border ))
00287             ret = true; // bail out or tell all?
00288     return ret;
00289     }
00290 
00291 void EffectsHandlerImpl::mouseChanged( const QPoint& pos, const QPoint& oldpos,
00292     Qt::MouseButtons buttons, Qt::MouseButtons oldbuttons,
00293     Qt::KeyboardModifiers modifiers, Qt::KeyboardModifiers oldmodifiers )
00294     {
00295     foreach( const EffectPair &ep, loaded_effects )
00296         ep.second->mouseChanged( pos, oldpos, buttons, oldbuttons, modifiers, oldmodifiers );
00297     }
00298 
00299 bool EffectsHandlerImpl::grabKeyboard( Effect* effect )
00300     {
00301     if( keyboard_grab_effect != NULL )
00302         return false;
00303     bool ret = grabXKeyboard();
00304     if( !ret )
00305         return false;
00306     keyboard_grab_effect = effect;
00307     return true;
00308     }
00309 
00310 void EffectsHandlerImpl::ungrabKeyboard()
00311     {
00312     assert( keyboard_grab_effect != NULL );
00313     ungrabXKeyboard();
00314     keyboard_grab_effect = NULL;
00315     }
00316 
00317 void EffectsHandlerImpl::grabbedKeyboardEvent( QKeyEvent* e )
00318     {
00319     if( keyboard_grab_effect != NULL )
00320         keyboard_grab_effect->grabbedKeyboardEvent( e );
00321     }
00322 
00323 bool EffectsHandlerImpl::hasKeyboardGrab() const
00324     {
00325     return keyboard_grab_effect != NULL;
00326     }
00327 
00328 void EffectsHandlerImpl::propertyNotify( EffectWindow* c, long atom )
00329     {
00330     if( !registered_atoms.contains( atom ))
00331         return;
00332     foreach( const EffectPair &ep, loaded_effects )
00333         ep.second->propertyNotify( c, atom );
00334     }
00335 
00336 void EffectsHandlerImpl::registerPropertyType( long atom, bool reg )
00337     {
00338     if( reg )
00339         ++registered_atoms[ atom ]; // initialized to 0 if not present yet
00340     else
00341         {
00342         if( --registered_atoms[ atom ] == 0 )
00343             registered_atoms.remove( atom );
00344         }
00345     }
00346 
00347 void EffectsHandlerImpl::activateWindow( EffectWindow* c )
00348     {
00349     if( Client* cl = dynamic_cast< Client* >( static_cast<EffectWindowImpl*>(c)->window()))
00350         Workspace::self()->activateClient( cl, true );
00351     }
00352 
00353 EffectWindow* EffectsHandlerImpl::activeWindow() const
00354     {
00355     return Workspace::self()->activeClient() ? Workspace::self()->activeClient()->effectWindow() : NULL;
00356     }
00357 
00358 void EffectsHandlerImpl::moveWindow( EffectWindow* w, const QPoint& pos )
00359     {
00360     Client* cl = dynamic_cast< Client* >( static_cast<EffectWindowImpl*>(w)->window());
00361     if( cl && cl->isMovable())
00362         cl->move( pos );
00363     }
00364 
00365 void EffectsHandlerImpl::windowToDesktop( EffectWindow* w, int desktop )
00366     {
00367     Client* cl = dynamic_cast< Client* >( static_cast<EffectWindowImpl*>(w)->window());
00368     if( cl && !cl->isDesktop() && !cl->isDock() && !cl->isTopMenu())
00369         Workspace::self()->sendClientToDesktop( cl, desktop, true );
00370     }
00371 
00372 int EffectsHandlerImpl::currentDesktop() const
00373     {
00374     return Workspace::self()->currentDesktop();
00375     }
00376 
00377 int EffectsHandlerImpl::numberOfDesktops() const
00378     {
00379     return Workspace::self()->numberOfDesktops();
00380     }
00381 
00382 void EffectsHandlerImpl::setCurrentDesktop( int desktop )
00383     {
00384     Workspace::self()->setCurrentDesktop( desktop );
00385     }
00386 
00387 QString EffectsHandlerImpl::desktopName( int desktop ) const
00388     {
00389     return Workspace::self()->desktopName( desktop );
00390     }
00391 
00392 void EffectsHandlerImpl::calcDesktopLayout(int* x, int* y, Qt::Orientation* orientation) const
00393     {
00394     Workspace::self()->calcDesktopLayout( x, y, orientation );
00395     }
00396 
00397 bool EffectsHandlerImpl::optionRollOverDesktops() const
00398     {
00399     return options->rollOverDesktops;
00400     }
00401 
00402 int EffectsHandlerImpl::desktopToLeft( int desktop, bool wrap ) const
00403     {
00404     return Workspace::self()->desktopToLeft( desktop, wrap );
00405     }
00406 
00407 int EffectsHandlerImpl::desktopToRight( int desktop, bool wrap ) const
00408     {
00409     return Workspace::self()->desktopToRight( desktop, wrap );
00410     }
00411 
00412 int EffectsHandlerImpl::desktopUp( int desktop, bool wrap ) const
00413     {
00414     return Workspace::self()->desktopUp( desktop, wrap );
00415     }
00416 
00417 int EffectsHandlerImpl::desktopDown( int desktop, bool wrap ) const
00418     {
00419     return Workspace::self()->desktopDown( desktop, wrap );
00420     }
00421 
00422 int EffectsHandlerImpl::displayWidth() const
00423     {
00424     return KWin::displayWidth();
00425     }
00426 
00427 int EffectsHandlerImpl::displayHeight() const
00428     {
00429     return KWin::displayWidth();
00430     }
00431 
00432 EffectWindow* EffectsHandlerImpl::findWindow( WId id ) const
00433     {
00434     if( Client* w = Workspace::self()->findClient( WindowMatchPredicate( id )))
00435         return w->effectWindow();
00436     if( Unmanaged* w = Workspace::self()->findUnmanaged( WindowMatchPredicate( id )))
00437         return w->effectWindow();
00438     return NULL;
00439     }
00440 
00441 EffectWindowList EffectsHandlerImpl::stackingOrder() const
00442     {
00443     ClientList list = Workspace::self()->stackingOrder();
00444     EffectWindowList ret;
00445     foreach( Client* c, list )
00446         ret.append( effectWindow( c ));
00447     return ret;
00448     }
00449 
00450 void EffectsHandlerImpl::setElevatedWindow( EffectWindow* w, bool set )
00451     {
00452     elevated_windows.removeAll( w );
00453     if( set )
00454         elevated_windows.append( w );
00455     }
00456 
00457 void EffectsHandlerImpl::setTabBoxWindow(EffectWindow* w)
00458     {
00459     if( Client* c = dynamic_cast< Client* >( static_cast< EffectWindowImpl* >( w )->window()))
00460         Workspace::self()->setTabBoxClient( c );
00461     }
00462 
00463 void EffectsHandlerImpl::setTabBoxDesktop(int desktop)
00464     {
00465     Workspace::self()->setTabBoxDesktop( desktop );
00466     }
00467 
00468 EffectWindowList EffectsHandlerImpl::currentTabBoxWindowList() const
00469     {
00470     EffectWindowList ret;
00471     ClientList clients = Workspace::self()->currentTabBoxClientList();
00472     foreach( Client* c, clients )
00473         ret.append( c->effectWindow());
00474     return ret;
00475     }
00476 
00477 void EffectsHandlerImpl::refTabBox()
00478     {
00479     Workspace::self()->refTabBox();
00480     }
00481 
00482 void EffectsHandlerImpl::unrefTabBox()
00483     {
00484     Workspace::self()->unrefTabBox();
00485     }
00486 
00487 void EffectsHandlerImpl::closeTabBox()
00488     {
00489     Workspace::self()->closeTabBox();
00490     }
00491 
00492 QList< int > EffectsHandlerImpl::currentTabBoxDesktopList() const
00493     {
00494     return Workspace::self()->currentTabBoxDesktopList();
00495     }
00496 
00497 int EffectsHandlerImpl::currentTabBoxDesktop() const
00498     {
00499     return Workspace::self()->currentTabBoxDesktop();
00500     }
00501 
00502 EffectWindow* EffectsHandlerImpl::currentTabBoxWindow() const
00503     {
00504     if( Client* c = Workspace::self()->currentTabBoxClient())
00505         return c->effectWindow();
00506     return NULL;
00507     }
00508 
00509 void EffectsHandlerImpl::pushRenderTarget(GLRenderTarget* target)
00510 {
00511 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00512     target->enable();
00513     render_targets.push(target);
00514 #endif
00515 }
00516 
00517 GLRenderTarget* EffectsHandlerImpl::popRenderTarget()
00518 {
00519 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
00520     GLRenderTarget* ret = render_targets.pop();
00521     ret->disable();
00522     if( !render_targets.isEmpty() )
00523         render_targets.top()->enable();
00524     return ret;
00525 #else
00526     return 0;
00527 #endif
00528 }
00529 
00530 void EffectsHandlerImpl::addRepaintFull()
00531     {
00532     Workspace::self()->addRepaintFull();
00533     }
00534 
00535 void EffectsHandlerImpl::addRepaint( const QRect& r )
00536     {
00537     Workspace::self()->addRepaint( r );
00538     }
00539 
00540 void EffectsHandlerImpl::addRepaint( const QRegion& r )
00541     {
00542     Workspace::self()->addRepaint( r );
00543     }
00544 
00545 void EffectsHandlerImpl::addRepaint( int x, int y, int w, int h )
00546     {
00547     Workspace::self()->addRepaint( x, y, w, h );
00548     }
00549 
00550 int EffectsHandlerImpl::activeScreen() const
00551     {
00552     return Workspace::self()->activeScreen();
00553     }
00554 
00555 int EffectsHandlerImpl::numScreens() const
00556     {
00557     return Workspace::self()->numScreens();
00558     }
00559 
00560 int EffectsHandlerImpl::screenNumber( const QPoint& pos ) const
00561     {
00562     return Workspace::self()->screenNumber( pos );
00563     }
00564 
00565 QRect EffectsHandlerImpl::clientArea( clientAreaOption opt, int screen, int desktop ) const
00566     {
00567     return Workspace::self()->clientArea( opt, screen, desktop );
00568     }
00569 
00570 QRect EffectsHandlerImpl::clientArea( clientAreaOption opt, const EffectWindow* c ) const
00571     {
00572     const Toplevel* t = static_cast< const EffectWindowImpl* >(c)->window();
00573     if( const Client* cl = dynamic_cast< const Client* >( t ))
00574         return Workspace::self()->clientArea( opt, cl );
00575     else
00576         return Workspace::self()->clientArea( opt, t->geometry().center(), Workspace::self()->currentDesktop());
00577     }
00578 
00579 QRect EffectsHandlerImpl::clientArea( clientAreaOption opt, const QPoint& p, int desktop ) const
00580     {
00581     return Workspace::self()->clientArea( opt, p, desktop );
00582     }
00583 
00584 Window EffectsHandlerImpl::createInputWindow( Effect* e, int x, int y, int w, int h, const QCursor& cursor )
00585     {
00586     XSetWindowAttributes attrs;
00587     attrs.override_redirect = True;
00588     Window win = XCreateWindow( display(), rootWindow(), x, y, w, h, 0, 0, InputOnly, CopyFromParent,
00589         CWOverrideRedirect, &attrs );
00590     // TODO keeping on top?
00591     // TODO enter/leave notify?
00592     XSelectInput( display(), win, ButtonPressMask | ButtonReleaseMask | PointerMotionMask );
00593     XDefineCursor( display(), win, cursor.handle());
00594     XMapWindow( display(), win );
00595     input_windows.append( qMakePair( e, win ));
00596     return win;
00597     }
00598 
00599 void EffectsHandlerImpl::destroyInputWindow( Window w )
00600     {
00601     foreach( const InputWindowPair &pos, input_windows )
00602         {
00603         if( pos.second == w )
00604             {
00605             input_windows.removeAll( pos );
00606             XDestroyWindow( display(), w );
00607             return;
00608             }
00609         }
00610     assert( false );
00611     }
00612 
00613 bool EffectsHandlerImpl::checkInputWindowEvent( XEvent* e )
00614     {
00615     if( e->type != ButtonPress && e->type != ButtonRelease && e->type != MotionNotify )
00616         return false;
00617     foreach( const InputWindowPair &pos, input_windows )
00618         {
00619         if( pos.second == e->xany.window )
00620             {
00621             switch( e->type )
00622                 {
00623                 case ButtonPress:
00624                     {
00625                     XButtonEvent* e2 = &e->xbutton;
00626                     Qt::MouseButton button = x11ToQtMouseButton( e2->button );
00627                     Qt::MouseButtons buttons = x11ToQtMouseButtons( e2->state ) | button;
00628                     QMouseEvent ev( QEvent::MouseButtonPress,
00629                         QPoint( e2->x, e2->y ), QPoint( e2->x_root, e2->y_root ),
00630                         button, buttons, x11ToQtKeyboardModifiers( e2->state ));
00631                     pos.first->windowInputMouseEvent( pos.second, &ev );
00632                     break; // --->
00633                     }
00634                 case ButtonRelease:
00635                     {
00636                     XButtonEvent* e2 = &e->xbutton;
00637                     Qt::MouseButton button = x11ToQtMouseButton( e2->button );
00638                     Qt::MouseButtons buttons = x11ToQtMouseButtons( e2->state ) & ~button;
00639                     QMouseEvent ev( QEvent::MouseButtonRelease,
00640                         QPoint( e2->x, e2->y ), QPoint( e2->x_root, e2->y_root ),
00641                         button, buttons, x11ToQtKeyboardModifiers( e2->state ));
00642                     pos.first->windowInputMouseEvent( pos.second, &ev );
00643                     break; // --->
00644                     }
00645                 case MotionNotify:
00646                     {
00647                     XMotionEvent* e2 = &e->xmotion;
00648                     QMouseEvent ev( QEvent::MouseMove, QPoint( e2->x, e2->y ), QPoint( e2->x_root, e2->y_root ),
00649                         Qt::NoButton, x11ToQtMouseButtons( e2->state ), x11ToQtKeyboardModifiers( e2->state ));
00650                     pos.first->windowInputMouseEvent( pos.second, &ev );
00651                     break; // --->
00652                     }
00653                 }
00654             return true; // eat event
00655             }
00656         }
00657     return false;
00658     }
00659 
00660 void EffectsHandlerImpl::checkInputWindowStacking()
00661     {
00662     if( input_windows.count() == 0 )
00663         return;
00664     Window* wins = new Window[ input_windows.count() ];
00665     int pos = 0;
00666     foreach( const InputWindowPair &it, input_windows )
00667         wins[ pos++ ] = it.second;
00668     XRaiseWindow( display(), wins[ 0 ] );
00669     XRestackWindows( display(), wins, pos );
00670     delete[] wins;
00671     }
00672 
00673 QPoint EffectsHandlerImpl::cursorPos() const
00674     {
00675     return Workspace::self()->cursorPos();
00676     }
00677 
00678 void EffectsHandlerImpl::checkElectricBorder(const QPoint &pos, Time time)
00679     {
00680     Workspace::self()->checkElectricBorder( pos, time );
00681     }
00682 
00683 void EffectsHandlerImpl::reserveElectricBorder( ElectricBorder border )
00684     {
00685     Workspace::self()->reserveElectricBorder( border );
00686     }
00687 
00688 void EffectsHandlerImpl::unreserveElectricBorder( ElectricBorder border )
00689     {
00690     Workspace::self()->unreserveElectricBorder( border );
00691     }
00692 
00693 void EffectsHandlerImpl::reserveElectricBorderSwitching( bool reserve )
00694     {
00695     Workspace::self()->reserveElectricBorderSwitching( reserve );
00696     }
00697 
00698 unsigned long EffectsHandlerImpl::xrenderBufferPicture()
00699     {
00700 #ifdef KWIN_HAVE_XRENDER_COMPOSITING
00701     if( SceneXrender* s = dynamic_cast< SceneXrender* >( scene ))
00702         return s->bufferPicture();
00703 #endif
00704     return None;
00705     }
00706 
00707 KLibrary* EffectsHandlerImpl::findEffectLibrary( KService* service )
00708     {
00709     QString libname = service->library();
00710     KLibrary* library = KLibLoader::self()->library(libname);
00711     if( !library )
00712         {
00713         kError( 1212 ) << "couldn't open library for effect '" <<
00714                 service->name() << "'" << endl;
00715         return 0;
00716         }
00717 
00718     return library;
00719     }
00720 
00721 void EffectsHandlerImpl::toggleEffect( const QString& name )
00722     {
00723     if( isEffectLoaded( name ))
00724         unloadEffect( name );
00725     else
00726         loadEffect( name );
00727     }
00728 
00729 QStringList EffectsHandlerImpl::loadedEffects() const
00730     {
00731     QStringList listModules;
00732     for(QVector< EffectPair >::const_iterator it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it)
00733         {
00734         listModules <<(*it).first;
00735         }
00736     return listModules;
00737     }
00738 
00739 QStringList EffectsHandlerImpl::listOfEffects() const
00740     {
00741     KService::List offers = KServiceTypeTrader::self()->query("KWin/Effect");
00742     QStringList listOfModules;
00743     // First unload necessary effects
00744     foreach( const KService::Ptr &service, offers )
00745         {
00746         KPluginInfo plugininfo( service );
00747         listOfModules<<plugininfo.pluginName();
00748         }
00749     return listOfModules;
00750     }
00751 
00752 bool EffectsHandlerImpl::loadEffect( const QString& name )
00753     {
00754     Workspace::self()->addRepaintFull();
00755     assert( current_paint_screen == 0 );
00756     assert( current_paint_window == 0 );
00757     assert( current_draw_window == 0 );
00758     assert( current_transform == 0 );
00759 
00760     if( !name.startsWith("kwin4_effect_") )
00761         kWarning( 1212 ) << "Effect names usually have kwin4_effect_ prefix" ;
00762 
00763     // Make sure a single effect won't be loaded multiple times
00764     for(QVector< EffectPair >::const_iterator it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); ++it)
00765         {
00766         if( (*it).first == name )
00767             {
00768             kDebug( 1212 ) << "EffectsHandler::loadEffect : Effect already loaded : " << name;
00769             return true;
00770             }
00771         }
00772 
00773 
00774     kDebug( 1212 ) << "Trying to load " << name;
00775     QString internalname = name.toLower();
00776 
00777     QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(internalname);
00778     KService::List offers = KServiceTypeTrader::self()->query("KWin/Effect", constraint);
00779     if(offers.isEmpty())
00780     {
00781         kError( 1212 ) << "Couldn't find effect " << name << endl;
00782         return false;
00783     }
00784     KService::Ptr service = offers.first();
00785 
00786     KLibrary* library = findEffectLibrary( service.data() );
00787     if( !library )
00788         {
00789         return false;
00790         }
00791 
00792     QString version_symbol = "effect_version_" + name;
00793     KLibrary::void_function_ptr version_func = library->resolveFunction(version_symbol.toAscii());
00794     if( version_func == NULL )
00795         {
00796         kWarning( 1212 ) << "Effect " << name << " does not provide required API version, ignoring.";
00797         return false;
00798         }
00799     typedef int (*t_versionfunc)();
00800     int version = reinterpret_cast< t_versionfunc >( version_func )(); // call it
00801     // Version must be the same or less, but major must be the same.
00802     // With major 0 minor must match exactly.
00803     if( version > KWIN_EFFECT_API_VERSION
00804         || ( version >> 8 ) != KWIN_EFFECT_API_VERSION_MAJOR
00805         || ( KWIN_EFFECT_API_VERSION_MAJOR == 0 && version != KWIN_EFFECT_API_VERSION ))
00806         {
00807         kWarning( 1212 ) << "Effect " << name << " requires unsupported API version " << version;
00808         return false;
00809         }
00810     QString supported_symbol = "effect_supported_" + name;
00811     KLibrary::void_function_ptr supported_func = library->resolveFunction(supported_symbol.toAscii().data());
00812     QString create_symbol = "effect_create_" + name;
00813     KLibrary::void_function_ptr create_func = library->resolveFunction(create_symbol.toAscii().data());
00814     if( supported_func )
00815         {
00816         typedef bool (*t_supportedfunc)();
00817         t_supportedfunc supported = reinterpret_cast<t_supportedfunc>(supported_func);
00818         if(!supported())
00819             {
00820             kWarning( 1212 ) << "EffectsHandler::loadEffect : Effect " << name << " is not supported" ;
00821             library->unload();
00822             return false;
00823             }
00824         }
00825     if(!create_func)
00826         {
00827         kError( 1212 ) << "EffectsHandler::loadEffect : effect_create function not found" << endl;
00828         library->unload();
00829         return false;
00830         }
00831     typedef Effect* (*t_createfunc)();
00832     t_createfunc create = reinterpret_cast<t_createfunc>(create_func);
00833 
00834     // Make sure all depenedencies have been loaded
00835     // TODO: detect circular deps
00836     KPluginInfo plugininfo( service );
00837     QStringList dependencies = plugininfo.dependencies();
00838     foreach( const QString &depName, dependencies )
00839         {
00840         if( !loadEffect(depName))
00841             {
00842             kError() << "EffectsHandler::loadEffect : Couldn't load dependencies for effect " << name << endl;
00843             library->unload();
00844             return false;
00845             }
00846         }
00847 
00848     Effect* e = create();
00849 
00850     effect_order.insert( service->property( "X-KDE-Ordering" ).toInt(), EffectPair( name, e ));
00851     effectsChanged();
00852     effect_libraries[ name ] = library;
00853 
00854     return true;
00855     }
00856 
00857 void EffectsHandlerImpl::unloadEffect( const QString& name )
00858     {
00859     Workspace::self()->addRepaintFull();
00860     assert( current_paint_screen == 0 );
00861     assert( current_paint_window == 0 );
00862     assert( current_draw_window == 0 );
00863     assert( current_transform == 0 );
00864 
00865     for( QMap< int, EffectPair >::iterator it = effect_order.begin(); it != effect_order.end(); ++it)
00866         {
00867         if ( it.value().first == name )
00868             {
00869             kDebug( 1212 ) << "EffectsHandler::unloadEffect : Unloading Effect : " << name;
00870             if( activeFullScreenEffect() == it.value().second )
00871                 {
00872                 setActiveFullScreenEffect( 0 );
00873                 }
00874             delete it.value().second;
00875             effect_order.erase(it);
00876             effectsChanged();
00877             effect_libraries[ name ]->unload();
00878             return;
00879             }
00880         }
00881 
00882     kDebug( 1212 ) << "EffectsHandler::unloadEffect : Effect not loaded : " << name;
00883     }
00884 
00885 void EffectsHandlerImpl::reloadEffect( const QString& name )
00886     {
00887     if( isEffectLoaded( name ))
00888         {
00889         unloadEffect( name );
00890         loadEffect( name );
00891         }
00892     }
00893 
00894 bool EffectsHandlerImpl::isEffectLoaded( const QString& name )
00895     {
00896     for( QVector< EffectPair >::iterator it = loaded_effects.begin(); it != loaded_effects.end(); ++it)
00897         if ( (*it).first == name )
00898             return true;
00899 
00900     return false;
00901     }
00902 
00903 void EffectsHandlerImpl::effectsChanged()
00904     {
00905     loaded_effects.clear();
00906 //    kDebug(1212) << "Recreating effects' list:";
00907     foreach( const EffectPair &effect, effect_order )
00908         {
00909 //        kDebug(1212) << effect.first;
00910         loaded_effects.append( effect );
00911         }
00912     }
00913 
00914 
00915 //****************************************
00916 // EffectWindowImpl
00917 //****************************************
00918 
00919 EffectWindowImpl::EffectWindowImpl() : EffectWindow()
00920     , toplevel( NULL )
00921     , sw( NULL )
00922     {
00923     }
00924 
00925 EffectWindowImpl::~EffectWindowImpl()
00926     {
00927     }
00928 
00929 bool EffectWindowImpl::isPaintingEnabled()
00930     {
00931     return sceneWindow()->isPaintingEnabled();
00932     }
00933 
00934 void EffectWindowImpl::enablePainting( int reason )
00935     {
00936     sceneWindow()->enablePainting( reason );
00937     }
00938 
00939 void EffectWindowImpl::disablePainting( int reason )
00940     {
00941     sceneWindow()->disablePainting( reason );
00942     }
00943 
00944 void EffectWindowImpl::addRepaint( const QRect& r )
00945     {
00946     toplevel->addRepaint( r );
00947     }
00948 
00949 void EffectWindowImpl::addRepaint( int x, int y, int w, int h )
00950     {
00951     toplevel->addRepaint( x, y, w, h );
00952     }
00953 
00954 void EffectWindowImpl::addRepaintFull()
00955     {
00956     toplevel->addRepaintFull();
00957     }
00958 
00959 int EffectWindowImpl::desktop() const
00960     {
00961     return toplevel->desktop();
00962     }
00963 
00964 bool EffectWindowImpl::isOnAllDesktops() const
00965     {
00966     return desktop() == NET::OnAllDesktops;
00967     }
00968 
00969 QString EffectWindowImpl::caption() const
00970     {
00971     if( Client* c = dynamic_cast<Client*>( toplevel ))
00972         return c->caption();
00973     else
00974         return "";
00975     }
00976 
00977 QString EffectWindowImpl::windowClass() const
00978     {
00979     return toplevel->resourceName() + ' ' + toplevel->resourceClass();
00980     }
00981 
00982 QString EffectWindowImpl::windowRole() const
00983     {
00984     return toplevel->windowRole();
00985     }
00986 
00987 QPixmap EffectWindowImpl::icon() const
00988     {
00989     if( Client* c = dynamic_cast<Client*>( toplevel ))
00990         return c->icon();
00991     return QPixmap(); // TODO
00992     }
00993 
00994 const EffectWindowGroup* EffectWindowImpl::group() const
00995     {
00996     if( Client* c = dynamic_cast< Client* >( toplevel ))
00997         return c->group()->effectGroup();
00998     return NULL; // TODO
00999     }
01000 
01001 bool EffectWindowImpl::isMinimized() const
01002     {
01003     if( Client* c = dynamic_cast<Client*>( toplevel ))
01004         return c->isMinimized();
01005     else
01006         return false;
01007     }
01008 
01009 double EffectWindowImpl::opacity() const
01010     {
01011     return toplevel->opacity();
01012     }
01013 
01014 bool EffectWindowImpl::isDeleted() const
01015     {
01016     return (dynamic_cast<Deleted*>( toplevel ) != 0);
01017     }
01018 
01019 void EffectWindowImpl::refWindow()
01020     {
01021     if( Deleted* d = dynamic_cast< Deleted* >( toplevel ))
01022         return d->refWindow();
01023     abort(); // TODO
01024     }
01025 
01026 void EffectWindowImpl::unrefWindow()
01027     {
01028     if( Deleted* d = dynamic_cast< Deleted* >( toplevel ))
01029         return d->unrefWindow( true ); // delayed
01030     abort(); // TODO
01031     }
01032 
01033 void EffectWindowImpl::setWindow( Toplevel* w )
01034     {
01035     toplevel = w;
01036     }
01037 
01038 void EffectWindowImpl::setSceneWindow( Scene::Window* w )
01039     {
01040     sw = w;
01041     }
01042 
01043 int EffectWindowImpl::x() const
01044     {
01045     return toplevel->x();
01046     }
01047 
01048 int EffectWindowImpl::y() const
01049     {
01050     return toplevel->y();
01051     }
01052 
01053 int EffectWindowImpl::width() const
01054     {
01055     return toplevel->width();
01056     }
01057 
01058 int EffectWindowImpl::height() const
01059     {
01060     return toplevel->height();
01061     }
01062 
01063 QRect EffectWindowImpl::geometry() const
01064     {
01065     return toplevel->geometry();
01066     }
01067 
01068 QRegion EffectWindowImpl::shape() const
01069     {
01070     return sw ? sw->shape() : geometry();
01071     }
01072 
01073 int EffectWindowImpl::screen() const
01074     {
01075     return toplevel->screen();
01076     }
01077 
01078 bool EffectWindowImpl::hasOwnShape() const
01079     {
01080     return toplevel->shape();
01081     }
01082 
01083 QSize EffectWindowImpl::size() const
01084     {
01085     return toplevel->size();
01086     }
01087 
01088 QPoint EffectWindowImpl::pos() const
01089     {
01090     return toplevel->pos();
01091     }
01092 
01093 QRect EffectWindowImpl::rect() const
01094     {
01095     return toplevel->rect();
01096     }
01097 
01098 QRect EffectWindowImpl::contentsRect() const
01099     {
01100     return QRect( toplevel->clientPos(), toplevel->clientSize());
01101     }
01102 
01103 QByteArray EffectWindowImpl::readProperty( long atom, long type, int format ) const
01104     {
01105     int len = 32768;
01106     for(;;)
01107         {
01108         unsigned char* data;
01109         Atom rtype;
01110         int rformat;
01111         unsigned long nitems, after;
01112         if( XGetWindowProperty( QX11Info::display(), window()->window(),
01113             atom, 0, len, False, AnyPropertyType,
01114             &rtype, &rformat, &nitems, &after, &data ) == Success )
01115             {
01116             if( after > 0 )
01117                 {
01118                 XFree( data );
01119                 len *= 2;
01120                 continue;
01121                 }
01122             if( long( rtype ) == type && rformat == format )
01123                 {
01124                 int bytelen = format == 8 ? nitems : format == 16 ? nitems * sizeof( short ) : nitems * sizeof( long );
01125                 QByteArray ret( reinterpret_cast< const char* >( data ), bytelen );
01126                 XFree( data );
01127                 return ret;
01128                 }
01129             else // wrong format, type or something
01130                 {
01131                 XFree( data );
01132                 return QByteArray();
01133                 }
01134             }
01135         else // XGetWindowProperty() failed
01136             return QByteArray();
01137         }
01138     }
01139 
01140 bool EffectWindowImpl::isMovable() const
01141     {
01142     if( Client* c = dynamic_cast< Client* >( toplevel ))
01143         return c->isMovable();
01144     return false;
01145     }
01146 
01147 bool EffectWindowImpl::isUserMove() const
01148     {
01149     if( Client* c = dynamic_cast< Client* >( toplevel ))
01150         return c->isMove();
01151     return false;
01152     }
01153 
01154 bool EffectWindowImpl::isUserResize() const
01155     {
01156     if( Client* c = dynamic_cast< Client* >( toplevel ))
01157         return c->isResize();
01158     return false;
01159     }
01160 
01161 QRect EffectWindowImpl::iconGeometry() const
01162     {
01163     if( Client* c = dynamic_cast< Client* >( toplevel ))
01164         return c->iconGeometry();
01165     return QRect();
01166     }
01167 
01168 bool EffectWindowImpl::isDesktop() const
01169     {
01170     return toplevel->isDesktop();
01171     }
01172 
01173 bool EffectWindowImpl::isDock() const
01174     {
01175     return toplevel->isDock();
01176     }
01177 
01178 bool EffectWindowImpl::isToolbar() const
01179     {
01180     return toplevel->isToolbar();
01181     }
01182 
01183 bool EffectWindowImpl::isTopMenu() const
01184     {
01185     return toplevel->isTopMenu();
01186     }
01187 
01188 bool EffectWindowImpl::isMenu() const
01189     {
01190     return toplevel->isMenu();
01191     }
01192 
01193 bool EffectWindowImpl::isNormalWindow() const
01194     {
01195     return toplevel->isNormalWindow();
01196     }
01197 
01198 bool EffectWindowImpl::isSpecialWindow() const
01199     {
01200     if( Client* c = dynamic_cast<Client*>( toplevel ))
01201         return c->isSpecialWindow();
01202     else
01203         return true;
01204     }
01205 
01206 bool EffectWindowImpl::isDialog() const
01207     {
01208     return toplevel->isDialog();
01209     }
01210 
01211 bool EffectWindowImpl::isSplash() const
01212     {
01213     return toplevel->isSplash();
01214     }
01215 
01216 bool EffectWindowImpl::isUtility() const
01217     {
01218     return toplevel->isUtility();
01219     }
01220 
01221 bool EffectWindowImpl::isDropdownMenu() const
01222     {
01223     return toplevel->isDropdownMenu();
01224     }
01225 
01226 bool EffectWindowImpl::isPopupMenu() const
01227     {
01228     return toplevel->isPopupMenu();
01229     }
01230 
01231 bool EffectWindowImpl::isTooltip() const
01232     {
01233     return toplevel->isTooltip();
01234     }
01235 
01236 bool EffectWindowImpl::isNotification() const
01237     {
01238     return toplevel->isNotification();
01239     }
01240 
01241 bool EffectWindowImpl::isComboBox() const
01242     {
01243     return toplevel->isComboBox();
01244     }
01245 
01246 bool EffectWindowImpl::isDNDIcon() const
01247     {
01248     return toplevel->isDNDIcon();
01249     }
01250 
01251 bool EffectWindowImpl::isManaged() const
01252     {
01253     return dynamic_cast< const Client* >( toplevel ) != NULL;
01254     }
01255 
01256 bool EffectWindowImpl::isModal() const
01257     {
01258     if( Client* c = dynamic_cast< Client* >( toplevel ))
01259         return c->isModal();
01260     return false;
01261     }
01262 
01263 EffectWindow* EffectWindowImpl::findModal()
01264     {
01265     if( Client* c = dynamic_cast< Client* >( toplevel ))
01266         {
01267         if( Client* c2 = c->findModal())
01268             return c2->effectWindow();
01269         }
01270     return NULL;
01271     }
01272 
01273 EffectWindowList EffectWindowImpl::mainWindows() const
01274     {
01275     if( Client* c = dynamic_cast< Client* >( toplevel ))
01276         {
01277         EffectWindowList ret;
01278         ClientList mainclients = c->mainClients();
01279         foreach( Client* tmp, mainclients )
01280             ret.append( tmp->effectWindow());
01281         return ret;
01282         }
01283     return EffectWindowList();
01284     }
01285 
01286 WindowQuadList EffectWindowImpl::buildQuads() const
01287     {
01288     return sceneWindow()->buildQuads();
01289     }
01290 
01291 EffectWindow* effectWindow( Toplevel* w )
01292     {
01293     EffectWindowImpl* ret = w->effectWindow();
01294     return ret;
01295     }
01296 
01297 EffectWindow* effectWindow( Scene::Window* w )
01298     {
01299     EffectWindowImpl* ret = w->window()->effectWindow();
01300     ret->setSceneWindow( w );
01301     return ret;
01302     }
01303 
01304 //****************************************
01305 // EffectWindowGroupImpl
01306 //****************************************
01307 
01308 
01309 EffectWindowList EffectWindowGroupImpl::members() const
01310     {
01311     EffectWindowList ret;
01312     foreach( Toplevel* c, group->members())
01313         ret.append( c->effectWindow());
01314     return ret;
01315     }
01316 
01317 } // namespace

KWin

Skip menu "KWin"
  • Main Page
  • 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