Experimental fade effect, blatantly inspired by compiz.
Note that this while this can reliably fade opened/closed windows, it will only fade opacity/brightness/saturation changes from previously loaded effects. Until we can specify effects' loading order, the results may not be what you expect. Don't be too surprised if this gets reverted. svn path=/trunk/KDE/kdebase/workspace/; revision=683983
This commit is contained in:
parent
c2ff6a4d7a
commit
09bb0f7cd2
2 changed files with 142 additions and 89 deletions
202
effects/fade.cpp
202
effects/fade.cpp
|
@ -10,121 +10,173 @@ License. See the file "COPYING" for the exact licensing terms.
|
|||
|
||||
#include "fade.h"
|
||||
|
||||
#include <kconfiggroup.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
KWIN_EFFECT( fade, FadeEffect )
|
||||
|
||||
FadeEffect::FadeEffect()
|
||||
: fade_in_speed( 20 )
|
||||
, fade_out_speed( 70 )
|
||||
{
|
||||
KConfigGroup conf = effects->effectConfig( "Fade" );
|
||||
fadeInTime = qMax( conf.readEntry( "FadeInTime", 150 ), 1 );
|
||||
fadeOutTime = qMax( conf.readEntry( "FadeOutTime", 150 ), 1 );
|
||||
fadeWindows = conf.readEntry( "FadeWindows", true );
|
||||
}
|
||||
|
||||
void FadeEffect::prePaintScreen( int* mask, QRegion* region, int time )
|
||||
{
|
||||
if( !windows.isEmpty())
|
||||
{
|
||||
fadeInStep = time / double( fadeInTime );
|
||||
fadeOutStep = time / double( fadeOutTime );
|
||||
}
|
||||
effects->prePaintScreen( mask, region, time );
|
||||
}
|
||||
|
||||
void FadeEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time )
|
||||
{
|
||||
if( windows.contains( w ))
|
||||
{
|
||||
if( windows[ w ].current < windows[ w ].target )
|
||||
windows[ w ].fadeInStep += fadeInStep;
|
||||
windows[ w ].fadeOutStep += fadeOutStep;
|
||||
if( windows[ w ].opacity < 1.0 )
|
||||
{
|
||||
windows[ w ].current += time / double( 10000 / fade_in_speed ) * windows[ w ].step_mult;
|
||||
if( windows[ w ].current > windows[ w ].target )
|
||||
windows[ w ].current = windows[ w ].target;
|
||||
}
|
||||
else if( windows[ w ].current > windows[ w ].target )
|
||||
{
|
||||
windows[ w ].current -= time / double( 10000 / fade_out_speed ) * windows[ w ].step_mult;
|
||||
if( windows[ w ].current < windows[ w ].target )
|
||||
windows[ w ].current = windows[ w ].target;
|
||||
}
|
||||
|
||||
if( !windows[ w ].isFading())
|
||||
{
|
||||
if( windows[ w ].deleted )
|
||||
{
|
||||
w->unrefWindow();
|
||||
windows.remove( w );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*mask |= PAINT_WINDOW_TRANSLUCENT;
|
||||
*mask &= ~PAINT_WINDOW_OPAQUE;
|
||||
if( windows[ w ].deleted )
|
||||
*mask |= PAINT_WINDOW_TRANSLUCENT;
|
||||
}
|
||||
if( windows[ w ].deleted )
|
||||
{
|
||||
if( windows[ w ].opacity <= 0.0 )
|
||||
{
|
||||
windows.remove( w );
|
||||
w->unrefWindow();
|
||||
}
|
||||
else
|
||||
w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DELETE );
|
||||
}
|
||||
}
|
||||
effects->prePaintWindow( w, mask, paint, clip, time );
|
||||
if( windows.contains( w ) && !w->isPaintingEnabled())
|
||||
{ // if the window isn't to be painted, then let's make sure
|
||||
// to track its progress
|
||||
if( windows[ w ].fadeInStep < 1.0
|
||||
|| windows[ w ].fadeOutStep < 1.0 )
|
||||
{ // but only if the total change is less than the
|
||||
// maximum possible change
|
||||
w->addRepaintFull();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FadeEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
|
||||
{
|
||||
if( windows.contains( w ))
|
||||
data.opacity = ( data.opacity + ( w->opacity() == 0.0 ? 1 : 0 )) * windows[ w ].current;
|
||||
{
|
||||
if( windows[ w ].deleted
|
||||
|| windows[ w ].opacity != data.opacity
|
||||
|| windows[ w ].saturation != data.saturation
|
||||
|| windows[ w ].brightness != data.brightness )
|
||||
{
|
||||
WindowPaintData new_data = data;
|
||||
|
||||
if( windows[ w ].deleted )
|
||||
new_data.opacity = 0.0;
|
||||
|
||||
if( new_data.opacity > windows[ w ].opacity )
|
||||
{
|
||||
windows[ w ].opacity = qMin( new_data.opacity,
|
||||
windows[ w ].opacity + windows[ w ].fadeInStep );
|
||||
}
|
||||
else if( new_data.opacity < windows[ w ].opacity )
|
||||
{
|
||||
windows[ w ].opacity = qMax( new_data.opacity,
|
||||
windows[ w ].opacity - windows[ w ].fadeOutStep );
|
||||
}
|
||||
|
||||
if( new_data.saturation > windows[ w ].saturation )
|
||||
{
|
||||
windows[ w ].saturation = qMin( new_data.saturation,
|
||||
windows[ w ].saturation + float( windows[ w ].fadeInStep ));
|
||||
}
|
||||
else if( new_data.saturation < windows[ w ].saturation )
|
||||
{
|
||||
windows[ w ].saturation = qMax( new_data.saturation,
|
||||
windows[ w ].saturation - float( windows[ w ].fadeOutStep ));
|
||||
}
|
||||
|
||||
if( new_data.brightness > windows[ w ].brightness )
|
||||
{
|
||||
windows[ w ].brightness = qMin( new_data.brightness,
|
||||
windows[ w ].brightness + float( windows[ w ].fadeInStep ));
|
||||
}
|
||||
else if( new_data.brightness < windows[ w ].brightness )
|
||||
{
|
||||
windows[ w ].brightness = qMax( new_data.brightness,
|
||||
windows[ w ].brightness - float( windows[ w ].fadeOutStep ));
|
||||
}
|
||||
|
||||
windows[ w ].opacity = qBound( 0.0, windows[ w ].opacity, 1.0 );
|
||||
windows[ w ].saturation = qBound( 0.0f, windows[ w ].saturation, 1.0f );
|
||||
windows[ w ].brightness = qBound( 0.0f, windows[ w ].brightness, 1.0f );
|
||||
windows[ w ].fadeInStep = 0.0;
|
||||
windows[ w ].fadeOutStep = 0.0;
|
||||
|
||||
new_data.opacity = windows[ w ].opacity;
|
||||
new_data.saturation = windows[ w ].saturation;
|
||||
new_data.brightness = windows[ w ].brightness;
|
||||
effects->paintWindow( w, mask, region, new_data );
|
||||
if( windows[ w ].opacity != data.opacity
|
||||
|| windows[ w ].saturation != data.saturation
|
||||
|| windows[ w ].brightness != data.brightness )
|
||||
w->addRepaintFull();
|
||||
return;
|
||||
}
|
||||
windows[ w ].fadeInStep = 0.0;
|
||||
windows[ w ].fadeOutStep = 0.0;
|
||||
}
|
||||
effects->paintWindow( w, mask, region, data );
|
||||
}
|
||||
|
||||
void FadeEffect::postPaintWindow( EffectWindow* w )
|
||||
void FadeEffect::windowOpacityChanged( EffectWindow* w, double old_opacity )
|
||||
{
|
||||
if( windows.contains( w ) && windows.value( w ).isFading())
|
||||
w->addRepaintFull(); // trigger next animation repaint
|
||||
effects->postPaintWindow( w );
|
||||
if( !windows.contains( w ))
|
||||
windows[ w ].opacity = old_opacity;
|
||||
if( windows[ w ].opacity == 1.0 )
|
||||
windows[ w ].opacity -= 0.1 / fadeOutTime;
|
||||
w->addRepaintFull();
|
||||
}
|
||||
|
||||
void FadeEffect::windowOpacityChanged( EffectWindow* c, double old_opacity )
|
||||
void FadeEffect::windowAdded( EffectWindow* w )
|
||||
{
|
||||
double new_opacity = c->opacity();
|
||||
if( !windows.contains( c ))
|
||||
windows[ c ].current = 1;
|
||||
if( new_opacity == 0.0 )
|
||||
{ // special case; if opacity is 0, we can't just multiply data.opacity
|
||||
windows[ c ].current = windows[ c ].current * ( old_opacity == 0.0 ? 1 : old_opacity );
|
||||
windows[ c ].target = 0;
|
||||
windows[ c ].step_mult = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
windows[ c ].current = ( windows[ c ].current * ( old_opacity == 0.0 ? 1 : old_opacity )) / new_opacity;
|
||||
windows[ c ].target = 1;
|
||||
windows[ c ].step_mult = 1 / new_opacity;
|
||||
}
|
||||
c->addRepaintFull();
|
||||
if( !fadeWindows || !isFadeWindow( w ))
|
||||
return;
|
||||
windows[ w ].opacity = 0.0;
|
||||
w->addRepaintFull();
|
||||
}
|
||||
|
||||
void FadeEffect::windowAdded( EffectWindow* c )
|
||||
void FadeEffect::windowClosed( EffectWindow* w )
|
||||
{
|
||||
if( !windows.contains( c ))
|
||||
windows[ c ].current = 0;
|
||||
if( c->opacity() == 0.0 )
|
||||
{
|
||||
windows[ c ].target = 0;
|
||||
windows[ c ].step_mult = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
windows[ c ].target = 1;
|
||||
windows[ c ].step_mult = 1 / c->opacity();
|
||||
}
|
||||
c->addRepaintFull();
|
||||
if( !fadeWindows || !isFadeWindow( w ))
|
||||
return;
|
||||
if( !windows.contains( w ))
|
||||
windows[ w ].opacity = w->opacity();
|
||||
if( windows[ w ].opacity == 1.0 )
|
||||
windows[ w ].opacity -= 0.1 / fadeOutTime;
|
||||
windows[ w ].deleted = true;
|
||||
w->refWindow();
|
||||
w->addRepaintFull();
|
||||
}
|
||||
|
||||
void FadeEffect::windowClosed( EffectWindow* c )
|
||||
void FadeEffect::windowDeleted( EffectWindow* w )
|
||||
{
|
||||
if( !windows.contains( c ))
|
||||
windows[ c ].current = 1;
|
||||
if( c->opacity() == 0.0 )
|
||||
windows[ c ].step_mult = 1;
|
||||
else
|
||||
windows[ c ].step_mult = 1 / c->opacity();
|
||||
windows[ c ].target = 0;
|
||||
windows[ c ].deleted = true;
|
||||
c->addRepaintFull();
|
||||
c->refWindow();
|
||||
windows.remove( w );
|
||||
}
|
||||
|
||||
void FadeEffect::windowDeleted( EffectWindow* c )
|
||||
bool FadeEffect::isFadeWindow( EffectWindow* w )
|
||||
{
|
||||
windows.remove( c );
|
||||
return !w->isDesktop();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -21,41 +21,42 @@ class FadeEffect
|
|||
{
|
||||
public:
|
||||
FadeEffect();
|
||||
virtual void prePaintScreen( 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
|
||||
virtual void windowOpacityChanged( EffectWindow* c, double old_opacity );
|
||||
virtual void windowAdded( EffectWindow* c );
|
||||
virtual void windowClosed( EffectWindow* c );
|
||||
virtual void windowDeleted( EffectWindow* c );
|
||||
|
||||
bool isFadeWindow( EffectWindow* w );
|
||||
private:
|
||||
int fade_in_speed, fade_out_speed; // TODO make these configurable
|
||||
class WindowInfo;
|
||||
QHash< const EffectWindow*, WindowInfo > windows;
|
||||
double fadeInStep, fadeOutStep;
|
||||
int fadeInTime, fadeOutTime;
|
||||
bool fadeWindows;
|
||||
};
|
||||
|
||||
class FadeEffect::WindowInfo
|
||||
{
|
||||
public:
|
||||
WindowInfo()
|
||||
: current( 0 )
|
||||
, target( 0 )
|
||||
, step_mult( 0 )
|
||||
: fadeInStep( 0.0 )
|
||||
, fadeOutStep( 0.0 )
|
||||
, opacity( 1.0 )
|
||||
, saturation( 1.0 )
|
||||
, brightness( 1.0 )
|
||||
, deleted( false )
|
||||
{}
|
||||
bool isFading() const;
|
||||
double current;
|
||||
double target;
|
||||
double step_mult;
|
||||
double fadeInStep, fadeOutStep;
|
||||
double opacity;
|
||||
float saturation, brightness;
|
||||
bool deleted;
|
||||
};
|
||||
|
||||
inline bool FadeEffect::WindowInfo::isFading() const
|
||||
{
|
||||
return current != target;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue