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