1 /********************************************************************
2 KWin - the KDE window manager
3 This file is part of the KDE project.
5 Copyright (C) 2006 Lubos Lunak <l.lunak@kde.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *********************************************************************/
26 #include "scene_xrender.h"
27 #include "scene_opengl.h"
28 #include "unmanaged.h"
29 #include "workspace.h"
30 #include "kwinglutils.h"
35 #include "klibloader.h"
36 #include "kdesktopfile.h"
37 #include "kconfiggroup.h"
38 #include "kstandarddirs.h"
40 #include <kservicetypetrader.h>
41 #include <kplugininfo.h>
50 EffectsHandlerImpl::EffectsHandlerImpl(CompositingType type
)
51 : EffectsHandler(type
)
52 , keyboard_grab_effect( NULL
)
53 , fullscreen_effect( 0 )
54 , next_window_quad_type( EFFECT_QUAD_TYPE_START
)
59 EffectsHandlerImpl::~EffectsHandlerImpl()
61 if( keyboard_grab_effect
!= NULL
)
63 foreach( const EffectPair
&ep
, loaded_effects
)
64 unloadEffect( ep
.first
);
65 foreach( const InputWindowPair
&pos
, input_windows
)
66 XDestroyWindow( display(), pos
.second
);
69 void EffectsHandlerImpl::reconfigure()
71 KSharedConfig::Ptr _config
= KGlobal::config();
72 KConfigGroup
conf(_config
, "Plugins");
74 KService::List offers
= KServiceTypeTrader::self()->query("KWin/Effect");
75 QStringList effectsToBeLoaded
;
76 // First unload necessary effects
77 foreach( const KService::Ptr
&service
, offers
)
79 KPluginInfo
plugininfo( service
);
80 plugininfo
.load( conf
);
82 bool isloaded
= isEffectLoaded( plugininfo
.pluginName() );
83 bool shouldbeloaded
= plugininfo
.isPluginEnabled();
84 if( !shouldbeloaded
&& isloaded
)
85 unloadEffect( plugininfo
.pluginName() );
87 effectsToBeLoaded
.append( plugininfo
.pluginName() );
89 QStringList newLoaded
;
90 // Then load those that should be loaded
91 foreach( const QString
&effectName
, effectsToBeLoaded
)
93 if( !isEffectLoaded( effectName
))
95 loadEffect( effectName
);
96 newLoaded
.append( effectName
);
99 foreach( const EffectPair
&ep
, loaded_effects
)
101 if( !newLoaded
.contains( ep
.first
)) // don't reconfigure newly loaded effects
102 ep
.second
->reconfigure( Effect::ReconfigureAll
);
106 // the idea is that effects call this function again which calls the next one
107 void EffectsHandlerImpl::prePaintScreen( ScreenPrePaintData
& data
, int time
)
109 if( current_paint_screen
< loaded_effects
.size())
111 loaded_effects
[current_paint_screen
++].second
->prePaintScreen( data
, time
);
112 --current_paint_screen
;
114 // no special final code
117 void EffectsHandlerImpl::paintScreen( int mask
, QRegion region
, ScreenPaintData
& data
)
119 if( current_paint_screen
< loaded_effects
.size())
121 loaded_effects
[current_paint_screen
++].second
->paintScreen( mask
, region
, data
);
122 --current_paint_screen
;
125 scene
->finalPaintScreen( mask
, region
, data
);
128 void EffectsHandlerImpl::postPaintScreen()
130 if( current_paint_screen
< loaded_effects
.size())
132 loaded_effects
[current_paint_screen
++].second
->postPaintScreen();
133 --current_paint_screen
;
135 // no special final code
138 void EffectsHandlerImpl::prePaintWindow( EffectWindow
* w
, WindowPrePaintData
& data
, int time
)
140 if( current_paint_window
< loaded_effects
.size())
142 loaded_effects
[current_paint_window
++].second
->prePaintWindow( w
, data
, time
);
143 --current_paint_window
;
145 // no special final code
148 void EffectsHandlerImpl::paintWindow( EffectWindow
* w
, int mask
, QRegion region
, WindowPaintData
& data
)
150 if( current_paint_window
< loaded_effects
.size())
152 loaded_effects
[current_paint_window
++].second
->paintWindow( w
, mask
, region
, data
);
153 --current_paint_window
;
156 scene
->finalPaintWindow( static_cast<EffectWindowImpl
*>( w
), mask
, region
, data
);
159 void EffectsHandlerImpl::postPaintWindow( EffectWindow
* w
)
161 if( current_paint_window
< loaded_effects
.size())
163 loaded_effects
[current_paint_window
++].second
->postPaintWindow( w
);
164 --current_paint_window
;
166 // no special final code
169 void EffectsHandlerImpl::drawWindow( EffectWindow
* w
, int mask
, QRegion region
, WindowPaintData
& data
)
171 if( current_draw_window
< loaded_effects
.size())
173 loaded_effects
[current_draw_window
++].second
->drawWindow( w
, mask
, region
, data
);
174 --current_draw_window
;
177 scene
->finalDrawWindow( static_cast<EffectWindowImpl
*>( w
), mask
, region
, data
);
180 void EffectsHandlerImpl::buildQuads( EffectWindow
* w
, WindowQuadList
& quadList
)
182 if( current_build_quads
< loaded_effects
.size())
184 loaded_effects
[current_build_quads
++].second
->buildQuads( w
, quadList
);
185 --current_build_quads
;
189 bool EffectsHandlerImpl::hasDecorationShadows() const
191 return Workspace::self()->hasDecorationShadows();
194 QList
< QList
<QImage
> > EffectsHandlerImpl::shadowTextures()
196 return Workspace::self()->decorationShadowTextures();
199 int EffectsHandlerImpl::shadowTextureList( ShadowType type
) const
201 return Workspace::self()->decorationShadowTextureList( type
);
204 // start another painting pass
205 void EffectsHandlerImpl::startPaint()
207 assert( current_paint_screen
== 0 );
208 assert( current_paint_window
== 0 );
209 assert( current_draw_window
== 0 );
210 assert( current_build_quads
== 0 );
211 assert( current_transform
== 0 );
214 void EffectsHandlerImpl::windowUserMovedResized( EffectWindow
* c
, bool first
, bool last
)
216 foreach( const EffectPair
&ep
, loaded_effects
)
217 ep
.second
->windowUserMovedResized( c
, first
, last
);
220 void EffectsHandlerImpl::windowOpacityChanged( EffectWindow
* c
, double old_opacity
)
222 if( static_cast<EffectWindowImpl
*>(c
)->window()->opacity() == old_opacity
)
224 foreach( const EffectPair
&ep
, loaded_effects
)
225 ep
.second
->windowOpacityChanged( c
, old_opacity
);
228 void EffectsHandlerImpl::windowAdded( EffectWindow
* c
)
230 foreach( const EffectPair
&ep
, loaded_effects
)
231 ep
.second
->windowAdded( c
);
234 void EffectsHandlerImpl::windowDeleted( EffectWindow
* c
)
236 foreach( const EffectPair
&ep
, loaded_effects
)
237 ep
.second
->windowDeleted( c
);
238 elevated_windows
.removeAll( c
);
241 void EffectsHandlerImpl::windowClosed( EffectWindow
* c
)
243 foreach( const EffectPair
&ep
, loaded_effects
)
244 ep
.second
->windowClosed( c
);
247 void EffectsHandlerImpl::windowActivated( EffectWindow
* c
)
249 foreach( const EffectPair
&ep
, loaded_effects
)
250 ep
.second
->windowActivated( c
);
253 void EffectsHandlerImpl::windowMinimized( EffectWindow
* c
)
255 foreach( const EffectPair
&ep
, loaded_effects
)
256 ep
.second
->windowMinimized( c
);
259 void EffectsHandlerImpl::windowUnminimized( EffectWindow
* c
)
261 foreach( const EffectPair
&ep
, loaded_effects
)
262 ep
.second
->windowUnminimized( c
);
265 void EffectsHandlerImpl::desktopChanged( int old
)
267 foreach( const EffectPair
&ep
, loaded_effects
)
268 ep
.second
->desktopChanged( old
);
271 void EffectsHandlerImpl::windowDamaged( EffectWindow
* w
, const QRect
& r
)
275 foreach( const EffectPair
&ep
, loaded_effects
)
276 ep
.second
->windowDamaged( w
, r
);
279 void EffectsHandlerImpl::windowGeometryShapeChanged( EffectWindow
* w
, const QRect
& old
)
281 if( w
== NULL
) // during late cleanup effectWindow() may be already NULL
282 return; // in some functions that may still call this
283 foreach( const EffectPair
&ep
, loaded_effects
)
284 ep
.second
->windowGeometryShapeChanged( w
, old
);
287 void EffectsHandlerImpl::tabBoxAdded( int mode
)
289 foreach( const EffectPair
&ep
, loaded_effects
)
290 ep
.second
->tabBoxAdded( mode
);
293 void EffectsHandlerImpl::tabBoxClosed()
295 foreach( const EffectPair
&ep
, loaded_effects
)
296 ep
.second
->tabBoxClosed();
299 void EffectsHandlerImpl::tabBoxUpdated()
301 foreach( const EffectPair
&ep
, loaded_effects
)
302 ep
.second
->tabBoxUpdated();
305 void EffectsHandlerImpl::setActiveFullScreenEffect( Effect
* e
)
307 fullscreen_effect
= e
;
308 Workspace::self()->checkUnredirect();
311 Effect
* EffectsHandlerImpl::activeFullScreenEffect() const
313 return fullscreen_effect
;
316 bool EffectsHandlerImpl::borderActivated( ElectricBorder border
)
319 foreach( const EffectPair
&ep
, loaded_effects
)
320 if( ep
.second
->borderActivated( border
))
321 ret
= true; // bail out or tell all?
325 void EffectsHandlerImpl::mouseChanged( const QPoint
& pos
, const QPoint
& oldpos
,
326 Qt::MouseButtons buttons
, Qt::MouseButtons oldbuttons
,
327 Qt::KeyboardModifiers modifiers
, Qt::KeyboardModifiers oldmodifiers
)
329 foreach( const EffectPair
&ep
, loaded_effects
)
330 ep
.second
->mouseChanged( pos
, oldpos
, buttons
, oldbuttons
, modifiers
, oldmodifiers
);
333 bool EffectsHandlerImpl::grabKeyboard( Effect
* effect
)
335 if( keyboard_grab_effect
!= NULL
)
337 bool ret
= grabXKeyboard();
340 keyboard_grab_effect
= effect
;
344 void EffectsHandlerImpl::ungrabKeyboard()
346 assert( keyboard_grab_effect
!= NULL
);
348 keyboard_grab_effect
= NULL
;
351 void EffectsHandlerImpl::grabbedKeyboardEvent( QKeyEvent
* e
)
353 if( keyboard_grab_effect
!= NULL
)
354 keyboard_grab_effect
->grabbedKeyboardEvent( e
);
357 bool EffectsHandlerImpl::hasKeyboardGrab() const
359 return keyboard_grab_effect
!= NULL
;
362 void EffectsHandlerImpl::propertyNotify( EffectWindow
* c
, long atom
)
364 if( !registered_atoms
.contains( atom
))
366 foreach( const EffectPair
&ep
, loaded_effects
)
367 ep
.second
->propertyNotify( c
, atom
);
370 void EffectsHandlerImpl::registerPropertyType( long atom
, bool reg
)
373 ++registered_atoms
[ atom
]; // initialized to 0 if not present yet
376 if( --registered_atoms
[ atom
] == 0 )
377 registered_atoms
.remove( atom
);
381 void EffectsHandlerImpl::activateWindow( EffectWindow
* c
)
383 if( Client
* cl
= dynamic_cast< Client
* >( static_cast<EffectWindowImpl
*>(c
)->window()))
384 Workspace::self()->activateClient( cl
, true );
387 EffectWindow
* EffectsHandlerImpl::activeWindow() const
389 return Workspace::self()->activeClient() ? Workspace::self()->activeClient()->effectWindow() : NULL
;
392 void EffectsHandlerImpl::moveWindow( EffectWindow
* w
, const QPoint
& pos
)
394 Client
* cl
= dynamic_cast< Client
* >( static_cast<EffectWindowImpl
*>(w
)->window());
395 if( cl
&& cl
->isMovable())
399 void EffectsHandlerImpl::windowToDesktop( EffectWindow
* w
, int desktop
)
401 Client
* cl
= dynamic_cast< Client
* >( static_cast<EffectWindowImpl
*>(w
)->window());
402 if( cl
&& !cl
->isDesktop() && !cl
->isDock() && !cl
->isTopMenu())
403 Workspace::self()->sendClientToDesktop( cl
, desktop
, true );
406 int EffectsHandlerImpl::currentDesktop() const
408 return Workspace::self()->currentDesktop();
411 int EffectsHandlerImpl::numberOfDesktops() const
413 return Workspace::self()->numberOfDesktops();
416 void EffectsHandlerImpl::setCurrentDesktop( int desktop
)
418 Workspace::self()->setCurrentDesktop( desktop
);
421 QString
EffectsHandlerImpl::desktopName( int desktop
) const
423 return Workspace::self()->desktopName( desktop
);
426 void EffectsHandlerImpl::calcDesktopLayout(int* x
, int* y
, Qt::Orientation
* orientation
) const
428 Workspace::self()->calcDesktopLayout( x
, y
, orientation
);
431 bool EffectsHandlerImpl::optionRollOverDesktops() const
433 return options
->rollOverDesktops
;
436 int EffectsHandlerImpl::desktopToLeft( int desktop
, bool wrap
) const
438 return Workspace::self()->desktopToLeft( desktop
, wrap
);
441 int EffectsHandlerImpl::desktopToRight( int desktop
, bool wrap
) const
443 return Workspace::self()->desktopToRight( desktop
, wrap
);
446 int EffectsHandlerImpl::desktopUp( int desktop
, bool wrap
) const
448 return Workspace::self()->desktopUp( desktop
, wrap
);
451 int EffectsHandlerImpl::desktopDown( int desktop
, bool wrap
) const
453 return Workspace::self()->desktopDown( desktop
, wrap
);
456 double EffectsHandlerImpl::animationTimeFactor() const
458 return options
->animationTimeFactor();
461 WindowQuadType
EffectsHandlerImpl::newWindowQuadType()
463 return WindowQuadType( next_window_quad_type
++ );
466 int EffectsHandlerImpl::displayWidth() const
468 return KWin::displayWidth();
471 int EffectsHandlerImpl::displayHeight() const
473 return KWin::displayWidth();
476 EffectWindow
* EffectsHandlerImpl::findWindow( WId id
) const
478 if( Client
* w
= Workspace::self()->findClient( WindowMatchPredicate( id
)))
479 return w
->effectWindow();
480 if( Unmanaged
* w
= Workspace::self()->findUnmanaged( WindowMatchPredicate( id
)))
481 return w
->effectWindow();
485 EffectWindowList
EffectsHandlerImpl::stackingOrder() const
487 ClientList list
= Workspace::self()->stackingOrder();
488 EffectWindowList ret
;
489 foreach( Client
* c
, list
)
490 ret
.append( effectWindow( c
));
494 void EffectsHandlerImpl::setElevatedWindow( EffectWindow
* w
, bool set
)
496 elevated_windows
.removeAll( w
);
498 elevated_windows
.append( w
);
501 void EffectsHandlerImpl::setTabBoxWindow(EffectWindow
* w
)
503 if( Client
* c
= dynamic_cast< Client
* >( static_cast< EffectWindowImpl
* >( w
)->window()))
504 Workspace::self()->setTabBoxClient( c
);
507 void EffectsHandlerImpl::setTabBoxDesktop(int desktop
)
509 Workspace::self()->setTabBoxDesktop( desktop
);
512 EffectWindowList
EffectsHandlerImpl::currentTabBoxWindowList() const
514 EffectWindowList ret
;
515 ClientList clients
= Workspace::self()->currentTabBoxClientList();
516 foreach( Client
* c
, clients
)
517 ret
.append( c
->effectWindow());
521 void EffectsHandlerImpl::refTabBox()
523 Workspace::self()->refTabBox();
526 void EffectsHandlerImpl::unrefTabBox()
528 Workspace::self()->unrefTabBox();
531 void EffectsHandlerImpl::closeTabBox()
533 Workspace::self()->closeTabBox();
536 QList
< int > EffectsHandlerImpl::currentTabBoxDesktopList() const
538 return Workspace::self()->currentTabBoxDesktopList();
541 int EffectsHandlerImpl::currentTabBoxDesktop() const
543 return Workspace::self()->currentTabBoxDesktop();
546 EffectWindow
* EffectsHandlerImpl::currentTabBoxWindow() const
548 if( Client
* c
= Workspace::self()->currentTabBoxClient())
549 return c
->effectWindow();
553 void EffectsHandlerImpl::pushRenderTarget(GLRenderTarget
* target
)
555 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
557 render_targets
.push(target
);
561 GLRenderTarget
* EffectsHandlerImpl::popRenderTarget()
563 #ifdef KWIN_HAVE_OPENGL_COMPOSITING
564 GLRenderTarget
* ret
= render_targets
.pop();
566 if( !render_targets
.isEmpty() )
567 render_targets
.top()->enable();
574 void EffectsHandlerImpl::addRepaintFull()
576 Workspace::self()->addRepaintFull();
579 void EffectsHandlerImpl::addRepaint( const QRect
& r
)
581 Workspace::self()->addRepaint( r
);
584 void EffectsHandlerImpl::addRepaint( const QRegion
& r
)
586 Workspace::self()->addRepaint( r
);
589 void EffectsHandlerImpl::addRepaint( int x
, int y
, int w
, int h
)
591 Workspace::self()->addRepaint( x
, y
, w
, h
);
594 int EffectsHandlerImpl::activeScreen() const
596 return Workspace::self()->activeScreen();
599 int EffectsHandlerImpl::numScreens() const
601 return Workspace::self()->numScreens();
604 int EffectsHandlerImpl::screenNumber( const QPoint
& pos
) const
606 return Workspace::self()->screenNumber( pos
);
609 QRect
EffectsHandlerImpl::clientArea( clientAreaOption opt
, int screen
, int desktop
) const
611 return Workspace::self()->clientArea( opt
, screen
, desktop
);
614 QRect
EffectsHandlerImpl::clientArea( clientAreaOption opt
, const EffectWindow
* c
) const
616 const Toplevel
* t
= static_cast< const EffectWindowImpl
* >(c
)->window();
617 if( const Client
* cl
= dynamic_cast< const Client
* >( t
))
618 return Workspace::self()->clientArea( opt
, cl
);
620 return Workspace::self()->clientArea( opt
, t
->geometry().center(), Workspace::self()->currentDesktop());
623 QRect
EffectsHandlerImpl::clientArea( clientAreaOption opt
, const QPoint
& p
, int desktop
) const
625 return Workspace::self()->clientArea( opt
, p
, desktop
);
628 Window
EffectsHandlerImpl::createInputWindow( Effect
* e
, int x
, int y
, int w
, int h
, const QCursor
& cursor
)
630 XSetWindowAttributes attrs
;
631 attrs
.override_redirect
= True
;
632 Window win
= XCreateWindow( display(), rootWindow(), x
, y
, w
, h
, 0, 0, InputOnly
, CopyFromParent
,
633 CWOverrideRedirect
, &attrs
);
634 // TODO keeping on top?
635 // TODO enter/leave notify?
636 XSelectInput( display(), win
, ButtonPressMask
| ButtonReleaseMask
| PointerMotionMask
);
637 XDefineCursor( display(), win
, cursor
.handle());
638 XMapWindow( display(), win
);
639 input_windows
.append( qMakePair( e
, win
));
643 void EffectsHandlerImpl::destroyInputWindow( Window w
)
645 foreach( const InputWindowPair
&pos
, input_windows
)
647 if( pos
.second
== w
)
649 input_windows
.removeAll( pos
);
650 XDestroyWindow( display(), w
);
657 bool EffectsHandlerImpl::checkInputWindowEvent( XEvent
* e
)
659 if( e
->type
!= ButtonPress
&& e
->type
!= ButtonRelease
&& e
->type
!= MotionNotify
)
661 foreach( const InputWindowPair
&pos
, input_windows
)
663 if( pos
.second
== e
->xany
.window
)
669 XButtonEvent
* e2
= &e
->xbutton
;
670 Qt::MouseButton button
= x11ToQtMouseButton( e2
->button
);
671 Qt::MouseButtons buttons
= x11ToQtMouseButtons( e2
->state
) | button
;
672 QMouseEvent
ev( QEvent::MouseButtonPress
,
673 QPoint( e2
->x
, e2
->y
), QPoint( e2
->x_root
, e2
->y_root
),
674 button
, buttons
, x11ToQtKeyboardModifiers( e2
->state
));
675 pos
.first
->windowInputMouseEvent( pos
.second
, &ev
);
680 XButtonEvent
* e2
= &e
->xbutton
;
681 Qt::MouseButton button
= x11ToQtMouseButton( e2
->button
);
682 Qt::MouseButtons buttons
= x11ToQtMouseButtons( e2
->state
) & ~button
;
683 QMouseEvent
ev( QEvent::MouseButtonRelease
,
684 QPoint( e2
->x
, e2
->y
), QPoint( e2
->x_root
, e2
->y_root
),
685 button
, buttons
, x11ToQtKeyboardModifiers( e2
->state
));
686 pos
.first
->windowInputMouseEvent( pos
.second
, &ev
);
691 XMotionEvent
* e2
= &e
->xmotion
;
692 QMouseEvent
ev( QEvent::MouseMove
, QPoint( e2
->x
, e2
->y
), QPoint( e2
->x_root
, e2
->y_root
),
693 Qt::NoButton
, x11ToQtMouseButtons( e2
->state
), x11ToQtKeyboardModifiers( e2
->state
));
694 pos
.first
->windowInputMouseEvent( pos
.second
, &ev
);
698 return true; // eat event
704 void EffectsHandlerImpl::checkInputWindowStacking()
706 if( input_windows
.count() == 0 )
708 Window
* wins
= new Window
[ input_windows
.count() ];
710 foreach( const InputWindowPair
&it
, input_windows
)
711 wins
[ pos
++ ] = it
.second
;
712 XRaiseWindow( display(), wins
[ 0 ] );
713 XRestackWindows( display(), wins
, pos
);
717 QPoint
EffectsHandlerImpl::cursorPos() const
719 return Workspace::self()->cursorPos();
722 void EffectsHandlerImpl::checkElectricBorder(const QPoint
&pos
, Time time
)
724 Workspace::self()->checkElectricBorder( pos
, time
);
727 void EffectsHandlerImpl::reserveElectricBorder( ElectricBorder border
)
729 Workspace::self()->reserveElectricBorder( border
);
732 void EffectsHandlerImpl::unreserveElectricBorder( ElectricBorder border
)
734 Workspace::self()->unreserveElectricBorder( border
);
737 void EffectsHandlerImpl::reserveElectricBorderSwitching( bool reserve
)
739 Workspace::self()->reserveElectricBorderSwitching( reserve
);
742 unsigned long EffectsHandlerImpl::xrenderBufferPicture()
744 #ifdef KWIN_HAVE_XRENDER_COMPOSITING
745 if( SceneXrender
* s
= dynamic_cast< SceneXrender
* >( scene
))
746 return s
->bufferPicture();
751 KLibrary
* EffectsHandlerImpl::findEffectLibrary( KService
* service
)
753 QString libname
= service
->library();
754 KLibrary
* library
= KLibLoader::self()->library(libname
);
757 kError( 1212 ) << "couldn't open library for effect '" <<
758 service
->name() << "'" << endl
;
765 void EffectsHandlerImpl::toggleEffect( const QString
& name
)
767 if( isEffectLoaded( name
))
768 unloadEffect( name
);
773 QStringList
EffectsHandlerImpl::loadedEffects() const
775 QStringList listModules
;
776 for(QVector
< EffectPair
>::const_iterator it
= loaded_effects
.constBegin(); it
!= loaded_effects
.constEnd(); ++it
)
778 listModules
<<(*it
).first
;
783 QStringList
EffectsHandlerImpl::listOfEffects() const
785 KService::List offers
= KServiceTypeTrader::self()->query("KWin/Effect");
786 QStringList listOfModules
;
787 // First unload necessary effects
788 foreach( const KService::Ptr
&service
, offers
)
790 KPluginInfo
plugininfo( service
);
791 listOfModules
<<plugininfo
.pluginName();
793 return listOfModules
;
796 bool EffectsHandlerImpl::loadEffect( const QString
& name
)
798 Workspace::self()->addRepaintFull();
799 assert( current_paint_screen
== 0 );
800 assert( current_paint_window
== 0 );
801 assert( current_draw_window
== 0 );
802 assert( current_build_quads
== 0 );
803 assert( current_transform
== 0 );
805 if( !name
.startsWith("kwin4_effect_") )
806 kWarning( 1212 ) << "Effect names usually have kwin4_effect_ prefix" ;
808 // Make sure a single effect won't be loaded multiple times
809 for(QVector
< EffectPair
>::const_iterator it
= loaded_effects
.constBegin(); it
!= loaded_effects
.constEnd(); ++it
)
811 if( (*it
).first
== name
)
813 kDebug( 1212 ) << "EffectsHandler::loadEffect : Effect already loaded : " << name
;
819 kDebug( 1212 ) << "Trying to load " << name
;
820 QString internalname
= name
.toLower();
822 QString constraint
= QString("[X-KDE-PluginInfo-Name] == '%1'").arg(internalname
);
823 KService::List offers
= KServiceTypeTrader::self()->query("KWin/Effect", constraint
);
826 kError( 1212 ) << "Couldn't find effect " << name
<< endl
;
829 KService::Ptr service
= offers
.first();
831 KLibrary
* library
= findEffectLibrary( service
.data() );
837 QString version_symbol
= "effect_version_" + name
;
838 KLibrary::void_function_ptr version_func
= library
->resolveFunction(version_symbol
.toAscii());
839 if( version_func
== NULL
)
841 kWarning( 1212 ) << "Effect " << name
<< " does not provide required API version, ignoring.";
844 typedef int (*t_versionfunc
)();
845 int version
= reinterpret_cast< t_versionfunc
>( version_func
)(); // call it
846 // Version must be the same or less, but major must be the same.
847 // With major 0 minor must match exactly.
848 if( version
> KWIN_EFFECT_API_VERSION
849 || ( version
>> 8 ) != KWIN_EFFECT_API_VERSION_MAJOR
850 || ( KWIN_EFFECT_API_VERSION_MAJOR
== 0 && version
!= KWIN_EFFECT_API_VERSION
))
852 kWarning( 1212 ) << "Effect " << name
<< " requires unsupported API version " << version
;
855 QString supported_symbol
= "effect_supported_" + name
;
856 KLibrary::void_function_ptr supported_func
= library
->resolveFunction(supported_symbol
.toAscii().data());
857 QString create_symbol
= "effect_create_" + name
;
858 KLibrary::void_function_ptr create_func
= library
->resolveFunction(create_symbol
.toAscii().data());
861 typedef bool (*t_supportedfunc
)();
862 t_supportedfunc supported
= reinterpret_cast<t_supportedfunc
>(supported_func
);
865 kWarning( 1212 ) << "EffectsHandler::loadEffect : Effect " << name
<< " is not supported" ;
872 kError( 1212 ) << "EffectsHandler::loadEffect : effect_create function not found" << endl
;
876 typedef Effect
* (*t_createfunc
)();
877 t_createfunc create
= reinterpret_cast<t_createfunc
>(create_func
);
879 // Make sure all depenedencies have been loaded
880 // TODO: detect circular deps
881 KPluginInfo
plugininfo( service
);
882 QStringList dependencies
= plugininfo
.dependencies();
883 foreach( const QString
&depName
, dependencies
)
885 if( !loadEffect(depName
))
887 kError(1212) << "EffectsHandler::loadEffect : Couldn't load dependencies for effect " << name
<< endl
;
893 Effect
* e
= create();
895 effect_order
.insert( service
->property( "X-KDE-Ordering" ).toInt(), EffectPair( name
, e
));
897 effect_libraries
[ name
] = library
;
902 void EffectsHandlerImpl::unloadEffect( const QString
& name
)
904 Workspace::self()->addRepaintFull();
905 assert( current_paint_screen
== 0 );
906 assert( current_paint_window
== 0 );
907 assert( current_draw_window
== 0 );
908 assert( current_build_quads
== 0 );
909 assert( current_transform
== 0 );
911 for( QMap
< int, EffectPair
>::iterator it
= effect_order
.begin(); it
!= effect_order
.end(); ++it
)
913 if ( it
.value().first
== name
)
915 kDebug( 1212 ) << "EffectsHandler::unloadEffect : Unloading Effect : " << name
;
916 if( activeFullScreenEffect() == it
.value().second
)
918 setActiveFullScreenEffect( 0 );
920 delete it
.value().second
;
921 effect_order
.erase(it
);
923 effect_libraries
[ name
]->unload();
928 kDebug( 1212 ) << "EffectsHandler::unloadEffect : Effect not loaded : " << name
;
931 void EffectsHandlerImpl::reconfigureEffect( const QString
& name
)
933 for( QVector
< EffectPair
>::iterator it
= loaded_effects
.begin(); it
!= loaded_effects
.end(); ++it
)
934 if ( (*it
).first
== name
)
936 (*it
).second
->reconfigure( Effect::ReconfigureAll
);
941 bool EffectsHandlerImpl::isEffectLoaded( const QString
& name
)
943 for( QVector
< EffectPair
>::iterator it
= loaded_effects
.begin(); it
!= loaded_effects
.end(); ++it
)
944 if ( (*it
).first
== name
)
950 void EffectsHandlerImpl::effectsChanged()
952 loaded_effects
.clear();
953 // kDebug(1212) << "Recreating effects' list:";
954 foreach( const EffectPair
&effect
, effect_order
)
956 // kDebug(1212) << effect.first;
957 loaded_effects
.append( effect
);
962 //****************************************
964 //****************************************
966 EffectWindowImpl::EffectWindowImpl() : EffectWindow()
972 EffectWindowImpl::~EffectWindowImpl()
976 bool EffectWindowImpl::isPaintingEnabled()
978 return sceneWindow()->isPaintingEnabled();
981 void EffectWindowImpl::enablePainting( int reason
)
983 sceneWindow()->enablePainting( reason
);
986 void EffectWindowImpl::disablePainting( int reason
)
988 sceneWindow()->disablePainting( reason
);
991 void EffectWindowImpl::addRepaint( const QRect
& r
)
993 toplevel
->addRepaint( r
);
996 void EffectWindowImpl::addRepaint( int x
, int y
, int w
, int h
)
998 toplevel
->addRepaint( x
, y
, w
, h
);
1001 void EffectWindowImpl::addRepaintFull()
1003 toplevel
->addRepaintFull();
1006 int EffectWindowImpl::desktop() const
1008 return toplevel
->desktop();
1011 bool EffectWindowImpl::isOnAllDesktops() const
1013 return desktop() == NET::OnAllDesktops
;
1016 QString
EffectWindowImpl::caption() const
1018 if( Client
* c
= dynamic_cast<Client
*>( toplevel
))
1019 return c
->caption();
1024 QString
EffectWindowImpl::windowClass() const
1026 return toplevel
->resourceName() + ' ' + toplevel
->resourceClass();
1029 QString
EffectWindowImpl::windowRole() const
1031 return toplevel
->windowRole();
1034 QPixmap
EffectWindowImpl::icon() const
1036 if( Client
* c
= dynamic_cast<Client
*>( toplevel
))
1038 return QPixmap(); // TODO
1041 const EffectWindowGroup
* EffectWindowImpl::group() const
1043 if( Client
* c
= dynamic_cast< Client
* >( toplevel
))
1044 return c
->group()->effectGroup();
1045 return NULL
; // TODO
1048 bool EffectWindowImpl::isMinimized() const
1050 if( Client
* c
= dynamic_cast<Client
*>( toplevel
))
1051 return c
->isMinimized();
1056 double EffectWindowImpl::opacity() const
1058 return toplevel
->opacity();
1061 bool EffectWindowImpl::isDeleted() const
1063 return (dynamic_cast<Deleted
*>( toplevel
) != 0);
1066 void EffectWindowImpl::refWindow()
1068 if( Deleted
* d
= dynamic_cast< Deleted
* >( toplevel
))
1069 return d
->refWindow();
1073 void EffectWindowImpl::unrefWindow()
1075 if( Deleted
* d
= dynamic_cast< Deleted
* >( toplevel
))
1076 return d
->unrefWindow( true ); // delayed
1080 void EffectWindowImpl::setWindow( Toplevel
* w
)
1085 void EffectWindowImpl::setSceneWindow( Scene::Window
* w
)
1090 int EffectWindowImpl::x() const
1092 return toplevel
->x();
1095 int EffectWindowImpl::y() const
1097 return toplevel
->y();
1100 int EffectWindowImpl::width() const
1102 return toplevel
->width();
1105 int EffectWindowImpl::height() const
1107 return toplevel
->height();
1110 QRect
EffectWindowImpl::geometry() const
1112 return toplevel
->geometry();
1115 QRegion
EffectWindowImpl::shape() const
1117 return sw
? sw
->shape() : geometry();
1120 int EffectWindowImpl::screen() const
1122 return toplevel
->screen();
1125 bool EffectWindowImpl::hasOwnShape() const
1127 return toplevel
->shape();
1130 QSize
EffectWindowImpl::size() const
1132 return toplevel
->size();
1135 QPoint
EffectWindowImpl::pos() const
1137 return toplevel
->pos();
1140 QRect
EffectWindowImpl::rect() const
1142 return toplevel
->rect();
1145 QRect
EffectWindowImpl::contentsRect() const
1147 return QRect( toplevel
->clientPos(), toplevel
->clientSize());
1150 QByteArray
EffectWindowImpl::readProperty( long atom
, long type
, int format
) const
1155 unsigned char* data
;
1158 unsigned long nitems
, after
;
1159 if( XGetWindowProperty( QX11Info::display(), window()->window(),
1160 atom
, 0, len
, False
, AnyPropertyType
,
1161 &rtype
, &rformat
, &nitems
, &after
, &data
) == Success
)
1169 if( long( rtype
) == type
&& rformat
== format
)
1171 int bytelen
= format
== 8 ? nitems
: format
== 16 ? nitems
* sizeof( short ) : nitems
* sizeof( long );
1172 QByteArray
ret( reinterpret_cast< const char* >( data
), bytelen
);
1176 else // wrong format, type or something
1179 return QByteArray();
1182 else // XGetWindowProperty() failed
1183 return QByteArray();
1187 bool EffectWindowImpl::isMovable() const
1189 if( Client
* c
= dynamic_cast< Client
* >( toplevel
))
1190 return c
->isMovable();
1194 bool EffectWindowImpl::isMovableAcrossScreens() const
1196 if( Client
* c
= dynamic_cast< Client
* >( toplevel
))
1197 return c
->isMovableAcrossScreens();
1201 bool EffectWindowImpl::isUserMove() const
1203 if( Client
* c
= dynamic_cast< Client
* >( toplevel
))
1208 bool EffectWindowImpl::isUserResize() const
1210 if( Client
* c
= dynamic_cast< Client
* >( toplevel
))
1211 return c
->isResize();
1215 QRect
EffectWindowImpl::iconGeometry() const
1217 if( Client
* c
= dynamic_cast< Client
* >( toplevel
))
1218 return c
->iconGeometry();
1222 bool EffectWindowImpl::isDesktop() const
1224 return toplevel
->isDesktop();
1227 bool EffectWindowImpl::isDock() const
1229 return toplevel
->isDock();
1232 bool EffectWindowImpl::isToolbar() const
1234 return toplevel
->isToolbar();
1237 bool EffectWindowImpl::isTopMenu() const
1239 return toplevel
->isTopMenu();
1242 bool EffectWindowImpl::isMenu() const
1244 return toplevel
->isMenu();
1247 bool EffectWindowImpl::isNormalWindow() const
1249 return toplevel
->isNormalWindow();
1252 bool EffectWindowImpl::isSpecialWindow() const
1254 if( Client
* c
= dynamic_cast<Client
*>( toplevel
))
1255 return c
->isSpecialWindow();
1260 bool EffectWindowImpl::isDialog() const
1262 return toplevel
->isDialog();
1265 bool EffectWindowImpl::isSplash() const
1267 return toplevel
->isSplash();
1270 bool EffectWindowImpl::isUtility() const
1272 return toplevel
->isUtility();
1275 bool EffectWindowImpl::isDropdownMenu() const
1277 return toplevel
->isDropdownMenu();
1280 bool EffectWindowImpl::isPopupMenu() const
1282 return toplevel
->isPopupMenu();
1285 bool EffectWindowImpl::isTooltip() const
1287 return toplevel
->isTooltip();
1290 bool EffectWindowImpl::isNotification() const
1292 return toplevel
->isNotification();
1295 bool EffectWindowImpl::isComboBox() const
1297 return toplevel
->isComboBox();
1300 bool EffectWindowImpl::isDNDIcon() const
1302 return toplevel
->isDNDIcon();
1305 bool EffectWindowImpl::isManaged() const
1307 return dynamic_cast< const Client
* >( toplevel
) != NULL
;
1310 bool EffectWindowImpl::isModal() const
1312 if( Client
* c
= dynamic_cast< Client
* >( toplevel
))
1313 return c
->isModal();
1317 EffectWindow
* EffectWindowImpl::findModal()
1319 if( Client
* c
= dynamic_cast< Client
* >( toplevel
))
1321 if( Client
* c2
= c
->findModal())
1322 return c2
->effectWindow();
1327 EffectWindowList
EffectWindowImpl::mainWindows() const
1329 if( Client
* c
= dynamic_cast< Client
* >( toplevel
))
1331 EffectWindowList ret
;
1332 ClientList mainclients
= c
->mainClients();
1333 foreach( Client
* tmp
, mainclients
)
1334 ret
.append( tmp
->effectWindow());
1337 return EffectWindowList();
1340 QList
<QRect
> EffectWindowImpl::shadowQuads( ShadowType type
) const
1342 if( type
== ShadowBorderedActive
|| type
== ShadowBorderedInactive
)
1344 if( Client
* c
= dynamic_cast< Client
* >( toplevel
))
1345 return c
->shadowQuads( type
);
1346 return QList
<QRect
>();
1348 return toplevel
->workspace()->decorationShadowQuads( type
, toplevel
->size() );
1351 double EffectWindowImpl::shadowOpacity( ShadowType type
) const
1353 if( type
== ShadowBorderedActive
|| type
== ShadowBorderedInactive
)
1355 if( Client
* c
= dynamic_cast< Client
* >( toplevel
))
1356 return c
->shadowOpacity( type
);
1359 return toplevel
->workspace()->decorationShadowOpacity( type
);
1362 double EffectWindowImpl::shadowBrightness( ShadowType type
) const
1364 if( type
== ShadowBorderedActive
|| type
== ShadowBorderedInactive
)
1366 if( Client
* c
= dynamic_cast< Client
* >( toplevel
))
1367 return c
->shadowBrightness( type
);
1370 return toplevel
->workspace()->decorationShadowBrightness( type
);
1373 double EffectWindowImpl::shadowSaturation( ShadowType type
) const
1375 if( type
== ShadowBorderedActive
|| type
== ShadowBorderedInactive
)
1377 if( Client
* c
= dynamic_cast< Client
* >( toplevel
))
1378 return c
->shadowSaturation( type
);
1381 return toplevel
->workspace()->decorationShadowSaturation( type
);
1384 WindowQuadList
EffectWindowImpl::buildQuads( bool force
) const
1386 return sceneWindow()->buildQuads( force
);
1389 EffectWindow
* effectWindow( Toplevel
* w
)
1391 EffectWindowImpl
* ret
= w
->effectWindow();
1395 EffectWindow
* effectWindow( Scene::Window
* w
)
1397 EffectWindowImpl
* ret
= w
->window()->effectWindow();
1398 ret
->setSceneWindow( w
);
1402 //****************************************
1403 // EffectWindowGroupImpl
1404 //****************************************
1407 EffectWindowList
EffectWindowGroupImpl::members() const
1409 EffectWindowList ret
;
1410 foreach( Toplevel
* c
, group
->members())
1411 ret
.append( c
->effectWindow());