* 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:
parent
3d59e00295
commit
4b0278ff86
2 changed files with 104 additions and 90 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue