Shadows. Right not it's only flat black rectangle, but otherwise

everything should work.


svn path=/branches/work/kwin_composite/; revision=646315
This commit is contained in:
Luboš Luňák 2007-03-25 10:48:07 +00:00
parent 9da3b593ad
commit 8b5b40e4e8
47 changed files with 379 additions and 119 deletions

View file

@ -78,6 +78,7 @@ set(kwin_KDEINIT_SRCS
effects/fallapart.cpp
effects/drunken.cpp
effects/flame.cpp
effects/shadow.cpp
effects/test_input.cpp
effects/test_thumbnail.cpp
)

View file

@ -137,6 +137,9 @@ XRender TODO
+ SceneXrender::Window::performPaint() doesn't use saturation
+ SceneXrender::Window::performPaint() doesn't use brightness
+ SceneXrender::paintTransformedScreen() doesn't handle properly extending of painted area
in window's pre-paint - see the transformedShape() comment
Effects framework TODO
==============================
@ -146,7 +149,9 @@ Effects framework TODO
! - window state changes
? more
* shadows
/ shadows
+ - right now is only a rectangle, probably needs some shape support
+ - right now is only a flat black color, probably should be improved
/ support for grabbing input
- during some more complicated effects, input (at least mouse) should be disabled,
@ -178,7 +183,7 @@ Effects TODO
? - I don't think these effects should be plugins or anything like that,
probably simply write to kwinrc and use the Option class in KWin
+ implements all effects Kompmgr could do
/ implements all effects Kompmgr could do
+ - all effects from the Opacity tab should be already doable
! - applying translucency only to the decoration
- use clientSize() and clientPos() from Client
@ -187,15 +192,12 @@ Effects TODO
- just clear the alpha channel in the alpha clear hack
- or do it while painting (see also the alpha clear hack todo entry)
! - the rest - should be simple
* - shadows
- framework is not ready for them yet (see the todo entry)
/ - shadows
+ - tab Effects
! - fade-in should be simple
+ - fade between changes
- will need notification about opacity changes
- not sure if this is doable for other opacity changes then the ones
initiated by the user or by the application
* - fade-out needs framework for disappearing windows (see the todo entry)
+ minimize/shade effects
- to replace the ones from KWin core

View file

@ -191,7 +191,7 @@ void Client::releaseWindow( bool on_shutdown )
finishWindowRules();
++block_geometry_updates;
if( isOnCurrentDesktop() && isShown( true ))
workspace()->addRepaint( geometry());
addWorkspaceRepaint( geometry());
setMappingState( WithdrawnState );
setModal( false ); // otherwise its mainwindow wouldn't get focus
hidden = true; // so that it's not considered visible anymore (can't use hideClient(), it would set flags)
@ -257,7 +257,7 @@ void Client::destroyClient()
finishWindowRules();
++block_geometry_updates;
if( isOnCurrentDesktop() && isShown( true ))
workspace()->addRepaint( geometry());
addWorkspaceRepaint( geometry());
setModal( false );
hidden = true; // so that it's not considered visible anymore
workspace()->clientHidden( this );
@ -655,7 +655,7 @@ void Client::setShade( ShadeMode mode )
// TODO all this unmapping, resizing etc. feels too much duplicated from elsewhere
if ( isShade())
{ // shade_mode == ShadeNormal
workspace()->addRepaint( geometry());
addWorkspaceRepaint( geometry());
// shade
shade_geometry_change = true;
QSize s( sizeForClientSize( QSize( clientSize())));
@ -826,7 +826,7 @@ void Client::rawShow()
*/
void Client::rawHide()
{
workspace()->addRepaint( geometry());
addWorkspaceRepaint( geometry());
// Here it may look like a race condition, as some other client might try to unmap
// the window between these two XSelectInput() calls. However, they're supposed to
// use XWithdrawWindow(), which also sends a synthetic event to the root window,

View file

@ -246,8 +246,10 @@ void Workspace::performCompositing()
if( children != NULL )
XFree( children );
foreach( Toplevel* c, windows )
{ // this could be possibly optimized WRT obscuring, but that'd need being already
// past prePaint() phase - probably not worth it
{ // This could be possibly optimized WRT obscuring, but that'd need being already
// past prePaint() phase - probably not worth it.
// TODO I think effects->transformWindowDamage() doesn't need to be called here,
// pre-paint will extend painted window areas as necessary.
repaints_region |= c->repaints().translated( c->pos());
c->resetRepaints( c->rect());
}
@ -470,4 +472,17 @@ void Toplevel::resetRepaints( const QRect& r )
repaints_region -= r;
}
void Toplevel::addWorkspaceRepaint( int x, int y, int w, int h )
{
addWorkspaceRepaint( QRect( x, y, w, h ));
}
void Toplevel::addWorkspaceRepaint( const QRect& r2 )
{
if( !compositing())
return;
QRect r = effects->transformWindowDamage( effectWindow(), r2 );
workspace()->addRepaint( r );
}
} // namespace

View file

@ -26,6 +26,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include "effects/minimizeanimation.h"
#include "effects/presentwindows.h"
#include "effects/scalein.h"
#include "effects/shadow.h"
#include "effects/shakymove.h"
#include "effects/shiftworkspaceup.h"
#include "effects/showfps.h"
@ -128,9 +129,9 @@ void Effect::postPaintScreen()
effects->postPaintScreen();
}
void Effect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time )
void Effect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
effects->prePaintWindow( w, mask, region, time );
effects->prePaintWindow( w, mask, paint, clip, time );
}
void Effect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
@ -148,6 +149,11 @@ void Effect::drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintD
effects->drawWindow( w, mask, region, data );
}
QRect Effect::transformWindowDamage( EffectWindow* w, const QRect& r )
{
return effects->transformWindowDamage( w, r );
}
void Effect::setPositionTransformations( WindowPaintData& data, QRect& region, EffectWindow* w,
const QRect& r, Qt::AspectRatioMode aspect )
{
@ -172,6 +178,7 @@ EffectsHandler::EffectsHandler()
: current_paint_screen( 0 )
, current_paint_window( 0 )
, current_draw_window( 0 )
, current_transform( 0 )
{
if( !compositing())
return;
@ -200,6 +207,7 @@ EffectsHandler::EffectsHandler()
registerEffect("DesktopChangeSlide", new GenericEffectFactory<DesktopChangeSlideEffect>);
registerEffect("BoxSwitch", new GenericEffectFactory<BoxSwitchEffect>);
registerEffect("Drunken", new GenericEffectFactory<DrunkenEffect>);
registerEffect("Shadow", new GenericEffectFactory<ShadowEffect>);
registerEffect("TestInput", new GenericEffectFactory<TestInputEffect>);
registerEffect("TestThumbnail", new GenericEffectFactory<TestThumbnailEffect>);
@ -319,6 +327,7 @@ void EffectsHandler::startPaint()
assert( current_paint_screen == 0 );
assert( current_paint_window == 0 );
assert( current_draw_window == 0 );
assert( current_transform == 0 );
}
// the idea is that effects call this function again which calls the next one
@ -353,11 +362,11 @@ void EffectsHandler::postPaintScreen()
// no special final code
}
void EffectsHandler::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time )
void EffectsHandler::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
if( current_paint_window < loaded_effects.size())
{
loaded_effects[current_paint_window++].second->prePaintWindow( w, mask, region, time );
loaded_effects[current_paint_window++].second->prePaintWindow( w, mask, paint, clip, time );
--current_paint_window;
}
// no special final code
@ -395,6 +404,18 @@ void EffectsHandler::drawWindow( EffectWindow* w, int mask, QRegion region, Wind
scene->finalDrawWindow( w, mask, region, data );
}
QRect EffectsHandler::transformWindowDamage( EffectWindow* w, const QRect& r )
{
if( current_transform < loaded_effects.size())
{
QRect rr = loaded_effects[current_transform++].second->transformWindowDamage( w, r );
--current_transform;
return rr;
}
else
return r;
}
Window EffectsHandler::createInputWindow( Effect* e, int x, int y, int w, int h, const QCursor& cursor )
{
XSetWindowAttributes attrs;
@ -502,6 +523,7 @@ void EffectsHandler::loadEffect( const QString& name )
assert( current_paint_screen == 0 );
assert( current_paint_window == 0 );
assert( current_draw_window == 0 );
assert( current_transform == 0 );
for(QVector< EffectPair >::const_iterator it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); it++)
{
@ -529,6 +551,7 @@ void EffectsHandler::unloadEffect( const QString& name )
assert( current_paint_screen == 0 );
assert( current_paint_window == 0 );
assert( current_draw_window == 0 );
assert( current_transform == 0 );
for( QVector< EffectPair >::iterator it = loaded_effects.begin(); it != loaded_effects.end(); it++)
{

View file

@ -68,13 +68,18 @@ class Effect
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void postPaintScreen();
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
// paintWindow() can do various transformations
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( EffectWindow* w );
// drawWindow() is used even for thumbnails etc. - it can alter the window itself where it
// makes sense (e.g.darkening out unresponsive windows), but it cannot do transformations
virtual void drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
// This function is used e.g. by the shadow effect which adds area around windows
// that needs to be painted as well - e.g. when a window is hidden and the workspace needs
// to be repainted at that area, shadow's transformWindowDamage() adds the shadow area
// to it, so that it is repainted as well.
virtual QRect transformWindowDamage( EffectWindow* w, const QRect& r );
// called when moved/resized or once after it's finished
virtual void windowUserMovedResized( EffectWindow* c, bool first, bool last );
virtual void windowOpacityChanged( EffectWindow* c, double old_opacity );
@ -135,10 +140,11 @@ class EffectsHandler
void prePaintScreen( int* mask, QRegion* region, int time );
void paintScreen( int mask, QRegion region, ScreenPaintData& data );
void postPaintScreen();
void prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time );
void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
void postPaintWindow( EffectWindow* w );
void drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
QRect transformWindowDamage( EffectWindow* w, const QRect& r );
// Functions for handling input - e.g. when an Expose-like effect is shown, an input window
// covering the whole screen is created and all mouse events will be intercepted by it.
// The effect's windowInputMouseEvent() will get called with such events.
@ -181,6 +187,7 @@ class EffectsHandler
int current_paint_screen;
int current_paint_window;
int current_draw_window;
int current_transform;
};
// This class is a representation of a window used by/for Effect classes.

View file

@ -44,7 +44,7 @@ void BoxSwitchEffect::prePaintScreen( int* mask, QRegion* region, int time )
effects->prePaintScreen( mask, region, time );
}
void BoxSwitchEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time )
void BoxSwitchEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
if( mActivated )
{
@ -67,7 +67,7 @@ void BoxSwitchEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* regio
}
}
}
effects->prePaintWindow( w, mask, region, time );
effects->prePaintWindow( w, mask, paint, clip, time );
}
void BoxSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )

View file

@ -33,7 +33,7 @@ class BoxSwitchEffect
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void windowInputMouseEvent( Window w, QEvent* e );

View file

