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