From f49c7be01835c24f41a6a1ff7197757a27f6eec5 Mon Sep 17 00:00:00 2001 From: Cristian Tibirna Date: Tue, 16 Nov 1999 08:53:02 +0000 Subject: [PATCH] CT: smart placement code. No! It isn't tested and isn't supposed to work. One 'if' gets a bad turn. But commit it 'cause I'm reknown for doing stupid things with unbacked-up code. Matthias, I managed to reduce all from 175 to 125 lines and from 4740 chars to 3260. This is what you wanted? Don't worry, kwin compiles and works as before. If somebody finds a way to teleport my office in some other dimension, I finish this tomorrow (that is, today + a couple of sleep hours). If not ... svn path=/trunk/kdebase/kwin/; revision=34034 --- options.cpp | 3 ++ options.h | 9 ++++ workspace.cpp | 132 +++++++++++++++++++++++++++++++++++++++++++++++++- workspace.h | 1 + 4 files changed, 144 insertions(+), 1 deletion(-) diff --git a/options.cpp b/options.cpp index ae95f0a17b..9b47660a97 100644 --- a/options.cpp +++ b/options.cpp @@ -11,6 +11,9 @@ Options::Options() for(i=0; i < KWINCOLORS*2; ++i) cg[i] = NULL; reload(); + + //CT + placement = Random; //ACHTUNG!! for the moment *only* } Options::~Options(){ diff --git a/options.h b/options.h index 3001357abf..ae5a9ce03d 100644 --- a/options.h +++ b/options.h @@ -51,6 +51,15 @@ public: MoveResizeMode resizeMode; MoveResizeMode moveMode; + /** + * Placement policies. How workspace decides the way windows get positioned + * on the screen. The better the policy, the heavier the resource use. + * Normally you don't have to worry. What the WM adds to the startup time + * is nil compared to the creation of the window itself in the memory + */ + enum PlacementPolicy { Random, Smart }; + PlacementPolicy placement; + bool focusPolicyIsReasonable() { return focusPolicy == ClickToFocus || focusPolicy == FocusFollowsMouse; } diff --git a/workspace.cpp b/workspace.cpp index 47e1f9e1af..c6a26638d5 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -838,7 +838,10 @@ void Workspace::showPopup( const QPoint& pos, Client* c) */ void Workspace::doPlacement( Client* c ) { + if (options->placement == Options::Random) randomPlacement( c ); + else if (options->placement == Options::Smart) + smartPlacement( c ); } /*! @@ -881,6 +884,134 @@ void Workspace::randomPlacement(Client* c){ c->move( tx, ty ); } +/*! + Place the client \a c according to a really smart placement algorithm :-) +*/ +void Workspace::smartPlacement(Client* c){ + /* + * SmartPlacement by Cristian Tibirna (tibirna@kde.org) + * adapted for kwm (16-19jan98) and for kwin (16Nov1999) using (with + * permission) ideas from fvwm, authored by + * Anthony Martin (amartin@engr.csulb.edu). + */ + + const int none = 0, least = -1, wrong = -2; // overlap types + int overlap, min_overlap; + int x_optimal, y_optimal; + int possible; + + int cxl, cxr, cyt, cyb; //temp coords + int xl, xr, yt, yb; //temp coords + + // get the maximum allowed windows space + QRect maxRect = clientArea(); + int x = maxRect.left(), y = maxRect.top(); + + //client gabarit + int ch = c->height(), cw = c->width(); + + //loop over possible positions + do { + + //test if enough room in x and y directions + if ( y + ch > maxRect.bottom() ) + overlap = -1; + else if( x + cw > maxRect.right() ) + overlap = -2; + else { + overlap = none; //initialize + + cxl = x; cxr = x + cw; + cyt = y; cyb = y + ch; + QValueList::ConstIterator l; + for(l = clients.begin(); l != clients.end() ; ++l ) { + if((*l)->isOnDesktop(currentDesktop()) || + !(*l)->isIconified() || !((*l) == c) ) { + + xl = (*l)->x(); yt = (*l)->y(); + xr = xl + (*l)->height(); yb = yt + (*l)->width(); + + //if windows overlap, calc the overlapping + if((cxl < xr) && (cxr > xl) && + (cyt < yb) && (cyb > yt)) { + xl = QMAX(cxl, xl); xr = QMIN(cxr, xr); + yt = QMAX(cyt, yt); yb = QMIN(cyb, yb); + overlap += (xr - xl) * (yb - yt); + } + } + } + } + + // really need to loop? test if there's any overlap + if ( overlap > none ) { + + possible = maxRect.right(); + if ( possible - cw > x) possible -= cw; + + // compare to the position of each client on the current desk + QValueList::ConstIterator l; + for(l = clients.begin(); l != clients.end() ; ++l) { + + if ( (*l)->isOnDesktop(currentDesktop()) || + !(*l)->isIconified() || !((*l) == c) ) { + + xl = (*l)->x(); yt = (*l)->y(); + xr = xl + (*l)->height(); yb = yt + (*l)->width(); + + // if not enough room above or under the current tested client + // determine the first non-overlapped x position + if( y < yb && yt < ch + y ) { + + if( yb > x ) + possible = possible < yb ? possible : yb; + + if( xl - cw > x ) + possible = possible < xl - cw ? possible : xl - cw; + } + } + x = possible; + } + } + + // ... else => not enough x dimension (overlap was -2) + else if (overlap == wrong) { + x = maxRect.left(); + + possible = maxRect.bottom(); + + if(possible - ch > y) possible -= ch; + + //test the position of each window on current desk + //07mar98. fixed bug which made iconified windows avoided as if visible + QValueList::ConstIterator l; + for(l = clients.begin(); l != clients.end() ; ++l) { + if( (*l)->isOnDesktop( currentDesktop() ) || + !((*l) == c) || !c->isIconified() ) { + + xl = (*l)->x(); yt = (*l)->y(); + xr = xl + (*l)->height(); yb = yt + (*l)->width(); + + if( yb > y) + possible = possible < yb ? possible : yb; + + if( yt - ch > y ) + possible = possible < yt - ch ? possible : yt - ch; + } + y = possible; + } + } + + min_overlap = overlap; + x_optimal = x; + y_optimal = y; + + } + while((overlap != none) && (overlap != least)); + + // place the window + c->move( x_optimal, y_optimal ); + +} /*! @@ -933,7 +1064,6 @@ void Workspace::raiseClient( Client* c ) } - /*! Private auxiliary function used in raiseClient() */ diff --git a/workspace.h b/workspace.h index 7e2d1a0d3c..abb626f13b 100644 --- a/workspace.h +++ b/workspace.h @@ -133,6 +133,7 @@ private: void raiseTransientsOf( ClientList& safeset, Client* c ); void randomPlacement(Client* c); + void smartPlacement(Client* c); void focusToNull(); Client* desktop_client;