@ -33,7 +33,7 @@ void DesktopChangeSlideEffect::prePaintScreen( int* mask, QRegion* region, int t
effects->prePaintScreen( mask, region, time );
}
void DesktopChangeSlideEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time )
void DesktopChangeSlideEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
if( progress != MAX_PROGRESS )
{
@ -50,7 +50,7 @@ void DesktopChangeSlideEffect::prePaintWindow( EffectWindow* w, int* mask, QRegi
*mask |= Scene::PAINT_WINDOW_TRANSFORMED;
}
}
effects->prePaintWindow( w, mask, region, time );
effects->prePaintWindow( w, mask, paint, clip, time );
}
void DesktopChangeSlideEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )

View file

@ -24,7 +24,7 @@ class DesktopChangeSlideEffect
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void postPaintScreen();
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void desktopChanged( int old );
private:

View file

@ -19,7 +19,7 @@ License. See the file "COPYING" for the exact licensing terms.
namespace KWinInternal
{
void DialogParentEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time )
void DialogParentEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
// How long does it take for the effect to get it's full strength (in ms)
const float changeTime = 200;
@ -38,7 +38,7 @@ void DialogParentEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* re
}
// Call the next effect
effects->prePaintWindow( w, mask, region, time );
effects->prePaintWindow( w, mask, paint, clip, time );
}
void DialogParentEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )

View file

@ -28,7 +28,7 @@ class DialogParentEffect
: public Effect
{
public:
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( EffectWindow* w );

View file

@ -22,7 +22,7 @@ void DrunkenEffect::prePaintScreen( int* mask, QRegion* region, int time )
effects->prePaintScreen( mask, region, time );
}
void DrunkenEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time )
void DrunkenEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
if( windows.contains( w ))
{
@ -32,7 +32,7 @@ void DrunkenEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region,
else
windows.remove( w );
}
effects->prePaintWindow( w, mask, region, time );
effects->prePaintWindow( w, mask, paint, clip, time );
}
void DrunkenEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )

View file

@ -21,7 +21,7 @@ class DrunkenEffect
{
public:
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( EffectWindow* w );
virtual void windowAdded( EffectWindow* w );

View file

@ -93,7 +93,7 @@ void ExplosionEffect::prePaintScreen( int* mask, QRegion* region, int time )
effects->prePaintScreen(mask, region, time);
}
void ExplosionEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time )
void ExplosionEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
if( mWindows.contains( w ))
{
@ -112,7 +112,7 @@ void ExplosionEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* regio
}
}
effects->prePaintWindow( w, mask, region, time );
effects->prePaintWindow( w, mask, paint, clip, time );
}
void ExplosionEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )

View file

@ -30,7 +30,7 @@ class ExplosionEffect
ExplosionEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintScreen();

View file

@ -22,7 +22,7 @@ FadeEffect::FadeEffect()
{
}
void FadeEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time )
void FadeEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
if( windows.contains( w ))
{
@ -55,7 +55,7 @@ void FadeEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, in
w->enablePainting( Scene::Window::PAINT_DISABLED_BY_DELETE );
}
}
effects->prePaintWindow( w, mask, region, time );
effects->prePaintWindow( w, mask, paint, clip, time );
}
void FadeEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )

View file

@ -21,7 +21,7 @@ class FadeEffect
{
public:
FadeEffect();
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( EffectWindow* w );
// TODO react also on virtual desktop changes

View file

@ -25,7 +25,7 @@ void FallApartEffect::prePaintScreen( int* mask, QRegion* region, int time )
effects->prePaintScreen(mask, region, time);
}
void FallApartEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time )
void FallApartEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
if( windows.contains( w ))
{
@ -47,7 +47,7 @@ void FallApartEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* regio
}
}
}
effects->prePaintWindow( w, mask, region, time );
effects->prePaintWindow( w, mask, paint, clip, time );
}
void FallApartEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )

View file

@ -21,7 +21,7 @@ class FallApartEffect
{
public:
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintScreen();
virtual void windowClosed( EffectWindow* c );

View file

@ -23,7 +23,7 @@ void FlameEffect::prePaintScreen( int* mask, QRegion* region, int time )
effects->prePaintScreen(mask, region, time);
}
void FlameEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time )
void FlameEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
if( windows.contains( w ))
{
@ -45,7 +45,7 @@ void FlameEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, i
}
}
}
effects->prePaintWindow( w, mask, region, time );
effects->prePaintWindow( w, mask, paint, clip, time );
}
void FlameEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )

View file

@ -21,7 +21,7 @@ class FlameEffect
{
public:
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( EffectWindow* w );
virtual void windowClosed( EffectWindow* c );

View file

@ -38,7 +38,7 @@ namespace KWinInternal
// region - the region of the screen that needs to be painted, support for modifying it
// is not fully implemented yet, do not use
// time - time in milliseconds since the last paint, useful for animations
void HowtoEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time )
void HowtoEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
// Is this window the one that is going to be faded out and in again?
if( w == fade_window )
@ -63,7 +63,7 @@ void HowtoEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, i
}
// Call the next effect (or the actual window painting code if this is the last effect).
// Effects are chained and they all modify something if needed and then call the next one.
effects->prePaintWindow( w, mask, region, time );
effects->prePaintWindow( w, mask, paint, clip, time );
}
// The function that handles the actual painting. Some simple modifications are possible

View file

@ -38,7 +38,7 @@ class HowtoEffect
// A pre-paint function. It tells the compositing code how the painting will
// be affected by this effect.
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
// A paint function. It actually performs the modifications to the painting.
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );

View file

