kwin Library API Documentation

placement.cpp

00001 /*****************************************************************
00002  KWin - the KDE window manager
00003  This file is part of the KDE project.
00004 
00005 Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
00006 Copyright (C) 1997 to 2002 Cristian Tibirna <tibirna@kde.org>
00007 Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
00008 
00009 You can Freely distribute this program under the GNU General Public
00010 License. See the file "COPYING" for the exact licensing terms.
00011 ******************************************************************/
00012 
00013 #include "placement.h"
00014 
00015 #include <qrect.h>
00016 #include <assert.h>
00017 
00018 #ifndef KCMRULES
00019 #include "workspace.h"
00020 #include "client.h"
00021 #include "options.h"
00022 #include "rules.h"
00023 #endif
00024 
00025 namespace KWinInternal
00026 {
00027 
00028 #ifndef KCMRULES
00029 
00030 Placement::Placement(Workspace* w)
00031     {
00032     m_WorkspacePtr = w;
00033 
00034     //CT initialize the cascading info
00035     for( int i = 0; i < m_WorkspacePtr->numberOfDesktops(); i++) 
00036         {
00037         DesktopCascadingInfo inf;
00038         inf.pos = QPoint(0,0);
00039         inf.col = 0;
00040         inf.row = 0;
00041         cci.append(inf);
00042         }
00043 
00044     }
00045 
00049 void Placement::place(Client* c, QRect& area )
00050     {
00051     Policy policy = c->rules()->checkPlacement( Default );
00052     if( policy != Default )
00053         return place( c, policy, area );
00054 
00055     if( c->isUtility())
00056         placeUtility(c, area);
00057     else if( c->isDialog())
00058         placeDialog(c, area);
00059     else if( c->isSplash())
00060         placeOnMainWindow( c, area ); // on mainwindow, if any, otherwise centered
00061     else
00062         place(c, options->placement, area);
00063     }
00064 
00065 void Placement::place(Client* c, Policy policy, QRect& area )
00066     {
00067     if( policy == Default )
00068         policy = options->placement;
00069     if( policy == NoPlacement )
00070         return;
00071     else if (policy == Random)
00072         placeAtRandom(c, area);
00073     else if (policy == Cascade)
00074         placeCascaded(c, area);
00075     else if (policy == Centered)
00076         placeCentered(c, area);
00077     else if (policy == ZeroCornered)
00078         placeZeroCornered(c, area);
00079     else if (policy == UnderMouse)
00080         placeUnderMouse(c, area);
00081     else if (policy == OnMainWindow)
00082         placeOnMainWindow(c, area);
00083     else
00084         placeSmart(c, area);
00085     }
00086 
00090 void Placement::placeAtRandom(Client* c, const QRect& area )
00091     {
00092     const int step  = 24;
00093     static int px = step;
00094     static int py = 2 * step;
00095     int tx,ty;
00096 
00097     const QRect maxRect = checkArea( c, area );
00098 
00099     if (px < maxRect.x())
00100         px = maxRect.x();
00101     if (py < maxRect.y())
00102         py = maxRect.y();
00103 
00104     px += step;
00105     py += 2*step;
00106 
00107     if (px > maxRect.width()/2)
00108         px =  maxRect.x() + step;
00109     if (py > maxRect.height()/2)
00110         py =  maxRect.y() + step;
00111     tx = px;
00112     ty = py;
00113     if (tx + c->width() > maxRect.right())
00114         {
00115         tx = maxRect.right() - c->width();
00116         if (tx < 0)
00117             tx = 0;
00118         px =  maxRect.x();
00119         }
00120     if (ty + c->height() > maxRect.bottom())
00121         {
00122         ty = maxRect.bottom() - c->height();
00123         if (ty < 0)
00124             ty = 0;
00125         py =  maxRect.y();
00126         }
00127     c->move(tx, ty);
00128     }
00129 
00133 void Placement::placeSmart(Client* c, const QRect& area )
00134     {
00135     /*
00136      * SmartPlacement by Cristian Tibirna (tibirna@kde.org)
00137      * adapted for kwm (16-19jan98) and for kwin (16Nov1999) using (with
00138      * permission) ideas from fvwm, authored by
00139      * Anthony Martin (amartin@engr.csulb.edu).
00140      * Xinerama supported added by Balaji Ramani (balaji@yablibli.com)
00141      * with ideas from xfce.
00142      */
00143 
00144     const int none = 0, h_wrong = -1, w_wrong = -2; // overlap types
00145     long int overlap, min_overlap = 0;
00146     int x_optimal, y_optimal;
00147     int possible;
00148     int desktop = c->desktop() == 0 || c->isOnAllDesktops() ? m_WorkspacePtr->currentDesktop() : c->desktop();
00149 
00150     int cxl, cxr, cyt, cyb;     //temp coords
00151     int  xl,  xr,  yt,  yb;     //temp coords
00152     int basket;                 //temp holder
00153 
00154     // get the maximum allowed windows space
00155     const QRect maxRect = checkArea( c, area );
00156     int x = maxRect.left(), y = maxRect.top();
00157     x_optimal = x; y_optimal = y;
00158 
00159     //client gabarit
00160     int ch = c->height() - 1;
00161     int cw = c->width()  - 1;
00162 
00163     bool first_pass = true; //CT lame flag. Don't like it. What else would do?
00164 
00165     //loop over possible positions
00166     do 
00167         {
00168         //test if enough room in x and y directions
00169         if (y + ch > maxRect.bottom() && ch < maxRect.height())
00170             overlap = h_wrong; // this throws the algorithm to an exit
00171         else if(x + cw > maxRect.right())
00172             overlap = w_wrong;
00173         else 
00174             {
00175             overlap = none; //initialize
00176 
00177             cxl = x; cxr = x + cw;
00178             cyt = y; cyb = y + ch;
00179             ClientList::ConstIterator l;
00180             for(l = m_WorkspacePtr->stackingOrder().begin(); l != m_WorkspacePtr->stackingOrder().end() ; ++l) 
00181                 {
00182                 if((*l)->isOnDesktop(desktop) &&
00183                    (*l)->isShown( false ) && (*l) != c) 
00184                     {
00185 
00186                     xl = (*l)->x();          yt = (*l)->y();
00187                     xr = xl + (*l)->width(); yb = yt + (*l)->height();
00188 
00189                     //if windows overlap, calc the overall overlapping
00190                     if((cxl < xr) && (cxr > xl) &&
00191                        (cyt < yb) && (cyb > yt)) 
00192                         {
00193                         xl = QMAX(cxl, xl); xr = QMIN(cxr, xr);
00194                         yt = QMAX(cyt, yt); yb = QMIN(cyb, yb);
00195                         if((*l)->keepAbove())
00196                             overlap += 16 * (xr - xl) * (yb - yt);
00197                         else if((*l)->keepBelow() && !(*l)->isDock()) // ignore KeepBelow windows
00198                             overlap += 0; // for placement (see Client::belongsToLayer() for Dock)
00199                         else
00200                             overlap += (xr - xl) * (yb - yt);
00201                         }
00202                     }
00203                 }
00204             }
00205 
00206         //CT first time we get no overlap we stop.
00207         if (overlap == none) 
00208             {
00209             x_optimal = x;
00210             y_optimal = y;
00211             break;
00212             }
00213 
00214         if (first_pass) 
00215             {
00216             first_pass = false;
00217             min_overlap = overlap;
00218             }
00219         //CT save the best position and the minimum overlap up to now
00220         else if (overlap >= none && overlap < min_overlap) 
00221             {
00222             min_overlap = overlap;
00223             x_optimal = x;
00224             y_optimal = y;
00225             }
00226 
00227         // really need to loop? test if there's any overlap
00228         if (overlap > none) 
00229             {
00230 
00231             possible = maxRect.right();
00232             if (possible - cw > x) possible -= cw;
00233 
00234             // compare to the position of each client on the same desk
00235             ClientList::ConstIterator l;
00236             for(l = m_WorkspacePtr->stackingOrder().begin(); l != m_WorkspacePtr->stackingOrder().end() ; ++l) 
00237                 {
00238 
00239                 if ((*l)->isOnDesktop(desktop) &&
00240                      (*l)->isShown( false ) &&  (*l) != c) 
00241                     {
00242 
00243                     xl = (*l)->x();          yt = (*l)->y();
00244                     xr = xl + (*l)->width(); yb = yt + (*l)->height();
00245 
00246                     // if not enough room above or under the current tested client
00247                     // determine the first non-overlapped x position
00248                     if((y < yb) && (yt < ch + y)) 
00249                         {
00250 
00251                         if((xr > x) && (possible > xr)) possible = xr;
00252 
00253                         basket = xl - cw;
00254                         if((basket > x) && (possible > basket)) possible = basket;
00255                         }
00256                     }
00257                 }
00258             x = possible;
00259             }
00260 
00261         // ... else ==> not enough x dimension (overlap was wrong on horizontal)
00262         else if (overlap == w_wrong) 
00263             {
00264             x = maxRect.left();
00265             possible = maxRect.bottom();
00266 
00267             if (possible - ch > y) possible -= ch;
00268 
00269             //test the position of each window on the desk
00270             ClientList::ConstIterator l;
00271             for(l = m_WorkspacePtr->stackingOrder().begin(); l != m_WorkspacePtr->stackingOrder().end() ; ++l) 
00272                 {
00273                 if((*l)->isOnDesktop(desktop) &&
00274                     (*l) != c   &&  c->isShown( false )) 
00275                     {
00276 
00277                     xl = (*l)->x();          yt = (*l)->y();
00278                     xr = xl + (*l)->width(); yb = yt + (*l)->height();
00279 
00280                     // if not enough room to the left or right of the current tested client
00281                     // determine the first non-overlapped y position
00282                     if((yb > y) && (possible > yb)) possible = yb;
00283 
00284                     basket = yt - ch;
00285                     if((basket > y) && (possible > basket)) possible = basket;
00286                     }
00287                 }
00288             y = possible;
00289             }
00290         }
00291     while((overlap != none) && (overlap != h_wrong) && (y < maxRect.bottom()));
00292 
00293     if(ch>= maxRect.height())
00294         y_optimal=maxRect.top();
00295 
00296     // place the window
00297     c->move(x_optimal, y_optimal);
00298 
00299     }
00300 
00304 void Placement::placeCascaded (Client* c, const QRect& area, bool re_init)
00305     {
00306     /* cascadePlacement by Cristian Tibirna (tibirna@kde.org) (30Jan98)
00307      */
00308     // work coords
00309     int xp, yp;
00310 
00311     //CT how do I get from the 'Client' class the size that NW squarish "handle"
00312     const int delta_x = 24;
00313     const int delta_y = 24;
00314 
00315     const int dn = c->desktop() == 0 || c->isOnAllDesktops() ? (m_WorkspacePtr->currentDesktop() - 1) : (c->desktop() - 1);
00316 
00317     // get the maximum allowed windows space and desk's origin
00318     QRect maxRect = checkArea( c, area );
00319 
00320     // initialize often used vars: width and height of c; we gain speed
00321     const int ch = c->height();
00322     const int cw = c->width();
00323     const int X = maxRect.left();
00324     const int Y = maxRect.top();
00325     const int H = maxRect.height();
00326     const int W = maxRect.width();
00327 
00328   //initialize if needed
00329     if (re_init || cci[dn].pos.x() < X || cci[dn].pos.y() < Y ) 
00330         {
00331         cci[dn].pos = QPoint(X, Y);
00332         cci[dn].col = cci[dn].row = 0;
00333         }
00334 
00335 
00336     xp = cci[dn].pos.x();
00337     yp = cci[dn].pos.y();
00338 
00339     //here to touch in case people vote for resize on placement
00340     if ((yp + ch) > H) yp = Y;
00341 
00342     if ((xp + cw) > W)
00343         if (!yp) 
00344         {
00345         placeSmart(c,area);
00346         return;
00347         }
00348     else xp = X;
00349 
00350   //if this isn't the first window
00351     if (cci[dn].pos.x() != X && cci[dn].pos.y() != Y) 
00352         {
00353         /* The following statements cause an internal compiler error with
00354          * egcs-2.91.66 on SuSE Linux 6.3. The equivalent forms compile fine.
00355          * 22-Dec-1999 CS
00356          *
00357          * if (xp != X && yp == Y) xp = delta_x * (++(cci[dn].col));
00358          * if (yp != Y && xp == X) yp = delta_y * (++(cci[dn].row));
00359          */
00360     if (xp != X && yp == Y)
00361             {
00362             ++(cci[dn].col);
00363             xp = delta_x * cci[dn].col;
00364             }
00365         if (yp != Y && xp == X)
00366             {
00367             ++(cci[dn].row);
00368             yp = delta_y * cci[dn].row;
00369             }
00370 
00371         // last resort: if still doesn't fit, smart place it
00372         if (((xp + cw) > W - X) || ((yp + ch) > H - Y)) 
00373             {
00374             placeSmart(c,area);
00375             return;
00376             }
00377         }
00378 
00379     // place the window
00380     c->move(QPoint(xp, yp));
00381 
00382     // new position
00383     cci[dn].pos = QPoint(xp + delta_x,  yp + delta_y);
00384     }
00385 
00389 void Placement::placeCentered (Client* c, const QRect& area )
00390     {
00391 
00392     // get the maximum allowed windows space and desk's origin
00393     const QRect maxRect = checkArea( c, area );
00394 
00395     const int xp = maxRect.left() + (maxRect.width() -  c->width())  / 2;
00396     const int yp = maxRect.top()  + (maxRect.height() - c->height()) / 2;
00397 
00398     // place the window
00399     c->move(QPoint(xp, yp));
00400     }
00401 
00405 void Placement::placeZeroCornered(Client* c, const QRect& area )
00406     {
00407     // get the maximum allowed windows space and desk's origin
00408     const QRect maxRect = checkArea( c, area );
00409 
00410     // place the window
00411     c->move(QPoint(maxRect.left(), maxRect.top()));
00412     }
00413 
00414 void Placement::placeUtility(Client* c, QRect& area )
00415     {
00416 // TODO kwin should try to place utility windows next to their mainwindow,
00417 // preferably at the right edge, and going down if there are more of them
00418 // if there's not enough place outside the mainwindow, it should prefer
00419 // top-right corner
00420     // use the default placement for now
00421     place( c, Default, area );
00422     }
00423 
00424 
00425 void Placement::placeDialog(Client* c, QRect& area )
00426     {
00427     placeOnMainWindow( c, area );
00428     }
00429 
00430 void Placement::placeUnderMouse(Client* c, QRect& area )
00431     {
00432     area = checkArea( c, area );
00433     QRect geom = c->geometry();
00434     geom.moveCenter( QCursor::pos());
00435     c->move( geom.topLeft());
00436     c->keepInArea( area ); // make sure it's kept inside workarea
00437     }
00438 
00439 void Placement::placeOnMainWindow(Client* c, QRect& area )
00440     {
00441     area = checkArea( c, area );
00442     ClientList mainwindows = c->mainClients();
00443     Client* place_on = NULL;
00444     Client* place_on2 = NULL;
00445     int mains_count = 0;
00446     for( ClientList::ConstIterator it = mainwindows.begin();
00447          it != mainwindows.end();
00448          ++it )
00449         {
00450         if( (*it)->isSpecialWindow() && !(*it)->isOverride())
00451             continue; // don't consider toolbars etc when placing
00452         ++mains_count;
00453         place_on2 = *it;
00454         if( (*it)->isOnCurrentDesktop())
00455             {
00456             if( place_on == NULL )
00457                 place_on = *it;
00458             else
00459                 { // two or more on current desktop -> center
00460                 placeCentered( c, area );
00461                 return;
00462                 }
00463             }
00464         }
00465     if( place_on == NULL )
00466         { // 'mains_count' is used because it doesn't include ignored mainwindows
00467         if( mains_count != 1 )
00468             {
00469             placeCentered( c, area );
00470             return;
00471             }
00472         place_on = place_on2; // use the only window filtered together with 'mains_count'
00473         }
00474     QRect geom = c->geometry();
00475     geom.moveCenter( place_on->geometry().center());
00476     c->move( geom.topLeft());
00477     // get area again, because the mainwindow may be on different xinerama screen
00478     area = checkArea( c, QRect()); 
00479     c->keepInArea( area ); // make sure it's kept inside workarea
00480     }
00481 
00482 QRect Placement::checkArea( const Client* c, const QRect& area )
00483     {
00484     if( area.isNull())
00485         return m_WorkspacePtr->clientArea( PlacementArea, c->geometry().center(), c->desktop());
00486     return area;
00487     }
00488 
00489 #endif
00490 
00491 
00492 Placement::Policy Placement::policyFromString( const QString& policy, bool no_special )
00493     {
00494     if( policy == "NoPlacement" )
00495         return NoPlacement;
00496     else if( policy == "Default" && !no_special )
00497         return Default;
00498     else if( policy == "Random" )
00499         return Random;
00500     else if( policy == "Cascade" )
00501         return Cascade;
00502     else if( policy == "Centered" )
00503         return Centered;
00504     else if( policy == "ZeroCornered" )
00505         return ZeroCornered;
00506     else if( policy == "UnderMouse" && !no_special)
00507         return UnderMouse;
00508     else if( policy == "OnMainWindow" && !no_special)
00509         return OnMainWindow;
00510     else
00511         return Smart;
00512     }
00513 
00514 const char* Placement::policyToString( Policy policy )
00515     {
00516     const char* const policies[] =
00517         { "NoPlacement", "Default", "Random", "Smart", "Cascade", "Centered",
00518             "ZeroCornered", "UnderMouse", "OnMainWindow" };
00519     assert( policy < int( sizeof( policies ) / sizeof( policies[ 0 ] )));
00520     return policies[ policy ];
00521     }
00522 
00523 
00524 #ifndef KCMRULES
00525 
00526 // ********************
00527 // Workspace
00528 // ********************
00529 
00533 void Workspace::slotWindowPackLeft()
00534     {
00535     if( active_client && active_client->isMovable())
00536         active_client->move( packPositionLeft( active_client, active_client->geometry().left(), true ),
00537             active_client->y());
00538     }
00539 
00540 void Workspace::slotWindowPackRight()
00541     {
00542     if( active_client && active_client->isMovable())
00543         active_client->move( 
00544             packPositionRight( active_client, active_client->geometry().right(), true )
00545             - active_client->width() + 1, active_client->y());
00546     }
00547 
00548 void Workspace::slotWindowPackUp()
00549     {
00550     if( active_client && active_client->isMovable())
00551         active_client->move( active_client->x(),
00552             packPositionUp( active_client, active_client->geometry().top(), true ));
00553     }
00554 
00555 void Workspace::slotWindowPackDown()
00556     {
00557     if( active_client && active_client->isMovable())
00558         active_client->move( active_client->x(),
00559             packPositionDown( active_client, active_client->geometry().bottom(), true ) - active_client->height() + 1 );
00560     }
00561 
00562 void Workspace::slotWindowGrowHorizontal()
00563     {
00564     if( active_client )
00565         active_client->growHorizontal();
00566     }
00567 
00568 void Client::growHorizontal()
00569     {
00570     if( !isResizable())
00571         return;
00572     QRect geom = geometry();
00573     geom.setRight( workspace()->packPositionRight( this, geom.right(), true ));
00574     QSize adjsize = adjustedSize( geom.size(), SizemodeFixedW );
00575     if( geometry().size() == adjsize && geom.size() != adjsize && xSizeHint.width_inc > 1 ) // take care of size increments
00576         {
00577         int newright = workspace()->packPositionRight( this, geom.right() + xSizeHint.width_inc - 1, true );
00578         // check that it hasn't grown outside of the area, due to size increments
00579         // TODO this may be wrong?
00580         if( workspace()->clientArea( MovementArea,
00581             QPoint(( x() + newright ) / 2, geometry().center().y()), desktop()).right() >= newright )
00582             geom.setRight( newright );
00583         }
00584     geom.setSize( adjustedSize( geom.size(), SizemodeFixedW ));
00585     setGeometry( geom );
00586     }
00587 
00588 void Workspace::slotWindowShrinkHorizontal()
00589     {
00590     if( active_client )
00591         active_client->shrinkHorizontal();
00592     }
00593 
00594 void Client::shrinkHorizontal()
00595     {
00596     if( !isResizable())
00597         return;
00598     QRect geom = geometry();
00599     geom.setRight( workspace()->packPositionLeft( this, geom.right(), false ));
00600     if( geom.width() <= 1 )
00601         return;
00602     geom.setSize( adjustedSize( geom.size(), SizemodeFixedW ));
00603     if( geom.width() > 20 )
00604         setGeometry( geom );
00605     }
00606 
00607 void Workspace::slotWindowGrowVertical()
00608     {
00609     if( active_client )
00610         active_client->growVertical();
00611     }
00612 
00613 void Client::growVertical()
00614     {
00615     if( !isResizable())
00616         return;
00617     QRect geom = geometry();
00618     geom.setBottom( workspace()->packPositionDown( this, geom.bottom(), true ));
00619     QSize adjsize = adjustedSize( geom.size(), SizemodeFixedH );
00620     if( geometry().size() == adjsize && geom.size() != adjsize && xSizeHint.height_inc > 1 ) // take care of size increments
00621         {
00622         int newbottom = workspace()->packPositionDown( this, geom.bottom() + xSizeHint.height_inc - 1, true );
00623         // check that it hasn't grown outside of the area, due to size increments
00624         if( workspace()->clientArea( MovementArea,
00625             QPoint( geometry().center().x(), ( y() + newbottom ) / 2 ), desktop()).bottom() >= newbottom )
00626             geom.setBottom( newbottom );
00627         }
00628     geom.setSize( adjustedSize( geom.size(), SizemodeFixedH ));
00629     setGeometry( geom );
00630     }
00631 
00632 
00633 void Workspace::slotWindowShrinkVertical()
00634     {
00635     if( active_client )
00636         active_client->shrinkVertical();
00637     }
00638 
00639 void Client::shrinkVertical()
00640     {
00641     if( !isResizable())
00642         return;
00643     QRect geom = geometry();
00644     geom.setBottom( workspace()->packPositionUp( this, geom.bottom(), false ));
00645     if( geom.height() <= 1 )
00646         return;
00647     geom.setSize( adjustedSize( geom.size(), SizemodeFixedH ));
00648     if( geom.height() > 20 )
00649         setGeometry( geom );
00650     }
00651 
00652 int Workspace::packPositionLeft( const Client* cl, int oldx, bool left_edge ) const
00653     {
00654     int newx = clientArea( MovementArea, cl ).left();
00655     if( oldx <= newx ) // try another Xinerama screen
00656         newx = clientArea( MovementArea,
00657             QPoint( cl->geometry().left() - 1, cl->geometry().center().y()), cl->desktop()).left();
00658     if( oldx <= newx )
00659         return oldx;
00660     for( ClientList::ConstIterator it = clients.begin();
00661          it != clients.end();
00662          ++it)
00663         {
00664         if( !(*it)->isShown( false ) || !(*it)->isOnDesktop( active_client->desktop()))
00665             continue;
00666         int x = left_edge ? (*it)->geometry().right() + 1 : (*it)->geometry().left() - 1;
00667         if( x > newx && x < oldx
00668             && !( cl->geometry().top() > (*it)->geometry().bottom() // they overlap in Y direction
00669                 || cl->geometry().bottom() < (*it)->geometry().top()))
00670             newx = x;
00671         }
00672     return newx;
00673     }
00674 
00675 int Workspace::packPositionRight( const Client* cl, int oldx, bool right_edge ) const
00676     {
00677     int newx = clientArea( MovementArea, cl ).right();
00678     if( oldx >= newx ) // try another Xinerama screen
00679         newx = clientArea( MovementArea,
00680             QPoint( cl->geometry().right() + 1, cl->geometry().center().y()), cl->desktop()).right();
00681     if( oldx >= newx )
00682         return oldx;
00683     for( ClientList::ConstIterator it = clients.begin();
00684          it != clients.end();
00685          ++it)
00686         {
00687         if( !(*it)->isShown( false ) || !(*it)->isOnDesktop( cl->desktop()))
00688             continue;
00689         int x = right_edge ? (*it)->geometry().left() - 1 : (*it)->geometry().right() + 1;
00690         if( x < newx && x > oldx
00691             && !( cl->geometry().top() > (*it)->geometry().bottom()
00692                 || cl->geometry().bottom() < (*it)->geometry().top()))
00693             newx = x;
00694         }
00695     return newx;
00696     }
00697 
00698 int Workspace::packPositionUp( const Client* cl, int oldy, bool top_edge ) const
00699     {
00700     int newy = clientArea( MovementArea, cl ).top();
00701     if( oldy <= newy ) // try another Xinerama screen
00702         newy = clientArea( MovementArea,
00703             QPoint( cl->geometry().center().x(), cl->geometry().top() - 1 ), cl->desktop()).top();
00704     if( oldy <= newy )
00705         return oldy;
00706     for( ClientList::ConstIterator it = clients.begin();
00707          it != clients.end();
00708          ++it)
00709         {
00710         if( !(*it)->isShown( false ) || !(*it)->isOnDesktop( cl->desktop()))
00711             continue;
00712         int y = top_edge ? (*it)->geometry().bottom() + 1 : (*it)->geometry().top() - 1;
00713         if( y > newy && y < oldy
00714             && !( cl->geometry().left() > (*it)->geometry().right() // they overlap in X direction
00715                 || cl->geometry().right() < (*it)->geometry().left()))
00716             newy = y;
00717         }
00718     return newy;
00719     }
00720 
00721 int Workspace::packPositionDown( const Client* cl, int oldy, bool bottom_edge ) const
00722     {
00723     int newy = clientArea( MovementArea, cl ).bottom();
00724     if( oldy >= newy ) // try another Xinerama screen
00725         newy = clientArea( MovementArea,
00726             QPoint( cl->geometry().center().x(), cl->geometry().bottom() + 1 ), cl->desktop()).bottom();
00727     if( oldy >= newy )
00728         return oldy;
00729     for( ClientList::ConstIterator it = clients.begin();
00730          it != clients.end();
00731          ++it)
00732         {
00733         if( !(*it)->isShown( false ) || !(*it)->isOnDesktop( cl->desktop()))
00734             continue;
00735         int y = bottom_edge ? (*it)->geometry().top() - 1 : (*it)->geometry().bottom() + 1;
00736         if( y < newy && y > oldy
00737             && !( cl->geometry().left() > (*it)->geometry().right()
00738                 || cl->geometry().right() < (*it)->geometry().left()))
00739             newy = y;
00740         }
00741     return newy;
00742     }
00743 
00747 void Workspace::place(Client* c, QRect& area)
00748     {
00749     initPositioning->place( c, area );
00750     }
00751 
00752 void Workspace::placeSmart(Client* c, const QRect& area)
00753     {
00754     initPositioning->placeSmart( c, area );
00755     }
00756 
00757 #endif
00758 
00759 } // namespace
KDE Logo
This file is part of the documentation for kwin Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Jun 14 01:19:58 2006 by doxygen 1.4.0 written by Dimitri van Heesch, © 1997-2003