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

View file

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