@ -15,7 +15,7 @@ License. See the file "COPYING" for the exact licensing terms.
namespace KWinInternal
{
void MakeTransparentEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time )
void MakeTransparentEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
const Client* c = dynamic_cast< const Client* >( w->window());
if(( c != NULL && ( c->isMove() || c->isResize())) || w->window()->isDialog())
@ -23,7 +23,7 @@ void MakeTransparentEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion*
*mask |= Scene::PAINT_WINDOW_TRANSLUCENT;
*mask &= ~Scene::PAINT_WINDOW_OPAQUE;
}
effects->prePaintWindow( w, mask, region, time );
effects->prePaintWindow( w, mask, paint, clip, time );
}
void MakeTransparentEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )

View file

@ -21,7 +21,7 @@ class MakeTransparentEffect
{
public:
virtual void windowUserMovedResized( EffectWindow* c, bool first, bool last );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
};

View file

@ -37,7 +37,7 @@ void MinimizeAnimationEffect::prePaintScreen( int* mask, QRegion* region, int ti
effects->prePaintScreen(mask, region, time);
}
void MinimizeAnimationEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time )
void MinimizeAnimationEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
const float changeTime = 500;
if( mAnimationProgress.contains( w ))
@ -69,7 +69,7 @@ void MinimizeAnimationEffect::prePaintWindow( EffectWindow* w, int* mask, QRegio
mActiveAnimations--;
}
effects->prePaintWindow( w, mask, region, time );
effects->prePaintWindow( w, mask, paint, clip, time );
}
void MinimizeAnimationEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )

View file

@ -28,7 +28,7 @@ class MinimizeAnimationEffect
MinimizeAnimationEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintScreen();

View file

@ -68,7 +68,7 @@ void PresentWindowsEffect::prePaintScreen( int* mask, QRegion* region, int time
effects->prePaintScreen(mask, region, time);
}
void PresentWindowsEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time )
void PresentWindowsEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
if( mActiveness > 0.0f && mWindowData.contains(w->window()) )
{
@ -83,7 +83,7 @@ void PresentWindowsEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion*
*mask |= Scene::PAINT_WINDOW_TRANSLUCENT;
}
effects->prePaintWindow( w, mask, region, time );
effects->prePaintWindow( w, mask, paint, clip, time );
}
void PresentWindowsEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )

View file

@ -31,7 +31,7 @@ class PresentWindowsEffect
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintScreen();

View file

@ -22,7 +22,7 @@ void ScaleInEffect::prePaintScreen( int* mask, QRegion* region, int time )
effects->prePaintScreen( mask, region, time );
}
void ScaleInEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time )
void ScaleInEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
if( windows.contains( w ))
{
@ -32,7 +32,7 @@ void ScaleInEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region,
else
windows.remove( w );
}
effects->prePaintWindow( w, mask, region, time );
effects->prePaintWindow( w, mask, paint, clip, time );
}
void ScaleInEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )

View file

@ -21,7 +21,7 @@ class ScaleInEffect
{
public:
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( EffectWindow* w );
// TODO react also on virtual desktop changes

86
effects/shadow.cpp Normal file
View file

@ -0,0 +1,86 @@
/*****************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2007 Lubos Lunak <l.lunak@kde.org>
You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
******************************************************************/
#include "shadow.h"
#ifdef HAVE_OPENGL
#include <GL/gl.h>
#endif
namespace KWinInternal
{
ShadowEffect::ShadowEffect()
: shadowXOffset( 10 )
, shadowYOffset( 10 )
{
}
void ShadowEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
*mask |= Scene::PAINT_WINDOW_TRANSLUCENT;
*paint |= ( QRegion( w->geometry()) & *paint ).translated( shadowXOffset, shadowYOffset );
effects->prePaintWindow( w, mask, paint, clip, time );
}
void ShadowEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
{
drawShadow( w, mask, region, data.opacity );
effects->paintWindow( w, mask, region, data );
}
void ShadowEffect::postPaintWindow( EffectWindow* w )
{
effects->postPaintWindow( w );
}
QRect ShadowEffect::transformWindowDamage( EffectWindow* w, const QRect& r )
{
QRect r2 = r | r.translated( shadowXOffset, shadowYOffset );
return effects->transformWindowDamage( w, r2 );
}
void ShadowEffect::drawShadow( EffectWindow* w, int mask, QRegion region, double opacity )
{
if(( mask & Scene::PAINT_WINDOW_TRANSLUCENT ) == 0 )
return;
glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glColor4f( 0, 0, 0, 0.2 * opacity ); // black
QRect r( w->geometry());
r.moveBy( shadowXOffset, shadowYOffset );
glEnableClientState( GL_VERTEX_ARRAY );
int verts[ 4 * 2 ] =
{
r.x(), r.y(),
r.x(), r.y() + r.height(),
r.x() + r.width(), r.y() + r.height(),
r.x() + r.width(), r.y()
};
glVertexPointer( 2, GL_INT, 0, verts );
if( mask & ( Scene::PAINT_WINDOW_TRANSFORMED | Scene::PAINT_SCREEN_TRANSFORMED ))
glDrawArrays( GL_QUADS, 0, 4 );
else
{ // clip by region
glEnable( GL_SCISSOR_TEST );
int dh = displayHeight();
foreach( QRect r, region.rects())
{
// Scissor rect has to be given in OpenGL coords
glScissor(r.x(), dh - r.y() - r.height(), r.width(), r.height());
glDrawArrays( GL_QUADS, 0, 4 );
}
}
glDisableClientState( GL_VERTEX_ARRAY );
glPopAttrib();
}
} // namespace

35
effects/shadow.h Normal file
View file

@ -0,0 +1,35 @@
/*****************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2007 Lubos Lunak <l.lunak@kde.org>
You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
******************************************************************/
#ifndef KWIN_SHADOW_H
#define KWIN_SHADOW_H
#include <effects.h>
namespace KWinInternal
{
class ShadowEffect
: public Effect
{
public:
ShadowEffect();
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintWindow( EffectWindow* w );
virtual QRect transformWindowDamage( EffectWindow* w, const QRect& r );
private:
void drawShadow( EffectWindow* w, int mask, QRegion region, double opacity );
int shadowXOffset, shadowYOffset;
};
} // namespace
#endif

