When the number of presented windows changes, do the rearranging smoothly.

Also rearrange only if the size of the grid would change.


svn path=/branches/work/kwin_composite/; revision=654209
icc-effect-5.14.5
Luboš Luňák 2007-04-15 13:25:44 +00:00
parent b65e6affd9
commit 894d08a522
2 changed files with 71 additions and 15 deletions

View File

@ -30,6 +30,7 @@ PresentWindowsEffect::PresentWindowsEffect()
: mShowWindowsFromAllDesktops ( false ) : mShowWindowsFromAllDesktops ( false )
, mActivated( false ) , mActivated( false )
, mActiveness( 0.0 ) , mActiveness( 0.0 )
, mRearranging( 1.0 )
, mHoverWindow( NULL ) , mHoverWindow( NULL )
{ {
@ -62,7 +63,11 @@ void PresentWindowsEffect::prePaintScreen( int* mask, QRegion* region, int time
// How long does it take for the effect to get it's full strength (in ms) // How long does it take for the effect to get it's full strength (in ms)
const float changeTime = 300; const float changeTime = 300;
if(mActivated) if(mActivated)
{
mActiveness = qMin(1.0f, mActiveness + time/changeTime); mActiveness = qMin(1.0f, mActiveness + time/changeTime);
if( mRearranging < 1 )
mRearranging = qMin(1.0f, mRearranging + time/changeTime);
}
else if(mActiveness > 0.0f) else if(mActiveness > 0.0f)
{ {
mActiveness = qMax(0.0f, mActiveness - time/changeTime); mActiveness = qMax(0.0f, mActiveness - time/changeTime);
@ -112,10 +117,22 @@ void PresentWindowsEffect::paintWindow( EffectWindow* w, int mask, QRegion regio
{ {
// Change window's position and scale // Change window's position and scale
const WindowData& windata = mWindowData[w]; const WindowData& windata = mWindowData[w];
data.xScale = interpolate(data.xScale, windata.scale, mActiveness); if( mRearranging < 1 ) // rearranging
data.yScale = interpolate(data.xScale, windata.scale, mActiveness); {
data.xTranslate = (int)interpolate(data.xTranslate, windata.area.left() - w->x(), mActiveness); data.xScale = interpolate(windata.old_scale, windata.scale, mRearranging);
data.yTranslate = (int)interpolate(data.yTranslate, windata.area.top() - w->y(), mActiveness); data.yScale = interpolate(windata.old_scale, windata.scale, mRearranging);
data.xTranslate = (int)interpolate(windata.old_area.left() - w->x(),
windata.area.left() - w->x(), mRearranging);
data.yTranslate = (int)interpolate(windata.old_area.top() - w->y(),
windata.area.top() - w->y(), mRearranging);
}
else
{
data.xScale = interpolate(data.xScale, windata.scale, mActiveness);
data.yScale = interpolate(data.xScale, windata.scale, mActiveness);
data.xTranslate = (int)interpolate(data.xTranslate, windata.area.left() - w->x(), mActiveness);
data.yTranslate = (int)interpolate(data.yTranslate, windata.area.top() - w->y(), mActiveness);
}
// Darken all windows except for the one under the cursor // Darken all windows except for the one under the cursor
data.brightness *= interpolate(1.0, 0.7, mActiveness * (1.0f - windata.hover)); data.brightness *= interpolate(1.0, 0.7, mActiveness * (1.0f - windata.hover));
// If it's minimized window or on another desktop and effect is not // If it's minimized window or on another desktop and effect is not
@ -132,6 +149,8 @@ void PresentWindowsEffect::postPaintScreen()
{ {
if( mActivated && mActiveness < 1.0 ) // activating effect if( mActivated && mActiveness < 1.0 ) // activating effect
effects->addRepaintFull(); effects->addRepaintFull();
if( mActivated && mRearranging < 1.0 ) // rearranging
effects->addRepaintFull();
if( !mActivated && mActiveness > 0.0 ) // deactivating effect if( !mActivated && mActiveness > 0.0 ) // deactivating effect
effects->addRepaintFull(); effects->addRepaintFull();
foreach( const WindowData& d, mWindowData ) foreach( const WindowData& d, mWindowData )
@ -207,6 +226,9 @@ void PresentWindowsEffect::setActive(bool active)
mHoverWindow = NULL; mHoverWindow = NULL;
if( mActivated ) if( mActivated )
{ {
mWindowData.clear();
effectActivated();
mActiveness = 0;
mWindowsToPresent.clear(); mWindowsToPresent.clear();
const EffectWindowList& originalwindowlist = effects->stackingOrder(); const EffectWindowList& originalwindowlist = effects->stackingOrder();
// Filter out special windows such as panels and taskbars // Filter out special windows such as panels and taskbars
@ -220,12 +242,14 @@ void PresentWindowsEffect::setActive(bool active)
continue; continue;
mWindowsToPresent.append(window); mWindowsToPresent.append(window);
} }
rearrangeWindows();
} }
else else
{
mWindowsToPresent.clear(); mWindowsToPresent.clear();
rearrangeWindows(); mRearranging = 1; // turn off
if( mActivated && mActiveness == 0.0f ) mActiveness = 1; // go back from arranged position
effectActivated(); }
effects->addRepaintFull(); // trigger next animation repaint effects->addRepaintFull(); // trigger next animation repaint
} }
@ -247,9 +271,30 @@ void PresentWindowsEffect::rearrangeWindows()
if( !mActivated ) if( !mActivated )
return; return;
mWindowData.clear();
EffectWindowList windowlist = mWindowsToPresent; EffectWindowList windowlist = mWindowsToPresent;
if( !mWindowData.isEmpty()) // this is not first arranging
{
bool canrearrange = canRearrangeClosest( windowlist );
QHash<EffectWindow*, WindowData> newdata;
for( QHash<EffectWindow*, WindowData>::ConstIterator it = mWindowData.begin();
it != mWindowData.end();
++it )
if( windowlist.contains( it.key())) // remove windows that are not in the window list
newdata[ it.key() ] = *it;
mWindowData = newdata;
if( !canrearrange ) // canRearrange was called before adjusting the list, so that
return; // changes can be detected
for( QHash<EffectWindow*, WindowData>::Iterator it = mWindowData.begin();
it != mWindowData.end();
++it )
{
(*it).old_area = (*it).area;
(*it).old_scale = (*it).scale;
}
mRearranging = 0; // start animation again
}
// Calculate new positions and scales for windows // Calculate new positions and scales for windows
// calculateWindowTransformationsDumb( windowlist ); // calculateWindowTransformationsDumb( windowlist );
// calculateWindowTransformationsKompose( windowlist ); // calculateWindowTransformationsKompose( windowlist );
@ -453,12 +498,7 @@ void PresentWindowsEffect::calculateWindowTransformationsClosest(EffectWindowLis
int columns = int( ceil( sqrt( windowlist.count()))); int columns = int( ceil( sqrt( windowlist.count())));
int rows = int( ceil( windowlist.count() / double( columns ))); int rows = int( ceil( windowlist.count() / double( columns )));
foreach( EffectWindow* w, windowlist ) foreach( EffectWindow* w, windowlist )
{ mWindowData[ w ].slot = -1;
WindowData d;
d.slot = -1;
d.hover = 0; // other data will be computed later
mWindowData[ w ] = d;
}
for(;;) for(;;)
{ {
// Assign each window to the closest available slot // Assign each window to the closest available slot
@ -487,6 +527,7 @@ void PresentWindowsEffect::calculateWindowTransformationsClosest(EffectWindowLis
geom.adjust( 10, 10, -10, -10 ); // borders geom.adjust( 10, 10, -10, -10 ); // borders
(*it).area = geom; (*it).area = geom;
(*it).scale = geom.width() / float( it.key()->width()); (*it).scale = geom.width() / float( it.key()->width());
(*it).hover = 0;
} }
} }
@ -559,6 +600,16 @@ void PresentWindowsEffect::getBestAssignments()
} }
} }
bool PresentWindowsEffect::canRearrangeClosest(EffectWindowList windowlist)
{
QRect area = effects->clientArea( PlacementArea, QPoint( 0, 0 ), effects->currentDesktop());
int columns = int( ceil( sqrt( windowlist.count())));
int rows = int( ceil( windowlist.count() / double( columns )));
int old_columns = int( ceil( sqrt( mWindowData.count())));
int old_rows = int( ceil( mWindowData.count() / double( columns )));
return old_columns != columns || old_rows != rows;
}
bool PresentWindowsEffect::borderActivated( ElectricBorder border ) bool PresentWindowsEffect::borderActivated( ElectricBorder border )
{ {
if( border == borderActivate && !mActivated ) if( border == borderActivate && !mActivated )

View File

@ -50,6 +50,7 @@ class PresentWindowsEffect
void calculateWindowTransformationsDumb(EffectWindowList windowlist); void calculateWindowTransformationsDumb(EffectWindowList windowlist);
void calculateWindowTransformationsKompose(EffectWindowList windowlist); void calculateWindowTransformationsKompose(EffectWindowList windowlist);
void calculateWindowTransformationsClosest(EffectWindowList windowlist); void calculateWindowTransformationsClosest(EffectWindowList windowlist);
bool canRearrangeClosest(EffectWindowList windowlist);
// Helper methods for layout calculation // Helper methods for layout calculation
float windowAspectRatio(EffectWindow* c); float windowAspectRatio(EffectWindow* c);
@ -71,6 +72,8 @@ class PresentWindowsEffect
bool mActivated; bool mActivated;
// 0 = not active, 1 = fully active // 0 = not active, 1 = fully active
float mActiveness; float mActiveness;
// 0 = start of rearranging (old_area), 1 = done
float mRearranging;
Window mInput; Window mInput;
@ -78,7 +81,9 @@ class PresentWindowsEffect
struct WindowData struct WindowData
{ {
QRect area; QRect area;
QRect old_area; // when rearranging, otherwise unset
float scale; float scale;
float old_scale; // when rearranging, otherwise unset
float hover; float hover;
int slot; int slot;
int slot_distance; int slot_distance;