Arrange windows to regularly spaced slots, try to find the closest one.

svn path=/branches/work/kwin_composite/; revision=654184
This commit is contained in:
Luboš Luňák 2007-04-15 10:53:01 +00:00
parent e18e701f7f
commit 812dd7238e
2 changed files with 123 additions and 4 deletions

View file

@ -19,8 +19,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include <math.h> #include <math.h>
#include <assert.h> #include <assert.h>
#include <limits.h>
namespace KWin namespace KWin
{ {
@ -245,7 +244,9 @@ void PresentWindowsEffect::rearrangeWindows()
} }
// Calculate new positions and scales for windows // Calculate new positions and scales for windows
calculateWindowTransformationsKompose( windowlist ); // calculateWindowTransformationsDumb( windowlist );
// calculateWindowTransformationsKompose( windowlist );
calculateWindowTransformationsClosest( windowlist );
// Schedule entire desktop to be repainted // Schedule entire desktop to be repainted
effects->addRepaintFull(); effects->addRepaintFull();
@ -303,7 +304,7 @@ int PresentWindowsEffect::windowHeightForWidth(EffectWindow* c, int w)
void PresentWindowsEffect::calculateWindowTransformationsKompose(EffectWindowList windowlist) void PresentWindowsEffect::calculateWindowTransformationsKompose(EffectWindowList windowlist)
{ {
// Get rect which we can use on current desktop. This excludes e.g. panels // Get rect which we can use on current desktop. This excludes e.g. panels
QRect availRect = effects->clientArea( PlacementArea, QPoint( 0, 0 ), 0 ); QRect availRect = effects->clientArea( PlacementArea, QPoint( 0, 0 ), effects->currentDesktop());
// Following code is taken from Kompose 0.5.4, src/komposelayout.cpp // Following code is taken from Kompose 0.5.4, src/komposelayout.cpp
@ -439,6 +440,118 @@ void PresentWindowsEffect::calculateWindowTransformationsKompose(EffectWindowLis
} }
} }
void PresentWindowsEffect::calculateWindowTransformationsClosest(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 )));
foreach( EffectWindow* w, windowlist )
{
WindowData d;
d.slot = -1;
d.hover = 0; // other data will be computed later
mWindowData[ w ] = d;
}
for(;;)
{
// Assign each window to the closest available slot
assignSlots( area, columns, rows );
// Leave only the closest window in each slot, remove further conflicts
getBestAssignments();
bool all_assigned = true;
foreach( EffectWindow* w, windowlist )
if( mWindowData[ w ].slot == -1 )
{
all_assigned = false;
break;
}
if( all_assigned )
break; // ok
}
int slotwidth = area.width() / columns;
int slotheight = area.height() / rows;
for( QHash<EffectWindow*, WindowData>::Iterator it = mWindowData.begin();
it != mWindowData.end();
++it )
{
QRect geom( area.x() + ((*it).slot % columns ) * slotwidth,
area.y() + ((*it).slot / columns ) * slotheight,
slotwidth, slotheight );
geom.adjust( 10, 10, -10, -10 ); // borders
(*it).area = geom;
(*it).scale = geom.width() / float( it.key()->width());
}
}
void PresentWindowsEffect::assignSlots( const QRect& area, int columns, int rows )
{
QVector< bool > taken;
taken.fill( false, columns * rows );
foreach( const WindowData& d, mWindowData )
{
if( d.slot != -1 )
taken[ d.slot ] = true;
}
int slotwidth = area.width() / columns;
int slotheight = area.height() / rows;
for( QHash<EffectWindow*, WindowData>::Iterator it = mWindowData.begin();
it != mWindowData.end();
++it )
{
if( (*it).slot != -1 )
continue; // it already has a slot
QPoint pos = it.key()->geometry().center();
if( pos.x() < area.left())
pos.setX( area.left());
if( pos.x() > area.right())
pos.setX( area.right());
if( pos.y() < area.top())
pos.setY( area.top());
if( pos.y() > area.bottom())
pos.setY( area.bottom());
int distance = INT_MAX;
for( int x = 0;
x < columns;
++x )
for( int y = 0;
y < rows;
++y )
{
int slot = x + y * columns;
if( taken[ slot ] )
continue;
int xdiff = pos.x() - ( area.x() + slotwidth * x + slotwidth / 2 ); // slotwidth/2 for center
int ydiff = pos.y() - ( area.y() + slotheight * y + slotheight / 2 );
int dist = int( sqrt( xdiff * xdiff + ydiff * ydiff ));
if( dist < distance )
{
distance = dist;
(*it).slot = slot;
(*it).slot_distance = distance;
}
}
}
}
void PresentWindowsEffect::getBestAssignments()
{
for( QHash<EffectWindow*, WindowData>::Iterator it1 = mWindowData.begin();
it1 != mWindowData.end();
++it1 )
{
for( QHash<EffectWindow*, WindowData>::ConstIterator it2 = mWindowData.begin();
it2 != mWindowData.end();
++it2 )
{
if( it1.key() != it2.key() && (*it1).slot == (*it2).slot
&& (*it1).slot_distance >= (*it2).slot_distance )
{
(*it1).slot = -1;
}
}
}
}
bool PresentWindowsEffect::borderActivated( ElectricBorder border ) bool PresentWindowsEffect::borderActivated( ElectricBorder border )
{ {
if( border == borderActivate && !mActivated ) if( border == borderActivate && !mActivated )

View file

@ -50,12 +50,16 @@ class PresentWindowsEffect
void rearrangeWindows(); void rearrangeWindows();
void calculateWindowTransformationsDumb(EffectWindowList windowlist); void calculateWindowTransformationsDumb(EffectWindowList windowlist);
void calculateWindowTransformationsKompose(EffectWindowList windowlist); void calculateWindowTransformationsKompose(EffectWindowList windowlist);
void calculateWindowTransformationsClosest(EffectWindowList windowlist);
// Helper methods for layout calculation // Helper methods for layout calculation
float windowAspectRatio(EffectWindow* c); float windowAspectRatio(EffectWindow* c);
int windowWidthForHeight(EffectWindow* c, int h); int windowWidthForHeight(EffectWindow* c, int h);
int windowHeightForWidth(EffectWindow* c, int w); int windowHeightForWidth(EffectWindow* c, int w);
void assignSlots( const QRect& area, int columns, int rows );
void getBestAssignments();
// Called once the effect is activated (and wasn't activated before) // Called once the effect is activated (and wasn't activated before)
void effectActivated(); void effectActivated();
// Called once the effect has terminated // Called once the effect has terminated
@ -76,6 +80,8 @@ class PresentWindowsEffect
QRect area; QRect area;
float scale; float scale;
float hover; float hover;
int slot;
int slot_distance;
}; };
QHash<EffectWindow*, WindowData> mWindowData; QHash<EffectWindow*, WindowData> mWindowData;
EffectWindow* mHoverWindow; EffectWindow* mHoverWindow;