* replace qhash by qmap and avoid side-effect prone QHash::operator[]

* use TimeLine data memeber instead pointer to prevent leaking
* only setTransformed() if there's really a current animation, not if "a window we know is mapped"
* therefore use a poperty to know whether the effect manages a deleted window
* set the TRANSFORMED flag in prePaintWindow as it should be

BUG: 242693


svn path=/trunk/KDE/kdebase/workspace/; revision=1192387
This commit is contained in:
Thomas Lübking 2010-11-02 20:33:54 +00:00
parent 3d59e00295
commit 4b0278ff86
2 changed files with 104 additions and 90 deletions

View file

@ -32,8 +32,9 @@ namespace KWin
KWIN_EFFECT( glide, GlideEffect )
KWIN_EFFECT_SUPPORTED( glide, GlideEffect::supported() )
static const int IsGlideWindow = 0x22A982D4;
GlideEffect::GlideEffect()
: windowCount( 0 )
{
reconfigure( ReconfigureAll );
}
@ -53,111 +54,115 @@ void GlideEffect::reconfigure( ReconfigureFlags )
void GlideEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
if( windowCount > 0 )
if( !windows.isEmpty() )
data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
effects->prePaintScreen( data, time );
}
void GlideEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
if( windows.contains( w ) && ( windows[ w ].added || windows[ w ].closed ) )
InfoHash::iterator info = windows.find( w );
if( info != windows.end() )
{
if( windows[ w ].added )
windows[ w ].timeLine->addTime( time );
if( windows[ w ].closed )
data.setTransformed();
if( info->added )
info->timeLine.addTime( time );
else if( info->closed )
{
windows[ w ].timeLine->removeTime( time );
if( windows[ w ].deleted )
{
info->timeLine.removeTime( time );
if( info->deleted )
w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DELETE );
}
}
}
effects->prePaintWindow( w, data, time );
if( windows.contains( w ) && !w->isPaintingEnabled() && !effects->activeFullScreenEffect() )
{ // if the window isn't to be painted, then let's make sure
// to track its progress
if( windows[ w ].added || windows[ w ].closed )
{ // but only if the total change is less than the
// maximum possible change
w->addRepaintFull();
}
}
// if the window isn't to be painted, then let's make sure
// to track its progress
if( info != windows.end() && !w->isPaintingEnabled() && !effects->activeFullScreenEffect() )
w->addRepaintFull();
}
void GlideEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
{
if( windows.contains( w ) )
InfoHash::const_iterator info = windows.find( w );
if( info != windows.constEnd() )
{
const double progress = info->timeLine.value();
RotationData rot;
rot.axis = RotationData::XAxis;
rot.angle = angle * ( 1 - windows[ w ].timeLine->value() );
rot.angle = angle * ( 1 - progress );
data.rotation = &rot;
data.opacity *= windows[ w ].timeLine->value();
if( effect == GlideInOut )
data.opacity *= progress;
switch ( effect )
{
if( windows[ w ].added )
glideIn( w, data );
if( windows[ w ].closed )
glideOut( w, data );
default:
case GlideInOut:
if( info->added )
glideIn( w, data );
else if( info->closed )
glideOut( w, data );
break;
case GlideOutIn:
if( info->added )
glideOut( w, data );
if( info->closed )
glideIn( w, data );
break;
case GlideIn: glideIn( w, data ); break;
case GlideOut: glideOut( w, data ); break;
}
if( effect == GlideOutIn )
{
if( windows[ w ].added )
glideOut( w, data );
if( windows[ w ].closed )
glideIn( w, data );
}
if( effect == GlideIn )
glideIn( w, data );
if( effect == GlideOut )
glideOut( w, data );
effects->paintWindow( w, PAINT_WINDOW_TRANSFORMED, region, data );
}
else
effects->paintWindow( w, mask, region, data );
effects->paintWindow( w, mask, region, data );
}
void GlideEffect::glideIn(EffectWindow* w, WindowPaintData& data )
{
data.xScale *= windows[ w ].timeLine->value();
data.yScale *= windows[ w ].timeLine->value();
data.zScale *= windows[ w ].timeLine->value();
data.xTranslate += int( w->width() / 2 * ( 1 - windows[ w ].timeLine->value() ) );
data.yTranslate += int( w->height() / 2 * ( 1 - windows[ w ].timeLine->value() ) );
InfoHash::const_iterator info = windows.find( w );
if ( info == windows.constEnd() )
return;
const double progress = info->timeLine.value();
data.xScale *= progress;
data.yScale *= progress;
data.zScale *= progress;
data.xTranslate += int( w->width() / 2 * ( 1 - progress ) );
data.yTranslate += int( w->height() / 2 * ( 1 - progress ) );
}
void GlideEffect::glideOut(EffectWindow* w, WindowPaintData& data )
{
data.xScale *= ( 2 - windows[ w ].timeLine->value() );
data.yScale *= ( 2 - windows[ w ].timeLine->value() );
data.zScale *= ( 2 - windows[ w ].timeLine->value() );
data.xTranslate -= int( w->width() / 2 * ( 1 - windows[ w ].timeLine->value() ) );
data.yTranslate -= int( w->height() / 2 * ( 1 - windows[ w ].timeLine->value() ) );
InfoHash::const_iterator info = windows.find( w );
if ( info == windows.constEnd() )
return;
const double progress = info->timeLine.value();
data.xScale *= ( 2 - progress );
data.yScale *= ( 2 - progress );
data.zScale *= ( 2 - progress );
data.xTranslate -= int( w->width() / 2 * ( 1 - progress ) );
data.yTranslate -= int( w->height() / 2 * ( 1 - progress ) );
}
void GlideEffect::postPaintWindow( EffectWindow* w )
{
if( windows.contains( w ) )
InfoHash::iterator info = windows.find( w );
if( info != windows.end() )
{
if( windows[ w ].added && windows[ w ].timeLine->value() == 1.0 )
if( info->added && info->timeLine.value() == 1.0 )
{
windows[ w ].added = false;
windowCount--;
windows.remove( w );
effects->addRepaintFull();
}
if( windows[ w ].closed && windows[ w ].timeLine->value() == 0.0 )
else if( info->closed && info->timeLine.value() == 0.0 )
{
windows[ w ].closed = false;
if( windows[ w ].deleted )
info->closed = false;
if( info->deleted )
{
windows.remove( w );
w->unrefWindow();
}
windowCount--;
effects->addRepaintFull();
}
if( windows[ w ].added || windows[ w ].closed )
if( info->added || info->closed )
w->addRepaintFull();
}
effects->postPaintWindow( w );
@ -167,45 +172,58 @@ void GlideEffect::windowAdded( EffectWindow* w )
{
if( !isGlideWindow( w ) )
return;
w->setData( IsGlideWindow, true );
const void *addGrab = w->data( WindowAddedGrabRole ).value<void*>();
if ( addGrab && addGrab != this )
return;
w->setData( WindowAddedGrabRole, QVariant::fromValue( static_cast<void*>( this )));
windows[ w ] = WindowInfo();
windows[ w ].added = true;
windows[ w ].closed = false;
windows[ w ].deleted = false;
windows[ w ].timeLine->setDuration( duration );
windows[ w ].timeLine->setCurveShape( TimeLine::EaseOutCurve );
windowCount++;
InfoHash::iterator it = windows.find( w );
WindowInfo *info = ( it == windows.end() ) ? &windows[w] : &it.value();
info->added = true;
info->closed = false;
info->deleted = false;
info->timeLine.setDuration( duration );
info->timeLine.setCurveShape( TimeLine::EaseOutCurve );
w->addRepaintFull();
}
void GlideEffect::windowClosed( EffectWindow* w )
{
if( !windows.contains( w ) )
if ( !isGlideWindow( w ) )
return;
const void *closeGrab = w->data( WindowClosedGrabRole ).value<void*>();
if ( closeGrab && closeGrab != this )
return;
w->setData( WindowClosedGrabRole, QVariant::fromValue( static_cast<void*>( this )));
windows[ w ].added = false;
windows[ w ].closed = true;
windows[ w ].deleted = true;
windows[ w ].timeLine->setDuration( duration );
windows[ w ].timeLine->setCurveShape( TimeLine::EaseInCurve );
windowCount++;
w->refWindow();
w->setData( WindowClosedGrabRole, QVariant::fromValue( static_cast<void*>( this )));
InfoHash::iterator it = windows.find( w );
WindowInfo *info = ( it == windows.end() ) ? &windows[w] : &it.value();
info->added = false;
info->closed = true;
info->deleted = true;
info->timeLine.setDuration( duration );
info->timeLine.setCurveShape( TimeLine::EaseInCurve );
info->timeLine.setProgress( 1.0 );
w->addRepaintFull();
}
void GlideEffect::windowDeleted( EffectWindow* w )
{
//delete windows[ w ].timeLine;
windows[ w ].timeLine = NULL;
windows.remove( w );
}
bool GlideEffect::isGlideWindow( EffectWindow* w )
{
const void* e = w->data( WindowAddedGrabRole ).value<void*>();
// TODO: isSpecialWindow is rather generic, maybe tell windowtypes separately?
if ( w->isPopupMenu() || w->isSpecialWindow() || w->isUtility() || ( e && e != this ))
if ( effects->activeFullScreenEffect() )
return false;
if ( w->data( IsGlideWindow ).toBool() )
return true;
if ( w->hasDecoration() )
return true;
if ( !w->isManaged() || w->isMenu() || w->isNotification() || w->isDesktop() ||
w->isDock() || w->isSplash() || w->isTopMenu() || w->isToolbar() )
return false;
return true;
}

View file

@ -45,14 +45,14 @@ class GlideEffect
static bool supported();
private:
class WindowInfo;
typedef QMap< const EffectWindow*, WindowInfo > InfoHash;
void glideIn( EffectWindow* w, WindowPaintData& data );
void glideOut( EffectWindow* w, WindowPaintData& data );
class WindowInfo;
bool isGlideWindow( EffectWindow* w );
QHash< const EffectWindow*, WindowInfo > windows;
InfoHash windows;
float duration;
int angle;
int windowCount;
enum EffectStyle
{
GlideIn = 0,
@ -69,18 +69,14 @@ class GlideEffect::WindowInfo
WindowInfo()
: deleted( false )
, added( false )
, closed( false )
{
timeLine = new TimeLine();
}
, closed( false ) { }
~WindowInfo()
{
timeLine = NULL;
}
bool deleted;
bool added;
bool closed;
TimeLine* timeLine;
TimeLine timeLine;
};
} // namespace