View file

@ -30,11 +30,11 @@ void ShakyMoveEffect::prePaintScreen( int* mask, QRegion* region, int time )
effects->prePaintScreen( mask, region, time );
}
void ShakyMoveEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time )
void ShakyMoveEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
if( windows.contains( w ))
*mask |= Scene::PAINT_WINDOW_TRANSFORMED;
effects->prePaintWindow( w, mask, region, time );
effects->prePaintWindow( w, mask, paint, clip, time );
}
void ShakyMoveEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )

View file

@ -25,7 +25,7 @@ class ShakyMoveEffect
public:
ShakyMoveEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void windowUserMovedResized( EffectWindow* c, bool first, bool last );
virtual void windowClosed( EffectWindow* c );

View file

@ -41,7 +41,7 @@ void WavyWindowsEffect::prePaintScreen( int* mask, QRegion* region, int time )
effects->prePaintScreen(mask, region, time);
}
void WavyWindowsEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time )
void WavyWindowsEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
{
// This window will be transformed by the effect
*mask |= Scene::PAINT_WINDOW_TRANSFORMED;
@ -52,7 +52,7 @@ void WavyWindowsEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* reg
// pixels big
glwin->requestVertexGrid(30);
effects->prePaintWindow( w, mask, region, time );
effects->prePaintWindow( w, mask, paint, clip, time );
}
void WavyWindowsEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )

View file

@ -28,7 +28,7 @@ class WavyWindowsEffect
WavyWindowsEffect();
virtual void prePaintScreen( int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time );
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void postPaintScreen();

View file

@ -1665,7 +1665,7 @@ void Unmanaged::configureNotifyEvent( XConfigureEvent* e )
QRect newgeom( e->x, e->y, e->width, e->height );
if( newgeom == geom )
return;
workspace()->addRepaint( geometry()); // damage old area
addWorkspaceRepaint( geometry()); // damage old area
QRect old = geom;
geom = newgeom;
discardWindowPixmap();

View file

@ -1707,7 +1707,7 @@ void Client::setGeometry( int x, int y, int w, int h, ForceGeometry_t force )
if( effects != NULL )
effects->windowGeometryShapeChanged( effectWindow(), geom_before_block );
}
workspace()->addRepaint( geom_before_block );
addWorkspaceRepaint( geom_before_block );
geom_before_block = geom;
}
@ -1768,7 +1768,7 @@ void Client::plainResize( int w, int h, ForceGeometry_t force )
scene->windowGeometryShapeChanged( this );
if( effects != NULL )
effects->windowGeometryShapeChanged( effectWindow(), geom_before_block );
workspace()->addRepaint( geom_before_block );
addWorkspaceRepaint( geom_before_block );
geom_before_block = geom;
}
@ -1791,8 +1791,8 @@ void Client::move( int x, int y, ForceGeometry_t force )
updateWindowRules();
checkMaximizeGeometry();
// client itself is not damaged
workspace()->addRepaint( geom_before_block );
workspace()->addRepaint( geom ); // trigger repaint of window's new location
addWorkspaceRepaint( geom_before_block );
addWorkspaceRepaint( geom ); // trigger repaint of window's new location
geom_before_block = geom;
}

View file

@ -109,6 +109,7 @@ void Scene::paintScreen( int* mask, QRegion* region )
{ // whole screen, not transformed, force region to be full
*region = QRegion( 0, 0, displayWidth(), displayHeight());
}
painted_region = *region;
if( *mask & PAINT_SCREEN_BACKGROUND_FIRST )
paintBackground( *region );
ScreenPaintData data;
@ -116,6 +117,9 @@ void Scene::paintScreen( int* mask, QRegion* region )
effects->postPaintScreen();
foreach( Window* w, stacking_order )
effects->postPaintWindow( effectWindow( w ));
*region |= painted_region;
// make sure not to go outside of the screen area
*region &= QRegion( 0, 0, displayWidth(), displayHeight());
}
// Compute time since the last painting pass.
@ -161,12 +165,13 @@ void Scene::paintGenericScreen( int orig_mask, ScreenPaintData )
{
int mask = orig_mask | ( w->isOpaque() ? PAINT_WINDOW_OPAQUE : PAINT_WINDOW_TRANSLUCENT );
w->resetPaintingEnabled();
QRegion damage = infiniteRegion();
QRegion paint = infiniteRegion(); // no clipping, so doesn't really matter
QRegion clip = QRegion();
// preparation step
effects->prePaintWindow( effectWindow( w ), &mask, &damage, time_diff );
effects->prePaintWindow( effectWindow( w ), &mask, &paint, &clip, time_diff );
if( !w->isPaintingEnabled())
continue;
paintWindow( w, mask, damage );
paintWindow( w, mask, infiniteRegion());
}
}
@ -180,6 +185,7 @@ void Scene::paintSimpleScreen( int orig_mask, QRegion region )
assert(( orig_mask & ( PAINT_WINDOW_TRANSFORMED | PAINT_SCREEN_TRANSFORMED
| PAINT_WINDOW_TRANSLUCENT | PAINT_WINDOW_OPAQUE )) == 0 );
QList< Phase2Data > phase2;
QRegion allclips;
// Draw each opaque window top to bottom, subtracting the bounding rect of
// each window from the clip region after it's been drawn.
for( int i = stacking_order.count() - 1; // top to bottom
@ -187,25 +193,32 @@ void Scene::paintSimpleScreen( int orig_mask, QRegion region )
--i )
{
Window* w = stacking_order[ i ];
if( region.isEmpty()) // completely clipped
continue;
int mask = orig_mask | ( w->isOpaque() ? PAINT_WINDOW_OPAQUE : PAINT_WINDOW_TRANSLUCENT );
w->resetPaintingEnabled();
QRegion damage = region;
QRegion paint = region;
QRegion clip = w->isOpaque() ? w->shape().translated( w->x(), w->y()) : QRegion();
// preparation step
effects->prePaintWindow( effectWindow( w ), &mask, &damage, time_diff );
effects->prePaintWindow( effectWindow( w ), &mask, &paint, &clip, time_diff );
if( !w->isPaintingEnabled())
continue;
paint -= allclips; // make sure to avoid already clipped areas
if( paint.isEmpty()) // completely clipped
continue;
if( paint != region ) // prepaint added area to draw
{
region |= paint; // make sure other windows in that area get painted too
painted_region |= paint; // make sure it makes it to the screen
}
// If the window is transparent, the transparent part will be done
// in the 2nd pass.
if( mask & PAINT_WINDOW_TRANSLUCENT )
phase2.prepend( Phase2Data( w, region, mask ));
phase2.prepend( Phase2Data( w, paint, mask ));
if( mask & PAINT_WINDOW_OPAQUE )
{
paintWindow( w, mask, region );
// If the window is not transparent at all, it can clip windows below.
if( ( mask & PAINT_WINDOW_TRANSLUCENT ) == 0 )
region -= w->shape().translated( w->x(), w->y());
paintWindow( w, mask, paint );
// The window can clip by its opaque parts the windows below.
region -= clip;
allclips |= clip;
}
}
if( !( orig_mask & PAINT_SCREEN_BACKGROUND_FIRST ))
@ -213,10 +226,14 @@ void Scene::paintSimpleScreen( int orig_mask, QRegion region )
// Now walk the list bottom to top, drawing translucent windows.
// That we draw bottom to top is important now since we're drawing translucent objects
// and also are clipping only by opaque windows.
QRegion add_paint;
foreach( Phase2Data d, phase2 )
{
Window* w = d.window;
paintWindow( w, d.mask, d.region );
paintWindow( w, d.mask, d.region | add_paint );
// It is necessary to also add paint regions of windows below, because their
// pre-paint's might have extended the paint area, so those areas need to be painted too.
add_paint |= d.region;
}
}

View file

@ -106,6 +106,12 @@ class Scene
};
// windows in their stacking order
QVector< Window* > stacking_order;
// The region which actually has been painted by paintScreen() and should be
// copied from the buffer to the screen. I.e. the region returned from Scene::paintScreen().
// Since prePaintWindow() can extend areas to paint, these changes would have to propagate
// up all the way from paintSimpleScreen() up to paintScreen(), so save them here rather
// than propagate them up in arguments.
QRegion painted_region;
// time since last repaint
int time_diff;
QTime last_time;

View file

