• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kwin
 

kwin

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

kwin

Skip menu "kwin"
  • Main Page
  • Alphabetical List
  • Class List
  • File List
  • Class Members

kwin

Skip menu "kwin"
  • kate
  • kwin
  •   lib
  • libkonq
Generated for kwin by doxygen 1.6.3
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |