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
This commit is contained in:
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 )
, mActivated( false )
, mActiveness( 0.0 )
, mRearranging( 1.0 )
, 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)
const float changeTime = 300;
if(mActivated)
{
mActiveness = qMin(1.0f, mActiveness + time/changeTime);
if( mRearranging < 1 )
mRearranging = qMin(1.0f, mRearranging + time/changeTime);
}
else if(mActiveness > 0.0f)
{
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
const WindowData& windata = mWindowData[w];
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);
if( mRearranging < 1 ) // rearranging
{
data.xScale = interpolate(windata.old_scale, windata.scale, mRearranging);
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
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
@ -132,6 +149,8 @@ void PresentWindowsEffect::postPaintScreen()
{
if( mActivated && mActiveness < 1.0 ) // activating effect
effects->addRepaintFull();
if( mActivated && mRearranging < 1.0 ) // rearranging
effects->addRepaintFull();
if( !mActivated && mActiveness > 0.0 ) // deactivating effect
effects->addRepaintFull();
foreach( const WindowData& d, mWindowData )
@ -207,6 +226,9 @@ void PresentWindowsEffect::setActive(bool active)
mHoverWindow = NULL;
if( mActivated )
{
mWindowData.clear();
effectActivated();
mActiveness = 0;
mWindowsToPresent.clear();
const EffectWindowList& originalwindowlist = effects->stackingOrder();
// Filter out special windows such as panels and taskbars
@ -220,12 +242,14 @@ void PresentWindowsEffect::setActive(bool active)
continue;
mWindowsToPresent.append(window);
}
rearrangeWindows();
}
else
{
mWindowsToPresent.clear();
rearrangeWindows();
if( mActivated && mActiveness == 0.0f )
effectActivated();
mRearranging = 1; // turn off
mActiveness = 1; // go back from arranged position
}
effects->addRepaintFull(); // trigger next animation repaint
}
@ -247,9 +271,30 @@ void PresentWindowsEffect::rearrangeWindows()
if( !mActivated )
return;
mWindowData.clear();
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
// calculateWindowTransformationsDumb( windowlist );
// calculateWindowTransformationsKompose( windowlist );
@ -453,12 +498,7 @@ void PresentWindowsEffect::calculateWindowTransformationsClosest(EffectWindowLis
int columns = int( ceil( sqrt( windowlist.count())));
int rows = int( ceil( windowlist.count() / double( columns )));
foreach( EffectWindow* w, windowlist )
{
WindowData d;
d.slot = -1;
d.hover = 0; // other data will be computed later
mWindowData[ w ] = d;
}
mWindowData[ w ].slot = -1;
for(;;)
{
// Assign each window to the closest available slot
@ -487,6 +527,7 @@ void PresentWindowsEffect::calculateWindowTransformationsClosest(EffectWindowLis
geom.adjust( 10, 10, -10, -10 ); // borders
(*it).area = geom;
(*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 )
{
if( border == borderActivate && !mActivated )

View file

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