00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
00089 foreach( const QString &effectName, effectsToBeLoaded )
00090 {
00091 if( !isEffectLoaded( effectName ))
00092 {
00093 loadEffect( effectName );
00094 }
00095 }
00096 }
00097
00098
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
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
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
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
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
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 )
00249 return;
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;
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 ];
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
00591
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;
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
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
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 )();
00801
00802
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
00835
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
00907 foreach( const EffectPair &effect, effect_order )
00908 {
00909
00910 loaded_effects.append( effect );
00911 }
00912 }
00913
00914
00915
00916
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();
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;
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();
01024 }
01025
01026 void EffectWindowImpl::unrefWindow()
01027 {
01028 if( Deleted* d = dynamic_cast< Deleted* >( toplevel ))
01029 return d->unrefWindow( true );
01030 abort();
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
01130 {
01131 XFree( data );
01132 return QByteArray();
01133 }
01134 }
01135 else
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
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 }