From 812dd7238e2a1329e1af1626abca50eaf1b12c5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Sun, 15 Apr 2007 10:53:01 +0000 Subject: [PATCH] Arrange windows to regularly spaced slots, try to find the closest one. svn path=/branches/work/kwin_composite/; revision=654184 --- effects/presentwindows.cpp | 121 +++++++++++++++++++++++++++++++++++-- effects/presentwindows.h | 6 ++ 2 files changed, 123 insertions(+), 4 deletions(-) diff --git a/effects/presentwindows.cpp b/effects/presentwindows.cpp index e7058ecaf7..90370279cc 100644 --- a/effects/presentwindows.cpp +++ b/effects/presentwindows.cpp @@ -19,8 +19,7 @@ License. See the file "COPYING" for the exact licensing terms. #include #include - - +#include namespace KWin { @@ -245,7 +244,9 @@ void PresentWindowsEffect::rearrangeWindows() } // Calculate new positions and scales for windows - calculateWindowTransformationsKompose( windowlist ); +// calculateWindowTransformationsDumb( windowlist ); +// calculateWindowTransformationsKompose( windowlist ); + calculateWindowTransformationsClosest( windowlist ); // Schedule entire desktop to be repainted effects->addRepaintFull(); @@ -303,7 +304,7 @@ int PresentWindowsEffect::windowHeightForWidth(EffectWindow* c, int w) void PresentWindowsEffect::calculateWindowTransformationsKompose(EffectWindowList windowlist) { // 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 @@ -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::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::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::Iterator it1 = mWindowData.begin(); + it1 != mWindowData.end(); + ++it1 ) + { + for( QHash::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 ) { if( border == borderActivate && !mActivated ) diff --git a/effects/presentwindows.h b/effects/presentwindows.h index e1c6f89a89..adc4accecc 100644 --- a/effects/presentwindows.h +++ b/effects/presentwindows.h @@ -50,12 +50,16 @@ class PresentWindowsEffect void rearrangeWindows(); void calculateWindowTransformationsDumb(EffectWindowList windowlist); void calculateWindowTransformationsKompose(EffectWindowList windowlist); + void calculateWindowTransformationsClosest(EffectWindowList windowlist); // Helper methods for layout calculation float windowAspectRatio(EffectWindow* c); int windowWidthForHeight(EffectWindow* c, int h); 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) void effectActivated(); // Called once the effect has terminated @@ -76,6 +80,8 @@ class PresentWindowsEffect QRect area; float scale; float hover; + int slot; + int slot_distance; }; QHash mWindowData; EffectWindow* mHoverWindow;