@ -557,8 +557,6 @@ void SceneOpenGL::waitSync()
// actually paint to the screen (double-buffer swap or copy from pixmap buffer)
void SceneOpenGL::flushBuffer( int mask, QRegion damage )
{
if( mask & PAINT_SCREEN_REGION )// make sure not to go outside visible screen
damage &= QRegion( 0, 0, displayWidth(), displayHeight());
if( db )
{
if( mask & PAINT_SCREEN_REGION )

View file

@ -157,6 +157,7 @@ void SceneXrender::paintTransformedScreen( int orig_mask )
{
QRegion region( 0, 0, displayWidth(), displayHeight());
QList< Phase2Data > phase2;
QRegion allclips;
// Draw each opaque window top to bottom, subtracting the bounding rect of
// each window from the clip region after it's been drawn.
for( int i = stacking_order.count() - 1; // top to bottom
@ -164,26 +165,33 @@ void SceneXrender::paintTransformedScreen( int orig_mask )
--i )
{
Window* w = static_cast< Window* >( stacking_order[ i ] );
if( region.isEmpty()) // completely clipped
continue;
int mask = orig_mask | ( w->isOpaque() ? PAINT_WINDOW_OPAQUE : PAINT_WINDOW_TRANSLUCENT );
w->resetPaintingEnabled();
QRegion damage = region;
QRegion paint = region;
// TODO this is wrong, transformedShape() should be used here, but is not known yet
QRegion clip = w->isOpaque() ? region : QRegion();
// preparation step
effects->prePaintWindow( effectWindow( w ), &mask, &damage, time_diff );
effects->prePaintWindow( effectWindow( w ), &mask, &paint, &clip, time_diff );
if( !w->isPaintingEnabled())
continue;
paint -= allclips; // make sure to avoid already clipped areas
if( paint.isEmpty()) // completely clipped
continue;
if( paint != region ) // prepaint added area to draw
{
region |= paint; // make sure other windows in that area get painted too
painted_region |= paint; // make sure it makes it to the screen
}
// If the window is transparent, the transparent part will be done
// in the 2nd pass.
if( mask & PAINT_WINDOW_TRANSLUCENT )
phase2.prepend( Phase2Data( w, region, mask ));
phase2.prepend( Phase2Data( w, paint, mask ));
if( mask & PAINT_WINDOW_OPAQUE )
{
w->setTransformedShape( QRegion());
paintWindow( w, mask, region );
// If the window is not transparent at all, it can clip windows below.
if( ( mask & PAINT_WINDOW_TRANSLUCENT ) == 0 )
region -= w->transformedShape();
paintWindow( w, mask, paint );
// The window can clip by its opaque parts the windows below.
region -= w->transformedShape();
}
}
if( !( orig_mask & PAINT_SCREEN_BACKGROUND_FIRST ))
@ -191,10 +199,14 @@ void SceneXrender::paintTransformedScreen( int orig_mask )
// Now walk the list bottom to top, drawing translucent windows.
// That we draw bottom to top is important now since we're drawing translucent objects
// and also are clipping only by opaque windows.
QRegion add_paint;
foreach( Phase2Data d, phase2 )
{
Scene::Window* w = d.window;
paintWindow( w, d.mask, d.region );
paintWindow( w, d.mask, d.region | add_paint );
// It is necessary to also add paint regions of windows below, because their
// pre-paint's might have extended the paint area, so those areas need to be painted too.
add_paint |= d.region;
}
}

View file

@ -90,6 +90,9 @@ class Toplevel
void addRepaint( const QRect& r );
void addRepaint( int x, int y, int w, int h );
void addRepaintFull();
// these call workspace->addRepaint(), but first transform the damage if needed
void addWorkspaceRepaint( const QRect& r );
void addWorkspaceRepaint( int x, int y, int w, int h );
QRegion repaints() const;
void resetRepaints( const QRect& r );
QRegion damage() const;

View file

@ -80,7 +80,7 @@ void Unmanaged::release()
if( Extensions::shapeAvailable())
XShapeSelectInput( display(), window(), NoEventMask );
XSelectInput( display(), window(), NoEventMask );
workspace()->addRepaint( geometry());
addWorkspaceRepaint( geometry());
disownDataPassedToDeleted();
del->unrefWindow();
deleteUnmanaged( this, Allowed );

View file

@ -18,6 +18,8 @@ License. See the file "COPYING" for the exact licensing terms.
#include <QCursor>
#include <netwm.h>
#include <kxmessages.h>
#include <qdatetime.h>
#include <kmanagerselection.h>
#include "utils.h"
#include "kdecoration.h"
@ -77,7 +79,7 @@ class Workspace : public QObject, public KDecorationDefines
virtual ~Workspace();
static Workspace * self() { return _self; }
bool workspaceEvent( XEvent * );
KDecoration* createDecoration( KDecorationBridge* bridge );
@ -87,6 +89,9 @@ class Workspace : public QObject, public KDecorationDefines
template< typename T > Client* findClient( T predicate );
template< typename T1, typename T2 > void forEachClient( T1 procedure, T2 predicate );
template< typename T > void forEachClient( T procedure );
template< typename T > Unmanaged* findUnmanaged( T predicate );
template< typename T1, typename T2 > void forEachUnmanaged( T1 procedure, T2 predicate );
template< typename T > void forEachUnmanaged( T procedure );
QRect clientArea( clientAreaOption, const QPoint& p, int desktop ) const;
QRect clientArea( clientAreaOption, const Client* c ) const;
@ -165,12 +170,17 @@ class Workspace : public QObject, public KDecorationDefines
QWidget* desktopWidget();
// for TabBox
Client* currentTabBoxClient() const;
ClientList currentTabBoxClientList() const;
int currentTabBoxDesktop() const;
Client* nextFocusChainClient(Client*) const;
Client* previousFocusChainClient(Client*) const;
Client* nextStaticClient(Client*) const;
Client* previousStaticClient(Client*) const;
int nextDesktopFocusChain( int iDesktop ) const;
int previousDesktopFocusChain( int iDesktop ) const;
void refTabBox();
void unrefTabBox();
void closeTabBox();
/**
@ -181,7 +191,7 @@ class Workspace : public QObject, public KDecorationDefines
ClientList ensureStackingOrder( const ClientList& clients ) const;
Client* topClientOnDesktop( int desktop, bool unconstrained = false, bool only_normal = true ) const;
Client* topClientOnDesktop( int desktop, bool unconstrained = false ) const;
Client* findDesktop( bool topmost, int desktop ) const;
void sendClientToDesktop( Client* c, int desktop, bool dont_activate );
void windowToPreviousDesktop( Client* c );
@ -190,6 +200,10 @@ class Workspace : public QObject, public KDecorationDefines
// KDE4 remove me - and it's also in the DCOP interface :(
void showWindowMenuAt( unsigned long id, int x, int y );
void loadEffect( const QString& name );
void unloadEffect( const QString& name );
/**
* Shows the menu operations menu for the client and makes it active if
* it's not already.
@ -213,8 +227,6 @@ class Workspace : public QObject, public KDecorationDefines
WindowRules findWindowRules( const Client*, bool );
void rulesUpdated();
void discardUsedWindowRules( Client* c, bool withdraw );
void disableRulesUpdates( bool disable );
bool rulesUpdatesDisabled() const;
// dcop interface
void cascadeDesktop();
@ -226,7 +238,7 @@ class Workspace : public QObject, public KDecorationDefines
void circulateDesktopApplications();
QString desktopName( int desk ) const;
void setDesktopLayout(NET::Orientation o, int x, int y, NET::DesktopLayoutCorner c);
void setDesktopLayout(int o, int x, int y);
void setShowingDesktop( bool showing );
void resetShowingDesktop( bool keep_hidden );
bool showingDesktop() const;
@ -236,14 +248,17 @@ class Workspace : public QObject, public KDecorationDefines
void sendPingToWindow( Window w, Time timestamp ); // called from Client::pingWindow()
void sendTakeActivity( Client* c, Time timestamp, long flags ); // called from Client::takeActivity()
// only called from Client::destroyClient() or Client::releaseWindow()
void removeClient( Client*, allowed_t );
void removeClient( Client*, allowed_t ); // only called from Client::destroyClient() or Client::releaseWindow()
void setActiveClient( Client*, allowed_t );
Group* findGroup( Window leader ) const;
void addGroup( Group* group, allowed_t );
void removeGroup( Group* group, allowed_t );
Group* findClientLeaderGroup( const Client* c ) const;
void removeUnmanaged( Unmanaged*, allowed_t ); // only called from Unmanaged::release()
void removeDeleted( Deleted*, allowed_t );
void addDeleted( Deleted*, allowed_t );
bool checkStartupNotification( Window w, KStartupInfoId& id, KStartupInfoData& data );
void focusToNull(); // SELI public?
@ -279,6 +294,19 @@ class Workspace : public QObject, public KDecorationDefines
void toggleTopDockShadows(bool on);
// when adding repaints caused by a window, you probably want to use
// either Toplevel::addRepaint() or Toplevel::addWorkspaceRepaint()
void addRepaint( const QRect& r );
void addRepaint( int x, int y, int w, int h );
void addRepaintFull();
// creates XComposite overlay window, call initOverlay() afterwards
bool createOverlay();
// init overlay and the destination window in it
void setupOverlay( Window window );
// destroys XComposite overlay window
void destroyOverlay();
Window overlayWindow();
public slots:
void refresh();
// keybindings
@ -408,15 +436,14 @@ class Workspace : public QObject, public KDecorationDefines
void cleanupTemporaryRules();
void writeWindowRules();
void slotBlockShortcuts(int data);
void slotReloadConfig();
// kompmgr
void setPopupClientOpacity(int v);
void resetClientOpacity();
void setTransButtonText(int value);
// end
void setPopupClientOpacity( QAction* action );
void setupCompositing();
void performCompositing();
void lostCMSelection();
protected:
bool keyPressMouseEmulation( XKeyEvent& ev );
bool netCheck( XEvent* e );
private:
void init();
@ -460,6 +487,8 @@ class Workspace : public QObject, public KDecorationDefines
// this is the right way to create a new client
Client* createClient( Window w, bool is_mapped );
void addClient( Client* c, allowed_t );
Unmanaged* createUnmanaged( Window w );
void addUnmanaged( Unmanaged* c, allowed_t );
Window findSpecialEventWindow( XEvent* e );
@ -501,6 +530,9 @@ class Workspace : public QObject, public KDecorationDefines
void closeActivePopup();
void updateClientArea( bool force );
void finishCompositing();
bool windowRepaintsPending() const;
SystemTrayWindowList systemTrayWins;
@ -521,7 +553,6 @@ class Workspace : public QObject, public KDecorationDefines
QList<Rules*> rules;
KXMessages temporaryRulesMessages;
QTimer rulesUpdatedTimer;
bool rules_updates_disabled;
static const char* windowTypeToTxt( NET::WindowType type );
static NET::WindowType txtToWindowType( const char* txt );
static bool sessionInfoWindowTypeMatch( Client* c, SessionInfo* info );
@ -538,10 +569,12 @@ class Workspace : public QObject, public KDecorationDefines
ClientList clients;
ClientList desktops;
UnmanagedList unmanaged;
DeletedList deleted;
ClientList unconstrained_stacking_order; // topmost last
ClientList stacking_order; // topmost last
QVector< ClientList > focus_chain; // currently ative last
ClientList unconstrained_stacking_order;
ClientList stacking_order;
QVector< ClientList > focus_chain;
ClientList global_focus_chain; // this one is only for things like tabbox's MRU
ClientList should_get_focus; // last is most recent
ClientList attention_chain;
@ -575,6 +608,7 @@ class Workspace : public QObject, public KDecorationDefines
QMenu *popup;
QMenu *advanced_popup;
QMenu *trans_popup;
QMenu *desk_popup;
int desk_popup_index;
@ -658,12 +692,14 @@ class Workspace : public QObject, public KDecorationDefines
bool forced_global_mouse_grab;
friend class StackingUpdatesBlocker;
//kompmgr
KSelectionOwner* cm_selection;
QTimer compositeTimer;
QTime lastCompositePaint;
int compositeRate;
QRegion repaints_region;
Window overlay; // XComposite overlay window
QSlider *transSlider;
QPushButton *transButton;
private:
friend bool performTransiencyCheck();
};
// helper for Workspace::blockStackingUpdates() being called in pairs (true/false)
@ -806,10 +842,9 @@ inline bool Workspace::globalShortcutsDisabled() const
return global_shortcuts_disabled || global_shortcuts_disabled_for_client;
}
inline
bool Workspace::rulesUpdatesDisabled() const
inline Window Workspace::overlayWindow()
{
return rules_updates_disabled;
return overlay;
}
template< typename T >
@ -839,7 +874,27 @@ inline void Workspace::forEachClient( T procedure )
return forEachClient( procedure, TruePredicate());
}
KWIN_COMPARE_PREDICATE( ClientMatchPredicate, const Client*, cl == value );
template< typename T >
inline Unmanaged* Workspace::findUnmanaged( T predicate )
{
return findUnmanagedInList( unmanaged, predicate );
}
template< typename T1, typename T2 >
inline void Workspace::forEachUnmanaged( T1 procedure, T2 predicate )
{
for ( UnmanagedList::ConstIterator it = unmanaged.begin(); it != unmanaged.end(); ++it)
if ( predicate( const_cast< const Unmanaged* >( *it)))
procedure( *it );
}
template< typename T >
inline void Workspace::forEachUnmanaged( T procedure )
{
return forEachUnmanaged( procedure, TruePredicate());
}
KWIN_COMPARE_PREDICATE( ClientMatchPredicate, Client, const Client*, cl == value );
inline bool Workspace::hasClient( const Client* c )
{
return findClient( ClientMatchPredicate( c ));